Home > Software design >  How to abandon a manual Room migration script, and fall back to destructive migration?
How to abandon a manual Room migration script, and fall back to destructive migration?

Time:03-05

In the app I'm working on, we had a complex manual migration that required data parsing, manual SQL commands, etc. This was to convert a List<X> column into a new linked table of X. I've crashlytics truncated error

Losing customer data isn't catastrophic in this context, but being stuck in the current "try migrate, crash, reopen app and repeat" loop is. As such, I want to just give up on the migration and fall back to a destructive migration if we encounter an exception.

Any ideas how this can be done? My current solution is rerunning the DB changes (but not the presumably failing data migration) inside the catch, but this feels very hacky.


Our database is defined as:

Room.databaseBuilder(
        context.applicationContext,
        CreationDatabase::class.java,
        "creation_database"
    )
    .addMigrations(MIGRATION_11_12, MIGRATION_14_15)
    .fallbackToDestructiveMigration()
    .build()

where MIGRATION_14_15 is:

private val MIGRATION_14_15 = object : Migration(14, 15) {
    override fun migrate(database: SupportSQLiteDatabase) {
        try {
            // database.execSQL create table etc
        } catch (e: Exception) {
            e.printStackTrace()
            // Here is where I want to give up, and start the DB from scratch
        }
    }
}

CodePudding user response:

The problem you have is that you cannot (at least easily) invoke the fall-back as that is only invoked when there is no migration.

What you could do is to mimic what fall back does (well close to what it does). That is the fall-back will delete (I think) the database file and create the database from scratch and then invoke the databases _Impl (generated java) createAllTables method.

However, you would likely have issues if you deleted the file as the database connection has been passed to the migration.

So instead you could DROP all the app's tables using the code copied from the dropAllTables method from the generated java. You could then follow this with the code from the createAllTables method.

  • These methods are in the generated java as the class that is the same as the class that is annotated with @Database suffixed with _Impl.

The gotcha, is that the exception enter image description here

(Expected .... Found ....) that you have shown is NOT within the migration but after the migration when Room is trying to build the database, so you have no control/place to do the above fall-back mimic unless this was done for all 14-15 migrations.

Perhaps what you could do is to trap the exception, present a dialog requesting the user to uninstall the app and to then re-install. This would then bypass the migration as it would be a fresh install.

  • Related