Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android room migration add a list of enums

I'm saving

data class Settings(
    val foo: Int
)

into my room database version 1.

Now I need to extend Settings to

data class Settings(
    val foo: Int,
    val bar: ArrayList<Baz>
)

where

enum class Baz {
    A, B, C
}

so I need to do a migration to version 2.

I have type converters for bar. I'm currently trying something like

val MIGRATION_1_2: Migration = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("ALTER TABLE settings ADD COLUMN bar TEXT")
    }
}

but this gives me an IllegalStateException: Migration didn't properly handle Settings... error.

And I'm stuck. So please help! How do I get that migration working??

like image 209
Algar Avatar asked Nov 07 '22 19:11

Algar


1 Answers

Turns out it was my lack of SQLite skills that was in the way.

First of all, I needed to set a default value since my barwasn't allowed to be null. Second, ALTER TABLE is crazy limited and didn't allow me to set a default value in one line.

I ended up doing

val MIGRATION_1_2: Migration = object : Migration(1, 2) {
    override fun migrate(database: SupportSQLiteDatabase) {
        database.execSQL("CREATE TABLE settings_new (foo INTEGER NOT NULL, bar TEXT NOT NULL, PRIMARY KEY(foo))")
        database.execSQL("INSERT INTO settings_new (foo, bar) SELECT foo, '[]' AS bar FROM settings")
        database.execSQL("DROP TABLE settings")
        database.execSQL("ALTER TABLE settings_new RENAME TO settings")
    }
}

In other words

  1. Create a new temporary table (settings_new)
  2. Move old values into the new one. Notice that we set bar as an empty array as default.
  3. Drop the original (settings) table
  4. Rename the temporary to the old name (i.e. settings_new --> settings)
like image 60
Algar Avatar answered Nov 11 '22 11:11

Algar