Improve performance from thread being updated to data available to render.

This commit is contained in:
Cody Henthorne
2023-04-14 16:28:56 -04:00
parent 9d17bf473c
commit 4f06a0d27c
39 changed files with 497 additions and 815 deletions

View File

@@ -19,6 +19,6 @@ class CallLinkTable(context: Context, databaseHelper: SignalDatabase) : Database
CREATE TABLE $TABLE_NAME (
$ID INTEGER PRIMARY KEY
)
""".trimIndent()
"""
}
}

View File

@@ -76,7 +76,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
UNIQUE ($CALL_ID, $PEER, $CALL_LINK) ON CONFLICT FAIL,
CHECK (($PEER IS NULL AND $CALL_LINK IS NOT NULL) OR ($PEER IS NOT NULL AND $CALL_LINK IS NULL))
)
""".trimIndent()
"""
val CREATE_INDEXES = arrayOf(
"CREATE INDEX call_call_id_index ON $TABLE_NAME ($CALL_ID)",
@@ -760,7 +760,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
${RecipientTable.TABLE_NAME}.${RecipientTable.PHONE} GLOB ? OR
${RecipientTable.TABLE_NAME}.${RecipientTable.EMAIL} GLOB ?
)
""".trimIndent()
"""
SqlUtil.buildQuery(selection, 0, 0, glob, glob, glob, glob)
} else {
SqlUtil.buildQuery("")
@@ -854,7 +854,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
LEFT JOIN ${GroupTable.TABLE_NAME} ON ${GroupTable.TABLE_NAME}.${GroupTable.RECIPIENT_ID} = ${RecipientTable.TABLE_NAME}.${RecipientTable.ID}
WHERE true_parent = p.$ID ${if (queryClause.where.isNotEmpty()) "AND ${queryClause.where}" else ""}
$offsetLimit
""".trimIndent()
"""
return readableDatabase.query(
statement,

View File

@@ -23,7 +23,7 @@ class ChatColorsTable(context: Context, databaseHelper: SignalDatabase) : Databa
$ID INTEGER PRIMARY KEY AUTOINCREMENT,
$CHAT_COLORS BLOB
)
""".trimIndent()
"""
}
fun getById(chatColorsId: ChatColors.Id): ChatColors {

View File

@@ -31,7 +31,7 @@ class DonationReceiptTable(context: Context, databaseHelper: SignalDatabase) : D
$CURRENCY TEXT NOT NULL,
$SUBSCRIPTION_LEVEL INTEGER NOT NULL
)
""".trimIndent()
"""
val CREATE_INDEXS = arrayOf(
"CREATE INDEX IF NOT EXISTS donation_receipt_type_index ON $TABLE_NAME ($TYPE)",

View File

@@ -28,7 +28,6 @@ import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullString
import org.signal.core.util.requireString
import org.signal.core.util.select
import org.signal.core.util.toSingleLine
import org.signal.core.util.update
import org.signal.core.util.withinTransaction
import org.signal.libsignal.zkgroup.groups.GroupMasterKey
@@ -171,7 +170,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
WHERE ${MembershipTable.TABLE_NAME}.${MembershipTable.GROUP_ID} = $TABLE_NAME.$GROUP_ID
) as $MEMBER_GROUP_CONCAT
FROM $TABLE_NAME
""".toSingleLine()
"""
val CREATE_TABLES = arrayOf(CREATE_TABLE, MembershipTable.CREATE_TABLE)
}
@@ -193,7 +192,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
$RECIPIENT_ID INTEGER NOT NULL,
UNIQUE($GROUP_ID, $RECIPIENT_ID)
)
""".toSingleLine()
"""
}
}
@@ -371,7 +370,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
WHERE $ACTIVE = 1 AND ${MembershipTable.TABLE_NAME}.${MembershipTable.RECIPIENT_ID} IN (${subquery.where})
GROUP BY ${MembershipTable.TABLE_NAME}.${MembershipTable.GROUP_ID}
ORDER BY $TITLE COLLATE NOCASE ASC
""".toSingleLine()
"""
return databaseHelper.signalReadableDatabase.query(statement, subquery.whereArgs)
}
@@ -383,7 +382,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
$JOINED_GROUP_SELECT
WHERE ${query.where}
ORDER BY $TITLE COLLATE NOCASE ASC
""".trimIndent()
"""
val cursor = databaseHelper.signalReadableDatabase.query(statement, query.whereArgs)
return Reader(cursor)
@@ -432,7 +431,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
FROM ${MembershipTable.TABLE_NAME}
INNER JOIN $TABLE_NAME ON ${MembershipTable.TABLE_NAME}.${MembershipTable.GROUP_ID} = $TABLE_NAME.$GROUP_ID
WHERE $query
""".trimIndent()
"""
return Reader(readableDatabase.query(selection, queryArgs))
}
@@ -444,7 +443,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
INNER JOIN ${ThreadTable.TABLE_NAME} ON ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} = $TABLE_NAME.$RECIPIENT_ID
WHERE ${query.where}
ORDER BY ${ThreadTable.TABLE_NAME}.${ThreadTable.DATE} DESC
""".toSingleLine()
"""
return Reader(databaseHelper.signalReadableDatabase.rawQuery(sql, query.whereArgs))
}
@@ -534,7 +533,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
) as $MEMBER_GROUP_CONCAT
FROM $TABLE_NAME
WHERE $MEMBER_GROUP_CONCAT = ?
""".toSingleLine()
"""
return readableDatabase.rawQuery(statement, buildArgs(joinedTestMembers)).use { cursor ->
if (cursor.moveToNext()) {
@@ -577,7 +576,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
FROM ${MembershipTable.TABLE_NAME}
INNER JOIN $TABLE_NAME ON ${MembershipTable.TABLE_NAME}.${MembershipTable.GROUP_ID} = $TABLE_NAME.$GROUP_ID
LEFT JOIN ${ThreadTable.TABLE_NAME} ON $TABLE_NAME.$RECIPIENT_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID}
""".toSingleLine()
"""
var query = "${MembershipTable.TABLE_NAME}.${MembershipTable.RECIPIENT_ID} = ?"
var args = buildArgs(recipientId)
@@ -1291,7 +1290,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
)
)
ORDER BY active_timestamp DESC
""".toSingleLine()
"""
return readableDatabase
.query(query)

