diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h --- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h @@ -8,6 +8,7 @@ #include "entities/InboundP2PMessage.h" #include "entities/IntegrityThreadHash.h" #include "entities/KeyserverInfo.h" +#include "entities/LocalMessageInfo.h" #include "entities/Message.h" #include "entities/MessageStoreThread.h" #include "entities/OlmPersistAccount.h" @@ -113,6 +114,13 @@ virtual void removeEntries(const std::vector &ids) const = 0; virtual void removeAllEntries() const = 0; virtual std::vector getAllEntries() const = 0; + virtual void replaceMessageStoreLocalMessageInfo( + const LocalMessageInfo &local_message_info) const = 0; + virtual void removeMessageStoreLocalMessageInfos( + const std::vector &ids) const = 0; + virtual void removeAllMessageStoreLocalMessageInfos() const = 0; + virtual std::vector + getAllMessageStoreLocalMessageInfos() const = 0; virtual void beginTransaction() const = 0; virtual void commitTransaction() const = 0; virtual void rollbackTransaction() const = 0; diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h @@ -8,6 +8,7 @@ #include "entities/Draft.h" #include "entities/IntegrityThreadHash.h" #include "entities/KeyserverInfo.h" +#include "entities/LocalMessageInfo.h" #include "entities/ThreadActivityEntry.h" #include "entities/UserInfo.h" @@ -126,6 +127,13 @@ void removeEntries(const std::vector &ids) const override; void removeAllEntries() const override; std::vector getAllEntries() const override; + void replaceMessageStoreLocalMessageInfo( + const LocalMessageInfo &local_message_info) const override; + void removeMessageStoreLocalMessageInfos( + const std::vector &ids) const override; + void removeAllMessageStoreLocalMessageInfos() const override; + virtual std::vector + getAllMessageStoreLocalMessageInfos() const override; void beginTransaction() const override; void commitTransaction() const override; void rollbackTransaction() const override; 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 @@ -6,6 +6,7 @@ #include "entities/EntryInfo.h" #include "entities/IntegrityThreadHash.h" #include "entities/KeyserverInfo.h" +#include "entities/LocalMessageInfo.h" #include "entities/Metadata.h" #include "entities/SyncedMetadataEntry.h" #include "entities/UserInfo.h" @@ -2034,6 +2035,51 @@ SQLiteQueryExecutor::getConnection(), getAllEntriesSQL); } +void SQLiteQueryExecutor::replaceMessageStoreLocalMessageInfo( + const LocalMessageInfo &local_message_info) const { + static std::string replaceLocalMessageInfoSQL = + "REPLACE INTO message_store_local (id, local_message_info) " + "VALUES (?, ?);"; + replaceEntity( + SQLiteQueryExecutor::getConnection(), + replaceLocalMessageInfoSQL, + local_message_info); +} + +void SQLiteQueryExecutor::removeMessageStoreLocalMessageInfos( + const std::vector &ids) const { + if (!ids.size()) { + return; + } + + std::stringstream removeLocalMessageInfosByKeysSQLStream; + removeLocalMessageInfosByKeysSQLStream << "DELETE FROM message_store_local " + "WHERE id IN " + << getSQLStatementArray(ids.size()) + << ";"; + + removeEntitiesByKeys( + SQLiteQueryExecutor::getConnection(), + removeLocalMessageInfosByKeysSQLStream.str(), + ids); +} + +void SQLiteQueryExecutor::removeAllMessageStoreLocalMessageInfos() const { + static std::string removeAllLocalMessageInfosSQL = + "DELETE FROM message_store_local;"; + removeAllEntities( + SQLiteQueryExecutor::getConnection(), removeAllLocalMessageInfosSQL); +} + +std::vector +SQLiteQueryExecutor::getAllMessageStoreLocalMessageInfos() const { + static std::string getAllLocalMessageInfosSQL = + "SELECT * " + "FROM message_store_local;"; + return getAllEntities( + SQLiteQueryExecutor::getConnection(), getAllLocalMessageInfosSQL); +} + void SQLiteQueryExecutor::beginTransaction() const { executeQuery(SQLiteQueryExecutor::getConnection(), "BEGIN TRANSACTION;"); } diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/LocalMessageInfo.h b/native/cpp/CommonCpp/DatabaseManagers/entities/LocalMessageInfo.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/DatabaseManagers/entities/LocalMessageInfo.h @@ -0,0 +1,24 @@ +#pragma once + +#include "SQLiteDataConverters.h" +#include +#include + +namespace comm { + +struct LocalMessageInfo { + std::string id; + std::string local_message_info; + + static LocalMessageInfo fromSQLResult(sqlite3_stmt *sqlRow, int idx) { + return LocalMessageInfo{ + getStringFromSQLRow(sqlRow, idx), getStringFromSQLRow(sqlRow, idx + 1)}; + } + + int bindToSQL(sqlite3_stmt *sql, int idx) const { + bindStringToSQL(id, sql, idx); + return bindStringToSQL(local_message_info, sql, idx + 1); + } +}; + +} // namespace comm diff --git a/web/cpp/SQLiteQueryExecutorBindings.cpp b/web/cpp/SQLiteQueryExecutorBindings.cpp --- a/web/cpp/SQLiteQueryExecutorBindings.cpp +++ b/web/cpp/SQLiteQueryExecutorBindings.cpp @@ -71,6 +71,9 @@ value_object("EntryInfo") .field("id", &EntryInfo::id) .field("entry", &EntryInfo::entry); + value_object("LocalMessageInfo") + .field("id", &LocalMessageInfo::id) + .field("localMessageInfo", &LocalMessageInfo::local_message_info); value_object("WebThread") .field("id", &WebThread::id) @@ -245,6 +248,11 @@ .function("removeEntries", &SQLiteQueryExecutor::removeEntries) .function("removeAllEntries", &SQLiteQueryExecutor::removeAllEntries) .function("getAllEntries", &SQLiteQueryExecutor::getAllEntries) + .function("replaceMessageStoreLocalMessageInfo", &SQLiteQueryExecutor::replaceMessageStoreLocalMessageInfo) + .function("removeMessageStoreLocalMessageInfos", &SQLiteQueryExecutor::removeMessageStoreLocalMessageInfos) + .function( + "removeAllMessageStoreLocalMessageInfos", &SQLiteQueryExecutor::removeAllMessageStoreLocalMessageInfos) + .function("getAllMessageStoreLocalMessageInfos", &SQLiteQueryExecutor::getAllMessageStoreLocalMessageInfos) .function("beginTransaction", &SQLiteQueryExecutor::beginTransaction) .function("commitTransaction", &SQLiteQueryExecutor::commitTransaction) .function( 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$@ { + let queryExecutor; + let dbModule; + + beforeAll(async () => { + dbModule = getDatabaseModule(); + }); + + beforeEach(() => { + if (!dbModule) { + throw new Error('Database module is missing'); + } + queryExecutor = new dbModule.SQLiteQueryExecutor(FILE_PATH); + if (!queryExecutor) { + throw new Error('SQLiteQueryExecutor is missing'); + } + queryExecutor.replaceMessageStoreLocalMessageInfo({ + id: '1', + localMessageInfo: JSON.stringify({}), + }); + queryExecutor.replaceMessageStoreLocalMessageInfo({ + id: '2', + localMessageInfo: JSON.stringify({ sendFailed: '1' }), + }); + queryExecutor.replaceMessageStoreLocalMessageInfo({ + id: '3', + localMessageInfo: JSON.stringify({ sendFailed: '0' }), + }); + queryExecutor.replaceMessageStoreLocalMessageInfo({ + id: '4', + localMessageInfo: JSON.stringify({ sendFailed: '1' }), + }); + }); + + afterEach(() => { + clearSensitiveData(dbModule, FILE_PATH, queryExecutor); + }); + + it('should return all message store local message infos', () => { + const local = queryExecutor.getAllMessageStoreLocalMessageInfos(); + expect(local.length).toBe(4); + }); + + it('should remove all message store local message infos', () => { + queryExecutor.removeAllMessageStoreLocalMessageInfos(); + const local = queryExecutor.getAllMessageStoreLocalMessageInfos(); + expect(local.length).toBe(0); + }); + + it('should remove a subset of message store local message infos', () => { + queryExecutor.removeMessageStoreLocalMessageInfos(['2', '3']); + const local = queryExecutor.getAllMessageStoreLocalMessageInfos(); + expect(local.length).toBe(2); + }); +}); diff --git a/web/shared-worker/types/sqlite-query-executor.js b/web/shared-worker/types/sqlite-query-executor.js --- a/web/shared-worker/types/sqlite-query-executor.js +++ b/web/shared-worker/types/sqlite-query-executor.js @@ -10,6 +10,7 @@ import type { ClientDBThreadActivityEntry } from 'lib/ops/thread-activity-store-ops.js'; import type { ClientDBUserInfo } from 'lib/ops/user-store-ops.js'; import type { ClientDBDraftInfo } from 'lib/types/draft-types.js'; +import type { ClientDBLocalMessageInfo } from 'lib/types/message-types.js'; import type { OutboundP2PMessage, InboundP2PMessage, @@ -145,6 +146,13 @@ removeAllEntries(): void; getAllEntries(): $ReadOnlyArray; + replaceMessageStoreLocalMessageInfo( + localMessageInfo: ClientDBLocalMessageInfo, + ): void; + removeMessageStoreLocalMessageInfos(ids: $ReadOnlyArray): void; + removeAllMessageStoreLocalMessageInfos(): void; + getAllMessageStoreLocalMessageInfos(): ClientDBLocalMessageInfo[]; + beginTransaction(): void; commitTransaction(): void; rollbackTransaction(): void;