Search code examples
androidsqlkotlinandroid-room

How can I migrate Room database when I change nullable and add ColumnInfo annotation?


I've recently changed the table class like this.

data class Product(
    @PrimaryKey(autoGenerate = true)
    val seq: Long,
    val pucd: String,
    @ColumnInfo(name = "updated_at")
    @SerialName("updated_at")
    val updatedAt: String?
)
data class Product(
    @PrimaryKey(autoGenerate = true)
    val seq: Long,
    @ColumnInfo(name = "pucd") // added ColumnInfo
    val pucd: String,
    @ColumnInfo(name = "updated_at")
    @SerialName("updated_at")
    val updatedAt: String // to non-null
)

And I get crash. that says I might need to version up. But I still get the crash. So, I wanted to extract schema to migrate.

As I remember 2-3 years ago, the json schema file helped me to just copy and paste the migration query. But I only see createSql and setupQueries for something can be called query.

But all the createSql are for creating Table when the table doesn't exist. And setUpQueries is just like.

"setupQueries": [
      "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
      "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '0d7f64a73a5cbc11b1b1e481b24432ef')"
    ]

I have no idea what is hash and what it does. And It doesn't seem it's for migration. How can I solve this issue?


Solution

  • How can I solve this issue?

    • First compile the project after the changes have been made (Ctrl + F9).
    • Next locate the java(generated) from the Android view of Android Studio.
    • Find the class that is the same name as the @Database annotated class but suffixed with _Impl.
    • Find the createAllTables method, the SQL for creating the tables, including the required column definitions will be within the method.
    • assuming that you want the migration to keep any existing data then you will want to have the following in the Migration.
      • ALTER TABLE product RENAME TO original_product;
    • create the table according to the SQL as found above (i.e. creates a new version of the changed table)
    • populate the new table with the data from the renamed original table using
      • INSERT INTO product SELECT seq,pucd,coalesce(updated_at,'unknown') FROM original_product;
      • noting that null values instead of failing will use the value unknown, you may wish to change the value to something more suitable.
    • Last you can the drop the renamed original table
      • DROP TABLE IF EXISTS original_product;

    I have no idea what is hash and what it does

    The hash is a hash of the schema. It is generated at compile time. It is also stored in the room_master_table. If the schema is changed (as in your case) then the compiled version is compared against the stored version at run time. If they differ then the crash happens.