Bump @Database(version = …) and register migration classes. They run on open when the on-disk version is lower.
@Database(
version = 2,
tables = [User::class],
migrations = [AddEmailMigration::class],
)
abstract class AppDatabase : DBFlowDatabase<AppDatabase>()
@Migration(version = 2, priority = 1)
class AddEmailMigration : Migration {
override suspend fun MigrationScope.migrate() {
if (!(migrationAdapter("User") hasColumn "email")) {
(alterTable("User") addColumn ColumnAlter.Plain(
name = "email",
type = SQLiteType.TEXT,
)).execute()
}
}
}priority is lowest-first when several migrations share a version.
SQLite can ALTER TABLE … RENAME and ADD COLUMN. For anything else, create a new table, copy, drop, rename.
alterTable("User") addColumn ColumnAlter.Plain("email", SQLiteType.TEXT)
alterTable("User") dropColumn "legacy"
alterTable("User") renameTo "Person"MigrationScope is the only safe API during upgrade. Do not open the same database recursively from a migration.
Place statements in:
assets/migrations/{DatabaseName}/{version}.sql
Example: assets/migrations/AppDatabase/2.sql
Each statement ends with ;. -- comments must be on their own line.
@Migration(version = 0) runs only when the database is created, not on later upgrades.
Ship a starter .db in assets and point the open helper at it (see tests under PrepackagedDB). Run migrations after copy if version is higher than the packaged file.