I am using SQLDelight for my Kotlin Multi Platform application development.
Queries :
In the KotlinConf 2018 - A Multiplatform Delight video, there was a mention of sqlcipher being used with sqldelight but I haven't came across anything useful online which shows how to do that exactly.
Is there any example that you can point me to in this regard?
Thanks.
SQL Delight's Android driver is built on the AndroidX SQLite abstraction which means you can use any implementation underneath the library.
When creating the Android driver, you can supply a SupportSQLiteOpenHelper.Factory:
This defaults to the framework one (i.e., using the built-in SQLite in Android), but any should work. A quick Google yields https://github.com/commonsguy/cwac-saferoom which talks about Room but has nothing to do with Room. It's a SQLCipher implementation of SupportSQLiteOpenHelper that you can use.
Seems like cursor close is needed for SQLCipher
2019-06-12 08:03:46.251 26280-26289/com.nibras.mobile.debug E/System: Uncaught exception thrown by finalizer
2019-06-12 08:03:46.252 26280-26289/com.nibras.mobile.debug E/System: net.sqlcipher.database.SQLiteException: unable to close due to unfinalized statements or unfinished backups: sqlite3_close() failed
at net.sqlcipher.database.SQLiteDatabase.dbclose(Native Method)
at net.sqlcipher.database.SQLiteDatabase.onAllReferencesReleased(SQLiteDatabase.java:513)
at net.sqlcipher.database.SQLiteDatabase.finalize(SQLiteDatabase.java:2491)
at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:250)
at java.lang.Daemons$FinalizerDaemon.runInternal(Daemons.java:237)
at java.lang.Daemons$Daemon.run(Daemons.java:103)
at java.lang.Thread.run(Thread.java:764)
2019-06-12 08:03:46.270 2032-2522/system_process I/GnssLocationProvider: WakeLock acquired by sendMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@3ce80cb)
2019-06-12 08:03:46.272 2032-2051/system_process I/GnssLocationProvider: WakeLock released by handleMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@3ce80cb)
2019-06-12 08:03:46.303 26280-26289/com.nibras.mobile.debug W/SQLiteCompiledSql: Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: CREATE TABLE LOGS_TBL (
-- ROW_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,
CLIENT_ID INTEGER
net.sqlcipher.database.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62)
at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:79)
at net.sqlcipher.database.SQLiteStatement.<init>(SQLiteStatement.java:39)
at net.sqlcipher.database.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1702)
at com.commonsware.cwac.saferoom.Database.compileStatement(Database.java:54)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125)
at com.squareup.sqldelight.db.SqlDriver$DefaultImpls.execute$default(SqlDriver.kt:56)
at com.nibras.mobile.app.nibrasmobiledbImpl$Schema.create(nibrasmobiledbImpl.kt:35)
at com.squareup.sqldelight.android.AndroidSqliteDriver$Callback.onCreate(AndroidSqliteDriver.kt:146)
at com.commonsware.cwac.saferoom.Helper$OpenHelper.onCreate(Helper.java:168)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:177)
at com.commonsware.cwac.saferoom.Helper$OpenHelper.getWritableSupportDatabase(Helper.java:142)
at com.commonsware.cwac.saferoom.Helper.getWritableDatabase(Helper.java:77)
at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:26)
at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:19)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.squareup.sqldelight.android.AndroidSqliteDriver.getDatabase(Unknown Source:7)
at com.squareup.sqldelight.android.AndroidSqliteDriver.access$getDatabase$p(AndroidSqliteDriver.kt:19)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125)
at com.nibras.mobile.app.LogsQueriesImpl.insert(nibrasmobiledbImpl.kt:79)
at nibrasCommon.core.platform.Utils$Companion.saveLogsInDB(Utils.kt:14)
at nibrasCommon.features.login.AuthenticateViewModel.loginClick(AuthenticateViewModel.kt:161)
at com.nibras.mobile.features.LoginActivity$onCreate$1.onClick(LoginActivity.kt:161)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
2019-06-12 08:03:46.304 26280-26289/com.nibras.mobile.debug W/SQLiteCompiledSql: Releasing statement in a finalizer. Please ensure that you explicitly call close() on your cursor: CREATE TABLE UserElement_TBL (
-- ROW_ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,
User_ID IN
net.sqlcipher.database.DatabaseObjectNotClosedException: Application did not close the cursor or database object that was opened here
at net.sqlcipher.database.SQLiteCompiledSql.<init>(SQLiteCompiledSql.java:62)
at net.sqlcipher.database.SQLiteProgram.<init>(SQLiteProgram.java:79)
at net.sqlcipher.database.SQLiteStatement.<init>(SQLiteStatement.java:39)
at net.sqlcipher.database.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1702)
at com.commonsware.cwac.saferoom.Database.compileStatement(Database.java:54)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125)
at com.squareup.sqldelight.db.SqlDriver$DefaultImpls.execute$default(SqlDriver.kt:56)
at com.nibras.mobile.app.nibrasmobiledbImpl$Schema.create(nibrasmobiledbImpl.kt:47)
at com.squareup.sqldelight.android.AndroidSqliteDriver$Callback.onCreate(AndroidSqliteDriver.kt:146)
at com.commonsware.cwac.saferoom.Helper$OpenHelper.onCreate(Helper.java:168)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:177)
at com.commonsware.cwac.saferoom.Helper$OpenHelper.getWritableSupportDatabase(Helper.java:142)
at com.commonsware.cwac.saferoom.Helper.getWritableDatabase(Helper.java:77)
at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:26)
at com.squareup.sqldelight.android.AndroidSqliteDriver$database$2.invoke(AndroidSqliteDriver.kt:19)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.squareup.sqldelight.android.AndroidSqliteDriver.getDatabase(Unknown Source:7)
at com.squareup.sqldelight.android.AndroidSqliteDriver.access$getDatabase$p(AndroidSqliteDriver.kt:19)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:125)
at com.squareup.sqldelight.android.AndroidSqliteDriver$execute$1.invoke(AndroidSqliteDriver.kt:19)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:110)
at com.squareup.sqldelight.android.AndroidSqliteDriver.execute(AndroidSqliteDriver.kt:125)
at com.nibras.mobile.app.LogsQueriesImpl.insert(nibrasmobiledbImpl.kt:79)
at nibrasCommon.core.platform.Utils$Companion.saveLogsInDB(Utils.kt:14)
at nibrasCommon.features.login.AuthenticateViewModel.loginClick(AuthenticateViewModel.kt:161)
at com.nibras.mobile.features.LoginActivity$onCreate$1.onClick(LoginActivity.kt:161)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Most helpful comment
SQL Delight's Android driver is built on the AndroidX SQLite abstraction which means you can use any implementation underneath the library.
When creating the Android driver, you can supply a
SupportSQLiteOpenHelper.Factory:https://github.com/square/sqldelight/blob/d04b16a6921f1e89b4f58447fa65eb8ddf739ac0/drivers/android-driver/src/main/java/com/squareup/sqldelight/android/AndroidSqliteDriver.kt#L41
This defaults to the framework one (i.e., using the built-in SQLite in Android), but any should work. A quick Google yields https://github.com/commonsguy/cwac-saferoom which talks about Room but has nothing to do with Room. It's a SQLCipher implementation of SupportSQLiteOpenHelper that you can use.