Add in possible recovery for DB error handler.
A bad FTS index can result in the corruption handler being triggered. We can attempt to rebuild it to see if that helps.
This commit is contained in:
parent
66cb2a04c3
commit
431e366e76
2 changed files with 42 additions and 3 deletions
|
@ -34,20 +34,24 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
"CREATE VIRTUAL TABLE $FTS_TABLE_NAME USING fts5($BODY, $THREAD_ID UNINDEXED, content=${MessageTable.TABLE_NAME}, content_rowid=${MessageTable.ID})"
|
||||
)
|
||||
|
||||
private const val TRIGGER_AFTER_INSERT = "message_ai"
|
||||
private const val TRIGGER_AFTER_DELETE = "message_ad"
|
||||
private const val TRIGGER_AFTER_UPDATE = "message_au"
|
||||
|
||||
@Language("sql")
|
||||
val CREATE_TRIGGERS = arrayOf(
|
||||
"""
|
||||
CREATE TRIGGER message_ai AFTER INSERT ON ${MessageTable.TABLE_NAME} BEGIN
|
||||
CREATE TRIGGER $TRIGGER_AFTER_INSERT 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 message_ad AFTER DELETE ON ${MessageTable.TABLE_NAME} BEGIN
|
||||
CREATE TRIGGER $TRIGGER_AFTER_DELETE 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 message_au AFTER UPDATE ON ${MessageTable.TABLE_NAME} BEGIN
|
||||
CREATE TRIGGER $TRIGGER_AFTER_UPDATE 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;
|
||||
|
@ -217,6 +221,32 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Drops all tables and recreates them. Should only be done in extreme circumstances.
|
||||
*/
|
||||
fun fullyResetTables() {
|
||||
Log.w(TAG, "[fullyResetTables] Dropping tables and triggers...")
|
||||
writableDatabase.execSQL("DROP TABLE IF EXISTS $FTS_TABLE_NAME")
|
||||
writableDatabase.execSQL("DROP TABLE IF EXISTS ${FTS_TABLE_NAME}_config")
|
||||
writableDatabase.execSQL("DROP TABLE IF EXISTS ${FTS_TABLE_NAME}_content")
|
||||
writableDatabase.execSQL("DROP TABLE IF EXISTS ${FTS_TABLE_NAME}_data")
|
||||
writableDatabase.execSQL("DROP TABLE IF EXISTS ${FTS_TABLE_NAME}_idx")
|
||||
writableDatabase.execSQL("DROP TRIGGER IF EXISTS $TRIGGER_AFTER_INSERT")
|
||||
writableDatabase.execSQL("DROP TRIGGER IF EXISTS $TRIGGER_AFTER_DELETE")
|
||||
writableDatabase.execSQL("DROP TRIGGER IF EXISTS $TRIGGER_AFTER_UPDATE")
|
||||
|
||||
Log.w(TAG, "[fullyResetTables] Recreating table...")
|
||||
CREATE_TABLE.forEach { writableDatabase.execSQL(it) }
|
||||
|
||||
Log.w(TAG, "[fullyResetTables] Recreating triggers...")
|
||||
CREATE_TRIGGERS.forEach { writableDatabase.execSQL(it) }
|
||||
|
||||
Log.w(TAG, "[fullyResetTables] Rebuilding index...")
|
||||
rebuildIndex()
|
||||
|
||||
Log.w(TAG, "[fullyResetTables] Done")
|
||||
}
|
||||
|
||||
private fun createFullTextSearchQuery(query: String): String {
|
||||
return query
|
||||
.split(" ")
|
||||
|
|
|
@ -30,6 +30,7 @@ class SqlCipherErrorHandler(private val databaseName: String) : DatabaseErrorHan
|
|||
|
||||
if (result is DiagnosticResults.Success) {
|
||||
if (result.pragma1Passes && result.pragma2Passes) {
|
||||
attemptToClearFullTextSearchIndex()
|
||||
throw DatabaseCorruptedError_BothChecksPass(lines)
|
||||
} else if (!result.pragma1Passes && result.pragma2Passes) {
|
||||
throw DatabaseCorruptedError_NormalCheckFailsCipherCheckPasses(lines)
|
||||
|
@ -138,6 +139,14 @@ class SqlCipherErrorHandler(private val databaseName: String) : DatabaseErrorHan
|
|||
}
|
||||
}
|
||||
|
||||
private fun attemptToClearFullTextSearchIndex() {
|
||||
try {
|
||||
SignalDatabase.messageSearch.fullyResetTables()
|
||||
} catch (e: Throwable) {
|
||||
Log.w(TAG, "Failed to clear full text search index.", e)
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class DiagnosticResults(val logs: String) {
|
||||
class Success(
|
||||
val pragma1Passes: Boolean,
|
||||
|
|
Loading…
Add table
Reference in a new issue