View File

@@ -65,7 +65,7 @@ class LocalMetricsDatabase private constructor(
$SPLIT_NAME TEXT NOT NULL,
$DURATION INTEGER NOT NULL
)
""".trimIndent()
"""
private val CREATE_INDEXES = arrayOf(
"CREATE INDEX events_create_at_index ON $TABLE_NAME ($CREATED_AT)",
@@ -99,7 +99,7 @@ class LocalMetricsDatabase private constructor(
SELECT $EVENT_ID, $EVENT_NAME, SUM($DURATION) AS $DURATION
FROM $TABLE_NAME
GROUP BY $EVENT_ID
""".trimIndent()
"""
}
override fun onCreate(db: SQLiteDatabase) {
@@ -231,7 +231,7 @@ class LocalMetricsDatabase private constructor(
OFFSET (SELECT COUNT(*)
FROM $table
WHERE $where) * $percent / 100 - 1
""".trimIndent()
"""
readableDatabase.rawQuery(query, null).use { cursor ->
return if (cursor.moveToFirst()) {

View File

@@ -70,7 +70,7 @@ class LogDatabase private constructor(
$BODY TEXT,
$SIZE INTEGER
)
""".trimIndent()
"""
private val CREATE_INDEXES = arrayOf(
"CREATE INDEX keep_longer_index ON $TABLE_NAME ($KEEP_LONGER)",

View File

@@ -6,7 +6,6 @@ import android.database.Cursor
import org.signal.core.util.requireInt
import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullString
import org.signal.core.util.toSingleLine
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.MediaUtil
@@ -80,7 +79,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
${AttachmentTable.STICKER_PACK_ID} IS NULL AND
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} > 0 AND
$THREAD_RECIPIENT_ID > 0
""".toSingleLine()
"""
private val UNIQUE_MEDIA_QUERY = """
SELECT
@@ -92,14 +91,14 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
${AttachmentTable.STICKER_PACK_ID} IS NULL AND
${AttachmentTable.TRANSFER_STATE} = ${AttachmentTable.TRANSFER_PROGRESS_DONE}
GROUP BY ${AttachmentTable.DATA}
""".toSingleLine()
"""
private val GALLERY_MEDIA_QUERY = String.format(
BASE_MEDIA_QUERY,
"""
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'image/svg%' AND
(${AttachmentTable.CONTENT_TYPE} LIKE 'image/%' OR ${AttachmentTable.CONTENT_TYPE} LIKE 'video/%')
""".toSingleLine()
"""
)
private val AUDIO_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, "${AttachmentTable.CONTENT_TYPE} LIKE 'audio/%'")
@@ -113,7 +112,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'video/%' AND
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'audio/%' AND
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'text/x-signal-plain'
)""".toSingleLine()
)"""
)
private fun applyEqualityOperator(threadId: Long, query: String): String {
@@ -224,20 +223,20 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
${AttachmentTable.TABLE_NAME}.${AttachmentTable.MMS_ID} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ROW_ID} DESC
""".toSingleLine()
"""
),
Oldest(
"""
${AttachmentTable.TABLE_NAME}.${AttachmentTable.MMS_ID} ASC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ROW_ID} ASC
""".toSingleLine()
"""
),
Largest(
"""
${AttachmentTable.TABLE_NAME}.${AttachmentTable.SIZE} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER} DESC
""".toSingleLine()
"""
);
private val postFix: String

View File

