diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java index 2e18039f89..1f05c4962e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java @@ -134,7 +134,7 @@ public class MentionDatabase extends Database { void deleteAbandonedMentions() { SQLiteDatabase db = databaseHelper.getWritableDatabase(); - String where = MESSAGE_ID + " NOT IN (SELECT _id FROM " + MmsDatabase.TABLE_NAME + ")"; + String where = MESSAGE_ID + " NOT IN (SELECT _id FROM " + MmsDatabase.TABLE_NAME + ") OR " + THREAD_ID + " NOT IN (SELECT _id FROM " + ThreadDatabase.TABLE_NAME + ")"; db.delete(TABLE_NAME, where, null); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 1551e3b94d..b544ca339d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -68,6 +68,7 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.util.LinkedList; import java.util.List; public class SQLCipherOpenHelper extends SQLiteOpenHelper { @@ -149,8 +150,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { private static final int STICKER_EMOJI_IN_NOTIFICATIONS = 73; private static final int THUMBNAIL_CLEANUP = 74; private static final int STICKER_CONTENT_TYPE_CLEANUP = 75; + private static final int MENTION_CLEANUP = 76; - private static final int DATABASE_VERSION = 75; + private static final int DATABASE_VERSION = 76; private static final String DATABASE_NAME = "signal.db"; private final Context context; @@ -1060,6 +1062,30 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper { Log.i(TAG, "Updated " + rows + " sticker attachment content types."); } + if (oldVersion < MENTION_CLEANUP) { + String selectMentionIdsNotInGroupsV2 = "select mention._id from mention left join thread on mention.thread_id = thread._id left join recipient on thread.recipient_ids = recipient._id where recipient.group_type != 3"; + db.delete("mention", "_id in (" + selectMentionIdsNotInGroupsV2 + ")", null); + db.delete("mention", "message_id NOT IN (SELECT _id FROM mms) OR thread_id NOT IN (SELECT _id from thread)", null); + + List idsToDelete = new LinkedList<>(); + try (Cursor cursor = db.rawQuery("select mention.*, mms.body from mention inner join mms on mention.message_id = mms._id", null)) { + while (cursor != null && cursor.moveToNext()) { + int rangeStart = CursorUtil.requireInt(cursor, "range_start"); + int rangeLength = CursorUtil.requireInt(cursor, "range_length"); + String body = CursorUtil.requireString(cursor, "body"); + + if (body == null || body.isEmpty() || rangeStart < 0 || rangeLength < 0 || (rangeStart + rangeLength) > body.length()) { + idsToDelete.add(CursorUtil.requireLong(cursor, "_id")); + } + } + } + + if (Util.hasItems(idsToDelete)) { + String ids = TextUtils.join(",", idsToDelete); + db.delete("mention", "_id in (" + ids + ")", null); + } + } + db.setTransactionSuccessful(); } finally { db.endTransaction();