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 8b58f528aa..7f8427d42c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -268,6 +268,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat private const val INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID = "message_thread_story_parent_story_scheduled_date_latest_revision_id_index" private const val INDEX_DATE_SENT_FROM_TO_THREAD = "message_date_sent_from_to_thread_index" + private const val INDEX_THREAD_COUNT = "message_thread_count_index" @JvmField val CREATE_INDEXS = arrayOf( @@ -286,7 +287,9 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat "CREATE INDEX IF NOT EXISTS message_latest_revision_id_index ON $TABLE_NAME ($LATEST_REVISION_ID)", "CREATE INDEX IF NOT EXISTS message_from_recipient_id_index ON $TABLE_NAME ($FROM_RECIPIENT_ID)", "CREATE INDEX IF NOT EXISTS message_to_recipient_id_index ON $TABLE_NAME ($TO_RECIPIENT_ID)", - "CREATE UNIQUE INDEX IF NOT EXISTS message_unique_sent_from_thread ON $TABLE_NAME ($DATE_SENT, $FROM_RECIPIENT_ID, $THREAD_ID)" + "CREATE UNIQUE INDEX IF NOT EXISTS message_unique_sent_from_thread ON $TABLE_NAME ($DATE_SENT, $FROM_RECIPIENT_ID, $THREAD_ID)", + // This index is created specifically for getting the number of messages in a thread and therefore needs to be kept in sync with that query + "CREATE INDEX IF NOT EXISTS $INDEX_THREAD_COUNT ON $TABLE_NAME ($THREAD_ID) WHERE $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL" ) private val MMS_PROJECTION_BASE = arrayOf( @@ -1810,17 +1813,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat fun getMessageCountForThread(threadId: Long): Int { return readableDatabase .select("COUNT(*)") - .from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID") - .where("$THREAD_ID = ? AND $STORY_TYPE = ? AND $PARENT_STORY_ID <= ? AND $SCHEDULED_DATE = ? AND $LATEST_REVISION_ID IS NULL", threadId, 0, 0, -1) - .run() - .readToSingleInt() - } - - fun getMessageCountForThread(threadId: Long, beforeTime: Long): Int { - return readableDatabase - .select("COUNT(*)") - .from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID") - .where("$THREAD_ID = ? AND $DATE_RECEIVED < ? AND $STORY_TYPE = ? AND $PARENT_STORY_ID <= ? AND $SCHEDULED_DATE = ? AND $LATEST_REVISION_ID IS NULL", threadId, beforeTime, 0, 0, -1) + .from("$TABLE_NAME INDEXED BY $INDEX_THREAD_COUNT") + .where("$THREAD_ID = $threadId AND $STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND $SCHEDULED_DATE = -1 AND $LATEST_REVISION_ID IS NULL") .run() .readToSingleInt() } 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 f7a99fc370..cc8d6262fb 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 @@ -61,6 +61,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V202_DropMessageTab import org.thoughtcrime.securesms.database.helpers.migration.V203_PreKeyStaleTimestamp import org.thoughtcrime.securesms.database.helpers.migration.V204_GroupForeignKeyMigration import org.thoughtcrime.securesms.database.helpers.migration.V205_DropPushTable +import org.thoughtcrime.securesms.database.helpers.migration.V206_AddConversationCountIndex /** * Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness. @@ -69,7 +70,7 @@ object SignalDatabaseMigrations { val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass) - const val DATABASE_VERSION = 205 + const val DATABASE_VERSION = 206 @JvmStatic fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { @@ -300,6 +301,10 @@ object SignalDatabaseMigrations { if (oldVersion < 205) { V205_DropPushTable.migrate(context, db, oldVersion, newVersion) } + + if (oldVersion < 206) { + V206_AddConversationCountIndex.migrate(context, db, oldVersion, newVersion) + } } @JvmStatic diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V206_AddConversationCountIndex.kt b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V206_AddConversationCountIndex.kt new file mode 100644 index 0000000000..83a155b5cf --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/migration/V206_AddConversationCountIndex.kt @@ -0,0 +1,19 @@ +/* + * 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 + +/** + * Add an index to speed up thread counts. + */ +@Suppress("ClassName") +object V206_AddConversationCountIndex : SignalDatabaseMigration { + override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + db.execSQL("CREATE INDEX IF NOT EXISTS message_thread_count_index ON message (thread_id) WHERE story_type = 0 AND parent_story_id <= 0 AND scheduled_date = -1 AND latest_revision_id IS NULL") + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java index e18d2b6504..42787a3eab 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestRepository.java @@ -373,10 +373,8 @@ public final class MessageRequestRepository { @WorkerThread private boolean isLegacyThread(@NonNull Recipient recipient) { - Context context = ApplicationDependencies.getApplication(); - Long threadId = SignalDatabase.threads().getThreadIdFor(recipient.getId()); + Long threadId = SignalDatabase.threads().getThreadIdFor(recipient.getId()); - return threadId != null && - (RecipientUtil.hasSentMessageInThread(threadId) || RecipientUtil.isPreMessageRequestThread(threadId)); + return threadId != null && RecipientUtil.hasSentMessageInThread(threadId); } } 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 654cc3f447..7484a16774 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -138,9 +138,10 @@ public class ApplicationMigrations { static final int IDENTITY_FIX = 94; static final int COPY_USERNAME_TO_SIGNAL_STORE = 95; static final int RECHECK_PAYMENTS = 96; + static final int THREAD_COUNT_DB_MIGRATION = 97; } - public static final int CURRENT_VERSION = 96; + public static final int CURRENT_VERSION = 97; /** * This *must* be called after the {@link JobManager} has been instantiated, but *before* the call @@ -627,6 +628,10 @@ public class ApplicationMigrations { jobs.put(Version.RECHECK_PAYMENTS, new RecheckPaymentsMigrationJob()); } + if (lastSeenVersion < Version.THREAD_COUNT_DB_MIGRATION) { + jobs.put(Version.THREAD_COUNT_DB_MIGRATION, new DatabaseMigrationJob()); + } + return jobs; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java index 993a52b6cd..19418a198d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java @@ -280,27 +280,13 @@ public class RecipientUtil { return isCallRequestAccepted(threadId, threadRecipient); } - /** - * @return True if a conversation existed before we enabled message requests, otherwise false. - */ - @WorkerThread - public static boolean isPreMessageRequestThread(@Nullable Long threadId) { - long beforeTime = SignalStore.misc().getMessageRequestEnableTime(); - return threadId != null && SignalDatabase.messages().getMessageCountForThread(threadId, beforeTime) > 0; - } - @WorkerThread public static void shareProfileIfFirstSecureMessage(@NonNull Recipient recipient) { if (recipient.isProfileSharing()) { return; } - long threadId = SignalDatabase.threads().getThreadIdIfExistsFor(recipient.getId()); - - if (isPreMessageRequestThread(threadId)) { - return; - } - + long threadId = SignalDatabase.threads().getThreadIdIfExistsFor(recipient.getId()); boolean firstMessage = SignalDatabase.messages().getOutgoingSecureMessageCount(threadId) == 0; if (firstMessage || recipient.isHidden()) { @@ -364,8 +350,7 @@ public class RecipientUtil { !threadRecipient.isRegistered() || (!threadRecipient.isHidden() && ( hasSentMessageInThread(threadId) || - noSecureMessagesAndNoCallsInThread(threadId) || - isPreMessageRequestThread(threadId)) + noSecureMessagesAndNoCallsInThread(threadId)) ); } @@ -373,8 +358,7 @@ public class RecipientUtil { private static boolean isCallRequestAccepted(@Nullable Long threadId, @NonNull Recipient threadRecipient) { return threadRecipient.isProfileSharing() || threadRecipient.isSystemContact() || - hasSentMessageInThread(threadId) || - isPreMessageRequestThread(threadId); + hasSentMessageInThread(threadId); } @WorkerThread