mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-24 21:15:48 +00:00
Improve thread update performance by avoiding costly join query.
This commit is contained in:
@@ -6,6 +6,7 @@ public interface MmsSmsColumns {
|
||||
public static final String ID = "_id";
|
||||
public static final String NORMALIZED_DATE_SENT = "date_sent";
|
||||
public static final String NORMALIZED_DATE_RECEIVED = "date_received";
|
||||
public static final String NORMALIZED_TYPE = "type";
|
||||
public static final String DATE_SERVER = "date_server";
|
||||
public static final String THREAD_ID = "thread_id";
|
||||
public static final String READ = "read";
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.notifications.v2.MessageNotifierV2;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
import org.thoughtcrime.securesms.util.CursorUtil;
|
||||
import org.thoughtcrime.securesms.util.SqlUtil;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
|
||||
import java.io.Closeable;
|
||||
@@ -105,6 +106,14 @@ public class MmsSmsDatabase extends Database {
|
||||
MmsSmsColumns.NOTIFIED_TIMESTAMP,
|
||||
MmsSmsColumns.VIEWED_RECEIPT_COUNT};
|
||||
|
||||
private static final String SNIPPET_QUERY = "SELECT " + MmsSmsColumns.ID + ", 0 AS " + TRANSPORT + ", " + SmsDatabase.TYPE + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + SmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + SmsDatabase.TABLE_NAME + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? AND " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + ") " +
|
||||
"UNION ALL " +
|
||||
"SELECT " + MmsSmsColumns.ID + ", 1 AS " + TRANSPORT + ", " + MmsDatabase.MESSAGE_BOX + " AS " + MmsSmsColumns.NORMALIZED_TYPE + ", " + MmsDatabase.DATE_RECEIVED + " AS " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " FROM " + MmsDatabase.TABLE_NAME + " " +
|
||||
"WHERE " + MmsSmsColumns.THREAD_ID + " = ? " +
|
||||
"ORDER BY " + MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC " +
|
||||
"LIMIT 1";
|
||||
|
||||
public MmsSmsDatabase(Context context, SQLCipherOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
@@ -209,11 +218,33 @@ public class MmsSmsDatabase extends Database {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
public Cursor getConversationSnippet(long threadId) {
|
||||
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " DESC";
|
||||
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId + " AND (" + SmsDatabase.TYPE + " IS NULL OR " + SmsDatabase.TYPE + " NOT IN (" + SmsDatabase.Types.PROFILE_CHANGE_TYPE + ", " + SmsDatabase.Types.GV1_MIGRATION_TYPE + "))";
|
||||
public @NonNull MessageRecord getConversationSnippet(long threadId) throws NoSuchMessageException {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
try (Cursor cursor = db.rawQuery(SNIPPET_QUERY, SqlUtil.buildArgs(threadId, threadId))) {
|
||||
if (cursor.moveToFirst()) {
|
||||
boolean isMms = CursorUtil.requireBoolean(cursor, TRANSPORT);
|
||||
long id = CursorUtil.requireLong(cursor, MmsSmsColumns.ID);
|
||||
|
||||
return queryTables(PROJECTION, selection, order, "1");
|
||||
if (isMms) {
|
||||
return DatabaseFactory.getMmsDatabase(context).getMessageRecord(id);
|
||||
} else {
|
||||
return DatabaseFactory.getSmsDatabase(context).getMessageRecord(id);
|
||||
}
|
||||
} else {
|
||||
throw new NoSuchMessageException("no message");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public long getConversationSnippetType(long threadId) throws NoSuchMessageException {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
try (Cursor cursor = db.rawQuery(SNIPPET_QUERY, SqlUtil.buildArgs(threadId, threadId))) {
|
||||
if (cursor.moveToFirst()) {
|
||||
return CursorUtil.requireLong(cursor, MmsSmsColumns.NORMALIZED_TYPE);
|
||||
} else {
|
||||
throw new NoSuchMessageException("no message");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Cursor getUnread() {
|
||||
@@ -791,18 +822,6 @@ public class MmsSmsDatabase extends Database {
|
||||
return databaseHelper.getReadableDatabase().rawQuery(query, null);
|
||||
}
|
||||
|
||||
public static long getType(@NonNull Cursor cursor) {
|
||||
String transportType = CursorUtil.requireString(cursor, TRANSPORT);
|
||||
|
||||
if (MmsSmsDatabase.MMS_TRANSPORT.equals(transportType)) {
|
||||
return CursorUtil.requireLong(cursor, MmsDatabase.MESSAGE_BOX);
|
||||
} else if (MmsSmsDatabase.SMS_TRANSPORT.equals(transportType)) {
|
||||
return CursorUtil.requireLong(cursor, SmsDatabase.TYPE);
|
||||
} else {
|
||||
throw new AssertionError("Bad transport type: " + transportType);
|
||||
}
|
||||
}
|
||||
|
||||
public static Reader readerFor(@NonNull Cursor cursor) {
|
||||
return new Reader(cursor);
|
||||
}
|
||||
|
||||
@@ -1226,8 +1226,8 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
private boolean update(long threadId, boolean unarchive, boolean allowDeletion, boolean notifyListeners) {
|
||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||
boolean meaningfulMessages = mmsSmsDatabase.hasMeaningfulMessage(threadId);
|
||||
MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
|
||||
boolean meaningfulMessages = mmsSmsDatabase.hasMeaningfulMessage(threadId);
|
||||
|
||||
if (!meaningfulMessages) {
|
||||
if (allowDeletion) {
|
||||
@@ -1236,43 +1236,49 @@ public class ThreadDatabase extends Database {
|
||||
return true;
|
||||
}
|
||||
|
||||
try (MmsSmsDatabase.Reader reader = MmsSmsDatabase.readerFor(mmsSmsDatabase.getConversationSnippet(threadId))) {
|
||||
MessageRecord record = reader.getNext();
|
||||
|
||||
if (record != null) {
|
||||
updateThread(threadId,
|
||||
meaningfulMessages,
|
||||
ThreadBodyUtil.getFormattedBodyFor(context, record),
|
||||
getAttachmentUriFor(record),
|
||||
getContentTypeFor(record),
|
||||
getExtrasFor(record),
|
||||
record.getTimestamp(),
|
||||
record.getDeliveryStatus(),
|
||||
record.getDeliveryReceiptCount(),
|
||||
record.getType(),
|
||||
unarchive,
|
||||
record.getExpiresIn(),
|
||||
record.getReadReceiptCount());
|
||||
if (notifyListeners) {
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
MessageRecord record;
|
||||
try {
|
||||
record = mmsSmsDatabase.getConversationSnippet(threadId);
|
||||
} catch (NoSuchMessageException e) {
|
||||
if (allowDeletion) {
|
||||
deleteConversation(threadId);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
updateThread(threadId,
|
||||
meaningfulMessages,
|
||||
ThreadBodyUtil.getFormattedBodyFor(context, record),
|
||||
getAttachmentUriFor(record),
|
||||
getContentTypeFor(record),
|
||||
getExtrasFor(record),
|
||||
record.getTimestamp(),
|
||||
record.getDeliveryStatus(),
|
||||
record.getDeliveryReceiptCount(),
|
||||
record.getType(),
|
||||
unarchive,
|
||||
record.getExpiresIn(),
|
||||
record.getReadReceiptCount());
|
||||
|
||||
if (notifyListeners) {
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void updateSnippetTypeSilently(long threadId) {
|
||||
try (Cursor cursor = DatabaseFactory.getMmsSmsDatabase(context).getConversationSnippet(threadId)) {
|
||||
if (cursor.moveToFirst()) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(SNIPPET_TYPE, MmsSmsDatabase.getType(cursor));
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, ID_WHERE, SqlUtil.buildArgs(threadId));
|
||||
}
|
||||
long type;
|
||||
try {
|
||||
type = DatabaseFactory.getMmsSmsDatabase(context).getConversationSnippetType(threadId);
|
||||
} catch (NoSuchMessageException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(SNIPPET_TYPE, type);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, ID_WHERE, SqlUtil.buildArgs(threadId));
|
||||
}
|
||||
|
||||
public @NonNull ThreadRecord getThreadRecordFor(@NonNull Recipient recipient) {
|
||||
|
||||
Reference in New Issue
Block a user