Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly add indices in database migration for Room?

Tags:

android

I have a problem migrating my Room database. In updated database I have to change one field from integer to double value. I read its not as easy as it sounds and in order to do that I have to create new temporary table with this changed property, copy all values from previous table, delete old one and finally rename the temporary table.

My entity has 2 indices, which are causing problems. Here is my current best solution that is not passing auto generated room migration validation.

oceny is the name of the original table, oceny_temp is the temportary name. Even though i am adding those indices in explicitly with create index the validation is still not passing as it says that in expected table has 2 indices and in found there is 0.

static final Migration MIGRATION_25_26 = new Migration(25,26) {
    @Override
    public void migrate(SupportSQLiteDatabase database) {

        database.execSQL("CREATE TABLE IF NOT EXISTS oceny_temp" +
                        "(`idOceny` TEXT NOT NULL, " +
                        "`idUcznia` TEXT, " +
                        "`idPrzedmiotu` TEXT, " +
                        "`semestr` INTEGER NOT NULL, " +
                        "`typOceny` INTEGER NOT NULL, " +
                        "`wartosc` TEXT, " +
                        "`wartoscDoSredniej` REAL, " +
                        "`czyProponowana` INTEGER NOT NULL, " +
                        "`kategoria` TEXT, " +
                        "`waga` REAL NOT NULL, " +
                        "`maxPunktow` REAL NOT NULL, " +
                        "`odczytana` INTEGER NOT NULL, " +
                        "`dataWystawienia` TEXT, " +
                        "`wystawiajacy` TEXT, " +
                        "`typOczekiwania` INTEGER NOT NULL, " +
                        "`wersjaRekordu` TEXT, " +
                        "`rekordUsuniety` INTEGER NOT NULL, " +
                        "PRIMARY KEY(`idOceny`), " +
                        "FOREIGN KEY(`idUcznia`) REFERENCES `uczniowie`(`idUcznia`) ON UPDATE NO ACTION ON DELETE CASCADE )");

        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idPrzedmiotu ON oceny_temp (idPrzedmiotu)");
        database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny_temp (idUcznia)");


        // Copy the data
        database.execSQL(
                "INSERT INTO oceny_temp (idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety) " +
                                "SELECT idOceny, idUcznia, idPrzedmiotu, semestr, typOceny, wartosc, wartoscDoSredniej, czyProponowana, kategoria, waga, maxPunktow, odczytana, dataWystawienia, wystawiajacy, typOczekiwania, wersjaRekordu, rekordUsuniety FROM oceny");

        // Remove the old table
        database.execSQL("DROP TABLE oceny");

        // Change the table name to the correct one
        database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");
    }
};

The error message:

Migration didn't properly handle 

oceny(de.wolterskluwer.idziennik.model.grades.Grade).
 Expected:
TableInfo{name='oceny', columns={dataWystawienia=Column{name='dataWystawienia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, typOczekiwania=Column{name='typOczekiwania', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idPrzedmiotu=Column{name='idPrzedmiotu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, kategoria=Column{name='kategoria', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, rekordUsuniety=Column{name='rekordUsuniety', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, wystawiajacy=Column{name='wystawiajacy', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wersjaRekordu=Column{name='wersjaRekordu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, maxPunktow=Column{name='maxPunktow', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, czyProponowana=Column{name='czyProponowana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, typOceny=Column{name='typOceny', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, semestr=Column{name='semestr', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, waga=Column{name='waga', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, odczytana=Column{name='odczytana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idUcznia=Column{name='idUcznia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, idOceny=Column{name='idOceny', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1}, wartosc=Column{name='wartosc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wartoscDoSredniej=Column{name='wartoscDoSredniej', type='REAL', affinity='4', notNull=false, primaryKeyPosition=0}}, foreignKeys=[ForeignKey{referenceTable='uczniowie', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[idUcznia], referenceColumnNames=[idUcznia]}], indices=[Index{name='index_oceny_idPrzedmiotu', unique=false, columns=[idPrzedmiotu]}, Index{name='index_oceny_idUcznia', unique=false, columns=[idUcznia]}]}
 Found:
TableInfo{name='oceny', columns={dataWystawienia=Column{name='dataWystawienia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, typOczekiwania=Column{name='typOczekiwania', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idPrzedmiotu=Column{name='idPrzedmiotu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, kategoria=Column{name='kategoria', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, rekordUsuniety=Column{name='rekordUsuniety', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, wystawiajacy=Column{name='wystawiajacy', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wersjaRekordu=Column{name='wersjaRekordu', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, maxPunktow=Column{name='maxPunktow', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, czyProponowana=Column{name='czyProponowana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, typOceny=Column{name='typOceny', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, semestr=Column{name='semestr', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, waga=Column{name='waga', type='REAL', affinity='4', notNull=true, primaryKeyPosition=0}, odczytana=Column{name='odczytana', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, idUcznia=Column{name='idUcznia', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, idOceny=Column{name='idOceny', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1}, wartosc=Column{name='wartosc', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, wartoscDoSredniej=Column{name='wartoscDoSredniej', type='REAL', affinity='4', notNull=false, primaryKeyPosition=0}}, foreignKeys=[ForeignKey{referenceTable='uczniowie', onDelete='CASCADE', onUpdate='NO ACTION', columnNames=[idUcznia], referenceColumnNames=[idUcznia]}], indices=[]}

Additional info: i added IF NOT EXISTS to the create index, because it was crashing saying that the index already exists, which doesn't make sense to me

like image 290
Kamil Grosicki Avatar asked Jan 19 '19 16:01

Kamil Grosicki


1 Answers

It seems like some how the indices are lost when the table is renamed. So I resolved this issue by adding one more line after renaming my temporal table to the correct one. This creates the indices on the renamed table. For your case it would be like this ...

    // Change the table name to the correct one
    database.execSQL("ALTER TABLE oceny_temp RENAME TO oceny");

    // Create the indices on the table
    database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idPrzedmiotu ON oceny (idPrzedmiotu)");
    database.execSQL("CREATE INDEX IF NOT EXISTS index_oceny_idUcznia ON oceny (idUcznia)");

    
like image 174
Njuacha Hubert Avatar answered Oct 05 '22 12:10

Njuacha Hubert