Implement database migrations manually and remove RoomMigrant

This commit is contained in:
Shinokuni 2024-06-25 14:30:05 +02:00
parent 85242e6ebf
commit b9aa09e103
4 changed files with 71 additions and 7 deletions

View File

@ -80,9 +80,6 @@ dependencies {
kapt(libs.room.compiler)
androidTestImplementation(libs.room.testing)
implementation 'com.github.MatrixDev.Roomigrant:RoomigrantLib:0.3.4' //TODO delete
kapt 'com.github.MatrixDev.Roomigrant:RoomigrantCompiler:0.3.4'
implementation(libs.bundles.paging)
api 'joda-time:joda-time:2.10.10' //TODO replace with java.time?

View File

@ -0,0 +1,42 @@
package com.readrops.db
import androidx.room.testing.MigrationTestHelper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class MigrationsTest {
private val dbName = "TEST-DB"
@get:Rule
val helper: MigrationTestHelper = MigrationTestHelper(
InstrumentationRegistry.getInstrumentation(),
Database::class.java
)
@Test
fun migrate1To2() {
helper.createDatabase(dbName, 1).apply {
close()
}
helper.runMigrationsAndValidate(dbName, 2, true, MigrationFrom1To2).apply {
close()
}
}
@Test
fun migrate2to3() {
helper.createDatabase(dbName, 2).apply {
close()
}
helper.runMigrationsAndValidate(dbName, 3, true, MigrationFrom2To3).apply {
close()
}
}
}

View File

@ -3,6 +3,8 @@ package com.readrops.db
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.readrops.db.dao.AccountDao
import com.readrops.db.dao.FeedDao
import com.readrops.db.dao.FolderDao
@ -21,12 +23,10 @@ import com.readrops.db.entities.Item
import com.readrops.db.entities.ItemState
import com.readrops.db.entities.ItemStateChange
import com.readrops.db.entities.account.Account
import dev.matrix.roomigrant.GenerateRoomMigrations
@Database(entities = [Feed::class, Item::class, Folder::class, Account::class,
ItemStateChange::class, ItemState::class], version = 3)
@TypeConverters(Converters::class)
@GenerateRoomMigrations
abstract class Database : RoomDatabase() {
abstract fun feedDao(): FeedDao
@ -53,4 +53,29 @@ abstract class Database : RoomDatabase() {
abstract fun newItemStateDao(): NewItemStateDao
abstract fun newItemStateChangeDao(): NewItemStateChangeDao
}
object MigrationFrom1To2 : Migration(1, 2) {
override fun migrate(db: SupportSQLiteDatabase) {
db.execSQL("""ALTER TABLE `Feed` ADD `notification_enabled` INTEGER NOT NULL DEFAULT 1""")
db.execSQL("""ALTER TABLE `Account` ADD `notifications_enabled` INTEGER NOT NULL DEFAULT 0""")
}
}
object MigrationFrom2To3 : Migration(2, 3) {
override fun migrate(db: SupportSQLiteDatabase) {
// new tables for separate item read/star state management
db.execSQL("""CREATE TABLE IF NOT EXISTS `ItemStateChange` (`id` INTEGER NOT NULL, `read_change` INTEGER NOT NULL, `star_change` INTEGER NOT NULL, `account_id` INTEGER NOT NULL, PRIMARY KEY(`id`), FOREIGN KEY(`account_id`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )""")
db.execSQL("""CREATE TABLE IF NOT EXISTS `ItemState` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `read` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `remote_id` TEXT NOT NULL, `account_id` INTEGER NOT NULL, FOREIGN KEY(`account_id`) REFERENCES `Account`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )""")
// removing read_changed and adding starred fields. Table is recreated to keep field order
db.execSQL("""CREATE TABLE IF NOT EXISTS `Item_MERGE_TABLE` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `title` TEXT, `description` TEXT, `clean_description` TEXT, `link` TEXT, `image_link` TEXT, `author` TEXT, `pub_date` INTEGER, `content` TEXT, `feed_id` INTEGER NOT NULL, `guid` TEXT, `read_time` REAL NOT NULL, `read` INTEGER NOT NULL, `starred` INTEGER NOT NULL, `read_it_later` INTEGER NOT NULL, `remoteId` TEXT, FOREIGN KEY(`feed_id`) REFERENCES `Feed`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )""")
db.execSQL("""INSERT INTO `Item_MERGE_TABLE` (`id`,`title`,`description`,`clean_description`,`link`,`image_link`,`author`,`pub_date`,`content`,`feed_id`,`guid`,`read_time`,`read`,`read_it_later`,`remoteId`,`starred`) SELECT `Item`.`id`,`Item`.`title`,`Item`.`description`,`Item`.`clean_description`,`Item`.`link`,`Item`.`image_link`,`Item`.`author`,`Item`.`pub_date`,`Item`.`content`,`Item`.`feed_id`,`Item`.`guid`,`Item`.`read_time`,`Item`.`read`,`Item`.`read_it_later`,`Item`.`remoteId`,0 FROM `Item`""")
db.execSQL("""DROP TABLE IF EXISTS `Item`""")
db.execSQL("""ALTER TABLE `Item_MERGE_TABLE` RENAME TO `Item`""")
db.execSQL("""CREATE INDEX IF NOT EXISTS `index_Item_feed_id` ON `Item` (`feed_id`)""")
db.execSQL("""CREATE INDEX IF NOT EXISTS `index_Item_guid` ON `Item` (`guid`)""")
}
}

View File

@ -7,7 +7,7 @@ val dbModule = module {
single(createdAtStart = true) {
Room.databaseBuilder(get(), Database::class.java, "readrops-db")
.addMigrations(*Database_Migrations.build())
.build()
.addMigrations(MigrationFrom1To2, MigrationFrom2To3)
.build()
}
}