diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteBackup.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteBackup.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteBackup.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteBackup.cpp @@ -29,6 +29,8 @@ "backup_entries", "backup_message_store_local", "holders", + "dm_operations", + "queued_dm_operations", }; void SQLiteBackup::cleanupDatabaseExceptAllowlist(sqlite3 *db) { diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -18,6 +18,7 @@ #include "entities/SQLiteDataConverters.h" #include "entities/SyncedMetadataEntry.h" #include "entities/UserInfo.h" +#include #include #include #include @@ -1731,6 +1732,12 @@ SQLiteBackup::tablesAllowlist.begin(), SQLiteBackup::tablesAllowlist.end()); + // Remove queued_dm_operations from tableNames since it needs special handling + // due to autoincrement ID column. + tableNames.erase( + std::remove(tableNames.begin(), tableNames.end(), "queued_dm_operations"), + tableNames.end()); + if (!SQLiteUtils::fileExists(sourceDatabasePath)) { std::stringstream errorMessage; errorMessage << "Error: Source file does not exist at path: " @@ -1752,6 +1759,13 @@ << " FROM sourceDB." << tableName << ";" << std::endl; } + // Handle queued_dm_operations separately since it has an autoincrement ID + // We need to insert without the ID column to let SQLite generate new IDs. + sql << "INSERT OR IGNORE INTO queued_dm_operations " + << " (queue_type, queue_key, operation_data, timestamp) " + << "SELECT queue_type, queue_key, operation_data, timestamp " + << "FROM sourceDB.queued_dm_operations;" << std::endl; + // There is a similar code for "live" index processing. Before making any // changes here, please reference `getMessageSearchStoreOps` in // `lib/reducers/db-ops-reducer.js`. diff --git a/web/shared-worker/_generated/comm_query_executor.wasm b/web/shared-worker/_generated/comm_query_executor.wasm index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@ { + // Test operations to add to backup database + const testOperations = [ + { + queueType: 'thread', + queueKey: 'thread123', + operationData: '{"type":"send_text_message","text":"Hello"}', + timestamp: '1642500000000', + }, + { + queueType: 'membership', + queueKey: 'thread456#user789', + operationData: '{"type":"add_members","userIDs":["user789"]}', + timestamp: '1642500001000', + }, + { + queueType: 'message', + queueKey: 'msg101', + operationData: '{"type":"send_reaction","reaction":"👍"}', + timestamp: '1642500002000', + }, + ]; + + // Add operations to backup database + testOperations.forEach(op => { + backupQueryExecutor.addQueuedDMOperation(op); + }); + + // Verify operations exist in backup + const backupOperations = backupQueryExecutor.getQueuedDMOperations(); + expect(backupOperations.length).toBe(3); + + // Verify main database is empty + let mainOperations = mainQueryExecutor.getQueuedDMOperations(); + expect(mainOperations.length).toBe(0); + + // Copy content from backup to main + mainQueryExecutor.copyContentFromDatabase(BACKUP_FILE_PATH, null); + + // Verify operations were copied to main database + mainOperations = mainQueryExecutor.getQueuedDMOperations(); + expect(mainOperations.length).toBe(3); + }); });