Fix full text search migration after table name change.

main
Greyson Parrelli 2023-01-26 18:59:30 -05:00
rodzic 22a4271dfb
commit fe40e37da4
6 zmienionych plików z 87 dodań i 32 usunięć

Wyświetl plik

@ -97,7 +97,7 @@ public class FullBackupExporter extends FullBackupBase {
SignedPreKeyTable.TABLE_NAME,
OneTimePreKeyTable.TABLE_NAME,
SessionTable.TABLE_NAME,
SearchTable.MMS_FTS_TABLE_NAME,
SearchTable.FTS_TABLE_NAME,
EmojiSearchTable.TABLE_NAME,
SenderKeyTable.TABLE_NAME,
SenderKeySharedTable.TABLE_NAME,
@ -368,7 +368,7 @@ public class FullBackupExporter extends FullBackupBase {
}
boolean isReservedTable = table.startsWith("sqlite_");
boolean isMmsFtsSecretTable = !table.equals(SearchTable.MMS_FTS_TABLE_NAME) && table.startsWith(SearchTable.MMS_FTS_TABLE_NAME);
boolean isMmsFtsSecretTable = !table.equals(SearchTable.FTS_TABLE_NAME) && table.startsWith(SearchTable.FTS_TABLE_NAME);
boolean isEmojiFtsSecretTable = !table.equals(EmojiSearchTable.TABLE_NAME) && table.startsWith(EmojiSearchTable.TABLE_NAME);
return !isReservedTable &&

Wyświetl plik

@ -127,7 +127,7 @@ public class FullBackupImporter extends FullBackupBase {
}
private static void processStatement(@NonNull SQLiteDatabase db, SqlStatement statement) {
boolean isForMmsFtsSecretTable = statement.getStatement().contains(SearchTable.MMS_FTS_TABLE_NAME + "_");
boolean isForMmsFtsSecretTable = statement.getStatement().contains(SearchTable.FTS_TABLE_NAME + "_");
boolean isForEmojiSecretTable = statement.getStatement().contains(EmojiSearchTable.TABLE_NAME + "_");
boolean isForSqliteSecretTable = statement.getStatement().toLowerCase().startsWith("create table sqlite_");

Wyświetl plik

@ -18,7 +18,7 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
companion object {
private val TAG = Log.tag(SearchTable::class.java)
const val MMS_FTS_TABLE_NAME = "mms_fts"
const val FTS_TABLE_NAME = "message_fts"
const val ID = "rowid"
const val BODY = MessageTable.BODY
const val THREAD_ID = MessageTable.THREAD_ID
@ -31,25 +31,25 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
@Language("sql")
val CREATE_TABLE = arrayOf(
"CREATE VIRTUAL TABLE $MMS_FTS_TABLE_NAME USING fts5($BODY, $THREAD_ID UNINDEXED, content=${MessageTable.TABLE_NAME}, content_rowid=${MessageTable.ID})",
"CREATE VIRTUAL TABLE $FTS_TABLE_NAME USING fts5($BODY, $THREAD_ID UNINDEXED, content=${MessageTable.TABLE_NAME}, content_rowid=${MessageTable.ID})",
)
@Language("sql")
val CREATE_TRIGGERS = arrayOf(
"""
CREATE TRIGGER mms_ai AFTER INSERT ON ${MessageTable.TABLE_NAME} BEGIN
INSERT INTO $MMS_FTS_TABLE_NAME($ID, $BODY, $THREAD_ID) VALUES (new.${MessageTable.ID}, new.${MessageTable.BODY}, new.${MessageTable.THREAD_ID});
CREATE TRIGGER message_ai AFTER INSERT ON ${MessageTable.TABLE_NAME} BEGIN
INSERT INTO $FTS_TABLE_NAME($ID, $BODY, $THREAD_ID) VALUES (new.${MessageTable.ID}, new.${MessageTable.BODY}, new.${MessageTable.THREAD_ID});
END;
""",
"""
CREATE TRIGGER mms_ad AFTER DELETE ON ${MessageTable.TABLE_NAME} BEGIN
INSERT INTO $MMS_FTS_TABLE_NAME($MMS_FTS_TABLE_NAME, $ID, $BODY, $THREAD_ID) VALUES('delete', old.${MessageTable.ID}, old.${MessageTable.BODY}, old.${MessageTable.THREAD_ID});
CREATE TRIGGER message_ad AFTER DELETE ON ${MessageTable.TABLE_NAME} BEGIN
INSERT INTO $FTS_TABLE_NAME($FTS_TABLE_NAME, $ID, $BODY, $THREAD_ID) VALUES('delete', old.${MessageTable.ID}, old.${MessageTable.BODY}, old.${MessageTable.THREAD_ID});
END;
""",
"""
CREATE TRIGGER mms_au AFTER UPDATE ON ${MessageTable.TABLE_NAME} BEGIN
INSERT INTO $MMS_FTS_TABLE_NAME($MMS_FTS_TABLE_NAME, $ID, $BODY, $THREAD_ID) VALUES('delete', old.${MessageTable.ID}, old.${MessageTable.BODY}, old.${MessageTable.THREAD_ID});
INSERT INTO $MMS_FTS_TABLE_NAME($ID, $BODY, $THREAD_ID) VALUES (new.${MessageTable.ID}, new.${MessageTable.BODY}, new.${MessageTable.THREAD_ID});
CREATE TRIGGER message_au AFTER UPDATE ON ${MessageTable.TABLE_NAME} BEGIN
INSERT INTO $FTS_TABLE_NAME($FTS_TABLE_NAME, $ID, $BODY, $THREAD_ID) VALUES('delete', old.${MessageTable.ID}, old.${MessageTable.BODY}, old.${MessageTable.THREAD_ID});
INSERT INTO $FTS_TABLE_NAME($ID, $BODY, $THREAD_ID) VALUES (new.${MessageTable.ID}, new.${MessageTable.BODY}, new.${MessageTable.THREAD_ID});
END;
"""
)
@ -59,18 +59,18 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
SELECT
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AS $CONVERSATION_RECIPIENT,
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
snippet($MMS_FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
snippet($FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
$MMS_FTS_TABLE_NAME.$THREAD_ID,
$MMS_FTS_TABLE_NAME.$BODY,
$MMS_FTS_TABLE_NAME.$ID AS $MESSAGE_ID,
$FTS_TABLE_NAME.$THREAD_ID,
$FTS_TABLE_NAME.$BODY,
$FTS_TABLE_NAME.$ID AS $MESSAGE_ID,
1 AS $IS_MMS
FROM
${MessageTable.TABLE_NAME}
INNER JOIN $MMS_FTS_TABLE_NAME ON $MMS_FTS_TABLE_NAME.$ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
INNER JOIN ${ThreadTable.TABLE_NAME} ON $MMS_FTS_TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID}
INNER JOIN $FTS_TABLE_NAME ON $FTS_TABLE_NAME.$ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
INNER JOIN ${ThreadTable.TABLE_NAME} ON $FTS_TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID}
WHERE
$MMS_FTS_TABLE_NAME MATCH ? AND
$FTS_TABLE_NAME MATCH ? AND
${MessageTable.TABLE_NAME}.${MessageTable.TYPE} & ${MessageTypes.GROUP_V2_BIT} = 0 AND
${MessageTable.TABLE_NAME}.${MessageTable.TYPE} & ${MessageTypes.SPECIAL_TYPE_PAYMENTS_NOTIFICATION} = 0
ORDER BY ${MessageTable.DATE_RECEIVED} DESC
@ -82,18 +82,18 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
SELECT
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AS $CONVERSATION_RECIPIENT,
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
snippet($MMS_FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
snippet($FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
$MMS_FTS_TABLE_NAME.$THREAD_ID,
$MMS_FTS_TABLE_NAME.$BODY,
$MMS_FTS_TABLE_NAME.$ID AS $MESSAGE_ID,
$FTS_TABLE_NAME.$THREAD_ID,
$FTS_TABLE_NAME.$BODY,
$FTS_TABLE_NAME.$ID AS $MESSAGE_ID,
1 AS $IS_MMS
FROM
${MessageTable.TABLE_NAME}
INNER JOIN $MMS_FTS_TABLE_NAME ON $MMS_FTS_TABLE_NAME.$ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
INNER JOIN ${ThreadTable.TABLE_NAME} ON $MMS_FTS_TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID}
INNER JOIN $FTS_TABLE_NAME ON $FTS_TABLE_NAME.$ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
INNER JOIN ${ThreadTable.TABLE_NAME} ON $FTS_TABLE_NAME.$THREAD_ID = ${ThreadTable.TABLE_NAME}.${ThreadTable.ID}
WHERE
$MMS_FTS_TABLE_NAME MATCH ? AND
$FTS_TABLE_NAME MATCH ? AND
${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID} = ?
ORDER BY ${MessageTable.DATE_RECEIVED} DESC
LIMIT 500
@ -136,7 +136,7 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
Log.i(TAG, "Reindexing ID's [$i, ${i + batchSize})")
writableDatabase.execSQL(
"""
INSERT INTO $MMS_FTS_TABLE_NAME ($ID, $BODY)
INSERT INTO $FTS_TABLE_NAME ($ID, $BODY)
SELECT
${MessageTable.ID},
${MessageTable.BODY}
@ -180,10 +180,10 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
writableDatabase.withinTransaction { db ->
// Note the negative page size -- see sqlite docs ref'd in kdoc
db.execSQL("INSERT INTO $MMS_FTS_TABLE_NAME ($MMS_FTS_TABLE_NAME, rank) values ('merge', -$pageSize)")
db.execSQL("INSERT INTO $FTS_TABLE_NAME ($FTS_TABLE_NAME, rank) values ('merge', -$pageSize)")
var previousCount = SqlUtil.getTotalChanges(db)
val iterativeStatement = db.compileStatement("INSERT INTO $MMS_FTS_TABLE_NAME ($MMS_FTS_TABLE_NAME, rank) values ('merge', $pageSize)")
val iterativeStatement = db.compileStatement("INSERT INTO $FTS_TABLE_NAME ($FTS_TABLE_NAME, rank) values ('merge', $pageSize)")
iterativeStatement.execute()
var count = SqlUtil.getTotalChanges(db)

Wyświetl plik

@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V171_ThreadForeignK
import org.thoughtcrime.securesms.database.helpers.migration.V172_GroupMembershipMigration
import org.thoughtcrime.securesms.database.helpers.migration.V173_ScheduledMessagesMigration
import org.thoughtcrime.securesms.database.helpers.migration.V174_ReactionForeignKeyMigration
import org.thoughtcrime.securesms.database.helpers.migration.V175_FixFullTextSearchLink
/**
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
@ -38,7 +39,7 @@ object SignalDatabaseMigrations {
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
const val DATABASE_VERSION = 174
const val DATABASE_VERSION = 175
@JvmStatic
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
@ -145,6 +146,10 @@ object SignalDatabaseMigrations {
if (oldVersion < 174) {
V174_ReactionForeignKeyMigration.migrate(context, db, oldVersion, newVersion)
}
if (oldVersion < 175) {
V175_FixFullTextSearchLink.migrate(context, db, oldVersion, newVersion)
}
}
@JvmStatic

Wyświetl plik

@ -0,0 +1,45 @@
package org.thoughtcrime.securesms.database.helpers.migration
import android.app.Application
import net.zetetic.database.sqlcipher.SQLiteDatabase
/**
* Turns out renaming a table will automatically update all of your indexes, foreign keys, triggers, basically everything... except full-text search tables.
* So we have to delete it and rebuild it.
*/
@Suppress("ClassName")
object V175_FixFullTextSearchLink : SignalDatabaseMigration {
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
db.execSQL("DROP TABLE mms_fts")
db.execSQL("DROP TRIGGER IF EXISTS mms_ai")
db.execSQL("DROP TRIGGER IF EXISTS mms_ad")
db.execSQL("DROP TRIGGER IF EXISTS mms_au")
db.execSQL("CREATE VIRTUAL TABLE message_fts USING fts5(body, thread_id UNINDEXED, content=message, content_rowid=_id)")
db.execSQL(
"""
CREATE TRIGGER message_ai AFTER INSERT ON message BEGIN
INSERT INTO message_fts(rowid, body, thread_id) VALUES (new._id, new.body, new.thread_id);
END;
"""
)
db.execSQL(
"""
CREATE TRIGGER message_ad AFTER DELETE ON message BEGIN
INSERT INTO message_fts(message_fts, rowid, body, thread_id) VALUES ('delete', old._id, old.body, old.thread_id);
END;
"""
)
db.execSQL(
"""
CREATE TRIGGER message_au AFTER UPDATE ON message BEGIN
INSERT INTO message_fts(message_fts, rowid, body, thread_id) VALUES('delete', old._id, old.body, old.thread_id);
INSERT INTO message_fts(rowid, body, thread_id) VALUES (new._id, new.body, new.thread_id);
END;
"""
)
}
}

Wyświetl plik

@ -117,9 +117,10 @@ public class ApplicationMigrations {
static final int UPDATE_SMS_JOBS = 73;
static final int OPTIMIZE_MESSAGE_FTS_INDEX = 74;
static final int REACTION_DATABASE_MIGRATION = 75;
static final int REBUILD_MESSAGE_FTS_INDEX_2 = 76;
}
public static final int CURRENT_VERSION = 75;
public static final int CURRENT_VERSION = 76;
/**
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
@ -521,6 +522,10 @@ public class ApplicationMigrations {
jobs.put(Version.REACTION_DATABASE_MIGRATION, new DatabaseMigrationJob());
}
if (lastSeenVersion < Version.REBUILD_MESSAGE_FTS_INDEX_2) {
jobs.put(Version.REBUILD_MESSAGE_FTS_INDEX_2, new RebuildMessageSearchIndexMigrationJob());
}
return jobs;
}