feat(db): migrate to androidx.room3 3.0.2 with SQLCipherDriver (#994)
Co-authored-by: M57 <hy4ri@users.noreply.github.com>
This commit is contained in:
1 parent
680b4082ca
commit
4d9dfb99db
6 files changed
+153
-77
No files matched your search
@@ -1,9 +1,9 @@
|
||||
package com.m57.hermescontrol.data.local
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import androidx.room3.Dao
|
||||
import androidx.room3.Insert
|
||||
import androidx.room3.OnConflictStrategy
|
||||
import androidx.room3.Query
|
||||
|
||||
@Dao
|
||||
interface ChatMessageDao {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.m57.hermescontrol.data.local
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.Index
|
||||
import androidx.room.PrimaryKey
|
||||
import androidx.room3.ColumnInfo
|
||||
import androidx.room3.Entity
|
||||
import androidx.room3.Index
|
||||
import androidx.room3.PrimaryKey
|
||||
|
||||
/**
|
||||
* Persisted chat message. Maps to the [com.m57.hermescontrol.ui.chat.ChatMessage]
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package com.m57.hermescontrol.data.local
|
||||
|
||||
import android.content.Context
|
||||
import androidx.room.Database
|
||||
import androidx.room.Room
|
||||
import androidx.room.RoomDatabase
|
||||
import androidx.room.migration.Migration
|
||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
|
||||
import androidx.room3.Database
|
||||
import androidx.room3.Room
|
||||
import androidx.room3.RoomDatabase
|
||||
import androidx.room3.migration.Migration
|
||||
import androidx.sqlite.SQLiteConnection
|
||||
import androidx.sqlite.execSQL
|
||||
import net.zetetic.database.sqlcipher.driver.SQLCipherDriver
|
||||
import java.io.File
|
||||
|
||||
@Database(
|
||||
@@ -21,6 +22,51 @@ abstract class HermesDatabase : RoomDatabase() {
|
||||
@Volatile
|
||||
private var instance: HermesDatabase? = null
|
||||
|
||||
val MIGRATION_2_3: Migration =
|
||||
object : Migration(2, 3) {
|
||||
override suspend fun migrate(connection: SQLiteConnection) {
|
||||
connection.execSQL(
|
||||
"CREATE INDEX IF NOT EXISTS `index_chat_messages_session_id_timestamp` " +
|
||||
"ON `chat_messages` (`session_id`, `timestamp`)",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_3_4: Migration =
|
||||
object : Migration(3, 4) {
|
||||
override suspend fun migrate(connection: SQLiteConnection) {
|
||||
connection.execSQL(
|
||||
"ALTER TABLE `chat_messages` ADD COLUMN `reasoning_text` TEXT NOT NULL DEFAULT ''",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_4_5: Migration =
|
||||
object : Migration(4, 5) {
|
||||
override suspend fun migrate(connection: SQLiteConnection) {
|
||||
// Issue #842: tool rows now carry the gateway's
|
||||
// tool call id (`call_00_...`) so REST transcript
|
||||
// rows can be matched 1:1 against their live WS
|
||||
// bubbles instead of fragile result-content
|
||||
// canonicalization.
|
||||
connection.execSQL(
|
||||
"ALTER TABLE `chat_messages` ADD COLUMN `tool_call_id` TEXT NOT NULL DEFAULT ''",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val MIGRATION_5_6: Migration =
|
||||
object : Migration(5, 6) {
|
||||
override suspend fun migrate(connection: SQLiteConnection) {
|
||||
// Issue #904: timeline markers (display_kind) keep
|
||||
// their tag through the Room cache so a cached
|
||||
// marker never degrades back into a user bubble.
|
||||
connection.execSQL(
|
||||
"ALTER TABLE `chat_messages` ADD COLUMN `display_kind` TEXT",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun get(context: Context): HermesDatabase =
|
||||
instance ?: synchronized(this) {
|
||||
// SQLCipher can't open plaintext SQLite databases — if an old
|
||||
@@ -31,68 +77,27 @@ abstract class HermesDatabase : RoomDatabase() {
|
||||
dbFile.delete()
|
||||
}
|
||||
|
||||
// Load SQLCipher native library before creating the factory
|
||||
// Load SQLCipher native library before creating the driver
|
||||
System.loadLibrary("sqlcipher")
|
||||
val factory = SupportOpenHelperFactory(AuthManager.getDatabasePassword())
|
||||
|
||||
val migration2to3 =
|
||||
object : Migration(2, 3) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"CREATE INDEX IF NOT EXISTS `index_chat_messages_session_id_timestamp` " +
|
||||
"ON `chat_messages` (`session_id`, `timestamp`)",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val migration3to4 =
|
||||
object : Migration(3, 4) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
db.execSQL(
|
||||
"ALTER TABLE `chat_messages` ADD COLUMN `reasoning_text` TEXT NOT NULL DEFAULT ''",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val migration4to5 =
|
||||
object : Migration(4, 5) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
// Issue #842: tool rows now carry the gateway's
|
||||
// tool call id (`call_00_...`) so REST transcript
|
||||
// rows can be matched 1:1 against their live WS
|
||||
// bubbles instead of fragile result-content
|
||||
// canonicalization.
|
||||
db.execSQL(
|
||||
"ALTER TABLE `chat_messages` ADD COLUMN `tool_call_id` TEXT NOT NULL DEFAULT ''",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val migration5to6 =
|
||||
object : Migration(5, 6) {
|
||||
override fun migrate(db: SupportSQLiteDatabase) {
|
||||
// Issue #904: timeline markers (display_kind) keep
|
||||
// their tag through the Room cache so a cached
|
||||
// marker never degrades back into a user bubble.
|
||||
db.execSQL(
|
||||
"ALTER TABLE `chat_messages` ADD COLUMN `display_kind` TEXT",
|
||||
)
|
||||
}
|
||||
}
|
||||
val driver =
|
||||
SQLCipherDriver(
|
||||
AuthManager.getDatabasePassword(),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
|
||||
instance ?: Room
|
||||
.databaseBuilder(
|
||||
context.applicationContext,
|
||||
HermesDatabase::class.java,
|
||||
"hermes_control.db",
|
||||
).openHelperFactory(factory)
|
||||
).setDriver(driver)
|
||||
.addMigrations(
|
||||
migration2to3,
|
||||
migration3to4,
|
||||
migration4to5,
|
||||
migration5to6,
|
||||
)
|
||||
.fallbackToDestructiveMigration(false)
|
||||
MIGRATION_2_3,
|
||||
MIGRATION_3_4,
|
||||
MIGRATION_4_5,
|
||||
MIGRATION_5_6,
|
||||
).fallbackToDestructiveMigration(false)
|
||||
.build()
|
||||
.also { instance = it }
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user