I have an app with multiple migrations, one of them is from a version previous to the use of Room to a version when Room was introduced. I have found that it runs with RoomOpenHelper.onUpgrade
callback, but when I use SafeHelperFactory
it creates an instance of SQLiteOpenHelper
which itself holds a callback to RoomOpenHelper
. I think it is creating conflicts in the migration path. The strange thing is that this issue is not happening when I migrate from a version of the app that already has Room (with no encryption) to a version with SafeRoom, it also runs smoothly when migrating from no Room to Room (with no encryption). The stacktrace I'm getting is the following (although not sure how much context on the migration will be needed, I don't think the migration itself is the issue as it works when migrating from no Room to Room and has been working for a while, the issue arises when I'm trying to introduce SafeRoom, please look at the order of the function/method calls being made).
Process: com.xx.xx.debug, PID: 16780
net.sqlcipher.database.SQLiteException: error in view guest_summary: no such table: main.my_guests: ALTER TABLE my_guests_temp RENAME TO my_guests
at net.sqlcipher.database.SQLiteDatabase.native_execSQL(Native Method)
at net.sqlcipher.database.SQLiteDatabase.execSQL(SQLiteDatabase.java:2417)
at com.commonsware.cwac.saferoom.Database.execSQL(Database.java:371)
at MyDatabaseKt$MIGRATION_15_16$1.migrate(MyDatabase.kt:460)
at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:87)
at com.commonsware.cwac.saferoom.Helper$OpenHelper.onUpgrade(Helper.java:207)
at net.sqlcipher.database.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:182)
at com.commonsware.cwac.saferoom.Helper$OpenHelper.getWritableSupportDatabase(Helper.java:172)
at com.commonsware.cwac.saferoom.Helper.getWritableDatabase(Helper.java:82)
at androidx.room.RoomDatabase.query(RoomDatabase.java:256)
at androidx.room.util.DBUtil.query(DBUtil.java:54)
The version with no room is 15. I use Dagger so the way I integrate SafeRoom is as follows.
/**
* Provide the single instance of our room database
*/
@Singleton
@Provides
fun provideDatabase(@Named("app") context: Context): MyDatabase {
val databaseState = SQLCipherUtils.getDatabaseState(context, "DatabaseName.db")
Log.d("ROOM", "database status: $databaseState")
if (databaseState == SQLCipherUtils.State.UNENCRYPTED) {
Log.d("ROOM", "start encryption")
val passphrase = "databasekey".toCharArray()
SQLCipherUtils.encrypt(context, "DatabaseName.db", passphrase)
Log.d("ROOM", "finish encryption")
}
val factory = SafeHelperFactory.fromUser(SpannableStringBuilder("databasekey"))
return Room
.databaseBuilder(
app,
MyDatabase::class.java,
"DatabaseName.db"
)
.openHelperFactory(factory)
.allowMainThreadQueries()
.addMigrations(*getMigrationList())
.build()
}
If more context is needed I can provide. If this is a known issue or already has a workable solution please redirect me. Thanks.