Room Database Migration doesnt properly handle ALTER TABLE migration

I faced this issue today, I just changed int fields to Integer in Entities. As int cannot be null but Integer objects could be null.


None of the answers are correct in any of the links. After much experiments, found a way for it. The ALTER query needs to be written in the following way to make it work:

database.execSQL("ALTER TABLE 'user' ADD COLUMN 'age' INTEGER NOT NULL DEFAULT 0")

However, the Integer DEFAULT value can be anything.

If you want to add String type column, add in the following manner:

database.execSQL("ALTER TABLE 'user' ADD COLUMN 'address' TEXT")

This works like a charm.


The error message is hard to parse, but there's a difference:

TableInfo{name='user', columns={name=Column{name='name', type='TEXT', notNull=false, primaryKeyPosition=0}, age=Column{name='age', type='INTEGER', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', notNull=true, primaryKeyPosition=1}}, foreignKeys=[]} Found:

Found

TableInfo{ name='user', columns={name=Column{name='name', type='TEXT', notNull=false, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', notNull=true, primaryKeyPosition=1}, age=Column{name='age', type='INTEGER', notNull=false, primaryKeyPosition=0}}, foreignKeys=[]}

Age is nullable but Room expected it to be not null.

Change your migration to:

database.execSQL("ALTER TABLE 'user' ADD COLUMN 'age' INTEGER NOT NULL");

Since this exception explanation is VERY difficult to parse, I have created a small script that does the diff for you.

Example:

mig "java.lang.IllegalStateException: Migration failed. expected:TableInfo{name='user', columns={name=Column{name='name', type='TEXT', notNull=false, primaryKeyPosition=0}, age=Column{name='age', type='INTEGER', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', notNull=true, primaryKeyPosition=1}}, foreignKeys=[]} , found:TableInfo{name='user', columns={name=Column{name='name', type='TEXT', notNull=false, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', notNull=true, primaryKeyPosition=1}, age=Column{name='age', type='INTEGER', notNull=false, primaryKeyPosition=0}}, foreignKeys=[]}"

Result:

expected/found diff


I too wrote a small JS script which you can find https://hrankit.github.io/RoomSQLiteDifferenceFinder/

The process is pretty Simple.

  1. Input the Expected error log in Expected column which is the Left One.

  2. Input the Found error log in Found column which is the Right One.

  3. Press Go. button. The error logs get converted to JSON.

  4. Press Compare button and Voila, you have the difference you need.

This plugin finds out the difference in the two Expected and Found dump from the Android Studio Logcat.

Checkout the image of comparison here