SQLDelightを導入するに当たって詰まったポイント
Roomは使ったことがあったので比較対象としてSQLDelightを試してみた際に詰まったポイントをメモ。
環境
- 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ファイルを作りマイグレーションの処理を書く。
今まで4回バージョンを上げてきたならそれぞれのバージョンアップで行ってきたマイグレーションを1.sqm, 2.sqm, 3.sqm, 4.sqmに記載する。再ビルドするとDatabaseImpl.Schemaのversionが5を返すようになる。