Add foreign key dependency between reactions and messages.

This commit is contained in:
Greyson Parrelli 2023-01-26 14:45:03 -05:00
parent c5c60b7214
commit 9b28585c59
7 changed files with 64 additions and 19 deletions

View file

@ -133,7 +133,7 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
private static final String TAG = Log.tag(MessageTable.class);
public static final String TABLE_NAME = "mms";
public static final String TABLE_NAME = "message";
public static final String ID = "_id";
public static final String DATE_SENT = "date_sent";
public static final String DATE_RECEIVED = "date_received";

View file

@ -21,7 +21,6 @@ class ReactionTable(context: Context, databaseHelper: SignalDatabase) : Database
private const val ID = "_id"
const val MESSAGE_ID = "message_id"
const val IS_MMS = "is_mms"
private const val AUTHOR_ID = "author_id"
private const val EMOJI = "emoji"
private const val DATE_SENT = "date_sent"
@ -31,26 +30,15 @@ class ReactionTable(context: Context, databaseHelper: SignalDatabase) : Database
val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME (
$ID INTEGER PRIMARY KEY,
$MESSAGE_ID INTEGER NOT NULL,
$IS_MMS INTEGER NOT NULL,
$MESSAGE_ID INTEGER NOT NULL REFERENCES ${MessageTable.TABLE_NAME} (${MessageTable.ID}) ON DELETE CASCADE,
$AUTHOR_ID INTEGER NOT NULL REFERENCES ${RecipientTable.TABLE_NAME} (${RecipientTable.ID}) ON DELETE CASCADE,
$EMOJI TEXT NOT NULL,
$DATE_SENT INTEGER NOT NULL,
$DATE_RECEIVED INTEGER NOT NULL,
UNIQUE($MESSAGE_ID, $IS_MMS, $AUTHOR_ID) ON CONFLICT REPLACE
UNIQUE($MESSAGE_ID, $AUTHOR_ID) ON CONFLICT REPLACE
)
""".trimIndent()
@JvmField
val CREATE_TRIGGERS = arrayOf(
"""
CREATE TRIGGER reactions_mms_delete AFTER DELETE ON ${MessageTable.TABLE_NAME}
BEGIN
DELETE FROM $TABLE_NAME WHERE $MESSAGE_ID = old.${MessageTable.ID} AND $IS_MMS = 1;
END
"""
)
private fun readReaction(cursor: Cursor): ReactionRecord {
return ReactionRecord(
emoji = CursorUtil.requireString(cursor, EMOJI),
@ -113,7 +101,6 @@ class ReactionTable(context: Context, databaseHelper: SignalDatabase) : Database
try {
val values = ContentValues().apply {
put(MESSAGE_ID, messageId.id)
put(IS_MMS, 0)
put(EMOJI, reaction.emoji)
put(AUTHOR_ID, reaction.author.serialize())
put(DATE_SENT, reaction.dateSent)

View file

@ -138,7 +138,6 @@ open class SignalDatabase(private val context: Application, databaseSecret: Data
executeStatements(db, SearchTable.CREATE_TRIGGERS)
executeStatements(db, MessageSendLogTables.CREATE_TRIGGERS)
executeStatements(db, ReactionTable.CREATE_TRIGGERS)
DistributionListTables.insertInitialDistributionListAtCreationTime(db)

View file

@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V170_CallTableMigra
import org.thoughtcrime.securesms.database.helpers.migration.V171_ThreadForeignKeyFix
import org.thoughtcrime.securesms.database.helpers.migration.V172_GroupMembershipMigration
import org.thoughtcrime.securesms.database.helpers.migration.V173_ScheduledMessagesMigration
import org.thoughtcrime.securesms.database.helpers.migration.V174_ReactionForeignKeyMigration
/**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
@ -37,7 +38,7 @@ object SignalDatabaseMigrations {
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
const val DATABASE_VERSION = 173
const val DATABASE_VERSION = 174
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@ -140,6 +141,10 @@ object SignalDatabaseMigrations {
if (oldVersion < 173) {
V173_ScheduledMessagesMigration.migrate(context, db, oldVersion, newVersion)
}
if (oldVersion < 174) {
V174_ReactionForeignKeyMigration.migrate(context, db, oldVersion, newVersion)
}
}
@JvmStatic

View file

@ -0,0 +1,48 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Adds a foreign key dependency between reactions and messages so we can remove the trigger.
* Also renames mms -> message because I feel like I should have done that before.
*/
@Suppress("ClassName")
object V174_ReactionForeignKeyMigration : SignalDatabaseMigration {
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL(
"""
CREATE TABLE reaction_tmp (
_id INTEGER PRIMARY KEY,
message_id INTEGER NOT NULL REFERENCES mms (_id) ON DELETE CASCADE,
author_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
emoji TEXT NOT NULL,
date_sent INTEGER NOT NULL,
date_received INTEGER NOT NULL,
UNIQUE(message_id, author_id) ON CONFLICT REPLACE
);
"""
)
db.execSQL(
"""
INSERT INTO reaction_tmp
SELECT
_id,
message_id,
author_id,
emoji,
date_sent,
date_received
FROM reaction
WHERE message_id IN (SELECT _id FROM mms)
"""
)
db.execSQL("DROP TABLE reaction")
db.execSQL("DROP TRIGGER IF EXISTS reactions_mms_delete")
db.execSQL("ALTER TABLE reaction_tmp RENAME TO reaction")
db.execSQL("ALTER TABLE mms RENAME TO message")
}
}

View file

@ -116,9 +116,10 @@ public class ApplicationMigrations {
static final int REBUILD_MESSAGE_FTS_INDEX = 72;
static final int UPDATE_SMS_JOBS = 73;
static final int OPTIMIZE_MESSAGE_FTS_INDEX = 74;
static final int REACTION_DATABASE_MIGRATION = 75;
}
public static final int CURRENT_VERSION = 74;
public static final int CURRENT_VERSION = 75;
/**
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
@ -516,6 +517,10 @@ public class ApplicationMigrations {
jobs.put(Version.OPTIMIZE_MESSAGE_FTS_INDEX, new OptimizeMessageSearchIndexMigrationJob());
}
if (lastSeenVersion < Version.REACTION_DATABASE_MIGRATION) {
jobs.put(Version.REACTION_DATABASE_MIGRATION, new DatabaseMigrationJob());
}
return jobs;
}

View file

@ -17,6 +17,7 @@
android:text="@string/ApplicationMigrationActivity__signal_is_updating"
android:gravity="center"
android:textSize="22sp"
android:textColor="@color/signal_colorOnBackground"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />