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 @@ -3,6 +3,7 @@ #include "../CryptoTools/Persist.h" #include "entities/AuxUserInfo.h" #include "entities/CommunityInfo.h" +#include "entities/DMOperation.h" #include "entities/Draft.h" #include "entities/EntryInfo.h" #include "entities/InboundP2PMessage.h" @@ -190,6 +191,13 @@ std::optional<std::string> messageIDCursor) const = 0; virtual std::vector<MessageEntity> getRelatedMessagesForSearch( const std::vector<std::string> &messageIDs) const = 0; + virtual void replaceDMOperation(const DMOperation &operation) const = 0; + virtual void removeAllDMOperations() const = 0; + virtual void + removeDMOperations(const std::vector<std::string> &ids) const = 0; + virtual std::vector<DMOperation> getDMOperations() const = 0; + virtual std::vector<DMOperation> + getDMOperationsByType(const std::string &operationType) const = 0; virtual ~DatabaseQueryExecutor() = default; #ifdef EMSCRIPTEN 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 @@ -5,6 +5,7 @@ #include "NativeSQLiteConnectionManager.h" #include "entities/AuxUserInfo.h" #include "entities/CommunityInfo.h" +#include "entities/DMOperation.h" #include "entities/Draft.h" #include "entities/IntegrityThreadHash.h" #include "entities/KeyserverInfo.h" @@ -204,6 +205,12 @@ std::optional<std::string> messageIDCursor) const override; std::vector<MessageEntity> getRelatedMessagesForSearch( const std::vector<std::string> &messageIDs) const override; + void replaceDMOperation(const DMOperation &operation) const override; + void removeAllDMOperations() const override; + void removeDMOperations(const std::vector<std::string> &ids) const override; + std::vector<DMOperation> getDMOperations() const override; + std::vector<DMOperation> + getDMOperationsByType(const std::string &operationType) const override; #ifdef EMSCRIPTEN std::vector<WebThread> getAllThreadsWeb() 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 @@ -824,6 +824,19 @@ return false; } +bool create_dm_operations_table(sqlite3 *db) { + std::string query = + "CREATE TABLE IF NOT EXISTS dm_operations (" + " id TEXT PRIMARY KEY," + " type TEXT NOT NULL," + " operation TEXT NOT NULL" + ");" + "CREATE INDEX IF NOT EXISTS dm_operations_idx_type" + " ON dm_operations (type);"; + + return create_table(db, query, "dm_operations"); +} + bool create_schema(sqlite3 *db) { char *error; int sidebarSourceTypeInt = static_cast<int>(MessageType::SIDEBAR_SOURCE); @@ -998,6 +1011,12 @@ " tokenize = porter" ");" + "CREATE TABLE IF NOT EXISTS dm_operations (" + " id TEXT PRIMARY KEY," + " type TEXT NOT NULL," + " operation TEXT NOT NULL" + ");" + "CREATE INDEX IF NOT EXISTS media_idx_container" " ON media (container);" @@ -1008,7 +1027,10 @@ " ON messages (target_message, type, time);" "CREATE INDEX IF NOT EXISTS outbound_p2p_messages_idx_id_timestamp" - " ON outbound_p2p_messages (device_id, timestamp);"; + " ON outbound_p2p_messages (device_id, timestamp);" + + "CREATE INDEX IF NOT EXISTS dm_operations_idx_type" + " ON dm_operations (type);"; sqlite3_exec(db, query.c_str(), nullptr, nullptr, &error); @@ -1261,7 +1283,8 @@ {50, {create_message_search_table, true}}, {51, {update_messages_idx_target_message_type_time, true}}, {52, {recreate_inbound_p2p_messages_table, true}}, - {53, {add_timestamps_column_to_threads_table, true}}}}; + {53, {add_timestamps_column_to_threads_table, true}}, + {54, {create_dm_operations_table, true}}}}; enum class MigrationResult { SUCCESS, FAILURE, NOT_APPLIED }; @@ -2887,6 +2910,54 @@ return this->processMessagesResults(preparedSQL); } +void SQLiteQueryExecutor::replaceDMOperation( + const DMOperation &operation) const { + static std::string query = + "REPLACE INTO dm_operations (id, type, operation) " + "VALUES (?, ?, ?);"; + replaceEntity<DMOperation>( + SQLiteQueryExecutor::getConnection(), query, operation); +} + +void SQLiteQueryExecutor::removeAllDMOperations() const { + static std::string query = "DELETE FROM dm_operations;"; + removeAllEntities(SQLiteQueryExecutor::getConnection(), query); +} + +void SQLiteQueryExecutor::removeDMOperations( + const std::vector<std::string> &ids) const { + if (!ids.size()) { + return; + } + + std::stringstream queryStream; + queryStream << "DELETE FROM dm_operations " + "WHERE id IN " + << getSQLStatementArray(ids.size()) << ";"; + removeEntitiesByKeys( + SQLiteQueryExecutor::getConnection(), queryStream.str(), ids); +} + +std::vector<DMOperation> SQLiteQueryExecutor::getDMOperations() const { + static std::string query = + "SELECT id, type, operation " + "FROM dm_operations;"; + return getAllEntities<DMOperation>( + SQLiteQueryExecutor::getConnection(), query); +} + +std::vector<DMOperation> SQLiteQueryExecutor::getDMOperationsByType( + const std::string &operationType) const { + static std::string query = + "SELECT id, type, operation " + "FROM dm_operations " + "WHERE type = ?;"; + + std::vector<std::string> types{operationType}; + return getAllEntitiesByPrimaryKeys<DMOperation>( + SQLiteQueryExecutor::getConnection(), query, types); +} + #ifdef EMSCRIPTEN std::vector<WebThread> SQLiteQueryExecutor::getAllThreadsWeb() const { auto threads = this->getAllThreads(); diff --git a/native/cpp/CommonCpp/DatabaseManagers/entities/DMOperation.h b/native/cpp/CommonCpp/DatabaseManagers/entities/DMOperation.h new file mode 100644 --- /dev/null +++ b/native/cpp/CommonCpp/DatabaseManagers/entities/DMOperation.h @@ -0,0 +1,28 @@ +#pragma once + +#include "SQLiteDataConverters.h" +#include <sqlite3.h> +#include <string> + +namespace comm { +struct DMOperation { + + std::string id; + std::string type; + std::string operation; + + static DMOperation fromSQLResult(sqlite3_stmt *sqlRow, int idx) { + return DMOperation{ + getStringFromSQLRow(sqlRow, idx), + getStringFromSQLRow(sqlRow, idx + 1), + getStringFromSQLRow(sqlRow, idx + 2)}; + } + + int bindToSQL(sqlite3_stmt *sql, int idx) const { + bindStringToSQL(id, sql, idx); + bindStringToSQL(type, sql, idx + 1); + return bindStringToSQL(operation, sql, idx + 2); + } +}; + +} // namespace comm diff --git a/native/ios/Comm.xcodeproj/project.pbxproj b/native/ios/Comm.xcodeproj/project.pbxproj --- a/native/ios/Comm.xcodeproj/project.pbxproj +++ b/native/ios/Comm.xcodeproj/project.pbxproj @@ -143,6 +143,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0E02676D2D81EAD800788249 /* DMOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DMOperation.h; sourceTree = "<group>"; }; 13B07F961A680F5B00A75B9A /* Comm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Comm.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Comm/AppDelegate.h; sourceTree = "<group>"; }; 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = Comm/AppDelegate.mm; sourceTree = "<group>"; }; @@ -551,6 +552,7 @@ 71BE84442636A944002849D2 /* entities */ = { isa = PBXGroup; children = ( + 0E02676D2D81EAD800788249 /* DMOperation.h */, 816D2D5B2C480E9E001C0B67 /* MessageSearchResult.h */, CB01F0C32B67F3970089E1F9 /* SQLiteStatementWrapper.cpp */, CB01F0C12B67EF470089E1F9 /* SQLiteDataConverters.cpp */, 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$@<O00001 literal 0 Hc$@<O00001