@@ -55,7 +55,6 @@ import org.signal.core.util.requireNonNullString
import org.signal.core.util.requireString
import org.signal.core.util.select
import org.signal.core.util.toOptional
import org.signal.core.util.toSingleLine
import org.signal.core.util.update
import org.signal.core.util.withinTransaction
import org.signal.libsignal.protocol.IdentityKey
@@ -363,7 +362,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
'${AttachmentTable.UPLOAD_TIMESTAMP}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.UPLOAD_TIMESTAMP}
)
) AS ${AttachmentTable.ATTACHMENT_JSON_ALIAS}
""".toSingleLine()
"""
private const val IS_STORY_CLAUSE = "$STORY_TYPE > 0 AND $REMOTE_DELETED = 0"
private const val RAW_ID_WHERE = "$TABLE_NAME.$ID = ?"
@@ -390,7 +389,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
${MessageTypes.SMS_EXPORT_TYPE}
)
ORDER BY $DATE_RECEIVED DESC LIMIT 1
""".toSingleLine()
"""
private val IS_CALL_TYPE_CLAUSE = """(
($TYPE = ${MessageTypes.INCOMING_AUDIO_CALL_TYPE})
@@ -406,7 +405,13 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
($TYPE = ${MessageTypes.MISSED_VIDEO_CALL_TYPE})
OR
($TYPE = ${MessageTypes.GROUP_CALL_TYPE})
)""".toSingleLine()
)"""
private val outgoingTypeClause: String by lazy {
MessageTypes.OUTGOING_MESSAGE_TYPES
.map { "($TABLE_NAME.$TYPE & ${MessageTypes.BASE_TYPE_MASK} = $it)" }
.joinToString(" OR ")
}
@JvmStatic
fun mmsReaderFor(cursor: Cursor): MmsReader {
@@ -620,7 +625,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
UPDATE $TABLE_NAME
SET $TYPE = ($TYPE & ${MessageTypes.TOTAL_MASK - maskOff} | $maskOn )
WHERE $ID = ?
""".toSingleLine(),
""",
buildArgs(id)
)
@@ -640,7 +645,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$BODY = ?,
$TYPE = ($TYPE & ${MessageTypes.TOTAL_MASK - maskOff} | $maskOn)
WHERE $ID = ?
""".toSingleLine(),
""",
arrayOf(body, messageId.toString() + "")
)
@@ -729,7 +734,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
val results: List<MarkedMessageInfo> = readableDatabase
.select(ID, TO_RECIPIENT_ID, DATE_SENT, THREAD_ID, STORY_TYPE)
.from(TABLE_NAME)
.where("""$ID IN (${Util.join(messageIds, ",")}) AND (${getOutgoingTypeClause()}) AND ($TYPE & ${MessageTypes.SPECIAL_TYPES_MASK} = ${MessageTypes.SPECIAL_TYPE_GIFT_BADGE}) AND $VIEWED_RECEIPT_COUNT = 0""")
.where("""$ID IN (${Util.join(messageIds, ",")}) AND ($outgoingTypeClause) AND ($TYPE & ${MessageTypes.SPECIAL_TYPES_MASK} = ${MessageTypes.SPECIAL_TYPE_GIFT_BADGE}) AND $VIEWED_RECEIPT_COUNT = 0""")
.run()
.readToList { it.toMarkedMessageInfo(outgoing = true) }
@@ -1294,7 +1299,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
null
}
var where = "$IS_STORY_CLAUSE AND (${getOutgoingTypeClause()})"
var where = "$IS_STORY_CLAUSE AND ($outgoingTypeClause)"
val whereArgs: Array<String>
if (threadId == null) {
@@ -1309,12 +1314,12 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
}
fun getAllOutgoingStories(reverse: Boolean, limit: Int): Reader {
val where = "$IS_STORY_CLAUSE AND (${getOutgoingTypeClause()})"
val where = "$IS_STORY_CLAUSE AND ($outgoingTypeClause)"
return MmsReader(rawQueryWithAttachments(where, null, reverse, limit.toLong()))
}
fun markAllIncomingStoriesRead(): List<MarkedMessageInfo> {
val where = "$IS_STORY_CLAUSE AND NOT (${getOutgoingTypeClause()}) AND $READ = 0"
val where = "$IS_STORY_CLAUSE AND NOT ($outgoingTypeClause) AND $READ = 0"
val markedMessageInfos = setMessagesRead(where, null)
notifyConversationListListeners()
return markedMessageInfos
@@ -1328,7 +1333,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
}
fun markAllFailedStoriesNotified() {
val where = "$IS_STORY_CLAUSE AND (${getOutgoingTypeClause()}) AND $NOTIFIED = 0 AND ($TYPE & ${MessageTypes.BASE_TYPE_MASK}) = ${MessageTypes.BASE_SENT_FAILED_TYPE}"
val where = "$IS_STORY_CLAUSE AND ($outgoingTypeClause) AND $NOTIFIED = 0 AND ($TYPE & ${MessageTypes.BASE_TYPE_MASK}) = ${MessageTypes.BASE_SENT_FAILED_TYPE}"
writableDatabase
.update("$TABLE_NAME INDEXED BY $INDEX_THREAD_DATE")
@@ -1340,7 +1345,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun markOnboardingStoryRead() {
val recipientId = SignalStore.releaseChannelValues().releaseChannelRecipientId ?: return
val where = "$IS_STORY_CLAUSE AND NOT (${getOutgoingTypeClause()}) AND $READ = 0 AND $FROM_RECIPIENT_ID = ?"
val where = "$IS_STORY_CLAUSE AND NOT ($outgoingTypeClause) AND $READ = 0 AND $FROM_RECIPIENT_ID = ?"
val markedMessageInfos = setMessagesRead(where, buildArgs(recipientId))
if (markedMessageInfos.isNotEmpty()) {
@@ -1358,7 +1363,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun getUnreadStories(recipientId: RecipientId, limit: Int): Reader {
val threadId = threads.getThreadIdIfExistsFor(recipientId)
val query = "$IS_STORY_CLAUSE AND NOT (${getOutgoingTypeClause()}) AND $THREAD_ID = ? AND $VIEWED_RECEIPT_COUNT = ?"
val query = "$IS_STORY_CLAUSE AND NOT ($outgoingTypeClause) AND $THREAD_ID = ? AND $VIEWED_RECEIPT_COUNT = ?"
val args = buildArgs(threadId, 0)
return MmsReader(rawQueryWithAttachments(query, args, false, limit.toLong()))
}
@@ -1411,7 +1416,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
writableDatabase.withinTransaction { db ->
db.select(FROM_RECIPIENT_ID)
.from(TABLE_NAME)
.where("$IS_STORY_CLAUSE AND $DATE_SENT IN ($timestamps) AND NOT (${getOutgoingTypeClause()}) AND $VIEWED_RECEIPT_COUNT > 0")
.where("$IS_STORY_CLAUSE AND $DATE_SENT IN ($timestamps) AND NOT ($outgoingTypeClause) AND $VIEWED_RECEIPT_COUNT > 0")
.run()
.readToList { cursor -> RecipientId.from(cursor.requireLong(FROM_RECIPIENT_ID)) }
.forEach { id -> recipients.updateLastStoryViewTimestamp(id) }
@@ -1431,7 +1436,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
val hasUnviewedStories = readableDatabase
.exists(TABLE_NAME)
.where("$IS_STORY_CLAUSE AND $THREAD_ID = ? AND $VIEWED_RECEIPT_COUNT = ? AND NOT (${getOutgoingTypeClause()})", threadId, 0)
.where("$IS_STORY_CLAUSE AND $THREAD_ID = ? AND $VIEWED_RECEIPT_COUNT = ? AND NOT ($outgoingTypeClause)", threadId, 0)
.run()
return if (hasUnviewedStories) {
@@ -1444,7 +1449,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun isOutgoingStoryAlreadyInDatabase(recipientId: RecipientId, sentTimestamp: Long): Boolean {
return readableDatabase
.exists(TABLE_NAME)
.where("$TO_RECIPIENT_ID = ? AND $STORY_TYPE > 0 AND $DATE_SENT = ? AND (${getOutgoingTypeClause()})", recipientId, sentTimestamp)
.where("$TO_RECIPIENT_ID = ? AND $STORY_TYPE > 0 AND $DATE_SENT = ? AND ($outgoingTypeClause)", recipientId, sentTimestamp)
.run()
}
@@ -1467,10 +1472,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
JOIN ${ThreadTable.TABLE_NAME} ON $TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID}
WHERE
$IS_STORY_CLAUSE AND
(${getOutgoingTypeClause()}) = 0 AND
($outgoingTypeClause) = 0 AND
$VIEWED_RECEIPT_COUNT = 0 AND
$TABLE_NAME.$READ = 0
""".toSingleLine()
"""
return readableDatabase
.rawQuery(query, null)
@@ -1478,7 +1483,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
}
fun hasFailedOutgoingStory(): Boolean {
val where = "$IS_STORY_CLAUSE AND (${getOutgoingTypeClause()}) AND $NOTIFIED = 0 AND ($TYPE & ${MessageTypes.BASE_TYPE_MASK}) = ${MessageTypes.BASE_SENT_FAILED_TYPE}"
val where = "$IS_STORY_CLAUSE AND ($outgoingTypeClause) AND $NOTIFIED = 0 AND ($TYPE & ${MessageTypes.BASE_TYPE_MASK}) = ${MessageTypes.BASE_SENT_FAILED_TYPE}"
return readableDatabase.exists(TABLE_NAME).where(where).run()
}
@@ -1488,11 +1493,11 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$TABLE_NAME.$DATE_SENT AS sent_timestamp,
$TABLE_NAME.$ID AS mms_id,
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID},
(${getOutgoingTypeClause()}) AS is_outgoing,
($outgoingTypeClause) AS is_outgoing,
$VIEWED_RECEIPT_COUNT,
$TABLE_NAME.$DATE_SENT,
$RECEIPT_TIMESTAMP,
(${getOutgoingTypeClause()}) = 0 AND $VIEWED_RECEIPT_COUNT = 0 AS is_unread
($outgoingTypeClause) = 0 AND $VIEWED_RECEIPT_COUNT = 0 AS is_unread
FROM $TABLE_NAME
JOIN ${ThreadTable.TABLE_NAME} ON $TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID}
WHERE
@@ -1506,7 +1511,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
WHEN is_outgoing = 0 AND viewed_receipt_count > 0 THEN $RECEIPT_TIMESTAMP
WHEN is_outgoing = 1 THEN $TABLE_NAME.$DATE_SENT
END DESC
""".toSingleLine()
"""
return readableDatabase
.rawQuery(query, null)
@@ -1545,7 +1550,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun hasSelfReplyInStory(parentStoryId: Long): Boolean {
return readableDatabase
.exists(TABLE_NAME)
.where("$PARENT_STORY_ID = ? AND (${getOutgoingTypeClause()})", -parentStoryId)
.where("$PARENT_STORY_ID = ? AND ($outgoingTypeClause)", -parentStoryId)
.run()
}
@@ -1589,7 +1594,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
FROM $TABLE_NAME
WHERE $storiesBeforeTimestampWhere
)
""".toSingleLine()
"""
val disassociateQuoteQuery = """
UPDATE $TABLE_NAME
@@ -1603,7 +1608,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
FROM $TABLE_NAME
WHERE $storiesBeforeTimestampWhere
)
""".toSingleLine()
"""
db.execSQL(deleteStoryRepliesQuery, sharedArgs)
db.execSQL(disassociateQuoteQuery, sharedArgs)
@@ -1726,7 +1731,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun getIncomingMeaningfulMessageCountSince(threadId: Long, afterTime: Long): Int {
val meaningfulMessagesQuery = buildMeaningfulMessagesQuery(threadId)
val where = "${meaningfulMessagesQuery.where} AND $DATE_RECEIVED >= ? AND NOT (${getOutgoingTypeClause()})"
val where = "${meaningfulMessagesQuery.where} AND $DATE_RECEIVED >= ? AND NOT ($outgoingTypeClause)"
val whereArgs = appendArg(meaningfulMessagesQuery.whereArgs, afterTime.toString())
return readableDatabase
@@ -1750,7 +1755,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$TYPE != ${MessageTypes.BOOST_REQUEST_TYPE} AND
$TYPE & ${MessageTypes.GROUP_V2_LEAVE_BITS} != ${MessageTypes.GROUP_V2_LEAVE_BITS}
)
""".toSingleLine()
"""
return SqlUtil.buildQuery(query, threadId)
}
@@ -1809,7 +1814,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$where
GROUP BY
$TABLE_NAME.$ID
""".toSingleLine()
"""
if (reverse) {
rawQueryString += " ORDER BY $TABLE_NAME.$ID DESC"
@@ -1851,7 +1856,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
UPDATE $TABLE_NAME
SET $TYPE = ($TYPE & ${MessageTypes.TOTAL_MASK - maskOff} | $maskOn )
WHERE $ID = ?
""".toSingleLine(),
""",
buildArgs(id)
)
@@ -2059,10 +2064,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$READ = 0 OR
(
$REACTIONS_UNREAD = 1 AND
(${getOutgoingTypeClause()})
($outgoingTypeClause)
)
)
""".toSingleLine()
"""
val args = mutableListOf(threadId.toString())
@@ -2083,10 +2088,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$READ = 0 OR
(
$REACTIONS_UNREAD = 1 AND
(${getOutgoingTypeClause()})
($outgoingTypeClause)
)
)
""".toSingleLine()
"""
val args = mutableListOf(threadId.toString(), groupStoryId.toString())
@@ -2133,7 +2138,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
}
fun setAllMessagesRead(): List<MarkedMessageInfo> {
return setMessagesRead("$STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND ($READ = 0 OR ($REACTIONS_UNREAD = 1 AND (${getOutgoingTypeClause()})))", null)
return setMessagesRead("$STORY_TYPE = 0 AND $PARENT_STORY_ID <= 0 AND ($READ = 0 OR ($REACTIONS_UNREAD = 1 AND ($outgoingTypeClause)))", null)
}
private fun setMessagesRead(where: String, arguments: Array<String>?): List<MarkedMessageInfo> {
@@ -3306,7 +3311,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
$TABLE_NAME INNER JOIN ${AttachmentTable.TABLE_NAME} ON $TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MMS_ID}
WHERE
${getInsecureMessageClause()} AND $EXPORTED < ${MessageExportStatus.EXPORTED.serialize()}
""".toSingleLine(),
""",
null
).readToSingleLong()
@@ -3415,7 +3420,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
WHERE
$VIEW_ONCE > 0 AND
(${AttachmentTable.DATA} NOT NULL OR ${AttachmentTable.TRANSFER_STATE} != ?)
""".toSingleLine()
"""
val args = buildArgs(AttachmentTable.TRANSFER_PROGRESS_DONE)
@@ -3503,16 +3508,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
return result.toOptional()
}
private fun getOutgoingTypeClause(): String {
val segments: MutableList<String> = ArrayList(MessageTypes.OUTGOING_MESSAGE_TYPES.size)
for (outgoingMessageType in MessageTypes.OUTGOING_MESSAGE_TYPES) {
segments.add("($TABLE_NAME.$TYPE & ${MessageTypes.BASE_TYPE_MASK} = $outgoingMessageType)")
}
return segments.joinToString(" OR ")
}
fun getInsecureMessageCount(): Int {
return readableDatabase
.select("COUNT(*)")
@@ -4247,7 +4242,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
($TO_RECIPIENT_ID = ? OR EXISTS (SELECT 1 FROM ${GroupTable.TABLE_NAME} WHERE ${GroupTable.TABLE_NAME}.${GroupTable.RECIPIENT_ID} = $TO_RECIPIENT_ID))
$qualifierWhere
RETURNING $ID, $THREAD_ID, $STORY_TYPE
""".toSingleLine(),
""",
buildArgs(receiptSentTimestamp, targetTimestamp, Recipient.self().id, receiptAuthor)
).forEach { cursor ->
val messageId = cursor.requireLong(ID)
@@ -4336,7 +4331,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
readableDatabase
.select(ID, THREAD_ID, EXPIRES_IN, EXPIRE_STARTED)
.from(TABLE_NAME)
.where("$DATE_SENT = ? AND ($FROM_RECIPIENT_ID = ? OR ($FROM_RECIPIENT_ID = ? AND ${getOutgoingTypeClause()}))", messageId.timetamp, messageId.recipientId, Recipient.self().id)
.where("$DATE_SENT = ? AND ($FROM_RECIPIENT_ID = ? OR ($FROM_RECIPIENT_ID = ? AND $outgoingTypeClause))", messageId.timetamp, messageId.recipientId, Recipient.self().id)
.run()
.forEach { cursor ->
val id = cursor.requireLong(ID)

View File

@@ -53,7 +53,7 @@ class NotificationProfileDatabase(context: Context, databaseHelper: SignalDataba
$ALLOW_ALL_CALLS INTEGER NOT NULL DEFAULT 0,
$ALLOW_ALL_MENTIONS INTEGER NOT NULL DEFAULT 0
)
""".trimIndent()
"""
}
private object NotificationProfileScheduleTable {
@@ -77,7 +77,7 @@ class NotificationProfileDatabase(context: Context, databaseHelper: SignalDataba
$END INTEGER NOT NULL,
$DAYS_ENABLED TEXT NOT NULL
)
""".trimIndent()
"""
const val CREATE_INDEX = "CREATE INDEX notification_profile_schedule_profile_index ON $TABLE_NAME ($NOTIFICATION_PROFILE_ID)"
}
@@ -96,7 +96,7 @@ class NotificationProfileDatabase(context: Context, databaseHelper: SignalDataba
$RECIPIENT_ID INTEGER NOT NULL,
UNIQUE($NOTIFICATION_PROFILE_ID, $RECIPIENT_ID) ON CONFLICT REPLACE
)
""".trimIndent()
"""
const val CREATE_INDEX = "CREATE INDEX notification_profile_allowed_members_profile_index ON $TABLE_NAME ($NOTIFICATION_PROFILE_ID)"
}

