From 01979b1c78126d42f8ee35953e02265a1d00f19d Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 9 Dec 2024 23:23:25 -0500 Subject: [PATCH] Fix dangling quote authors. --- .../securesms/database/CallLinkTable.kt | 4 +- .../securesms/database/CallTable.kt | 4 +- .../database/DistributionListTables.kt | 10 +-- .../securesms/database/GroupReceiptTable.kt | 7 +- .../securesms/database/MentionTable.kt | 7 +- .../database/MessageSendLogTables.kt | 17 +++-- .../securesms/database/MessageTable.kt | 12 +++- .../database/NotificationProfileTables.kt | 21 +++--- .../securesms/database/PaymentTable.java | 4 +- .../PendingPniSignatureMessageTable.kt | 10 +-- .../database/PendingRetryReceiptTable.java | 7 +- .../securesms/database/ReactionTable.kt | 17 +++-- .../securesms/database/StorySendTable.kt | 15 +++-- .../helpers/SignalDatabaseMigrations.kt | 6 +- .../migration/V260_RemapQuoteAuthors.kt | 66 +++++++++++++++++++ .../migrations/ApplicationMigrations.java | 7 +- 16 files changed, 165 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V260_RemapQuoteAuthors.kt 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 ba015772a8..c09263081d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallLinkTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallLinkTable.kt @@ -526,7 +526,7 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database } override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { - writableDatabase.update(TABLE_NAME) + val count = writableDatabase.update(TABLE_NAME) .values( contentValuesOf( RECIPIENT_ID to toId.toLong() @@ -534,5 +534,7 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database ) .where("$RECIPIENT_ID = ?", fromId.toLong()) .run() + + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } } 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 abf9dffa34..1a20396ff9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/CallTable.kt @@ -1489,11 +1489,13 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl } override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { - writableDatabase + val count = writableDatabase .update(TABLE_NAME) .values(PEER to toId.serialize()) .where("$PEER = ?", fromId) .run() + + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } /** diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt b/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt index e247228103..d4453285bc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DistributionListTables.kt @@ -525,12 +525,14 @@ class DistributionListTables constructor(context: Context?, databaseHelper: Sign .run() } - override fun remapRecipient(oldId: RecipientId, newId: RecipientId) { - writableDatabase + override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { + val count = writableDatabase .update(MembershipTable.TABLE_NAME) - .values(MembershipTable.RECIPIENT_ID to newId.serialize()) - .where("${MembershipTable.RECIPIENT_ID} = ?", oldId) + .values(MembershipTable.RECIPIENT_ID to toId.serialize()) + .where("${MembershipTable.RECIPIENT_ID} = ?", fromId) .run(SQLiteDatabase.CONFLICT_REPLACE) + + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } fun deleteList(distributionListId: DistributionListId, deletionTimestamp: Long = System.currentTimeMillis()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptTable.kt index 4af199534b..db275150b6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptTable.kt @@ -8,6 +8,7 @@ import org.signal.core.util.SqlUtil import org.signal.core.util.delete import org.signal.core.util.deleteAll import org.signal.core.util.forEach +import org.signal.core.util.logging.Log import org.signal.core.util.readToList import org.signal.core.util.requireBoolean import org.signal.core.util.requireInt @@ -20,6 +21,8 @@ import org.thoughtcrime.securesms.recipients.RecipientId class GroupReceiptTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseTable(context, databaseHelper), RecipientIdDatabaseReference { companion object { + private val TAG = Log.tag(GroupReceiptTable::class) + const val TABLE_NAME = "group_receipts" private const val ID = "_id" const val MMS_ID = "mms_id" @@ -174,11 +177,13 @@ class GroupReceiptTable(context: Context?, databaseHelper: SignalDatabase?) : Da } override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { - writableDatabase + val count = writableDatabase .update(TABLE_NAME) .values(RECIPIENT_ID to toId.serialize()) .where("$RECIPIENT_ID = ?", fromId) .run() + + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } private fun Cursor.toGroupReceiptInfo(): GroupReceiptInfo { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MentionTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MentionTable.kt index ab4b445559..be5432d82f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MentionTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MentionTable.kt @@ -6,6 +6,7 @@ import org.signal.core.util.SqlUtil import org.signal.core.util.delete import org.signal.core.util.deleteAll import org.signal.core.util.insertInto +import org.signal.core.util.logging.Log import org.signal.core.util.readToList import org.signal.core.util.requireInt import org.signal.core.util.requireLong @@ -18,6 +19,8 @@ import org.thoughtcrime.securesms.recipients.RecipientId class MentionTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTable(context, databaseHelper), RecipientIdDatabaseReference, ThreadIdDatabaseReference { companion object { + private val TAG = Log.tag(MentionTable::class) + const val TABLE_NAME = "mention" const val ID = "_id" const val THREAD_ID = "thread_id" @@ -165,11 +168,13 @@ class MentionTable(context: Context, databaseHelper: SignalDatabase) : DatabaseT } override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { - writableDatabase + val count = writableDatabase .update("$TABLE_NAME INDEXED BY $RECIPIENT_ID_INDEX") .values(RECIPIENT_ID to toId.serialize()) .where("$RECIPIENT_ID = ?", fromId) .run() + + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } override fun remapThread(fromId: Long, toId: Long) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageSendLogTables.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageSendLogTables.kt index 658db43b01..7b04a03754 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageSendLogTables.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageSendLogTables.kt @@ -11,6 +11,7 @@ import org.signal.core.util.readToList import org.signal.core.util.requireBoolean import org.signal.core.util.requireLong import org.signal.core.util.toInt +import org.signal.core.util.update import org.thoughtcrime.securesms.database.model.MessageId import org.thoughtcrime.securesms.database.model.MessageLogEntry import org.thoughtcrime.securesms.recipients.Recipient @@ -419,16 +420,14 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal writableDatabase.execSQL(MslPayloadTable.AFTER_MESSAGE_DELETE_TRIGGER) } - override fun remapRecipient(oldRecipientId: RecipientId, newRecipientId: RecipientId) { - val values = ContentValues().apply { - put(MslRecipientTable.RECIPIENT_ID, newRecipientId.serialize()) - } + override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { + val count = writableDatabase + .update(MslRecipientTable.TABLE_NAME) + .values(MslRecipientTable.RECIPIENT_ID to toId.serialize()) + .where("${MslRecipientTable.RECIPIENT_ID} = ?", fromId) + .run() - val db = databaseHelper.signalWritableDatabase - val query = "${MslRecipientTable.RECIPIENT_ID} = ?" - val args = SqlUtil.buildArgs(oldRecipientId.serialize()) - - db.update(MslRecipientTable.TABLE_NAME, values, query, args) + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } private data class RecipientDevice(val recipientId: RecipientId, val devices: List) diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index 9b16a16f1c..820e3b81f7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -4803,17 +4803,25 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { - writableDatabase + val fromCount = writableDatabase .update(TABLE_NAME) .values(FROM_RECIPIENT_ID to toId.serialize()) .where("$FROM_RECIPIENT_ID = ?", fromId) .run() - writableDatabase + val toCount = writableDatabase .update(TABLE_NAME) .values(TO_RECIPIENT_ID to toId.serialize()) .where("$TO_RECIPIENT_ID = ?", fromId) .run() + + val quoteAuthorCount = writableDatabase + .update(TABLE_NAME) + .values(QUOTE_AUTHOR to toId.serialize()) + .where("$QUOTE_AUTHOR = ?", fromId) + .run() + + Log.d(TAG, "Remapped $fromId to $toId. fromRecipient: $fromCount, toRecipient: $toCount, quoteAuthor: $quoteAuthorCount") } override fun remapThread(fromId: Long, toId: Long) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/NotificationProfileTables.kt b/app/src/main/java/org/thoughtcrime/securesms/database/NotificationProfileTables.kt index 255ecba35b..1cbb931d10 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/NotificationProfileTables.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/NotificationProfileTables.kt @@ -7,11 +7,13 @@ import android.content.Context import android.database.Cursor import android.database.sqlite.SQLiteConstraintException import org.signal.core.util.SqlUtil +import org.signal.core.util.logging.Log import org.signal.core.util.requireBoolean import org.signal.core.util.requireInt import org.signal.core.util.requireLong import org.signal.core.util.requireString import org.signal.core.util.toInt +import org.signal.core.util.update import org.thoughtcrime.securesms.conversation.colors.AvatarColor import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile @@ -25,6 +27,8 @@ import java.time.DayOfWeek class NotificationProfileTables(context: Context, databaseHelper: SignalDatabase) : DatabaseTable(context, databaseHelper), RecipientIdDatabaseReference { companion object { + private val TAG = Log.tag(NotificationProfileTable::class) + @JvmField val CREATE_TABLE: Array = arrayOf(NotificationProfileTable.CREATE_TABLE, NotificationProfileScheduleTable.CREATE_TABLE, NotificationProfileAllowedMembersTable.CREATE_TABLE) @@ -296,16 +300,15 @@ class NotificationProfileTables(context: Context, databaseHelper: SignalDatabase AppDependencies.databaseObserver.notifyNotificationProfileObservers() } - override fun remapRecipient(oldId: RecipientId, newId: RecipientId) { - val query = "${NotificationProfileAllowedMembersTable.RECIPIENT_ID} = ?" - val args = SqlUtil.buildArgs(oldId) - val values = ContentValues().apply { - put(NotificationProfileAllowedMembersTable.RECIPIENT_ID, newId.serialize()) - } - - databaseHelper.signalWritableDatabase.update(NotificationProfileAllowedMembersTable.TABLE_NAME, values, query, args) - + override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { + val count = writableDatabase + .update(NotificationProfileAllowedMembersTable.TABLE_NAME) + .values(NotificationProfileAllowedMembersTable.RECIPIENT_ID to toId.serialize()) + .where("${NotificationProfileAllowedMembersTable.RECIPIENT_ID} = ?", fromId) + .run() AppDependencies.databaseObserver.notifyNotificationProfileObservers() + + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } private fun getProfile(cursor: Cursor): NotificationProfile { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java index 9c11d1fed2..cf1313082a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/PaymentTable.java @@ -478,7 +478,9 @@ public final class PaymentTable extends DatabaseTable implements RecipientIdData public void remapRecipient(@NonNull RecipientId fromId, @NonNull RecipientId toId) { ContentValues values = new ContentValues(); values.put(RECIPIENT_ID, toId.serialize()); - getWritableDatabase().update(TABLE_NAME, values, RECIPIENT_ID + " = ?", SqlUtil.buildArgs(fromId)); + int count = getWritableDatabase().update(TABLE_NAME, values, RECIPIENT_ID + " = ?", SqlUtil.buildArgs(fromId)); + + Log.d(TAG, "Remapped " + fromId + " to " + toId + ". count: " + count); } public boolean markPaymentSubmitted(@NonNull UUID uuid, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/PendingPniSignatureMessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/PendingPniSignatureMessageTable.kt index dcd9c74ab2..9c2547237f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/PendingPniSignatureMessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/PendingPniSignatureMessageTable.kt @@ -121,11 +121,13 @@ class PendingPniSignatureMessageTable(context: Context, databaseHelper: SignalDa writableDatabase.deleteAll(TABLE_NAME) } - override fun remapRecipient(oldId: RecipientId, newId: RecipientId) { - writableDatabase + override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { + val count = writableDatabase .update(TABLE_NAME) - .values(RECIPIENT_ID to newId.serialize()) - .where("$RECIPIENT_ID = ?", oldId) + .values(RECIPIENT_ID to toId.serialize()) + .where("$RECIPIENT_ID = ?", fromId) .run() + + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/PendingRetryReceiptTable.java b/app/src/main/java/org/thoughtcrime/securesms/database/PendingRetryReceiptTable.java index 3940645d09..0c8348d838 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/PendingRetryReceiptTable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/PendingRetryReceiptTable.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import net.zetetic.database.sqlcipher.SQLiteDatabase; +import org.signal.core.util.logging.Log; import org.thoughtcrime.securesms.database.model.PendingRetryReceiptModel; import org.thoughtcrime.securesms.dependencies.AppDependencies; import org.thoughtcrime.securesms.recipients.RecipientId; @@ -24,6 +25,8 @@ import java.util.List; */ public final class PendingRetryReceiptTable extends DatabaseTable implements RecipientIdDatabaseReference, ThreadIdDatabaseReference { + private static final String TAG = Log.tag(PendingRetryReceiptTable.class); + public static final String TABLE_NAME = "pending_retry_receipts"; private static final String ID = "_id"; @@ -87,9 +90,11 @@ public final class PendingRetryReceiptTable extends DatabaseTable implements Rec public void remapRecipient(@NonNull RecipientId fromId, @NonNull RecipientId toId) { ContentValues values = new ContentValues(); values.put(AUTHOR, toId.serialize()); - getWritableDatabase().update(TABLE_NAME, values, AUTHOR + " = ?", SqlUtil.buildArgs(fromId)); + int count = getWritableDatabase().update(TABLE_NAME, values, AUTHOR + " = ?", SqlUtil.buildArgs(fromId)); AppDependencies.getPendingRetryReceiptCache().clear(); + + Log.d(TAG, "Remapped " + fromId + " to " + toId + ". count: " + count); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ReactionTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/ReactionTable.kt index d8129fab1a..10231f30bf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ReactionTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ReactionTable.kt @@ -7,6 +7,7 @@ import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil import org.signal.core.util.delete import org.signal.core.util.forEach +import org.signal.core.util.logging.Log import org.signal.core.util.select import org.signal.core.util.update import org.thoughtcrime.securesms.database.model.MessageId @@ -20,6 +21,8 @@ import org.thoughtcrime.securesms.recipients.RecipientId class ReactionTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTable(context, databaseHelper), RecipientIdDatabaseReference { companion object { + private val TAG = Log.tag(ReactionTable::class) + const val TABLE_NAME = "reaction" private const val ID = "_id" @@ -167,14 +170,14 @@ class ReactionTable(context: Context, databaseHelper: SignalDatabase) : Database } } - override fun remapRecipient(oldAuthorId: RecipientId, newAuthorId: RecipientId) { - val query = "$AUTHOR_ID = ?" - val args = SqlUtil.buildArgs(oldAuthorId) - val values = ContentValues().apply { - put(AUTHOR_ID, newAuthorId.serialize()) - } + override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { + val count = writableDatabase + .update(TABLE_NAME) + .values(AUTHOR_ID to toId.serialize()) + .where("$AUTHOR_ID = ?", fromId) + .run() - readableDatabase.update(TABLE_NAME, values, query, args) + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } fun deleteAbandonedReactions() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/StorySendTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/StorySendTable.kt index b098a68d5e..fd4643f940 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/StorySendTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/StorySendTable.kt @@ -5,6 +5,7 @@ import android.content.Context import androidx.core.content.contentValuesOf import org.signal.core.util.CursorUtil import org.signal.core.util.SqlUtil +import org.signal.core.util.logging.Log import org.signal.core.util.readToList import org.signal.core.util.requireLong import org.signal.core.util.select @@ -26,6 +27,8 @@ import org.whispersystems.signalservice.api.push.DistributionId class StorySendTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTable(context, databaseHelper), RecipientIdDatabaseReference { companion object { + private val TAG = Log.tag(StorySendTable::class) + const val TABLE_NAME = "story_sends" const val ID = "_id" const val MESSAGE_ID = "message_id" @@ -210,12 +213,14 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas return null } - override fun remapRecipient(oldId: RecipientId, newId: RecipientId) { - val query = "$RECIPIENT_ID = ?" - val args = SqlUtil.buildArgs(oldId) - val values = contentValuesOf(RECIPIENT_ID to newId.serialize()) + override fun remapRecipient(fromId: RecipientId, toId: RecipientId) { + val count = writableDatabase + .update(TABLE_NAME) + .values(RECIPIENT_ID to toId.serialize()) + .where("$RECIPIENT_ID = ?", fromId.serialize()) + .run() - writableDatabase.update(TABLE_NAME, values, query, args) + Log.d(TAG, "Remapped $fromId to $toId. count: $count") } /** 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 c25d60a88c..13119aa027 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 @@ -116,6 +116,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V256_FixIncremental import org.thoughtcrime.securesms.database.helpers.migration.V257_CreateBackupMediaSyncTable import org.thoughtcrime.securesms.database.helpers.migration.V258_FixGroupRevokedInviteeUpdate import org.thoughtcrime.securesms.database.helpers.migration.V259_AdjustNotificationProfileMidnightEndTimes +import org.thoughtcrime.securesms.database.helpers.migration.V260_RemapQuoteAuthors /** * Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness. @@ -234,10 +235,11 @@ object SignalDatabaseMigrations { 256 to V256_FixIncrementalDigestColumns, 257 to V257_CreateBackupMediaSyncTable, 258 to V258_FixGroupRevokedInviteeUpdate, - 259 to V259_AdjustNotificationProfileMidnightEndTimes + 259 to V259_AdjustNotificationProfileMidnightEndTimes, + 260 to V260_RemapQuoteAuthors ) - const val DATABASE_VERSION = 259 + const val DATABASE_VERSION = 260 @JvmStatic fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V260_RemapQuoteAuthors.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V260_RemapQuoteAuthors.kt new file mode 100644 index 0000000000..2d967a9f54 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V260_RemapQuoteAuthors.kt @@ -0,0 +1,66 @@ +package org.thoughtcrime.securesms.database.helpers.migration + +import android.app.Application +import net.zetetic.database.sqlcipher.SQLiteDatabase +import org.signal.core.util.logging.Log +import org.signal.core.util.readToSingleLong +import org.signal.core.util.select + +/** + * Previously, we weren't properly remapping quote authors when recipients were remapped. This repairs those scenarios the best we can. + */ +@Suppress("ClassName") +object V260_RemapQuoteAuthors : SignalDatabaseMigration { + + private val TAG = Log.tag(V260_RemapQuoteAuthors::class) + + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + // The following queries are really expensive without an index. So we create a temporary one. + db.execSQL("CREATE INDEX tmp_quote_author ON message (quote_author)") + + // Even with an index, the updates can be a little expensive, so we try to figure out if we need them at all by using a quick check. + val invalidQuoteCount = db + .select("count(*)") + .from("message INDEXED BY tmp_quote_author") + .where("quote_author != 0 AND quote_author NOT IN (SELECT _id FROM recipient)") + .run() + .readToSingleLong() + + if (invalidQuoteCount == 0L) { + Log.i(TAG, "No invalid quote authors, can skip migration.") + db.execSQL("DROP INDEX tmp_quote_author") + return + } + + // Remap all quote_authors using a remapped recipient + db.execSQL( + """ + UPDATE + message INDEXED BY tmp_quote_author + SET + quote_author = (SELECT new_id FROM remapped_recipients WHERE old_id = message.quote_author) + WHERE + quote_author IN (SELECT old_id FROM remapped_recipients) + """ + ) + + // If there are any remaining quote_authors that don't reference a real recipient, we have no choice but to clear the quote + db.execSQL( + """ + UPDATE + message INDEXED BY tmp_quote_author + SET + quote_id = 0, + quote_author = 0, + quote_body = null, + quote_missing = 0, + quote_mentions = null, + quote_type = 0 + WHERE + quote_author != 0 AND quote_author NOT IN (SELECT _id FROM recipient) + """ + ) + + db.execSQL("DROP INDEX tmp_quote_author") + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java index 8b90c38062..8dc082d4d2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -163,9 +163,10 @@ public class ApplicationMigrations { static final int AEP_INTRODUCTION = 119; static final int GROUP_EXTRAS_DB_FIX = 120; static final int EMOJI_SEARCH_INDEX_CHECK_2 = 121; + static final int QUOTE_AUTHOR_FIX = 122; } - public static final int CURRENT_VERSION = 121; + public static final int CURRENT_VERSION = 122; /** * This *must* be called after the {@link JobManager} has been instantiated, but *before* the call @@ -748,6 +749,10 @@ public class ApplicationMigrations { jobs.put(Version.EMOJI_SEARCH_INDEX_CHECK_2, new EmojiSearchIndexCheckMigrationJob()); } + if (lastSeenVersion < Version.QUOTE_AUTHOR_FIX) { + jobs.put(Version.QUOTE_AUTHOR_FIX, new DatabaseMigrationJob()); + } + return jobs; }