Skip trigger drop/recreate in deleteMessagesInThread when there are no messages to delete.

The deleteMessagesInThread method unconditionally drops and recreates FTS
and MSL triggers in every call, even when there are no messages matching
the delete criteria. Each trigger drop/create cycle changes the database
schema cookie, causing SQLITE_SCHEMA errors for concurrent reader
connections.
This commit is contained in:
Greyson Parrelli
2026-02-19 16:01:08 +00:00
committed by Cody Henthorne
parent e636a94de0
commit 85265412da

View File

@@ -3952,11 +3952,25 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
fun deleteMessagesInThread(threadIds: Collection<Long>, extraWhere: String = ""): Int {
var totalDeletedCount = 0
val threadsWithPossibleDeletes = threadIds.filter { threadId ->
readableDatabase
.select(ID)
.from(TABLE_NAME)
.where("$THREAD_ID = $threadId $extraWhere")
.limit(1)
.run()
.use { it.moveToFirst() }
}
if (threadsWithPossibleDeletes.isEmpty()) {
return 0
}
writableDatabase.withinTransaction { db ->
SignalDatabase.messageSearch.dropAfterMessageDeleteTrigger()
SignalDatabase.messageLog.dropAfterMessageDeleteTrigger()
for (threadId in threadIds) {
for (threadId in threadsWithPossibleDeletes) {
val subSelect = "SELECT ${TABLE_NAME}.$ID FROM $TABLE_NAME WHERE ${TABLE_NAME}.$THREAD_ID = $threadId $extraWhere LIMIT 1000"
do {
// Bulk deleting FK tables for large message delete efficiency