View File

@@ -37,7 +37,7 @@ class ReactionTable(context: Context, databaseHelper: SignalDatabase) : Database
$DATE_RECEIVED INTEGER NOT NULL,
UNIQUE($MESSAGE_ID, $AUTHOR_ID) ON CONFLICT REPLACE
)
""".trimIndent()
"""
private fun readReaction(cursor: Cursor): ReactionRecord {
return ReactionRecord(

View File

@@ -32,7 +32,6 @@ import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullString
import org.signal.core.util.requireString
import org.signal.core.util.select
import org.signal.core.util.toSingleLine
import org.signal.core.util.update
import org.signal.core.util.withinTransaction
import org.signal.libsignal.protocol.IdentityKey
@@ -254,7 +253,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
$REPORTING_TOKEN BLOB DEFAULT NULL,
$SYSTEM_NICKNAME TEXT DEFAULT NULL
)
""".trimIndent()
"""
val CREATE_INDEXS = arrayOf(
"CREATE INDEX IF NOT EXISTS recipient_group_type_index ON $TABLE_NAME ($GROUP_TYPE);",
@@ -343,7 +342,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
NULLIF($USERNAME, '')
)
) AS $SORT_NAME
""".trimIndent()
"""
)
@JvmField
@@ -385,7 +384,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
' ',
''
) AS $SORT_NAME
""".trimIndent()
"""
)
private val INSIGHTS_INVITEE_LIST =
@@ -1079,7 +1078,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
$TABLE_NAME LEFT OUTER JOIN ${IdentityTable.TABLE_NAME} ON $TABLE_NAME.$SERVICE_ID = ${IdentityTable.TABLE_NAME}.${IdentityTable.ADDRESS}
LEFT OUTER JOIN ${GroupTable.TABLE_NAME} ON $TABLE_NAME.$GROUP_ID = ${GroupTable.TABLE_NAME}.${GroupTable.GROUP_ID}
LEFT OUTER JOIN ${ThreadTable.TABLE_NAME} ON $TABLE_NAME.$ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID}
""".trimIndent()
"""
val out: MutableList<RecipientRecord> = ArrayList()
val columns: Array<String> = TYPED_RECIPIENT_PROJECTION + arrayOf(
SYSTEM_NICKNAME,
@@ -1129,7 +1128,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
FROM ${DistributionListTables.ListTable.TABLE_NAME}
)
)
""".toSingleLine(),
""",
GroupType.NONE.id,
Recipient.self().id,
GroupType.SIGNAL_V1.id
@@ -3158,7 +3157,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
ORDER BY $SORT_NAME, $SYSTEM_JOINED_NAME, $SEARCH_PROFILE_NAME, $PHONE
)
GROUP BY letter_header
""".trimIndent(),
""",
searchSelection.args
).use { cursor ->
if (cursor.count == 0) {
@@ -3263,7 +3262,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
$PHONE GLOB ? OR
$EMAIL GLOB ?
)
""".trimIndent()
"""
val args = SqlUtil.buildArgs(0, 0, query, query, query, query)
return readableDatabase.query(TABLE_NAME, SEARCH_PROJECTION, selection, args, null, null, null)
}
@@ -3284,7 +3283,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
$PHONE GLOB ? OR
$EMAIL GLOB ?
))
""".toSingleLine()
"""
return SqlUtil.Query(subquery, SqlUtil.buildArgs(0, 0, query, query, query, query))
}
@@ -3302,7 +3301,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
$PHONE GLOB ? OR
$EMAIL GLOB ?
)
""".toSingleLine()
"""
return readableDatabase.query(subquery, SqlUtil.buildArgs(0, 0, query, query, query, query))
}
@@ -3479,7 +3478,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
r.$PROFILE_SHARING = 0 AND (
EXISTS(SELECT 1 FROM ${MessageTable.TABLE_NAME} WHERE ${MessageTable.THREAD_ID} = t.${ThreadTable.ID} AND ${MessageTable.DATE_RECEIVED} < ?)
)
""".trimIndent()
"""
val idsToUpdate: MutableList<Long> = ArrayList()
readableDatabase.rawQuery(select, whereArgs).use { cursor ->
@@ -3998,7 +3997,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
UPDATE $TABLE_NAME
SET $SERVICE_ID = $PNI_COLUMN
WHERE $ID = ? AND $PNI_COLUMN NOT NULL
""".toSingleLine(),
""",
SqlUtil.buildArgs(recipientId)
)
@@ -4466,7 +4465,7 @@ open class RecipientTable(context: Context, databaseHelper: SignalDatabase) : Da
INNER JOIN ${GroupTable.TABLE_NAME} ON ${GroupTable.TABLE_NAME}.${GroupTable.GROUP_ID} = ${GroupTable.MembershipTable.TABLE_NAME}.${GroupTable.MembershipTable.GROUP_ID}
WHERE ${GroupTable.MembershipTable.TABLE_NAME}.${GroupTable.MembershipTable.RECIPIENT_ID} = $TABLE_NAME.$ID AND ${GroupTable.TABLE_NAME}.${GroupTable.ACTIVE} = 1 AND ${GroupTable.TABLE_NAME}.${GroupTable.MMS} = 0
)
""".toSingleLine()
"""
const val FILTER_GROUPS = " AND $GROUP_ID IS NULL"
const val FILTER_ID = " AND $ID != ?"
const val FILTER_BLOCKED = " AND $BLOCKED = ?"

