Related
I'm trying to implement this database with quite a few parameters. Unfortunately I cannot figure out why the order is mixed up that badly. The database is being read from the assets, it's already populated with ~250 items.
Error Message:
Expected:
TableInfo{name='Item', columns={tradingItem3Amount=Column{name='tradingItem3Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting2Amount=Column{name='itemCrafting2Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, description=Column{name='description', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting4Amount=Column{name='itemCrafting4Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, buoyancy=Column{name='buoyancy', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ItemCategory=Column{name='ItemCategory', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1Amount=Column{name='tradingItem1Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting3=Column{name='itemCrafting3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting4=Column{name='itemCrafting4', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting1=Column{name='itemCrafting1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting2=Column{name='itemCrafting2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount=Column{name='itemCraftingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, durability=Column{name='durability', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, weight=Column{name='weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, friction=Column{name='friction', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting3Amount=Column{name='itemCrafting3Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, imgUrl=Column{name='imgUrl', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1=Column{name='tradingItem1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2=Column{name='tradingItem2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem3=Column{name='tradingItem3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, name=Column{name='name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, flammable=Column{name='flammable', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting1Amount=Column{name='itemCrafting1Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2Amount=Column{name='tradingItem2Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, modpack=Column{name='modpack', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, extraInfo=Column{name='extraInfo', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingAmount=Column{name='tradingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='Item', columns={Category=Column{name='Category', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Description=Column{name='Description', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem3Amount=Column{name='tradingItem3Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Name=Column{name='Name', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1Amount=Column{name='tradingItem1Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting3=Column{name='itemCrafting3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting4=Column{name='itemCrafting4', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting1=Column{name='itemCrafting1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCrafting2=Column{name='itemCrafting2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount=Column{name='itemCraftingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1, defaultValue='null'}, itemCraftingAmount1=Column{name='itemCraftingAmount1', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount2=Column{name='itemCraftingAmount2', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount3=Column{name='itemCraftingAmount3', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, itemCraftingAmount4=Column{name='itemCraftingAmount4', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Durability=Column{name='Durability', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Flammable=Column{name='Flammable', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Bouyancy=Column{name='Bouyancy', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, ItemID=Column{name='ItemID', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Weight=Column{name='Weight', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem1=Column{name='tradingItem1', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2=Column{name='tradingItem2', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem3=Column{name='tradingItem3', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, Friction=Column{name='Friction', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingItem2Amount=Column{name='tradingItem2Amount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, modpack=Column{name='modpack', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, extraInfo=Column{name='extraInfo', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, tradingAmount=Column{name='tradingAmount', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
The create statement:
This statement is copied from SQLite Browser
CREATE TABLE "Item" (
"id" INTEGER,
"Name" TEXT,
"ItemID" TEXT,
"Category" TEXT,
"Description" TEXT,
"Weight" INTEGER,
"Durability" INTEGER,
"Friction" INTEGER,
"Bouyancy" INTEGER,
"Flammable" INTEGER,
"itemCrafting1" TEXT,
"itemCraftingAmount1" INTEGER,
"itemCrafting2" TEXT,
"itemCraftingAmount2" INTEGER,
"itemCrafting3" TEXT,
"itemCraftingAmount3" INTEGER,
"itemCrafting4" TEXT,
"itemCraftingAmount4" INTEGER,
"extraInfo" TEXT,
"itemCraftingAmount" INTEGER,
"tradingAmount" INTEGER,
"tradingItem1" TEXT,
"tradingItem1Amount" INTEGER,
"tradingItem2" TEXT,
"tradingItem2Amount" INTEGER,
"tradingItem3" TEXT,
"tradingItem3Amount" INTEGER,
"modpack" TEXT,
PRIMARY KEY("id")
)
Item.kt
package com.blazecode.scrapguidev2.ui.items
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.blazecode.scrapguidev2.ui.items.enums.Modpack
import com.blazecode.scrapguidev2.ui.items.enums.ItemCategory
#Entity
data class Item(
#PrimaryKey var id: String = "0",
#ColumnInfo(name = "name") var name: String?,
#ColumnInfo(name = "imgUrl") var imgUrl: Int?,
#ColumnInfo(name = "ItemCategory") var category: ItemCategory?,
#ColumnInfo(name = "description") var description: String?,
#ColumnInfo(name = "weight") var weight: Int?,
#ColumnInfo(name = "durability") var durability: Int?,
#ColumnInfo(name = "friction") var friction: Int?,
#ColumnInfo(name = "buoyancy") var buoyancy: Int?,
#ColumnInfo(name = "flammable") var flammable: Boolean?,
#ColumnInfo(name = "itemCrafting1") var itemCrafting1: String?,
#ColumnInfo(name = "itemCrafting2") var itemCrafting2: String?,
#ColumnInfo(name = "itemCrafting3") var itemCrafting3: String?,
#ColumnInfo(name = "itemCrafting4") var itemCrafting4: String?,
#ColumnInfo(name = "itemCrafting1Amount") var itemCrafting1Amount: Int?,
#ColumnInfo(name = "itemCrafting2Amount") var itemCrafting2Amount: Int?,
#ColumnInfo(name = "itemCrafting3Amount") var itemCrafting3Amount: Int?,
#ColumnInfo(name = "itemCrafting4Amount") var itemCrafting4Amount: Int?,
#ColumnInfo(name = "extraInfo") var extraInfo: String?,
#ColumnInfo(name = "itemCraftingAmount") var itemCraftingAmount: Int?,
#ColumnInfo(name = "tradingAmount") var tradingAmount: Int?,
#ColumnInfo(name = "tradingItem1") var tradingItem1: String?,
#ColumnInfo(name = "tradingItem1Amount") var tradingItem1Amount: Int?,
#ColumnInfo(name = "tradingItem2") var tradingItem2: String?,
#ColumnInfo(name = "tradingItem2Amount") var tradingItem2Amount: Int?,
#ColumnInfo(name = "tradingItem3") var tradingItem3: String?,
#ColumnInfo(name = "tradingItem3Amount") var tradingItem3Amount: Int?,
#ColumnInfo(name = "modpack") var modpack: Modpack?
)
The order is irrelevant, it is not an issue. From a very quick inspection (of the generated SQL - see below) you have an issue with NOT NULL being omitted for the id column. However as explained below comparison/adjustment isn't required as Room generates the exact SQL for the table(s).
The simple way to ascertain what Room expects (demands in reality) is to
Make the required changes to the #Entity annotated classes.
Include the #Entity annotated classes in the #Database annotated class.
Compile the project (CTRL + F9)
Using the Android View of Android Studio go to the java(generated) and expand it to locate the class that is the same name as the #Database annotated class but suffixed with _Impl.
Locate the createAllTables method and you will see the exact SQL for the creation of the table(s).
Ignore the room_master_table Room will ensure that this is created and populated.
The following is an example where your code has been added to an existing project (used for other answers):-
I have this data class, I added a new value into it requirePolice
#Entity
data class Crime(#PrimaryKey val id : UUID = UUID.randomUUID(),
var title: String ="",
var date: Date = Date(),
var isSolved: Boolean = false,
var requirePolice : Boolean = false, <--- this is the new value
var suspect: String = ""){
//designating a picture location p.317
val photoFileName
get() = "IMG_$id.jpg"
}
I upgraded the data base from 2 to 3 to include it in the SQLite table, i kept the previous upgrade code also there
#Database(entities = [Crime::class], version = 3)
#TypeConverters(CrimeTypeConverters::class)
abstract class CrimeDatabase: RoomDatabase(){
abstract fun crimeDao() : CrimeDao
}
val migration_1_2 = object : Migration(1,2){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Crime ADD COLUMN suspect TEXT NOT NULL DEFAULT ''")
}
}
val migration_2_3 = object : Migration(2,3){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Crime ADD COLUMN requirePolice TEXT NOT NULL DEFAULT ''")
}
}
I included the upgrade into the Repository this way
private const val DATABASE_NAME = "crime-database"
class CrimeRepository private constructor(context: Context){
private val database: CrimeDatabase = Room.databaseBuilder(
context.applicationContext,
CrimeDatabase::class.java,
DATABASE_NAME
).addMigrations(migration_1_2)
.addMigrations(migration_2_3)//adding latest migration
.build()
...
I keep getting this error
E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0
Process: com.bignerdranch.android.criminalintent, PID: 22566
java.lang.RuntimeException: Exception while computing database live data.
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:92)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:923)
Caused by: java.lang.IllegalStateException: Migration didn't properly handle: Crime(com.bignerdranch.android.criminalintent.Crime).
Expected:
TableInfo{name='Crime', columns={date=Column{name='date', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, requirePolice=Column{name='requirePolice', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, suspect=Column{name='suspect', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, isSolved=Column{name='isSolved', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='Crime', columns={date=Column{name='date', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, requirePolice=Column{name='requirePolice', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, isSolved=Column{name='isSolved', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, suspect=Column{name='suspect', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:103)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:177)
at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:416)
at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:316)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.getWritableSupportDatabase(FrameworkSQLiteOpenHelper.java:145)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper.getWritableDatabase(FrameworkSQLiteOpenHelper.java:106)
at androidx.room.RoomDatabase.inTransaction(RoomDatabase.java:731)
at androidx.room.RoomDatabase.assertNotSuspendingTransaction(RoomDatabase.java:508)
at androidx.room.RoomDatabase.query(RoomDatabase.java:551)
at androidx.room.util.DBUtil.query(DBUtil.java:83)
at com.bignerdranch.android.criminalintent.database.CrimeDao_Impl$3.call(CrimeDao_Impl.java:158)
at com.bignerdranch.android.criminalintent.database.CrimeDao_Impl$3.call(CrimeDao_Impl.java:155)
at androidx.room.RoomTrackingLiveData$1.run(RoomTrackingLiveData.java:90)
... 3 more
why it gave me this error?
how to make it work?
The reason for the failure is explained in :-
Expected:
TableInfo{name='Crime', columns={date=Column{name='date', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, requirePolice=Column{name='requirePolice', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, suspect=Column{name='suspect', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, isSolved=Column{name='isSolved', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='Crime', columns={date=Column{name='date', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, requirePolice=Column{name='requirePolice', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}, isSolved=Column{name='isSolved', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, suspect=Column{name='suspect', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, title=Column{name='title', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
More specifically the expected (what the Entity EXPECTS) is :-
requirePolice=Column{name='requirePolice', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0, defaultValue='null'}
Whilst the table (what was FOUND) has been altered to be :-
requirePolice=Column{name='requirePolice', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue=''''}
The main difference is that instead of a column type of INTEGER (Boolean equates to INTEGER) the ALTER has set the column type to TEXT.
i.e. EXPECTED INTEGER (Boolean) FOUND TEXT (String)
As such you need to use :-
val migration_2_3 = object : Migration(2,3){
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE Crime ADD COLUMN requirePolice INTEGER NOT NULL")
}
OR change the Entity to be (probably not what you want):-
#Entity
data class Crime(#PrimaryKey val id : UUID = UUID.randomUUID(),
var title: String ="",
var date: Date = Date(),
var isSolved: Boolean = false,
var requirePolice : String = "", <--- this is the new value
var suspect: String = ""){
//designating a picture location p.317
val photoFileName
get() = "IMG_$id.jpg"
}
It is likely that it is the ALTER statement that you want to change rather than the Entity.
How to avoid such EXPECTED/FOUND discrepancies - aka let Room do the work for you
You can actually ascertain what is EXPECTED by creating/changing the Entity and then compiling CTRL+F9, after a successful compile the underlying java is generated and this actually contains the SQL to create the table(s).
You can view the SQL by selecting Android View, locating the java (generated) folder, expanding it and then expanding the folders and then locating the class that is named the same as your #Database class suffixed with _Impl (CrimeDatabase_Impl in your case) in the class there will be a createAllTables method, this contains the EXPECTED SQL for all the tables you can then extract/copy the SQL for the definition(s) of the changed column(s) and use this in the ALTER statement (if adding a new Entity then you also have the SQL for the entire table).
Note as per the warning DO NOT CHANGE anything in the class.
Here's an example of the above (not for your project though) :-
If you are using sql light db, then you have to migrate the db in this way,
#Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 4) {
db.execSQL("ALTER TABLE " + TABLE_NOTIFICATION + " ADD COLUMN " + COLUMN_DEEP_LINK + " TEXT ");
}
}
Error:
java.lang.IllegalStateException: Migration didn't properly handle: insta_alerts(org.altruist.BajajExperia.Models.CEInstaViewDetailsDTO).
Expected:
TableInfo{name='insta_alerts', columns={isSeen=Column{name='isSeen',
type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, smsText=Column{name='smsText', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, sentDate=Column{name='sentDate', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, campaign=Column{name='campaign', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, customerId=Column{name='customerId',
type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, id=Column{name='id', type='INTEGER',
affinity='3', notNull=false, primaryKeyPosition=1,
defaultValue='null'}, header=Column{name='header', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, priority=Column{name='priority', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, notificationText=Column{name='notificationText',
type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, alertMessage=Column{name='alertMessage',
type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}}, foreignKeys=[],
indices=[Index{name='index_insta_alerts_smsText_customerId',
unique=true, columns=[smsText, customerId]}]}
Found:
TableInfo{name='insta_alerts', columns={isSeen=Column{name='isSeen',
type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, smsText=Column{name='smsText', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, sentDate=Column{name='sentDate', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, campaign=Column{name='campaign', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, customerId=Column{name='customerId',
type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, id=Column{name='id', type='INTEGER',
affinity='3', notNull=false, primaryKeyPosition=1,
defaultValue='null'}, header=Column{name='header', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, priority=Column{name='priority', type='TEXT',
affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, notificationText=Column{name='notificationText',
type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}, alertMessage=Column{name='alertMessage',
type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0,
defaultValue='null'}}, foreignKeys=[], indices=[]}
Query:
database.execSQL("CREATE TABLE IF NOT EXISTS insta_alerts(id INTEGER PRIMARY KEY,campaign TEXT,notificationText TEXT,header TEXT,alertMessage TEXT,priority TEXT,sentDate TEXT,smsText TEXT,customerId TEXT,isSeen INTEGER, CONSTRAINT index_insta_alerts_smsText_customerId UNIQUE(smsText, customerId) ON CONFLICT REPLACE)")
Model:
#Entity(
tableName = "insta_alerts", indices =
[Index(
value = ["smsText", "customerId"],
unique = true
)]
)
#Parcelize
data class CEInstaViewDetailsDTO(
#PrimaryKey(/*autoGenerate = true*/)
#ColumnInfo(name = "id")
#SerializedName("id")
var id: Long? = null,
#ColumnInfo(name = "campaign")
#SerializedName("campaign")
var campaign: String? = null,
#ColumnInfo(name = "notificationText")
#SerializedName("notificationText")
var notificationText: String? = null,
#ColumnInfo(name = "header")
#SerializedName("header")
var header: String? = null,
#ColumnInfo(name = "alertMessage")
#SerializedName("alertMessage")
var alertMessage: String? = null,
#ColumnInfo(name = "priority")
#SerializedName("priority")
var priority: String? = null,
#ColumnInfo(name = "sentDate")
#SerializedName("sentDate")
var sentDate: String? = null,
#ColumnInfo(name = "smsText")
#SerializedName("smsText")
var smsText: String? = null,
#ColumnInfo(name = "customerId")
#SerializedName("customerId")
var customerId: String? = null,
#ColumnInfo(name = "isSeen")
#SerializedName("isSeen")
var isSeen: Int? = null
) : Parcelable
You should add your index creation to your migration like
database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS index_insta_alerts_smsText_customerId ON insta_alerts (smsText,customerId)")
My Entity
#Entity(tableName = "user_table")
data class User(
val userID:String,
val userName:String,
val userRoleName:String,
val adminID:String,
val name:String,
val email:String,
val phoneNumber:String,
val adminType:String,
val batchID:String,
val centerID:String,
val batchName:String,
val centerName:String,
val password:String
) {
#PrimaryKey(autoGenerate = true)
var id: Int = 0
}
I added the password column;
The migration that I provided is
private val migration: Migration = object : Migration(1, 2) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE user_table ADD COLUMN password TEXT")
}
}
I have used it here
private fun buildDB(c: Context): MDatabase {
val dbName = "lms_database.db"
return Room.databaseBuilder(c.applicationContext, MDatabase::class.java, dbName)
.addMigrations(migration)
.build()
}
I am getting a lengthy error:
java.lang.IllegalStateException: Migration didn't properly handle: user_table(app.database.entities.User).
Expected:
TableInfo{name='user_table', columns={batchName=Column{name='batchName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, centerID=Column{name='centerID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, adminType=Column{name='adminType', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, userName=Column{name='userName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, batchID=Column{name='batchID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, userID=Column{name='userID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, password=Column{name='password', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, phoneNumber=Column{name='phoneNumber', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, adminID=Column{name='adminID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, email=Column{name='email', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, userRoleName=Column{name='userRoleName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, centerName=Column{name='centerName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='user_table', columns={batchName=Column{name='batchName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, centerID=Column{name='centerID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, adminType=Column{name='adminType', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, userName=Column{name='userName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, batchID=Column{name='batchID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, userID=Column{name='userID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, password=Column{name='password', type='Text', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, phoneNumber=Column{name='phoneNumber', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, adminID=Column{name='adminID', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, name=Column{name='name', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=1, defaultValue='null'}, email=Column{name='email', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, userRoleName=Column{name='userRoleName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}, centerName=Column{name='centerName', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
at androidx.room.RoomOpenHelper.onUpgrade(RoomOpenHelper.java:103)
at androidx.sqlite.db.framework.FrameworkSQLiteOpenHelper$OpenHelper.onUpgrade(FrameworkSQLiteOpenHelper.java:124)
The database already has some data right now.
You have to set password nullable in entity model or provide non null value during migration. Try setting
Either
val password:String?
Or
ALTER TABLE user_table ADD COLUMN password TEXT NOT NULL DEFAULT ''
N.B: Replace empty with your default one
I was trying to upgrade my Database version and in last version the table had a unique index created upon migration room gave me the following error
Expected:
TableInfo{name='ALERT_STATUS', columns={resolution_time=Column{name='resolution_time', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, status=Column{name='status', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, event_time=Column{name='event_time', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, is_uploaded=Column{name='is_uploaded', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, InvErrorCode=Column{name='InvErrorCode', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, is_fault=Column{name='is_fault', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, FaultDetails=Column{name='FaultDetails', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, code=Column{name='code', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, component=Column{name='component', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}}, foreignKeys=[], indices=[Index{name='index_ALERT_STATUS_code_event_time', unique=true, columns=[code, event_time]}]}
Found:
TableInfo{name='ALERT_STATUS', columns={resolution_time=Column{name='resolution_time', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, status=Column{name='status', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, id=Column{name='id', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=1}, event_time=Column{name='event_time', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, is_uploaded=Column{name='is_uploaded', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, InvErrorCode=Column{name='InvErrorCode', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, is_fault=Column{name='is_fault', type='INTEGER', affinity='3', notNull=true, primaryKeyPosition=0}, FaultDetails=Column{name='FaultDetails', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0}, code=Column{name='code', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=0}, component=Column{name='component', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0}}, foreignKeys=[], indices=[Index{name='code_time', unique=true, columns=[code, event_time]}]}
I tried removing the unique index and the migration worked fine but with unique index it never passed
My database Entity is below
#Entity(tableName = "ALERT_STATUS" , indices = {#Index(value = {"code", "event_time"},
unique = true)})
public class AlertStatus implements Serializable{
#PrimaryKey(autoGenerate = true)
public Integer id;
#NonNull
public String event_time;
public String resolution_time;
#NonNull
public String code;
public Integer component;
public int status;
public int is_fault;
public String FaultDetails;
public String InvErrorCode;
public int is_uploaded;
}
Try this worked for me.
Create a new Table i.e. Holder table which will hold your data between structural changes.
database.execSQL("CREATE TABLE TABLE_NAME (id INTEGER, column1 varchar(25), column2 varchar(25) , PRIMARY KEY(id))");
Create Unique Index as required
database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS <index-name> ON TABLE_NAME (column1,column2)");