diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/DatabaseConsistencyTest.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/DatabaseConsistencyTest.kt index 64d551339a..b2abf6bf22 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/DatabaseConsistencyTest.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/DatabaseConsistencyTest.kt @@ -114,7 +114,7 @@ class DatabaseConsistencyTest { .replace(Regex("\\s+"), " ") .replace(Regex.fromLiteral("( "), "(") .replace(Regex.fromLiteral(" )"), ")") - .replace(Regex("CREATE TABLE \"([a-z]+)\""), "CREATE TABLE $1") // for some reason SQLite will wrap table names in quotes for upgraded tables. This unwraps them. + .replace(Regex("CREATE TABLE \"([a-zA-Z_]+)\""), "CREATE TABLE $1") // for some reason SQLite will wrap table names in quotes for upgraded tables. This unwraps them. } private class InMemoryTestHelper(private val application: Application) : SQLiteOpenHelper(application, null, null, 1) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/CallLinkTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/CallLinkTable.kt index 60e487e15c..609f786a6e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallLinkTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallLinkTable.kt @@ -14,11 +14,27 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database const val TABLE_NAME = "call_link" const val ID = "_id" + const val ROOT_KEY = "root_key" + const val ROOM_ID = "room_id" + const val ADMIN_KEY = "admin_key" + const val NAME = "name" + const val RESTRICTIONS = "restrictions" + const val REVOKED = "revoked" + const val EXPIRATION = "expiration" + const val AVATAR_COLOR = "avatar_color" //language=sql - val CREATE_TABLE = """ + const val CREATE_TABLE = """ CREATE TABLE $TABLE_NAME ( - $ID INTEGER PRIMARY KEY + $ID INTEGER PRIMARY KEY, + $ROOT_KEY BLOB NOT NULL, + $ROOM_ID TEXT NOT NULL UNIQUE, + $ADMIN_KEY BLOB, + $NAME TEXT NOT NULL, + $RESTRICTIONS INTEGER NOT NULL, + $REVOKED INTEGER NOT NULL, + $EXPIRATION INTEGER NOT NULL, + $AVATAR_COLOR TEXT NOT NULL ) """ } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt index c470aa66ab..d5de3bf570 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt @@ -67,7 +67,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl $CALL_ID INTEGER NOT NULL, $MESSAGE_ID INTEGER DEFAULT NULL REFERENCES ${MessageTable.TABLE_NAME} (${MessageTable.ID}) ON DELETE SET NULL, $PEER INTEGER DEFAULT NULL REFERENCES ${RecipientTable.TABLE_NAME} (${RecipientTable.ID}) ON DELETE CASCADE, - $CALL_LINK INTEGER DEFAULT NULL REFERENCES ${CallLinkTable.TABLE_NAME} (${CallLinkTable.ID}) ON DELETE CASCADE, + $CALL_LINK TEXT DEFAULT NULL REFERENCES ${CallLinkTable.TABLE_NAME} (${CallLinkTable.ROOM_ID}) ON DELETE CASCADE, $TYPE INTEGER NOT NULL, $DIRECTION INTEGER NOT NULL, $EVENT INTEGER NOT NULL, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt index e667e8613c..ce42e650d8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SignalDatabaseMigrations.kt @@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V185_MessageRecipie import org.thoughtcrime.securesms.database.helpers.migration.V186_ForeignKeyIndicesMigration import org.thoughtcrime.securesms.database.helpers.migration.V187_MoreForeignKeyIndexesMigration import org.thoughtcrime.securesms.database.helpers.migration.V188_FixMessageRecipientsAndEditMessageMigration +import org.thoughtcrime.securesms.database.helpers.migration.V189_CreateCallLinkTableColumnsAndRebuildFKReference /** * Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness. @@ -52,7 +53,7 @@ object SignalDatabaseMigrations { val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass) - const val DATABASE_VERSION = 188 + const val DATABASE_VERSION = 189 @JvmStatic fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { @@ -215,6 +216,10 @@ object SignalDatabaseMigrations { if (oldVersion < 188) { V188_FixMessageRecipientsAndEditMessageMigration.migrate(context, db, oldVersion, newVersion) } + + if (oldVersion < 189) { + V189_CreateCallLinkTableColumnsAndRebuildFKReference.migrate(context, db, oldVersion, newVersion) + } } @JvmStatic diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V189_CreateCallLinkTableColumnsAndRebuildFKReference.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V189_CreateCallLinkTableColumnsAndRebuildFKReference.kt new file mode 100644 index 0000000000..adb234090c --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V189_CreateCallLinkTableColumnsAndRebuildFKReference.kt @@ -0,0 +1,82 @@ +/** + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.database.helpers.migration + +import android.app.Application +import net.zetetic.database.sqlcipher.SQLiteDatabase + +/** + * Fleshes out the call link table and rebuilds the call event table. + * At this point, there should be no records in the call link database. + */ +object V189_CreateCallLinkTableColumnsAndRebuildFKReference : SignalDatabaseMigration { + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + db.execSQL( + """ + CREATE TABLE call_link_tmp ( + _id INTEGER PRIMARY KEY, + root_key BLOB NOT NULL, + room_id TEXT NOT NULL UNIQUE, + admin_key BLOB, + name TEXT NOT NULL, + restrictions INTEGER NOT NULL, + revoked INTEGER NOT NULL, + expiration INTEGER NOT NULL, + avatar_color TEXT NOT NULL + ) + """.trimIndent() + ) + + db.execSQL( + """ + CREATE TABLE call_tmp ( + _id INTEGER PRIMARY KEY, + call_id INTEGER NOT NULL, + message_id INTEGER DEFAULT NULL REFERENCES message (_id) ON DELETE SET NULL, + peer INTEGER DEFAULT NULL REFERENCES recipient (_id) ON DELETE CASCADE, + call_link TEXT DEFAULT NULL REFERENCES call_link (room_id) ON DELETE CASCADE, + type INTEGER NOT NULL, + direction INTEGER NOT NULL, + event INTEGER NOT NULL, + timestamp INTEGER NOT NULL, + ringer INTEGER DEFAULT NULL, + deletion_timestamp INTEGER DEFAULT 0, + UNIQUE (call_id, peer, call_link) ON CONFLICT FAIL, + CHECK ((peer IS NULL AND call_link IS NOT NULL) OR (peer IS NOT NULL AND call_link IS NULL)) + ) + """.trimIndent() + ) + + db.execSQL( + """ + INSERT INTO call_tmp + SELECT + _id, + call_id, + message_id, + peer, + NULL as call_link, + type, + direction, + event, + timestamp, + ringer, + deletion_timestamp + FROM call + """.trimIndent() + ) + + db.execSQL("DROP TABLE call") + db.execSQL("ALTER TABLE call_tmp RENAME TO call") + db.execSQL("DROP TABLE call_link") + db.execSQL("ALTER TABLE call_link_tmp RENAME TO call_link") + + db.execSQL("CREATE INDEX IF NOT EXISTS call_call_id_index ON call (call_id)") + db.execSQL("CREATE INDEX IF NOT EXISTS call_message_id_index ON call (message_id)") + db.execSQL("CREATE INDEX IF NOT EXISTS call_call_link_index ON call (call_link)") + db.execSQL("CREATE INDEX IF NOT EXISTS call_peer_index ON call (peer)") + } +}