Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Room: How to Migrate Column Renaming?

Issue

My app is crashing because I am not handling migration properly. I'm looking for a solution to migrate the name of 1 column in my table.

In my project I a have a room table named 'content' with a Double attribute 'archivedCount'. In the latest version of the app the attribute archivedCount attribute is re-named to dismissCount, still as type Double.

Original Content model

@Entity(tableName = "content")
data class Content(@PrimaryKey var id: String, var archiveCount: Double) : Parcelable {...}

New Content model

@Entity(tableName = "content")
data class Content(@PrimaryKey var id: String, var dismissCount: Double) : Parcelable {...}

Attempted Solution

After reading a Google Developer Advocate's explanation Understanding migrations with Room, I attempted her solution outlined in the post's section Migrations with complex schema changes which entails making a copy of the original table, deleting the old table, then renaming the newly created table.

With the following approach below there is a runtime error on this line: database.execSQL("INSERT INTO content_new (id, dismissCount) SELECT id, archiveCount FROM users"); because I already cleared my app's cache so the old table no longer exists.

Can I update a single column without re-creating the entire table?

static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
    // Create the new table
    database.execSQL(
            "CREATE TABLE content_new (id TEXT, dismissCount REAL, PRIMARY KEY(id))");
    // Copy the data
    database.execSQL("INSERT INTO content_new (id, dismissCount) SELECT id, archiveCount FROM users");
    // Remove the old table
    database.execSQL("DROP TABLE content");
    // Change the table name to the correct one
    database.execSQL("ALTER TABLE content_new RENAME TO content");
  }
};
like image 511
Adam Hurwitz Avatar asked Oct 05 '18 02:10

Adam Hurwitz


People also ask

Is it possible to change column name?

The RENAME COLUMN statement can only be used to rename a column. If you need additional functions, such as changing the data definition, or position of a column, use the CHANGE clause instead. Note: The word COLUMN is obligatory for the ALTER TABLE RENAME COLUMN command.

What is export schema in Room Android?

Export schemas Room can export your database's schema information into a JSON file at compile time. To export the schema, set the room.schemaLocation annotation processor property in your app/build.gradle file: build.gradle.

Why should I migrate from SQLite to room database in Android?

The Room persistence library provides a number of benefits over using the SQLite APIs directly: Compile-time verification of SQL queries. Convenience annotations that minimize repetitive and error-prone boilerplate code.

How do I rename a column in SQLite?

It is not possible to rename a column, remove a column, or add or remove constraints from a table. The sqlite file format is very simple and that's why this operation is valid.


Video Answer


2 Answers

Solution

Thanks to the guidance from @TimBiegeleisen we discovered that the Android implementation of SQLite 3.19 for API 27 and 28 has not yet upgraded to the version 3.25 SQLite which allows this feature outlined in this StackOverflow post.

Once Android upgrades a command such as this to alter a table column will be possible: database.execSQL("ALTER TABLE content RENAME COLUMN archiveCount TO dismissCount")

like image 111
Adam Hurwitz Avatar answered Oct 25 '22 18:10

Adam Hurwitz


There is a solution without migration - use ColumnInfo:

data class Content(@PrimaryKey var id: String,  @ColumnInfo(name = "archiveCount") var dismissCount: Double) : Parcelable{...}

Database column will be still archiveCount, but in Kotlin property will be renamed.

like image 41
atarasenko Avatar answered Oct 25 '22 17:10

atarasenko