View File

@@ -80,7 +80,7 @@ class RemoteMegaphoneTable(context: Context, databaseHelper: SignalDatabase) : D
$SNOOZED_AT INTEGER DEFAULT 0,
$SEEN_COUNT INTEGER DEFAULT 0
)
""".trimIndent()
"""
const val VERSION_FINISHED = Int.MAX_VALUE
}

View File

@@ -0,0 +1,47 @@
package org.thoughtcrime.securesms.database
import io.reactivex.rxjava3.core.BackpressureStrategy
import io.reactivex.rxjava3.core.Emitter
import io.reactivex.rxjava3.core.Flowable
import io.reactivex.rxjava3.schedulers.Schedulers
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
/**
* Provide a shared Rx interface to listen to database updates and ensure listeners
* execute on [Schedulers.io].
*/
object RxDatabaseObserver {
val conversationList: Flowable<Unit> by lazy { conversationListFlowable() }
private fun conversationListFlowable(): Flowable<Unit> {
val flowable = Flowable.create(
{
val listener = RxObserver(it)
ApplicationDependencies.getDatabaseObserver().registerConversationListObserver(listener)
it.setCancellable { ApplicationDependencies.getDatabaseObserver().unregisterObserver(listener) }
listener.prime()
},
BackpressureStrategy.LATEST
)
return flowable
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.replay(1)
.refCount()
.observeOn(Schedulers.io())
}
private class RxObserver(private val emitter: Emitter<Unit>) : DatabaseObserver.Observer {
fun prime() {
emitter.onNext(Unit)
}
override fun onChanged() {
emitter.onNext(Unit)
}
}
}

