After adding new migration I have the next exception. What didn't I do? When I debuging, migration was done. The new column is text and I try to write all data in one cell.
java.lang.IllegalStateException: Pre-packaged database has an invalid schema: library(com.tnco.runar.model.LibraryItemsModel).
Expected:
TableInfo{name='library', columns={audio_duration=Column{name='audio_duration', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, rune_tags=Column{name='rune_tags', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, image_url=Column{name='image_url', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, link_url=Column{name='link_url', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, link_title=Column{name='link_title', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, audio_url=Column{name='audio_url', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, title=Column{name='title', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, type=Column{name='type', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, childs=Column{name='childs', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, sort_order=Column{name='sort_order', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, content=Column{name='content', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Found:
TableInfo{name='library', columns={audio_duration=Column{name='audio_duration', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, image_url=Column{name='image_url', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, link_url=Column{name='link_url', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, link_title=Column{name='link_title', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, audio_url=Column{name='audio_url', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, id=Column{name='id', type='TEXT', affinity='2', notNull=true, primaryKeyPosition=1, defaultValue='null'}, title=Column{name='title', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, type=Column{name='type', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, childs=Column{name='childs', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}, sort_order=Column{name='sort_order', type='INTEGER', affinity='3', notNull=false, primaryKeyPosition=0, defaultValue='null'}, content=Column{name='content', type='TEXT', affinity='2', notNull=false, primaryKeyPosition=0, defaultValue='null'}}, foreignKeys=[], indices=[]}
Expected: rune_tags=Column BUT didn't found
My DataBase class:
@Database(entities = [LibraryItemsModel::class, ...],
version = 4,
exportSchema = false)
abstract class AppDB : RoomDatabase() {
abstract fun appDAO(): AppDAO
companion object {
@Volatile
private lateinit var INSTANCE: AppDB
fun init(context: Context) {
var dataBaseFilePath = "database/layouts.db"
INSTANCE = Room.databaseBuilder(context, AppDB::class.java, "EN_DATABASE")
.createFromAsset(dataBaseFilePath)
.addMigrations(MIGRATION_2_3, MIGRATION_3_4)
.build()
}
fun getLayoutDB(): AppDB {
return INSTANCE
}
private val MIGRATION_2_3 = object : Migration(2, 3) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("CREATE TABLE runes_generator (id INTEGER PRIMARY KEY NOT NULL, imgUrl TEXT, enTitle TEXT, ruTitle TEXT)")
}
}
private val MIGRATION_3_4 = object : Migration(3, 4) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE library ADD COLUMN rune_tags TEXT")
}
}
Model class:
@Entity(tableName = "library")
@TypeConverters(LibraryConverter::class)
data class LibraryItemsModel(
@PrimaryKey
var id: String,
var childs: List<String>?,
var content: String?,
var title: String?,
@ColumnInfo(name = "image_url")
var imageUrl: String?,
@ColumnInfo(name = "sort_order")
var sortOrder: Int?,
var type: String?,
@ColumnInfo(name = "link_title")
var linkTitle: String?,
@ColumnInfo(name = "link_url")
var linkUrl: String?,
@ColumnInfo(name = "audio_url")
var audioUrl: String?,
@ColumnInfo(name = "audio_duration")
var audioDuration: Int?,
@ColumnInfo(name = "rune_tags")
var runeTags: List<String>?
) {
constructor() : this(
"null",
listOf(),
null,
null,
null,
null,
null,
null,
null,
null,
null,
listOf()
)
}
I added @ColumnInfo(name = "rune_tags") var runeTags: List?
Also I have Converter class
class LibraryConverter {
@TypeConverter
fun fromList(items: List<String>?): String? {
return items?.stream()?.collect(Collectors.joining("|"))
}
@TypeConverter
fun toList(data: String?): List<String> {
return data?.split("|") ?: listOf()
}
}
Your issue is that the pre-packaged database (the asset) does not include the schema change (and if I recall correctly is not at version 3) AND that the database doesn't exist on the device (so the database is being copied from the asset/prepackaged database).
Thus the pre-packaged database is being copied, it's version is then set to, or already at version 4 so no migration is undertaken and thus the resultant message:-
Pre-packaged database ....
To cater for new installs you need/should to have the pre-packaged database using the current schema.
Or you could use the PrePackagedDatabaseCallback to alter the table. You may find How do I use Room's prepackagedDatabaseCallback? useful.