Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Room cannot verify the data integrity even when I change the version number

I'm creating my first Room SQLite Migration and I can't figure out what I'm supposed to do now, the version number in the old Database is 2 and I'm changing it to 3. I get the following error in the console when I try to compile the App:

java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.

My Database code looks like this:

@Database(entities = {Vehicle.class, ShockAbsorver.class, Customer.class, Review.class, BadRatingOption.class}, version = 3)
public abstract class AppDatabase extends RoomDatabase{
private static AppDatabase INSTANCE;

public abstract VehicleDao vehicleDao();
public abstract ShockAbsorverDao absorverDao();
public abstract  CustomerDao customerDao();
public abstract ReviewDao reviewDao();
public abstract  OptionDao optionDao();

static final Migration MIGRATION_2_3 = new Migration(2,3) {
    @Override
    public void migrate(@NonNull SupportSQLiteDatabase database) {

        database.execSQL("PRAGMA foreign_keys=off;");

        // REMOVE COLUMN 'original' FROM Vehicle
        database.beginTransaction();
        database.execSQL("ALTER TABLE vehicle RENAME TO temp_vehicle;");
        database.execSQL("DROP INDEX vehicleRemoteId");
        database.execSQL("CREATE TABLE vehicle(id TEXT NOT NULL PRIMARY KEY,idSuperk INTEGER,idRemote TEXT,model TEXT,year INTEGER,plate TEXT,km INTEGER, FOREIGN KEY(idRemote) REFERENCES review(vehicleId));");
        database.execSQL("CREATE INDEX vehicleRemoteId ON vehicle(idRemote)");
        database.execSQL("INSERT INTO vehicle (id,idRemote,model,year,plate,km) SELECT id,idRemote,model,year,plate,km FROM temp_vehicle;");
        database.execSQL("DROP TABLE temp_vehicle;");
        database.endTransaction();

        // ADD CLOUMN 'id' INTO ShockAbsorver
        database.execSQL("ALTER TABLE shockAbsorver ADD COLUMN id TEXT");

        // CREATE TABLE BadRatingOption
        database.execSQL("CREATE TABLE options (id TEXT NOT NULL PRIMARY KEY,absorverId TEXT,option INTEGER);");
        database.execSQL("CREATE UNIQUE INDEX id ON options(id)");
        database.execSQL("CREATE INDEX absorverId ON options(absorverId)");

        //POPULATE BadRatingOption WITH OPTIONS FROM ShockAbsorver
        Cursor cursor = database.query("SELECT * FROM shockAbsorver");

        ArrayList<String> reviewIds = new ArrayList<>();
        ArrayList<Integer> indexes = new ArrayList<>();
        ArrayList<Integer> options = new ArrayList<>();

        try {
            while (cursor.moveToNext()) {
                reviewIds.add(cursor.getString(cursor.getColumnIndex("reviewId")));
                indexes.add(cursor.getInt(cursor.getColumnIndex("index")));
                options.add(cursor.getInt(cursor.getColumnIndex("option")));

            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            cursor.close();
        }


        for(int i = 0;i<reviewIds.size();i++){
            String absorverId = UUID.randomUUID().toString();
            String optionId = UUID.randomUUID().toString();
            database.execSQL("UPDATE shockAbsorver SET id='"+absorverId+"' WHERE reviewId = '"+reviewIds.get(i)+"' AND `index` = "+String.valueOf(indexes.get(i))+";");
            database.execSQL("INSERT INTO options (id,absorverId,option) VALUES ('"+optionId+"','"+absorverId+"','"+options.get(i)+"');");
        }

        reviewIds = null;
        indexes = null;
        options = null;


        //REMOVE 'option' FROM ShockAbsorver
        database.beginTransaction();
        database.execSQL("ALTER TABLE shockAbsorver RENAME TO temp_shockAbsorver;");
        database.execSQL("CREATE TABLE shockAbsorver(`index` INTEGER NOT NULL,id TEXT,remoteId TEXT,isGood INTEGER,rating INTEGER,isNew INTEGER NOT NULL,isEdited INTEGER NOT NULL,isOriginal INTEGER,observation TEXT,filename TEXT,vehicle TEXT NOT NULL,reviewId TEXT NOT NULL,remoteReviewId TEXT,PRIMARY KEY(reviewId,`index`), FOREIGN KEY(reviewId) REFERENCES review(id));");
        database.execSQL("INSERT INTO shockAbsorver (`index`,remoteId,isGood,rating,isNew,isEdited,isOriginal,observation,filename,vehicle,reviewId,remoteReviewId) SELECT `index`,remoteId,isGood,rating,isNew,isEdited,isOriginal,observation,filename,vehicle,reviewId,remoteReviewId FROM temp_shockAbsorver;");
        database.execSQL("DROP TABLE temp_shockAbsorver;");
        database.endTransaction();


        database.execSQL("PRAGMA foreign_keys=on;");

    }
};

public static AppDatabase getAppDatabase(Context context){
    if(INSTANCE == null){
        INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                AppDatabase.class,
                "shock-absorver-database")
                .allowMainThreadQueries()
                .addMigrations(MIGRATION_2_3)
                .build();
    }
    return INSTANCE;
}

public static void destroyInstance(){
    INSTANCE = null;
}
}

While I was writing the migration code I was getting "Migration didn't properly handle" until I fixed then all, after that I started getting the data integrity error.

Thanks in advance.

like image 213
Jopz Avatar asked Nov 08 '22 11:11

Jopz


1 Answers

For production type: You need to write code for migrating from one DB to another https://developer.android.com/training/data-storage/room/migrating-db-versions

For develop debuging version: Try to uninstall app from your phone. (it will remove old database). And than simply build and run again.

like image 105
Jakub S. Avatar answered Nov 15 '22 10:11

Jakub S.