View File

@@ -150,7 +150,7 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
WHERE
${MessageTable.ID} >= $i AND
${MessageTable.ID} < ${i + batchSize}
""".trimIndent()
"""
)
}
}

View File

@@ -42,7 +42,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
$ALLOWS_REPLIES INTEGER NOT NULL,
$DISTRIBUTION_ID TEXT NOT NULL REFERENCES ${DistributionListTables.LIST_TABLE_NAME} (${DistributionListTables.DISTRIBUTION_ID}) ON DELETE CASCADE
)
""".trimIndent()
"""
val CREATE_INDEXS = arrayOf(
"CREATE INDEX story_sends_recipient_id_sent_timestamp_allows_replies_index ON $TABLE_NAME ($RECIPIENT_ID, $SENT_TIMESTAMP, $ALLOWS_REPLIES)",
@@ -110,7 +110,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
AND $MESSAGE_ID > $messageId
AND $ALLOWS_REPLIES > ${allowsReplies.toInt()}
)
""".trimIndent()
"""
readableDatabase.rawQuery(query, null).use { cursor ->
while (cursor.moveToNext()) {
@@ -146,7 +146,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
WHERE ${MessageTable.REMOTE_DELETED} = 0
)
)
""".trimIndent()
"""
readableDatabase.rawQuery(query, null).use { cursor ->
while (cursor.moveToNext()) {
@@ -227,7 +227,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
"""
$SENT_TIMESTAMP = ? AND
(SELECT ${MessageTable.REMOTE_DELETED} FROM ${MessageTable.TABLE_NAME} WHERE ${MessageTable.ID} = $MESSAGE_ID) = 0
""".trimIndent(),
""",
sentTimestamp
)
.orderBy(MESSAGE_ID)
@@ -272,7 +272,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
FROM ${MessageTable.TABLE_NAME}
INNER JOIN ${DistributionListTables.LIST_TABLE_NAME} ON ${DistributionListTables.LIST_TABLE_NAME}.${DistributionListTables.RECIPIENT_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.TO_RECIPIENT_ID}
WHERE ${MessageTable.DATE_SENT} = $sentTimestamp AND ${DistributionListTables.DISTRIBUTION_ID} IS NOT NULL
""".trimIndent()
"""
val distributionIdToMessageId = readableDatabase.query(query).use { cursor ->
val results: MutableMap<DistributionId, Long> = mutableMapOf()
@@ -351,7 +351,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
FROM $TABLE_NAME
INNER JOIN ${MessageTable.TABLE_NAME} ON ${MessageTable.TABLE_NAME}.${MessageTable.ID} = $TABLE_NAME.$MESSAGE_ID
WHERE $TABLE_NAME.$SENT_TIMESTAMP = ?
""".trimIndent(),
""",
arrayOf(sentTimestamp)
).use { cursor ->
val results: MutableMap<RecipientId, SentStorySyncManifest.Entry> = mutableMapOf()

View File

@@ -23,7 +23,6 @@ import org.signal.core.util.requireInt
import org.signal.core.util.requireLong
import org.signal.core.util.requireString
import org.signal.core.util.select
import org.signal.core.util.toSingleLine
import org.signal.core.util.update
import org.signal.core.util.withinTransaction
import org.signal.libsignal.zkgroup.InvalidInputException
@@ -135,7 +134,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
$PINNED INTEGER DEFAULT 0,
$UNREAD_SELF_MENTION_COUNT INTEGER DEFAULT 0
)
""".trimIndent()
"""
@JvmField
val CREATE_INDEXS = arrayOf(
@@ -607,7 +606,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
$UNREAD_SELF_MENTION_COUNT = $UNREAD_SELF_MENTION_COUNT + ?,
$LAST_SCROLLED = ?
WHERE $ID = ?
""".toSingleLine(),
""",
SqlUtil.buildArgs(unreadAmount, unreadSelfMentionAmount, 0, threadId)
)
}
@@ -1683,7 +1682,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
) as MembershipAlias ON MembershipAlias.${GroupTable.MembershipTable.GROUP_ID} = ${GroupTable.TABLE_NAME}.${GroupTable.GROUP_ID}
WHERE $where
ORDER BY $orderBy
""".trimIndent()
"""
if (limit > 0) {
query += " LIMIT $limit"
@@ -1693,7 +1692,7 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
query += " OFFSET $offset"
}
return query.toSingleLine()
return query
}
private fun isSilentType(type: Long): Boolean {

View File

@@ -8,7 +8,6 @@ import org.signal.core.util.delete
import org.signal.core.util.logging.Log
import org.signal.core.util.readToList
import org.signal.core.util.requireLong
import org.signal.core.util.toSingleLine
import org.signal.core.util.update
/**
@@ -58,7 +57,7 @@ object V166_ThreadAndMessageForeignKeys : SignalDatabaseMigration {
COUNT(*) AS thread_count
FROM thread
GROUP BY thread_recipient_id HAVING thread_count > 1
""".toSingleLine()
"""
).use { cursor ->
while (cursor.moveToNext()) {
val recipientId = cursor.requireLong("thread_recipient_id")

View File

@@ -7,7 +7,6 @@ import org.signal.core.util.delete
import org.signal.core.util.logging.Log
import org.signal.core.util.readToList
import org.signal.core.util.requireLong
import org.signal.core.util.toSingleLine
import org.signal.core.util.update
/**
@@ -38,7 +37,7 @@ object V171_ThreadForeignKeyFix : SignalDatabaseMigration {
COUNT(*) AS thread_count
FROM thread
GROUP BY recipient_id HAVING thread_count > 1
""".toSingleLine()
"""
).use { cursor ->
while (cursor.moveToNext()) {
val recipientId = cursor.requireLong("recipient_id")

View File

@@ -12,7 +12,6 @@ import org.signal.core.util.readToSingleObject
import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullString
import org.signal.core.util.requireString
import org.signal.core.util.toSingleLine
import org.thoughtcrime.securesms.database.KeyValueDatabase
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.recipients.RecipientId
@@ -182,7 +181,7 @@ object V185_MessageRecipientsMigration : SignalDatabaseMigration {
from_recipient_id = ${selfId.toLong()},
from_device_id = 1
WHERE $outgoingClause
""".toSingleLine()
"""
)
}
stopwatch.split("update-data")

View File

@@ -33,7 +33,7 @@ class AvatarPickerDatabase(context: Context, databaseHelper: SignalDatabase) : D
$GROUP_ID TEXT DEFAULT NULL,
$AVATAR BLOB NOT NULL
)
""".trimIndent()
"""
}
fun saveAvatarForSelf(avatar: Avatar): Avatar {