phicdy devlog

Androidアプリ開発やその他技術系の記事をたまに書きます

AndroidとかiOSとかモバイル多め。その他技術的なことも書いていきます。

SQLDelightを導入するに当たって詰まったポイント

Roomは使ったことがあったので比較対象としてSQLDelightを試してみた際に詰まったポイントをメモ。

github.com

cashapp.github.io

環境

  • Android Studio 4.1.3
  • SQLDelgiht 1.5.0
  • Gradle 6.8.3
  • 既存アプリで別のデータベース管理中(バージョンは5)

SQL Delight Gradle plugin applied in project ':' but no supported Kotlin plugin was found

Getting Startedのドキュメントを見ると apply plugin: 'com.squareup.sqldelight' をプロジェクトルートのbuild.gradleに適用しているように見えるがこれは適用する必要がない。 使用するモジュールに対して適用する

サンプルもプロジェクトルートには適用していない

https://github.com/cashapp/sqldelight/blob/master/sample/build.gradle

使用するモジュールで適用している。

https://github.com/cashapp/sqldelight/blob/master/sample/common/build.gradle#L3

primary keyエラー

/your/project/app/src/main/sqldelight/com/phicdy/hoge/Fuga.sq line 2:16 - ')', ',', <column constraint real> or AS expected, got 'primary'
1    CREATE TABLE fuga (
2        _id integer primary key autoincrement,
                     ^^^^^^^
3        name text,
4    )

primary key autoincrementは大文字である必要がある。

Unable to find method 'kotlin.jvm.internal.FunctionReferenceImpl.(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V'kotlin.jvm.internal.FunctionReferenceImpl.(ILjava/lang/Class;Ljava/lang/String;Ljava/lang/String;I)V

Gradle 6.8以上にアップデートする。

Fuelで似た問題があった。 https://stackoverflow.com/questions/64238451/execution-failed-for-task-void-kotlin-jvm-internal-mutablepropertyreference1i

Gradle 6.7まではKotlin 1.3系が使われおりKotlin 1.4系と互換性がないことが問題ぽい。

Gradle 6.8でKotlin 1.4になっている。 https://docs.gradle.org/6.8/release-notes.html

SQLDelightもKotlin 1.4系なのでGradle 6.8以上を使う。

デフォルトのデータベースバージョンが1でクラッシュ

AndroidSqliteDriverのコンストラクタでSupportSQLiteOpenHelperのインスタンスを引数のfactoryから生成している。factory.create()の中でSupportSQLiteOpenHelper.Callbackを設定している。コンストラクタにcallbackを指定しなければデフォルトではAndroidSqliteDriver.Callback(schema)が使われる。中の実装を見るとschema.versionがバージョンとして指定される。

open class Callback(
    private val schema: SqlDriver.Schema,
    vararg callbacks: AfterVersion,
  ) : SupportSQLiteOpenHelper.Callback(schema.version) {

schemaはドキュメントに従えばDatabase.Schemaを渡す。これは内部で生成されるクラス。Database.SchemaはDatabaseImpl.Schemaでversionは生成時に固定されている。

internal val KClass<Database>.schema: SqlDriver.Schema
  get() = DatabaseImpl.Schema

internal fun KClass<Database>.newInstance(driver: SqlDriver): Database = DatabaseImpl(driver)

private class DatabaseImpl(
  driver: SqlDriver
) : TransacterImpl(driver), Database {
  public override val feedQueries: FeedQueriesImpl = FeedQueriesImpl(this, driver)

  public override val filtersQueries: FiltersQueriesImpl = FiltersQueriesImpl(this, driver)

  public object Schema : SqlDriver.Schema {
    public override val version: Int
      get() = 1

このバージョンをあげるにはMigrationsのドキュメントに従ってsqmファイルを作りマイグレーションの処理を書く。

cashapp.github.io

今まで4回バージョンを上げてきたならそれぞれのバージョンアップで行ってきたマイグレーションを1.sqm, 2.sqm, 3.sqm, 4.sqmに記載する。再ビルドするとDatabaseImpl.Schemaのversionが5を返すようになる。