Remove is_mms field from MSL tables.

main
Greyson Parrelli 2023-02-01 23:02:28 -05:00 zatwierdzone przez Nicholas Tinsley
rodzic 35ff977df9
commit 987fafff92
4 zmienionych plików z 146 dodań i 65 usunięć

Wyświetl plik

@ -19,7 +19,7 @@ import org.whispersystems.signalservice.api.messages.SendMessageResult
import org.whispersystems.signalservice.internal.push.SignalServiceProtos import org.whispersystems.signalservice.internal.push.SignalServiceProtos
/** /**
* Stores a 24-hr buffer of all outgoing messages. Used for the retry logic required for sender key. * Stores a rolling buffer of all outgoing messages. Used for the retry logic required for sender key.
* *
* General note: This class is actually three tables: * General note: This class is actually three tables:
* - one to store the entry * - one to store the entry
@ -53,16 +53,16 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
private val TAG = Log.tag(MessageSendLogTables::class.java) private val TAG = Log.tag(MessageSendLogTables::class.java)
@JvmField @JvmField
val CREATE_TABLE: Array<String> = arrayOf(PayloadTable.CREATE_TABLE, RecipientTable.CREATE_TABLE, MessageTable.CREATE_TABLE) val CREATE_TABLE: Array<String> = arrayOf(MslPayloadTable.CREATE_TABLE, MslRecipientTable.CREATE_TABLE, MslMessageTable.CREATE_TABLE)
@JvmField @JvmField
val CREATE_INDEXES: Array<String> = PayloadTable.CREATE_INDEXES + RecipientTable.CREATE_INDEXES + MessageTable.CREATE_INDEXES val CREATE_INDEXES: Array<String> = MslPayloadTable.CREATE_INDEXES + MslRecipientTable.CREATE_INDEXES + MslMessageTable.CREATE_INDEXES
@JvmField @JvmField
val CREATE_TRIGGERS: Array<String> = PayloadTable.CREATE_TRIGGERS val CREATE_TRIGGERS: Array<String> = MslPayloadTable.CREATE_TRIGGERS
} }
private object PayloadTable { private object MslPayloadTable {
const val TABLE_NAME = "msl_payload" const val TABLE_NAME = "msl_payload"
const val ID = "_id" const val ID = "_id"
@ -88,21 +88,21 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
val CREATE_TRIGGERS = arrayOf( val CREATE_TRIGGERS = arrayOf(
""" """
CREATE TRIGGER msl_mms_delete AFTER DELETE ON ${org.thoughtcrime.securesms.database.MessageTable.TABLE_NAME} CREATE TRIGGER msl_message_delete AFTER DELETE ON ${MessageTable.TABLE_NAME}
BEGIN BEGIN
DELETE FROM $TABLE_NAME WHERE $ID IN (SELECT ${MessageTable.PAYLOAD_ID} FROM ${MessageTable.TABLE_NAME} WHERE ${MessageTable.MESSAGE_ID} = old.${org.thoughtcrime.securesms.database.MessageTable.ID} AND ${MessageTable.IS_MMS} = 1); DELETE FROM $TABLE_NAME WHERE $ID IN (SELECT ${MslMessageTable.PAYLOAD_ID} FROM ${MslMessageTable.TABLE_NAME} WHERE ${MslMessageTable.MESSAGE_ID} = old.${MessageTable.ID});
END END
""", """,
""" """
CREATE TRIGGER msl_attachment_delete AFTER DELETE ON ${AttachmentTable.TABLE_NAME} CREATE TRIGGER msl_attachment_delete AFTER DELETE ON ${AttachmentTable.TABLE_NAME}
BEGIN BEGIN
DELETE FROM $TABLE_NAME WHERE $ID IN (SELECT ${MessageTable.PAYLOAD_ID} FROM ${MessageTable.TABLE_NAME} WHERE ${MessageTable.MESSAGE_ID} = old.${AttachmentTable.MMS_ID} AND ${MessageTable.IS_MMS} = 1); DELETE FROM $TABLE_NAME WHERE $ID IN (SELECT ${MslMessageTable.PAYLOAD_ID} FROM ${MslMessageTable.TABLE_NAME} WHERE ${MslMessageTable.MESSAGE_ID} = old.${AttachmentTable.MMS_ID});
END END
""" """
) )
} }
private object RecipientTable { private object MslRecipientTable {
const val TABLE_NAME = "msl_recipient" const val TABLE_NAME = "msl_recipient"
const val ID = "_id" const val ID = "_id"
@ -113,7 +113,7 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
const val CREATE_TABLE = """ const val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME ( CREATE TABLE $TABLE_NAME (
$ID INTEGER PRIMARY KEY, $ID INTEGER PRIMARY KEY,
$PAYLOAD_ID INTEGER NOT NULL REFERENCES ${PayloadTable.TABLE_NAME} (${PayloadTable.ID}) ON DELETE CASCADE, $PAYLOAD_ID INTEGER NOT NULL REFERENCES ${MslPayloadTable.TABLE_NAME} (${MslPayloadTable.ID}) ON DELETE CASCADE,
$RECIPIENT_ID INTEGER NOT NULL, $RECIPIENT_ID INTEGER NOT NULL,
$DEVICE INTEGER NOT NULL $DEVICE INTEGER NOT NULL
) )
@ -126,26 +126,24 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
) )
} }
private object MessageTable { private object MslMessageTable {
const val TABLE_NAME = "msl_message" const val TABLE_NAME = "msl_message"
const val ID = "_id" const val ID = "_id"
const val PAYLOAD_ID = "payload_id" const val PAYLOAD_ID = "payload_id"
const val MESSAGE_ID = "message_id" const val MESSAGE_ID = "message_id"
const val IS_MMS = "is_mms"
const val CREATE_TABLE = """ const val CREATE_TABLE = """
CREATE TABLE $TABLE_NAME ( CREATE TABLE $TABLE_NAME (
$ID INTEGER PRIMARY KEY, $ID INTEGER PRIMARY KEY,
$PAYLOAD_ID INTEGER NOT NULL REFERENCES ${PayloadTable.TABLE_NAME} (${PayloadTable.ID}) ON DELETE CASCADE, $PAYLOAD_ID INTEGER NOT NULL REFERENCES ${MslPayloadTable.TABLE_NAME} (${MslPayloadTable.ID}) ON DELETE CASCADE,
$MESSAGE_ID INTEGER NOT NULL, $MESSAGE_ID INTEGER NOT NULL,
$IS_MMS INTEGER NOT NULL
) )
""" """
/** Created for [PayloadTable.CREATE_TRIGGERS] and [deleteAllRelatedToMessage] */ /** Created for [MslPayloadTable.CREATE_TRIGGERS] and [deleteAllRelatedToMessage] */
val CREATE_INDEXES = arrayOf( val CREATE_INDEXES = arrayOf(
"CREATE INDEX msl_message_message_index ON $TABLE_NAME ($MESSAGE_ID, $IS_MMS, $PAYLOAD_ID)" "CREATE INDEX msl_message_message_index ON $TABLE_NAME ($MESSAGE_ID, $PAYLOAD_ID)"
) )
} }
@ -205,12 +203,12 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
try { try {
sendMessageResult.success.devices.forEach { device -> sendMessageResult.success.devices.forEach { device ->
val recipientValues = ContentValues().apply { val recipientValues = ContentValues().apply {
put(RecipientTable.PAYLOAD_ID, payloadId) put(MslRecipientTable.PAYLOAD_ID, payloadId)
put(RecipientTable.RECIPIENT_ID, recipientId.serialize()) put(MslRecipientTable.RECIPIENT_ID, recipientId.serialize())
put(RecipientTable.DEVICE, device) put(MslRecipientTable.DEVICE, device)
} }
db.insert(RecipientTable.TABLE_NAME, null, recipientValues) db.insert(MslRecipientTable.TABLE_NAME, null, recipientValues)
} }
db.setTransactionSuccessful() db.setTransactionSuccessful()
@ -233,36 +231,35 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
db.beginTransaction() db.beginTransaction()
try { try {
val payloadValues = ContentValues().apply { val payloadValues = ContentValues().apply {
put(PayloadTable.DATE_SENT, dateSent) put(MslPayloadTable.DATE_SENT, dateSent)
put(PayloadTable.CONTENT, content.toByteArray()) put(MslPayloadTable.CONTENT, content.toByteArray())
put(PayloadTable.CONTENT_HINT, contentHint.type) put(MslPayloadTable.CONTENT_HINT, contentHint.type)
put(PayloadTable.URGENT, urgent.toInt()) put(MslPayloadTable.URGENT, urgent.toInt())
} }
val payloadId: Long = db.insert(PayloadTable.TABLE_NAME, null, payloadValues) val payloadId: Long = db.insert(MslPayloadTable.TABLE_NAME, null, payloadValues)
val recipientValues: MutableList<ContentValues> = mutableListOf() val recipientValues: MutableList<ContentValues> = mutableListOf()
recipients.forEach { recipientDevice -> recipients.forEach { recipientDevice ->
recipientDevice.devices.forEach { device -> recipientDevice.devices.forEach { device ->
recipientValues += ContentValues().apply { recipientValues += ContentValues().apply {
put(RecipientTable.PAYLOAD_ID, payloadId) put(MslRecipientTable.PAYLOAD_ID, payloadId)
put(RecipientTable.RECIPIENT_ID, recipientDevice.recipientId.serialize()) put(MslRecipientTable.RECIPIENT_ID, recipientDevice.recipientId.serialize())
put(RecipientTable.DEVICE, device) put(MslRecipientTable.DEVICE, device)
} }
} }
} }
SqlUtil.buildBulkInsert(RecipientTable.TABLE_NAME, arrayOf(RecipientTable.PAYLOAD_ID, RecipientTable.RECIPIENT_ID, RecipientTable.DEVICE), recipientValues) SqlUtil.buildBulkInsert(MslRecipientTable.TABLE_NAME, arrayOf(MslRecipientTable.PAYLOAD_ID, MslRecipientTable.RECIPIENT_ID, MslRecipientTable.DEVICE), recipientValues)
.forEach { query -> db.execSQL(query.where, query.whereArgs) } .forEach { query -> db.execSQL(query.where, query.whereArgs) }
val messageValues: MutableList<ContentValues> = mutableListOf() val messageValues: MutableList<ContentValues> = mutableListOf()
messageIds.forEach { messageId -> messageIds.forEach { messageId ->
messageValues += ContentValues().apply { messageValues += ContentValues().apply {
put(MessageTable.PAYLOAD_ID, payloadId) put(MslMessageTable.PAYLOAD_ID, payloadId)
put(MessageTable.MESSAGE_ID, messageId.id) put(MslMessageTable.MESSAGE_ID, messageId.id)
put(MessageTable.IS_MMS, 0)
} }
} }
SqlUtil.buildBulkInsert(MessageTable.TABLE_NAME, arrayOf(MessageTable.PAYLOAD_ID, MessageTable.MESSAGE_ID, MessageTable.IS_MMS), messageValues) SqlUtil.buildBulkInsert(MslMessageTable.TABLE_NAME, arrayOf(MslMessageTable.PAYLOAD_ID, MslMessageTable.MESSAGE_ID), messageValues)
.forEach { query -> db.execSQL(query.where, query.whereArgs) } .forEach { query -> db.execSQL(query.where, query.whereArgs) }
db.setTransactionSuccessful() db.setTransactionSuccessful()
@ -278,31 +275,31 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
trimOldMessages(System.currentTimeMillis(), FeatureFlags.retryRespondMaxAge()) trimOldMessages(System.currentTimeMillis(), FeatureFlags.retryRespondMaxAge())
val db = databaseHelper.signalReadableDatabase val db = databaseHelper.signalReadableDatabase
val table = "${PayloadTable.TABLE_NAME} LEFT JOIN ${RecipientTable.TABLE_NAME} ON ${PayloadTable.TABLE_NAME}.${PayloadTable.ID} = ${RecipientTable.TABLE_NAME}.${RecipientTable.PAYLOAD_ID}" val table = "${MslPayloadTable.TABLE_NAME} LEFT JOIN ${MslRecipientTable.TABLE_NAME} ON ${MslPayloadTable.TABLE_NAME}.${MslPayloadTable.ID} = ${MslRecipientTable.TABLE_NAME}.${MslRecipientTable.PAYLOAD_ID}"
val query = "${PayloadTable.DATE_SENT} = ? AND ${RecipientTable.RECIPIENT_ID} = ? AND ${RecipientTable.DEVICE} = ?" val query = "${MslPayloadTable.DATE_SENT} = ? AND ${MslRecipientTable.RECIPIENT_ID} = ? AND ${MslRecipientTable.DEVICE} = ?"
val args = SqlUtil.buildArgs(dateSent, recipientId, device) val args = SqlUtil.buildArgs(dateSent, recipientId, device)
db.query(table, null, query, args, null, null, null).use { entryCursor -> db.query(table, null, query, args, null, null, null).use { entryCursor ->
if (entryCursor.moveToFirst()) { if (entryCursor.moveToFirst()) {
val payloadId = CursorUtil.requireLong(entryCursor, RecipientTable.PAYLOAD_ID) val payloadId = CursorUtil.requireLong(entryCursor, MslRecipientTable.PAYLOAD_ID)
db.query(MessageTable.TABLE_NAME, null, "${MessageTable.PAYLOAD_ID} = ?", SqlUtil.buildArgs(payloadId), null, null, null).use { messageCursor -> db.query(MslMessageTable.TABLE_NAME, null, "${MslMessageTable.PAYLOAD_ID} = ?", SqlUtil.buildArgs(payloadId), null, null, null).use { messageCursor ->
val messageIds: MutableList<MessageId> = mutableListOf() val messageIds: MutableList<MessageId> = mutableListOf()
while (messageCursor.moveToNext()) { while (messageCursor.moveToNext()) {
messageIds.add( messageIds.add(
MessageId( MessageId(
id = CursorUtil.requireLong(messageCursor, MessageTable.MESSAGE_ID) id = CursorUtil.requireLong(messageCursor, MslMessageTable.MESSAGE_ID)
) )
) )
} }
return MessageLogEntry( return MessageLogEntry(
recipientId = RecipientId.from(CursorUtil.requireLong(entryCursor, RecipientTable.RECIPIENT_ID)), recipientId = RecipientId.from(CursorUtil.requireLong(entryCursor, MslRecipientTable.RECIPIENT_ID)),
dateSent = CursorUtil.requireLong(entryCursor, PayloadTable.DATE_SENT), dateSent = CursorUtil.requireLong(entryCursor, MslPayloadTable.DATE_SENT),
content = SignalServiceProtos.Content.parseFrom(CursorUtil.requireBlob(entryCursor, PayloadTable.CONTENT)), content = SignalServiceProtos.Content.parseFrom(CursorUtil.requireBlob(entryCursor, MslPayloadTable.CONTENT)),
contentHint = ContentHint.fromType(CursorUtil.requireInt(entryCursor, PayloadTable.CONTENT_HINT)), contentHint = ContentHint.fromType(CursorUtil.requireInt(entryCursor, MslPayloadTable.CONTENT_HINT)),
urgent = entryCursor.requireBoolean(PayloadTable.URGENT), urgent = entryCursor.requireBoolean(MslPayloadTable.URGENT),
relatedMessages = messageIds relatedMessages = messageIds
) )
} }
@ -312,14 +309,14 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
return null return null
} }
fun deleteAllRelatedToMessage(messageId: Long, mms: Boolean) { fun deleteAllRelatedToMessage(messageId: Long) {
if (!FeatureFlags.retryReceipts()) return if (!FeatureFlags.retryReceipts()) return
val db = databaseHelper.signalWritableDatabase val db = databaseHelper.signalWritableDatabase
val query = "${PayloadTable.ID} IN (SELECT ${MessageTable.PAYLOAD_ID} FROM ${MessageTable.TABLE_NAME} WHERE ${MessageTable.MESSAGE_ID} = ? AND ${MessageTable.IS_MMS} = ?)" val query = "${MslPayloadTable.ID} IN (SELECT ${MslMessageTable.PAYLOAD_ID} FROM ${MslMessageTable.TABLE_NAME} WHERE ${MslMessageTable.MESSAGE_ID} = ?)"
val args = SqlUtil.buildArgs(messageId, if (mms) 1 else 0) val args = SqlUtil.buildArgs(messageId)
db.delete(PayloadTable.TABLE_NAME, query, args) db.delete(MslPayloadTable.TABLE_NAME, query, args)
} }
fun deleteEntryForRecipient(dateSent: Long, recipientId: RecipientId, device: Int) { fun deleteEntryForRecipient(dateSent: Long, recipientId: RecipientId, device: Int) {
@ -336,19 +333,19 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
db.beginTransaction() db.beginTransaction()
try { try {
val query = """ val query = """
${RecipientTable.RECIPIENT_ID} = ? AND ${MslRecipientTable.RECIPIENT_ID} = ? AND
${RecipientTable.DEVICE} = ? AND ${MslRecipientTable.DEVICE} = ? AND
${RecipientTable.PAYLOAD_ID} IN ( ${MslRecipientTable.PAYLOAD_ID} IN (
SELECT ${PayloadTable.ID} SELECT ${MslPayloadTable.ID}
FROM ${PayloadTable.TABLE_NAME} FROM ${MslPayloadTable.TABLE_NAME}
WHERE ${PayloadTable.DATE_SENT} IN (${dateSent.joinToString(",")}) WHERE ${MslPayloadTable.DATE_SENT} IN (${dateSent.joinToString(",")})
)""" )"""
val args = SqlUtil.buildArgs(recipientId, device) val args = SqlUtil.buildArgs(recipientId, device)
db.delete(RecipientTable.TABLE_NAME, query, args) db.delete(MslRecipientTable.TABLE_NAME, query, args)
val cleanQuery = "${PayloadTable.ID} NOT IN (SELECT ${RecipientTable.PAYLOAD_ID} FROM ${RecipientTable.TABLE_NAME})" val cleanQuery = "${MslPayloadTable.ID} NOT IN (SELECT ${MslRecipientTable.PAYLOAD_ID} FROM ${MslRecipientTable.TABLE_NAME})"
db.delete(PayloadTable.TABLE_NAME, cleanQuery, null) db.delete(MslPayloadTable.TABLE_NAME, cleanQuery, null)
db.setTransactionSuccessful() db.setTransactionSuccessful()
} finally { } finally {
@ -359,29 +356,29 @@ class MessageSendLogTables constructor(context: Context?, databaseHelper: Signal
fun deleteAll() { fun deleteAll() {
if (!FeatureFlags.retryReceipts()) return if (!FeatureFlags.retryReceipts()) return
databaseHelper.signalWritableDatabase.delete(PayloadTable.TABLE_NAME, null, null) databaseHelper.signalWritableDatabase.delete(MslPayloadTable.TABLE_NAME, null, null)
} }
fun trimOldMessages(currentTime: Long, maxAge: Long) { fun trimOldMessages(currentTime: Long, maxAge: Long) {
if (!FeatureFlags.retryReceipts()) return if (!FeatureFlags.retryReceipts()) return
val db = databaseHelper.signalWritableDatabase val db = databaseHelper.signalWritableDatabase
val query = "${PayloadTable.DATE_SENT} < ?" val query = "${MslPayloadTable.DATE_SENT} < ?"
val args = SqlUtil.buildArgs(currentTime - maxAge) val args = SqlUtil.buildArgs(currentTime - maxAge)
db.delete(PayloadTable.TABLE_NAME, query, args) db.delete(MslPayloadTable.TABLE_NAME, query, args)
} }
override fun remapRecipient(oldRecipientId: RecipientId, newRecipientId: RecipientId) { override fun remapRecipient(oldRecipientId: RecipientId, newRecipientId: RecipientId) {
val values = ContentValues().apply { val values = ContentValues().apply {
put(RecipientTable.RECIPIENT_ID, newRecipientId.serialize()) put(MslRecipientTable.RECIPIENT_ID, newRecipientId.serialize())
} }
val db = databaseHelper.signalWritableDatabase val db = databaseHelper.signalWritableDatabase
val query = "${RecipientTable.RECIPIENT_ID} = ?" val query = "${MslRecipientTable.RECIPIENT_ID} = ?"
val args = SqlUtil.buildArgs(oldRecipientId.serialize()) val args = SqlUtil.buildArgs(oldRecipientId.serialize())
db.update(RecipientTable.TABLE_NAME, values, query, args) db.update(MslRecipientTable.TABLE_NAME, values, query, args)
} }
private data class RecipientDevice(val recipientId: RecipientId, val devices: List<Int>) private data class RecipientDevice(val recipientId: RecipientId, val devices: List<Int>)

Wyświetl plik

@ -1927,7 +1927,7 @@ public class MessageTable extends DatabaseTable implements MessageTypes, Recipie
deletedAttachments = SignalDatabase.attachments().deleteAttachmentsForMessage(messageId); deletedAttachments = SignalDatabase.attachments().deleteAttachmentsForMessage(messageId);
SignalDatabase.mentions().deleteMentionsForMessage(messageId); SignalDatabase.mentions().deleteMentionsForMessage(messageId);
SignalDatabase.messageLog().deleteAllRelatedToMessage(messageId, true); SignalDatabase.messageLog().deleteAllRelatedToMessage(messageId);
SignalDatabase.reactions().deleteReactions(new MessageId(messageId)); SignalDatabase.reactions().deleteReactions(new MessageId(messageId));
deleteGroupStoryReplies(messageId); deleteGroupStoryReplies(messageId);
disassociateStoryQuotes(messageId); disassociateStoryQuotes(messageId);

Wyświetl plik

@ -32,6 +32,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V173_ScheduledMessa
import org.thoughtcrime.securesms.database.helpers.migration.V174_ReactionForeignKeyMigration import org.thoughtcrime.securesms.database.helpers.migration.V174_ReactionForeignKeyMigration
import org.thoughtcrime.securesms.database.helpers.migration.V175_FixFullTextSearchLink import org.thoughtcrime.securesms.database.helpers.migration.V175_FixFullTextSearchLink
import org.thoughtcrime.securesms.database.helpers.migration.V176_AddScheduledDateToQuoteIndex import org.thoughtcrime.securesms.database.helpers.migration.V176_AddScheduledDateToQuoteIndex
import org.thoughtcrime.securesms.database.helpers.migration.V177_MessageSendLogTableCleanupMigration
/** /**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness. * Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
@ -40,7 +41,7 @@ object SignalDatabaseMigrations {
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass) val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
const val DATABASE_VERSION = 176 const val DATABASE_VERSION = 177
@JvmStatic @JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@ -155,6 +156,10 @@ object SignalDatabaseMigrations {
if (oldVersion < 176) { if (oldVersion < 176) {
V176_AddScheduledDateToQuoteIndex.migrate(context, db, oldVersion, newVersion) V176_AddScheduledDateToQuoteIndex.migrate(context, db, oldVersion, newVersion)
} }
if (oldVersion < 177) {
V177_MessageSendLogTableCleanupMigration.migrate(context, db, oldVersion, newVersion)
}
} }
@JvmStatic @JvmStatic

Wyświetl plik

@ -0,0 +1,79 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Removes the is_mms column from the MSL tables and fixes the triggers.
*/
@Suppress("ClassName")
object V177_MessageSendLogTableCleanupMigration : SignalDatabaseMigration {
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
// Delete old stuff
db.execSQL("DROP TRIGGER IF EXISTS msl_mms_delete")
db.execSQL("DROP TRIGGER IF EXISTS msl_attachment_delete")
db.execSQL("DROP INDEX IF EXISTS msl_message_message_index")
// Cleanup dangling messages
db.execSQL(
"""
DELETE FROM msl_payload
WHERE _id IN (
SELECT payload_id
FROM msl_message
WHERE message_id NOT IN (
SELECT _id
FROM message
)
)
"""
)
// Recreate msl_message table without an is_mms column
db.execSQL(
"""
CREATE TABLE msl_message_tmp (
_id INTEGER PRIMARY KEY,
payload_id INTEGER NOT NULL REFERENCES msl_payload (_id) ON DELETE CASCADE,
message_id INTEGER NOT NULL
)
"""
)
db.execSQL(
"""
INSERT INTO msl_message_tmp
SELECT
_id,
payload_id,
message_id
FROM msl_message
"""
)
db.execSQL("DROP TABLE msl_message")
db.execSQL("ALTER TABLE msl_message_tmp RENAME TO msl_message")
// Recreate the indexes
db.execSQL("CREATE INDEX msl_message_message_index ON msl_message (message_id, payload_id)")
// Recreate the triggers
db.execSQL(
"""
CREATE TRIGGER msl_message_delete AFTER DELETE ON message
BEGIN
DELETE FROM msl_payload WHERE _id IN (SELECT payload_id FROM msl_message WHERE message_id = old._id);
END
"""
)
db.execSQL(
"""
CREATE TRIGGER msl_attachment_delete AFTER DELETE ON part
BEGIN
DELETE FROM msl_payload WHERE _id IN (SELECT payload_id FROM msl_message WHERE message_id = old.mid);
END
"""
)
}
}