From be375bbf131f7647e3c8f49b66d0ed250a3ed2e5 Mon Sep 17 00:00:00 2001 From: zuojiangjiang Date: Mon, 22 May 2023 22:30:27 +0800 Subject: [PATCH] add GSDB interface Signed-off-by: zuojiangjiang --- .../frameworks/libs/distributeddb/BUILD.gn | 1 + .../relational/relational_schema_object.h | 1 + .../common/include/relational/table_info.h | 4 + .../distributeddb/common/src/db_constant.cpp | 2 +- .../libs/distributeddb/common/src/query.cpp | 5 + .../relational/relational_schema_object.cpp | 18 + .../common/src/relational/table_info.cpp | 11 + .../libs/distributeddb/distributeddb.gni | 1 + .../libs/distributeddb/include/query.h | 2 +- .../include/cloud/cloud_store_types.h | 20 +- .../interfaces/include/runtime_config.h | 3 + .../interfaces/include/store_observer.h | 8 +- .../interfaces/include/store_types.h | 2 + .../relational_store_delegate_impl.cpp | 7 +- .../relational_store_sqlite_ext.cpp | 35 +- .../interfaces/src/runtime_config.cpp | 4 + .../storage/include/isync_interface.h | 2 + .../include/relational_store_connection.h | 2 +- .../storage/include/sync_generic_interface.h | 2 +- .../sqlite/cloud_sync_log_table_manager.cpp | 120 ++++ .../src/sqlite/cloud_sync_log_table_manager.h | 43 ++ .../collaboration_log_table_manager.cpp | 2 +- .../src/sqlite/log_table_manager_factory.cpp | 15 +- .../src/sqlite/log_table_manager_factory.h | 4 +- .../sqlite_relational_database_upgrader.cpp | 53 +- .../sqlite_relational_database_upgrader.h | 2 + .../relational/sqlite_relational_store.cpp | 6 +- .../relational/sqlite_relational_store.h | 2 +- .../sqlite_relational_store_connection.cpp | 4 +- .../sqlite_relational_store_connection.h | 2 +- ...qlite_single_relational_storage_engine.cpp | 14 +- .../sqlite_single_relational_storage_engine.h | 5 +- .../sqlite/split_device_log_table_manager.cpp | 2 +- .../src/sqlite/sqlite_log_table_manager.cpp | 4 +- ...single_ver_relational_storage_executor.cpp | 19 +- ...e_single_ver_relational_storage_executor.h | 4 +- .../distributeddb/syncer/src/meta_data.cpp | 2 +- .../libs/distributeddb/syncer/src/meta_data.h | 2 +- .../syncer/src/remote_executor.cpp | 47 +- .../syncer/src/remote_executor.h | 3 +- .../syncer/src/remote_executor_packet.cpp | 15 + .../syncer/src/remote_executor_packet.h | 8 +- .../syncer/src/single_ver_data_sync.cpp | 10 +- .../distributeddb/syncer/src/sync_types.h | 1 + .../libs/distributeddb/test/BUILD.gn | 7 + .../distributeddb_interfaces_log_test.cpp | 4 +- ...buteddb_interfaces_relational_ext_test.cpp | 361 ++++++++++ ...uteddb_interfaces_relational_sync_test.cpp | 29 +- ...stributeddb_interfaces_relational_test.cpp | 643 +++++++++++++----- 49 files changed, 1323 insertions(+), 240 deletions(-) create mode 100644 kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp create mode 100644 kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h create mode 100644 kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_ext_test.cpp diff --git a/kv_store/frameworks/libs/distributeddb/BUILD.gn b/kv_store/frameworks/libs/distributeddb/BUILD.gn index cf7b051d..10a71422 100644 --- a/kv_store/frameworks/libs/distributeddb/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/BUILD.gn @@ -18,6 +18,7 @@ config("distrdb_config") { include_dirs = [ "include", "interfaces/include", + "interfaces/include/cloud", "interfaces/src", "interfaces/src/relational", "common/include", diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h index 13741f13..2f6e3965 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h @@ -70,6 +70,7 @@ private: int ParseCheckTableDefine(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableFieldInfo(const JsonObject &inJsonObject, const FieldPath &path, FieldInfo &table); int ParseCheckTableAutoInc(const JsonObject &inJsonObject, TableInfo &resultTable); + int ParseCheckTableSyncType(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableUnique(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTablePrimaryKey(const JsonObject &inJsonObject, TableInfo &resultTable); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h index d664b471..1eade6a7 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h @@ -19,6 +19,7 @@ #include #include +#include "cloud/cloud_store_types.h" #include "db_types.h" #include "schema_constant.h" #include "data_value.h" @@ -68,6 +69,7 @@ class TableInfo { public: const std::string &GetTableName() const; bool GetAutoIncrement() const; + TableSyncType GetTableSyncType() const; const std::string &GetCreateTableSql() const; const FieldInfoMap &GetFields() const; // const IndexInfoMap &GetIndexDefine() const; @@ -76,6 +78,7 @@ public: void SetTableName(const std::string &tableName); void SetAutoIncrement(bool autoInc); + void SetTableSyncType(TableSyncType tableSyncType); void SetCreateTableSql(const std::string &sql); // set 'autoInc_' flag when set sql void AddField(const FieldInfo &field); void AddIndexDefine(const std::string &indexName, const CompositeFields &indexDefine); @@ -120,6 +123,7 @@ private: std::string tableName_; bool autoInc_ = false; // only 'INTEGER PRIMARY KEY' could be defined as 'AUTOINCREMENT' + TableSyncType tableSyncType_ = DEVICE_COOPERATION; std::string sql_; FieldInfoMap fields_; std::map primaryKey_; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp index abba6423..e19c6683 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp @@ -71,7 +71,7 @@ const std::string DBConstant::TIMESTAMP_ALIAS = "naturalbase_rdb_aux_timestamp"; const std::string DBConstant::LOG_TABLE_VERSION_1 = "1.0"; const std::string DBConstant::LOG_TABLE_VERSION_2 = "2.0"; -const std::string DBConstant::LOG_TABLE_VERSION_CURRENT = "2.0"; +const std::string DBConstant::LOG_TABLE_VERSION_CURRENT = "3.0"; const std::string DBConstant::LOG_TABLE_VERSION_KEY = "log_table_version"; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/query.cpp b/kv_store/frameworks/libs/distributeddb/common/src/query.cpp index a1b566be..26939153 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/query.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/query.cpp @@ -30,6 +30,11 @@ Query Query::Select(const std::string &tableName) return query; } +Query &Query::FromTable(const std::vector &tableNames) +{ + return *this; +} + Query &Query::BeginGroup() { queryExpression_.BeginGroup(); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp index 18462ad6..075be5bf 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp @@ -335,6 +335,11 @@ int RelationalSchemaObject::ParseCheckTableInfo(const JsonObject &inJsonObject) if (errCode != E_OK) { return errCode; } + + errCode = ParseCheckTableSyncType(inJsonObject, resultTable); + if (errCode != E_OK) { + return errCode; + } errCode = ParseCheckTableIndex(inJsonObject, resultTable); if (errCode != E_OK) { return errCode; @@ -479,6 +484,19 @@ int RelationalSchemaObject::ParseCheckTablePrimaryKey(const JsonObject &inJsonOb return errCode; } +int RelationalSchemaObject::ParseCheckTableSyncType(const JsonObject &inJsonObject, TableInfo &resultTable) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, "TABLE_SYNC_TYPE", FieldType::LEAF_FIELD_INTEGER, + false, fieldValue); + if (errCode == E_OK) { + resultTable.SetTableSyncType(static_cast(fieldValue.integerValue)); + } else if (errCode != -E_NOT_FOUND) { + return errCode; + } + return E_OK; // if there is no "TABLE_SYNC_TYPE" filed, the table_sync_type is DEVICE_COOPERATION +} + int RelationalSchemaObject::ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable) { if (!inJsonObject.IsFieldPathExist(FieldPath {"INDEX"})) { // INDEX is not necessary diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp index 797d8b45..b43a3ca7 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp @@ -206,6 +206,16 @@ bool TableInfo::GetAutoIncrement() const return autoInc_; } +void TableInfo::SetTableSyncType(TableSyncType tableSyncType) +{ + tableSyncType_ = tableSyncType; +} + +TableSyncType TableInfo::GetTableSyncType() const +{ + return tableSyncType_; +} + const std::string &TableInfo::GetCreateTableSql() const { return sql_; @@ -634,6 +644,7 @@ std::string TableInfo::ToTableInfoString(const std::string &schemaVersion) const attrStr += R"("PRIMARY_KEY": [)" + primaryKey + "]"; } } + attrStr += R"(,"TABLE_SYNC_TYPE": )" + std::to_string(static_cast(tableSyncType_)); AddIndexDefineString(attrStr); attrStr += "}"; return attrStr; diff --git a/kv_store/frameworks/libs/distributeddb/distributeddb.gni b/kv_store/frameworks/libs/distributeddb/distributeddb.gni index 87c4b466..64a86a90 100644 --- a/kv_store/frameworks/libs/distributeddb/distributeddb.gni +++ b/kv_store/frameworks/libs/distributeddb/distributeddb.gni @@ -128,6 +128,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/relationaldb_properties.cpp", "${distributeddb_path}/storage/src/result_entries_window.cpp", "${distributeddb_path}/storage/src/single_ver_natural_store_commit_notify_data.cpp", + "${distributeddb_path}/storage/src/sqlite/cloud_sync_log_table_manager.cpp", "${distributeddb_path}/storage/src/sqlite/collaboration_log_table_manager.cpp", "${distributeddb_path}/storage/src/sqlite/log_table_manager_factory.cpp", "${distributeddb_path}/storage/src/sqlite/query_object.cpp", diff --git a/kv_store/frameworks/libs/distributeddb/include/query.h b/kv_store/frameworks/libs/distributeddb/include/query.h index 1a1f1d90..da287c7c 100644 --- a/kv_store/frameworks/libs/distributeddb/include/query.h +++ b/kv_store/frameworks/libs/distributeddb/include/query.h @@ -33,7 +33,7 @@ public: DB_API static Query Select(); DB_API static Query Select(const std::string &tableName); - DB_API Query FromTable(const std::vector &tableNames); + DB_API Query &FromTable(const std::vector &tableNames); template DB_API Query &EqualTo(const std::string &field, const T &value) diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h index 7d54fa98..dc09edf4 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h @@ -25,8 +25,6 @@ #include "store_types.h" namespace DistributedDB { -const std::string CLOUD_EXTEND_FIELD[] = { "GID_FIELD", "CREATE_FIELD", "MODIFY_FIELD" }; -const uint32_t MAX_UPLOAD_SIZE = 1024 * 1024 * 8; enum TableSyncType { DEVICE_COOPERATION = 0, CLOUD_COOPERATION = 1, @@ -46,11 +44,11 @@ struct Asset { std::string size; std::string hash; }; - +using Nil = std::monostate; using Assets = std::vector; using Bytes = std::vector; -using CloudValue = std::variant; -using VBucket = std::map; +using Type = std::variant; +using VBucket = std::map; enum ProcessStatus { PREPARED = 0, @@ -93,17 +91,5 @@ struct DataBaseSchema { std::vector tables; }; -struct CloudSyncBatch { - std::vector record; - std::vector extend; - std::vector rowid; -}; - -struct CloudSyncData { - const std::string tablename; - CloudSyncBatch insData; - CloudSyncBatch updData; - CloudSyncBatch delData; -}; } // namespace DistributedDB #endif // CLOUD_STORE_TYPE_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h index b5824447..e1bfbe48 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/runtime_config.h @@ -19,6 +19,7 @@ #include #include +#include "cloud/icloud_data_translate.h" #include "iprocess_communicator.h" #include "iprocess_system_api_adapter.h" #include "ithread_pool.h" @@ -54,6 +55,8 @@ public: DB_API static void SetTranslateToDeviceIdCallback(const TranslateToDeviceIdCallback &callback); DB_API static void SetThreadPool(const std::shared_ptr &threadPool); + + DB_API static void SetCloudTranslate(const std::shared_ptr &dataTranslate); private: static std::mutex communicatorMutex_; static std::mutex multiUserMutex_; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h index 0228b2da..3eebbb60 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h @@ -16,8 +16,8 @@ #ifndef STORE_OBSERVER_H #define STORE_OBSERVER_H -#include "store_changed_data.h" #include "cloud/cloud_store_types.h" +#include "store_changed_data.h" namespace DistributedDB { @@ -31,7 +31,7 @@ struct ChangedData { std::string tableName; // CLOUD_COOPERATION mode, primaryData store primary keys // primayData store row id if have no data - std::vector> primaryData[OP_BUTT]; + std::vector> primaryData[OP_BUTT]; std::vector field; }; @@ -47,9 +47,9 @@ public: virtual ~StoreObserver() {} // Data change callback - virtual void OnChange(const StoreChangedData &data) = 0; + virtual void OnChange(const StoreChangedData &data) {}; - virtual void OnChange(Origin origin, const std::string &originalId, ChangedData &&data) const {}; + virtual void OnChange(Origin origin, const std::string &originalId, ChangedData &&data) {}; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h index 21f693ed..fa665219 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -68,6 +68,8 @@ enum DBStatus { RATE_LIMIT, DATA_HANDLE_ERROR, // remote handle data failed CONSTRAINT, // constraint check failed in sqlite + CLOUD_ERROR, // cloud error + QUERY_END, // Indicates that query function has queried last data from cloud }; struct KvStoreConfig { diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index d92004ed..f10688e5 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -50,12 +50,17 @@ DBStatus RelationalStoreDelegateImpl::CreateDistributedTable(const std::string & return INVALID_ARGS; } + if (!(type == DEVICE_COOPERATION || type == CLOUD_COOPERATION)) { + LOGE("invalid table sync type."); + return INVALID_ARGS; + } + if (conn_ == nullptr) { LOGE("[RelationalStore Delegate] Invalid connection for operation!"); return DB_ERROR; } - int errCode = conn_->CreateDistributedTable(tableName); + int errCode = conn_->CreateDistributedTable(tableName, type); if (errCode != E_OK) { LOGE("[RelationalStore Delegate] Create Distributed table failed:%d", errCode); return TransferDBErrno(errCode); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index 65ab912f..7607b849 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -122,6 +122,16 @@ public: return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t } + static int GetSysCurrentRawTime(uint64_t &curTime) + { + int errCode = GetCurrentSysTimeInMicrosecond(curTime); + if (errCode != E_OK) { + return errCode; + } + curTime *= TO_100_NS; + return E_OK; + } + // Init the TimeHelper static void Initialize(Timestamp maxTimestamp) { @@ -249,9 +259,24 @@ void GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv) sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetTime(timeOffset)); } +void GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 0 || argv == nullptr) { // 0: function need zero parameter + return; + } + + uint64_t curTime = 0; + int errCode = TimeHelper::GetSysCurrentRawTime(curTime); + if (errCode != E_OK) { + sqlite3_result_error(ctx, "get raw sys time failed.", errCode); + return; + } + sqlite3_result_int64(ctx, (sqlite3_int64)(curTime)); +} + void GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv) { - if (ctx == nullptr || argc != 0 || argv == nullptr) { // 0: function need one parameter + if (ctx == nullptr || argc != 0 || argv == nullptr) { // 0: function need zero parameter return; } @@ -265,6 +290,13 @@ int RegisterGetSysTime(sqlite3 *db) return RegisterFunction(db, "get_sys_time", 1, nullptr, func); } +int RegisterGetRawSysTime(sqlite3 *db) +{ + TransactFunc func; + func.xFunc = &GetRawSysTime; + return RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func); +} + int RegisterGetLastTime(sqlite3 *db) { TransactFunc func; @@ -413,6 +445,7 @@ void PostHandle(sqlite3 *db) RegisterCalcHash(db); RegisterGetSysTime(db); RegisterGetLastTime(db); + RegisterGetRawSysTime(db); (void)sqlite3_set_droptable_handle(db, &ClearTheLogAfterDropTable); (void)sqlite3_busy_timeout(db, BUSY_TIMEOUT); std::string recursiveTrigger = "PRAGMA recursive_triggers = ON;"; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp index 19b72c43..b94ef7be 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp @@ -141,5 +141,9 @@ void RuntimeConfig::SetThreadPool(const std::shared_ptr &threadPool { RuntimeContext::GetInstance()->SetThreadPool(threadPool); } + +void RuntimeConfig::SetCloudTranslate(const std::shared_ptr &dataTranslate) +{ +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h index d64b3bba..893305b1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h @@ -67,6 +67,8 @@ public: virtual int GetAllMetaKeys(std::vector &keys) const = 0; virtual const DBProperties &GetDbProperties() const = 0; + + virtual int GetSecurityOption(SecurityOption &option) const = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h index bd48de49..4d529cd8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h @@ -50,7 +50,7 @@ public: virtual int Close() = 0; virtual int SyncToDevice(SyncInfo &info) = 0; virtual std::string GetIdentifier() = 0; - virtual int CreateDistributedTable(const std::string &tableName) = 0; + virtual int CreateDistributedTable(const std::string &tableName, TableSyncType syncType) = 0; virtual int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) = 0; virtual int RemoveDeviceData() = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h index 3954a4d0..1e3e2d52 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/sync_generic_interface.h @@ -83,7 +83,7 @@ public: return true; } - virtual int GetSecurityOption(SecurityOption &option) const + int GetSecurityOption(SecurityOption &option) const override { return -E_NOT_SUPPORT; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp new file mode 100644 index 00000000..1391e4f3 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cloud_sync_log_table_manager.h" + +namespace DistributedDB { +std::string CloudSyncLogTableManager::CalcPrimaryKeyHash(const std::string &references, const TableInfo &table, + const std::string &identity) +{ + (void)identity; + std::string sql; + if (table.GetPrimaryKey().size() == 1) { + sql = "calc_hash(" + references + "'" + table.GetPrimaryKey().at(0) + "')"; + } else { + std::set primaryKeySet; // we need sort primary key by name + for (const auto &it : table.GetPrimaryKey()) { + primaryKeySet.emplace(it.second); + } + sql = "calc_hash("; + for (const auto &it : primaryKeySet) { + sql += "calc_hash(" + references + "'" + it + "')||"; + } + sql.pop_back(); + sql.pop_back(); + sql += ")"; + } + return sql; +} + +void CloudSyncLogTableManager::GetIndexSql(const TableInfo &table, std::vector &schema) +{ + const std::string tableName = GetLogTableName(table); + + std::string indexTimestampFlagGid = "CREATE INDEX IF NOT EXISTS " + tableName + + "_cloud_time_flag_gid_index ON " + tableName + "(timestamp, flag, cloud_gid);"; + schema.emplace_back(indexTimestampFlagGid); + + std::string indexHashkey = "CREATE INDEX IF NOT EXISTS " + tableName + + "_cloud_hashkey_index ON " + tableName + "(hash_key);"; + schema.emplace_back(indexHashkey); +} + +std::string CloudSyncLogTableManager::GetPrimaryKeySql(const TableInfo &table) +{ + return "PRIMARY KEY(hash_key)"; +} + +// The parameter "identity" is a hash string that identifies a device. The same for the next two functions. +std::string CloudSyncLogTableManager::GetInsertTrigger(const TableInfo &table, const std::string &identity) +{ + std::string logTblName = DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; + std::string insertTrigger = "CREATE TRIGGER IF NOT EXISTS "; + insertTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_INSERT AFTER INSERT \n"; + insertTrigger += "ON '" + table.GetTableName() + "'\n"; + insertTrigger += "WHEN (SELECT count(*) from " + DBConstant::RELATIONAL_PREFIX + "metadata "; + insertTrigger += "WHERE key = 'log_trigger_switch' AND value = 'true')\n"; + insertTrigger += "BEGIN\n"; + insertTrigger += "\t INSERT OR REPLACE INTO " + logTblName; + insertTrigger += " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key, cloud_gid)"; + insertTrigger += " VALUES (new.rowid, '', '',"; + insertTrigger += " get_raw_sys_time(), get_raw_sys_time(), 0x02, "; + insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", '');\n"; + insertTrigger += "END;"; + return insertTrigger; +} + +std::string CloudSyncLogTableManager::GetUpdateTrigger(const TableInfo &table, const std::string &identity) +{ + std::string logTblName = DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; + std::string updateTrigger = "CREATE TRIGGER IF NOT EXISTS "; + updateTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_UPDATE AFTER UPDATE \n"; + updateTrigger += "ON '" + table.GetTableName() + "'\n"; + updateTrigger += "WHEN (SELECT count(*) from " + DBConstant::RELATIONAL_PREFIX + "metadata "; + updateTrigger += "WHERE key = 'log_trigger_switch' AND value = 'true')\n"; + updateTrigger += "BEGIN\n"; + if (table.GetPrimaryKey().size() == 1 && table.GetPrimaryKey().at(0) == "rowid") { + updateTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; + updateTrigger += " SET timestamp=get_raw_sys_time(), device='', flag=0x02"; + updateTrigger += " WHERE data_key = OLD.rowid;\n"; + } else { // the row id may be modified + updateTrigger += "\t UPDATE " + logTblName; + updateTrigger += " SET data_key=-1,timestamp=get_raw_sys_time(), device='', flag=0x03"; + updateTrigger += " WHERE hash_key=" + CalcPrimaryKeyHash("OLD.", table, identity) + ";\n"; + updateTrigger += "\t INSERT OR REPLACE INTO " + logTblName + " VALUES (NEW.rowid, '', '', "; + updateTrigger += "get_raw_sys_time(), (select wtimestamp from " + logTblName + " where hash_key = "; + updateTrigger += CalcPrimaryKeyHash("OLD.", table, identity) + "), 0x02, "; + updateTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", '');\n"; + } + updateTrigger += "END;"; + return updateTrigger; +} + +std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity) +{ + (void)identity; + std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS "; + deleteTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_DELETE BEFORE DELETE \n"; + deleteTrigger += "ON '" + table.GetTableName() + "'\n"; + deleteTrigger += "WHEN (SELECT count(*) from " + DBConstant::RELATIONAL_PREFIX + "metadata "; + deleteTrigger += "WHERE key = 'log_trigger_switch' AND VALUE = 'true')\n"; + deleteTrigger += "BEGIN\n"; + deleteTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; + deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_raw_sys_time()"; + deleteTrigger += " WHERE data_key = OLD.rowid;"; + deleteTrigger += "END;"; + return deleteTrigger; +} +} // DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h new file mode 100644 index 00000000..17bb59a1 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CLOUD_SYNC_LOG_TABLE_MANAGER_H +#define CLOUD_SYNC_LOG_TABLE_MANAGER_H + +#include "sqlite_log_table_manager.h" + +namespace DistributedDB { +class CloudSyncLogTableManager : public SqliteLogTableManager { +public: + CloudSyncLogTableManager() = default; + ~CloudSyncLogTableManager() override = default; + + // The parameter "references" is "", "NEW." or "OLD.". "identity" is a hash string that identifies a device. + std::string CalcPrimaryKeyHash(const std::string &references, const TableInfo &table, + const std::string &identity) override; + +private: + void GetIndexSql(const TableInfo &table, std::vector &schema) override; + std::string GetPrimaryKeySql(const TableInfo &table) override; + + // The parameter "identity" is a hash string that identifies a device. The same for the next two functions. + std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) override; + std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) override; + std::string GetDeleteTrigger(const TableInfo &table, const std::string &identity) override; +}; + +} // DistributedDB + +#endif //DISTRIBUTED_UT_CLOUD_SYNC_LOG_TABLE_MANAGER_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp index 2132dde0..5110060c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp @@ -84,7 +84,7 @@ std::string CollaborationLogTableManager::GetUpdateTrigger(const TableInfo &tabl updateTrigger += "\t INSERT OR REPLACE INTO " + logTblName + " VALUES (NEW.rowid, '', '', get_sys_time(0), " "get_last_time(), CASE WHEN (" + CalcPrimaryKeyHash("NEW.", table, identity) + " != " + CalcPrimaryKeyHash("NEW.", table, identity) + ") THEN 0x02 ELSE 0x22 END, " + - CalcPrimaryKeyHash("NEW.", table, identity) + ");\n"; + CalcPrimaryKeyHash("NEW.", table, identity) + ", '');\n"; } updateTrigger += "END;"; return updateTrigger; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.cpp index 841fa48c..a6f613f1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.cpp @@ -14,16 +14,21 @@ */ #include "log_table_manager_factory.h" - +#include "cloud_sync_log_table_manager.h" #include "collaboration_log_table_manager.h" #include "split_device_log_table_manager.h" namespace DistributedDB { -std::unique_ptr LogTableManagerFactory::GetTableManager(DistributedTableMode mode) +std::unique_ptr LogTableManagerFactory::GetTableManager(DistributedTableMode mode, + TableSyncType syncType) { - if (mode == DistributedTableMode::COLLABORATION) { - return std::make_unique(); + if (syncType == CLOUD_COOPERATION) { + return std::make_unique(); + } else { + if (mode == DistributedTableMode::COLLABORATION) { + return std::make_unique(); + } + return std::make_unique(); } - return std::make_unique(); } } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.h index e534ea32..b31f9d50 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/log_table_manager_factory.h @@ -16,13 +16,15 @@ #ifndef LOG_TABLE_MANAGER_FACTORY_H #define LOG_TABLE_MANAGER_FACTORY_H #include + +#include "cloud/cloud_store_types.h" #include "sqlite_log_table_manager.h" #include "types_export.h" namespace DistributedDB { class LogTableManagerFactory final { public: - static std::unique_ptr GetTableManager(DistributedTableMode mode); + static std::unique_ptr GetTableManager(DistributedTableMode mode, TableSyncType syncType); private: LogTableManagerFactory() {} diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp index a99792ab..cdc7b48d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp @@ -63,6 +63,12 @@ int SqliteRelationalDatabaseUpgrader::ExecuteUpgrade() return (errCode == -E_NOT_FOUND) ? E_OK : errCode; } + errCode = UpgradeLogTable(logTableVersion); + if (errCode != E_OK) { + LOGE("[Relational][Upgrade] Upgrade log table failed, err = %d.", errCode); + return errCode; + } + return UpgradeTrigger(logTableVersion); } @@ -75,9 +81,14 @@ int SqliteRelationalDatabaseUpgrader::EndUpgrade(bool isSuccess) return SQLiteUtils::RollbackTransaction(db_); } +bool SqliteRelationalDatabaseUpgrader::IsNewestVersion(const std::string &logTableVersion) +{ + return logTableVersion == DBConstant::LOG_TABLE_VERSION_CURRENT; +} + int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTableVersion) { - if (logTableVersion != DBConstant::LOG_TABLE_VERSION_1) { + if (IsNewestVersion(logTableVersion)) { LOGD("[Relational][Upgrade] No need upgrade trigger."); return E_OK; } @@ -98,10 +109,6 @@ int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTable } DistributedTableMode mode = schemaObject.GetTableMode(); - if (mode != DistributedTableMode::SPLIT_BY_DEVICE) { - return E_OK; - } - for (const auto &[tableName, tableInfo] : schemaObject.GetTables()) { std::string dropTriggerSql = "DROP TRIGGER IF EXISTS " + DBConstant::SYSTEM_TABLE_PREFIX + tableName + "_ON_UPDATE"; @@ -110,7 +117,7 @@ int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTable LOGE("[Relational][Upgrade] drop trigger failed.", errCode); return errCode; } - auto manager = LogTableManagerFactory::GetTableManager(mode); + auto manager = LogTableManagerFactory::GetTableManager(mode, tableInfo.GetTableSyncType()); errCode = manager->AddRelationalLogTableTrigger(db_, tableInfo, ""); if (errCode != E_OK) { LOGE("[Relational][Upgrade] recreate trigger failed.", errCode); @@ -119,4 +126,38 @@ int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTable } return E_OK; } + +int SqliteRelationalDatabaseUpgrader::UpgradeLogTable(const std::string &logTableVersion) +{ + if (IsNewestVersion(logTableVersion)) { + LOGD("[Relational][Upgrade] No need upgrade log table."); + return E_OK; + } + + // get schema from meta + std::string schemaDefine; + int errCode = SQLiteUtils::GetRelationalSchema(db_, schemaDefine); + if (errCode != E_OK) { + LOGW("[Relational][UpgradeLogTable] Get relational schema from meta return %d.", errCode); + return (errCode == -E_NOT_FOUND) ? E_OK : errCode; + } + + RelationalSchemaObject schemaObject; + errCode = schemaObject.ParseFromSchemaString(schemaDefine); + if (errCode != E_OK) { + LOGE("[Relational][UpgradeLogTable] Parse to relational schema failed.", errCode); + return errCode; + } + + for (const auto &item : schemaObject.GetTables()) { + std::string addColumnSql = "alter table " + DBConstant::RELATIONAL_PREFIX + item.first + + "_log add cloud_gid text after hash_key;"; + errCode = SQLiteUtils::ExecuteRawSQL(db_, addColumnSql); + if (errCode != E_OK) { + LOGE("[Relational][UpgradeLogTable] add column failed.", errCode); + return errCode; + } + } + return E_OK; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.h index 5eeff9df..4debfc1e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.h @@ -32,7 +32,9 @@ private: int ExecuteUpgrade(); int EndUpgrade(bool isSuccess); + bool IsNewestVersion(const std::string &logTableVersion); int UpgradeTrigger(const std::string &logTableVersion); + int UpgradeLogTable(const std::string &logTableVersion); sqlite3 *db_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index 1d85cfa0..746a47eb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -94,7 +94,7 @@ void SQLiteRelationalStore::ReleaseResources() int SQLiteRelationalStore::CheckDBMode() { int errCode = E_OK; - auto *handle = GetHandle(false, errCode); + auto *handle = GetHandle(true, errCode); if (handle == nullptr) { return errCode; } @@ -404,7 +404,7 @@ void SQLiteRelationalStore::WakeUpSyncer() syncAbleEngine_->WakeUpSyncer(); } -int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName) +int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName, TableSyncType syncType) { auto mode = static_cast(sqliteStorageEngine_->GetProperties().GetIntProp( RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE)); @@ -420,7 +420,7 @@ int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName) bool schemaChanged = false; int errCode = sqliteStorageEngine_->CreateDistributedTable(tableName, DBCommon::TransferStringToHex(localIdentity), - schemaChanged); + schemaChanged, syncType); if (errCode != E_OK) { LOGE("Create distributed table failed. %d", errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h index 7603a830..a66eac9c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h @@ -56,7 +56,7 @@ public: return storageEngine_; } - int CreateDistributedTable(const std::string &tableName); + int CreateDistributedTable(const std::string &tableName, TableSyncType syncType); int RemoveDeviceData(); int RemoveDeviceData(const std::string &device, const std::string &tableName); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp index 57fb3c36..37f3f2d2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp @@ -141,7 +141,7 @@ int SQLiteRelationalStoreConnection::RollBack() return errCode; } -int SQLiteRelationalStoreConnection::CreateDistributedTable(const std::string &tableName) +int SQLiteRelationalStoreConnection::CreateDistributedTable(const std::string &tableName, TableSyncType syncType) { auto *store = GetDB(); if (store == nullptr) { @@ -149,7 +149,7 @@ int SQLiteRelationalStoreConnection::CreateDistributedTable(const std::string &t return -E_INVALID_CONNECTION; } - int errCode = store->CreateDistributedTable(tableName); + int errCode = store->CreateDistributedTable(tableName, syncType); if (errCode != E_OK) { LOGE("[RelationalConnection] create distributed table failed. %d", errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h index 0c85ca89..27448106 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h @@ -36,7 +36,7 @@ public: int Close() override; int SyncToDevice(SyncInfo &info) override; std::string GetIdentifier() override; - int CreateDistributedTable(const std::string &tableName) override; + int CreateDistributedTable(const std::string &tableName, TableSyncType syncType) override; int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; int RemoveDeviceData() override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index 6b90670e..e9cf8dc8 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp @@ -141,13 +141,17 @@ int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, cons } int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName, - const std::string &identity, bool &schemaChanged) + const std::string &identity, bool &schemaChanged, TableSyncType syncType) { std::lock_guard lock(schemaMutex_); RelationalSchemaObject schema = schema_; bool isUpgraded = false; if (schema.GetTable(tableName).GetTableName() == tableName) { LOGI("distributed table bas been created."); + if (schema.GetTable(tableName).GetTableSyncType() != syncType) { + LOGE("table sync type mismatch."); + return -E_TYPE_MISMATCH; + } isUpgraded = true; int errCode = UpgradeDistributedTable(tableName, schemaChanged); if (errCode != E_OK) { @@ -162,11 +166,11 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::strin schemaChanged = true; } - return CreateDistributedTable(tableName, isUpgraded, identity, schema); + return CreateDistributedTable(tableName, isUpgraded, identity, schema, syncType); } int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName, bool isUpgraded, - const std::string &identity, RelationalSchemaObject &schema) + const std::string &identity, RelationalSchemaObject &schema, TableSyncType tableSyncType) { LOGD("Create distributed table."); int errCode = E_OK; @@ -185,7 +189,9 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::strin auto mode = static_cast(properties_.GetIntProp( RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE)); TableInfo table; - errCode = handle->CreateDistributedTable(tableName, mode, isUpgraded, identity, table); + table.SetTableName(tableName); + table.SetTableSyncType(tableSyncType); + errCode = handle->CreateDistributedTable(mode, isUpgraded, identity, table, tableSyncType); if (errCode != E_OK) { LOGE("create distributed table failed. %d", errCode); (void)handle->Rollback(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h index 540f499c..ff51bf64 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h @@ -34,7 +34,8 @@ public: RelationalSchemaObject GetSchema() const; - int CreateDistributedTable(const std::string &tableName, const std::string &identity, bool &schemaChanged); + int CreateDistributedTable(const std::string &tableName, const std::string &identity, bool &schemaChanged, + TableSyncType syncType); int CleanDistributedDeviceTable(std::vector &missingTables); @@ -55,7 +56,7 @@ private: int UpgradeDistributedTable(const std::string &tableName, bool &schemaChanged); int CreateDistributedTable(const std::string &tableName, bool isUpgraded, const std::string &identity, - RelationalSchemaObject &schema); + RelationalSchemaObject &schema, TableSyncType tableSyncType); int CreateRelationalMetaTable(sqlite3 *db); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp index 6f50bc5b..1f06f5b2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp @@ -72,7 +72,7 @@ std::string SplitDeviceLogTableManager::GetUpdateTrigger(const TableInfo &table, updateTrigger += "\t INSERT OR REPLACE INTO " + logTblName + " VALUES (NEW.rowid, '', '', get_sys_time(0), " "get_last_time(), CASE WHEN (" + CalcPrimaryKeyHash("NEW.", table, identity) + " != " + CalcPrimaryKeyHash("NEW.", table, identity) + ") THEN 0x02 ELSE 0x22 END, " + - CalcPrimaryKeyHash("NEW.", table, identity) + ");\n"; + CalcPrimaryKeyHash("NEW.", table, identity) + ", '');\n"; } updateTrigger += "END;"; return updateTrigger; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp index f1755b7b..053ed430 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp @@ -44,7 +44,9 @@ int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo "timestamp INT NOT NULL," \ "wtimestamp INT NOT NULL," \ "flag INT NOT NULL," \ - "hash_key BLOB NOT NULL," + primaryKey + ");"; + "hash_key BLOB NOT NULL," \ + "cloud_gid TEXT," \ + + primaryKey + ");"; std::vector logTableSchema; logTableSchema.emplace_back(createTableSql); GetIndexSql(table, logTableSchema); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp index 68aab389..a8836507 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp @@ -108,17 +108,18 @@ int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedData(sqlite3 std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; std::string sql = "INSERT INTO " + logTable + " SELECT rowid, '', '', " + timeOffsetStr + " + rowid, " + timeOffsetStr + " + rowid, 0x2, " + - calPrimaryKeyHash + " FROM '" + tableName + "' AS a WHERE 1=1;"; + calPrimaryKeyHash + ", ''" + " FROM '" + tableName + "' AS a WHERE 1=1;"; return SQLiteUtils::ExecuteRawSQL(db, sql); } -int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedTable(const std::string &tableName, - DistributedTableMode mode, bool isUpgraded, const std::string &identity, TableInfo &table) +int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedTable(DistributedTableMode mode, bool isUpgraded, + const std::string &identity, TableInfo &table, TableSyncType syncType) { if (dbHandle_ == nullptr) { return -E_INVALID_DB; } + const std::string tableName = table.GetTableName(); int errCode = SQLiteUtils::AnalysisSchema(dbHandle_, tableName, table); if (errCode != E_OK) { LOGE("[CreateDistributedTable] analysis table schema failed. %d", errCode); @@ -134,14 +135,16 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedTable(const std:: } } - errCode = CheckTableConstraint(table, mode); - if (errCode != E_OK) { - LOGE("[CreateDistributedTable] check table constraint failed."); - return errCode; + if (syncType != CLOUD_COOPERATION) { + errCode = CheckTableConstraint(table, mode); + if (errCode != E_OK) { + LOGE("[CreateDistributedTable] check table constraint failed."); + return errCode; + } } // create log table - auto tableManager = LogTableManagerFactory::GetTableManager(mode); + auto tableManager = LogTableManagerFactory::GetTableManager(mode, syncType); errCode = tableManager->CreateRelationalLogTable(dbHandle_, table); if (errCode != E_OK) { LOGE("[CreateDistributedTable] create log table failed"); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h index b90d2a8c..a98f0fba 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h @@ -36,8 +36,8 @@ public: DISABLE_COPY_ASSIGN_MOVE(SQLiteSingleVerRelationalStorageExecutor); // The parameter "identity" is a hash string that identifies a device - int CreateDistributedTable(const std::string &tableName, DistributedTableMode mode, bool isUpgraded, - const std::string &identity, TableInfo &table); + int CreateDistributedTable(DistributedTableMode mode, bool isUpgraded, const std::string &identity, + TableInfo &table, TableSyncType syncType); int UpgradeDistributedTable(const std::string &tableName, DistributedTableMode mode, bool &schemaChanged, RelationalSchemaObject &schema); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp index ffbad817..5f49fa29 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp @@ -596,7 +596,7 @@ int Metadata::SaveClientId(const std::string &deviceId, const std::string &clien return E_OK; } -int Metadata::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) +int Metadata::GetHashDeviceId(const std::string &clientId, std::string &hashDevId) const { // don't use cache here avoid invalid cache std::string keyStr; diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h index a73d60fa..ef0a2bf0 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.h @@ -114,7 +114,7 @@ public: int SaveClientId(const std::string &deviceId, const std::string &clientId); - int GetHashDeviceId(const std::string &clientId, std::string &hashDevId); + int GetHashDeviceId(const std::string &clientId, std::string &hashDevId) const; private: int SaveMetaDataValue(const DeviceID &deviceId, const MetaDataValue &inValue, bool isNeedHash = true); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp index 5a72a11d..36fe8f56 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp @@ -202,7 +202,7 @@ void RemoteExecutor::ParseOneRequestMessage(const std::string &device, Message * LOGW("[RemoteExecutor][ParseOneRequestMessage] closed"); return; } - int errCode = CheckPermissions(device); + int errCode = CheckPermissions(device, inMsg); if (errCode != E_OK) { (void)ResponseFailed(errCode, inMsg->GetSessionId(), inMsg->GetSequenceId(), device); return; @@ -213,7 +213,7 @@ void RemoteExecutor::ParseOneRequestMessage(const std::string &device, Message * } } -int RemoteExecutor::CheckPermissions(const std::string &device) +int RemoteExecutor::CheckPermissions(const std::string &device, Message *inMsg) { SyncGenericInterface *storage = static_cast(GetAndIncSyncInterface()); if (storage == nullptr) { @@ -229,7 +229,16 @@ int RemoteExecutor::CheckPermissions(const std::string &device) { userId, appId, storeId, device, instanceId }, CHECK_FLAG_SEND); if (errCode != E_OK) { LOGE("[RemoteExecutor][CheckPermissions] check permission errCode = %d.", errCode); + storage->DecRefCount(); + return errCode; + } + const auto *requestPacket = inMsg->GetObject(); + if (requestPacket == nullptr) { + LOGE("[RemoteExecutor] get packet object failed"); + storage->DecRefCount(); + return -E_INVALID_ARGS; } + errCode = CheckRemoteRecvData(device, storage, requestPacket->GetSecLabel()); storage->DecRefCount(); return errCode; } @@ -712,6 +721,17 @@ void RemoteExecutor::ClearInnerSource() int RemoteExecutor::FillRequestPacket(RemoteExecutorRequestPacket *packet, uint32_t sessionId, std::string &target) { + ISyncInterface *storage = GetAndIncSyncInterface(); + if (storage == nullptr) { + return -E_BUSY; + } + SecurityOption localOption; + int errCode = storage->GetSecurityOption(localOption); + storage->DecRefCount(); + storage = nullptr; + if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { + return -E_SECURITY_OPTION_CHECK_ERROR; + } Task task; { std::lock_guard autoLock(taskLock_); @@ -726,6 +746,7 @@ int RemoteExecutor::FillRequestPacket(RemoteExecutorRequestPacket *packet, uint3 packet->SetSql(task.condition.sql); packet->SetBindArgs(task.condition.bindArgs); packet->SetNeedResponse(); + packet->SetSecLabel(errCode == E_NOT_SUPPORT ? NOT_SURPPORT_SEC_CLASSIFICATION : localOption.securityLabel); target = task.target; return E_OK; } @@ -944,7 +965,7 @@ int RemoteExecutor::CheckSecurityOption(ISyncInterface *storage, ICommunicator * std::string device; communicator->GetLocalIdentity(device); SecurityOption localOption; - int errCode = static_cast(storage)->GetSecurityOption(localOption); + int errCode = storage->GetSecurityOption(localOption); if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { return -E_SECURITY_OPTION_CHECK_ERROR; } @@ -958,4 +979,24 @@ int RemoteExecutor::CheckSecurityOption(ISyncInterface *storage, ICommunicator * } return errCode; } + +int RemoteExecutor::CheckRemoteRecvData(const std::string &device, SyncGenericInterface *storage, + int32_t remoteSecLabel) +{ + SecurityOption localOption; + int errCode = storage->GetSecurityOption(localOption); + if (errCode == -E_NOT_SUPPORT) { + return E_OK; + } + if (errCode != E_OK) { + return -E_SECURITY_OPTION_CHECK_ERROR; + } + if (remoteSecLabel == UNKNOWN_SECURITY_LABEL || remoteSecLabel == NOT_SURPPORT_SEC_CLASSIFICATION) { + return E_OK; + } + if (RuntimeContext::GetInstance()->CheckDeviceSecurityAbility(device, localOption)) { + return E_OK; + } + return -E_SECURITY_OPTION_CHECK_ERROR; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h index f7c1fdd8..8c369574 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h @@ -93,7 +93,7 @@ private: int ReceiveRemoteExecutorAck(const std::string &targetDev, Message *inMsg); - int CheckPermissions(const std::string &device); + int CheckPermissions(const std::string &device, Message *inMsg); int SendRemoteExecutorData(const std::string &device, const Message *inMsg); @@ -143,6 +143,7 @@ private: ICommunicator *GetAndIncCommunicator() const; ISyncInterface *GetAndIncSyncInterface() const; + static int CheckRemoteRecvData(const std::string &device, SyncGenericInterface *storage, int32_t remoteSecLabel); std::mutex taskLock_; std::map> searchTaskQueue_; // key is device, value is sessionId queue diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.cpp index 5c0360a5..999bb0a4 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.cpp @@ -95,6 +95,7 @@ uint32_t RemoteExecutorRequestPacket::CalculateLen() const } } len = Parcel::GetEightByteAlign(len); // 8-byte align + len += Parcel::GetIntLen(); return len; } @@ -120,6 +121,7 @@ int RemoteExecutorRequestPacket::Serialization(Parcel &parcel) const parcel.WriteString(entry.second); } parcel.EightByteAlign(); + parcel.WriteInt(secLabel_); if (parcel.IsError()) { return -E_PARSE_FAIL; } @@ -155,6 +157,9 @@ int RemoteExecutorRequestPacket::DeSerialization(Parcel &parcel) extraConditions_[conditionKey] = conditionVal; } parcel.EightByteAlign(); + if (version_ >= REQUEST_PACKET_VERSION_V3) { + parcel.ReadInt(secLabel_); + } if (parcel.IsError()) { return -E_PARSE_FAIL; } @@ -176,6 +181,16 @@ void RemoteExecutorRequestPacket::SetBindArgs(const std::vector &bi preparedStmt_.SetBindArgs(bindArgs); } +void RemoteExecutorRequestPacket::SetSecLabel(int32_t secLabel) +{ + secLabel_ = secLabel; +} + +int32_t RemoteExecutorRequestPacket::GetSecLabel() const +{ + return secLabel_; +} + RemoteExecutorRequestPacket* RemoteExecutorRequestPacket::Create() { return new (std::nothrow) RemoteExecutorRequestPacket(); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h index d5549709..5d25262c 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h @@ -59,18 +59,24 @@ public: void SetBindArgs(const std::vector &bindArgs); + void SetSecLabel(int32_t secLabel); + + int32_t GetSecLabel() const; + static RemoteExecutorRequestPacket* Create(); static void Release(RemoteExecutorRequestPacket *&packet); static const uint32_t REQUEST_PACKET_VERSION_V1 = SOFTWARE_VERSION_RELEASE_6_0; static const uint32_t REQUEST_PACKET_VERSION_V2 = SOFTWARE_VERSION_RELEASE_6_0 + 1; - static const uint32_t REQUEST_PACKET_VERSION_CURRENT = REQUEST_PACKET_VERSION_V2; + static const uint32_t REQUEST_PACKET_VERSION_V3 = SOFTWARE_VERSION_RELEASE_6_0 + 2; + static const uint32_t REQUEST_PACKET_VERSION_CURRENT = REQUEST_PACKET_VERSION_V3; private: uint32_t version_ = 0u; uint32_t flag_ = 0u; // 0x01 mean need reply ack PreparedStmt preparedStmt_; std::map extraConditions_; + int32_t secLabel_ = UNKNOWN_SECURITY_LABEL; // source sec label }; class RemoteExecutorAckPacket : public ISyncPacket { diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp index 736f7821..05e9fcfc 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync.cpp @@ -66,13 +66,16 @@ int SingleVerDataSync::Initialize(ISyncInterface *inStorage, ICommunicator *inCo int SingleVerDataSync::SyncStart(int mode, SingleVerSyncTaskContext *context) { std::lock_guard lock(lock_); + int errCode = CheckPermitSendData(mode, context); + if (errCode != E_OK) { + return errCode; + } if (sessionId_ != 0) { // auto sync timeout resend return ReSendData(context); } ResetSyncStatus(mode, context); LOGI("[DataSync] SendStart,mode=%d,label=%s,device=%s", mode_, label_.c_str(), STR_MASK(deviceId_)); int tmpMode = SyncOperation::TransferSyncMode(mode); - int errCode = E_OK; if (tmpMode == SyncModeType::PUSH) { errCode = PushStart(context); } else if (tmpMode == SyncModeType::PUSH_AND_PULL) { @@ -100,6 +103,10 @@ int SingleVerDataSync::SyncStart(int mode, SingleVerSyncTaskContext *context) int SingleVerDataSync::InnerSyncStart(SingleVerSyncTaskContext *context) { + int errCode = CheckPermitSendData(mode_, context); + if (errCode != E_OK) { + return errCode; + } while (true) { if (windowSize_ <= 0 || isAllDataHasSent_) { LOGD("[DataSync] InnerDataSync winSize=%d,isAllSent=%d,label=%s,device=%s", windowSize_, isAllDataHasSent_, @@ -111,7 +118,6 @@ int SingleVerDataSync::InnerSyncStart(SingleVerSyncTaskContext *context) LOGE("[DataSync] unexpected error"); return -E_INVALID_ARGS; } - int errCode; context->IncSequenceId(); if (mode == SyncModeType::PUSH || mode == SyncModeType::PUSH_AND_PULL) { errCode = PushStart(context); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_types.h b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_types.h index 29253e54..26323c90 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_types.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_types.h @@ -76,6 +76,7 @@ struct InternalSyncParma { QuerySyncObject syncQuery; }; +constexpr int32_t UNKNOWN_SECURITY_LABEL = -1; constexpr int NOT_SURPPORT_SEC_CLASSIFICATION = 0xff; constexpr uint8_t QUERY_SYNC_MODE_BASE = SyncModeType::QUERY_PUSH; constexpr int AUTO_RETRY_TIMES = 3; diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index 77c10fd7..4f241312 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -25,6 +25,7 @@ config("module_private_config") { "./unittest/common/interfaces", "../include", "../interfaces/include", + "../interfaces/include/cloud", "../interfaces/include/relational", "../interfaces/src", "../interfaces/src/relational", @@ -185,6 +186,7 @@ ohos_source_set("src_file") { "../storage/src/relationaldb_properties.cpp", "../storage/src/result_entries_window.cpp", "../storage/src/single_ver_natural_store_commit_notify_data.cpp", + "../storage/src/sqlite/cloud_sync_log_table_manager.cpp", "../storage/src/sqlite/collaboration_log_table_manager.cpp", "../storage/src/sqlite/log_table_manager_factory.cpp", "../storage/src/sqlite/query_object.cpp", @@ -454,6 +456,10 @@ distributeddb_unittest("DistributedDBInterfacesNBDelegateTest") { ] } +distributeddb_unittest("DistributedDBInterfacesRelationalExtTest") { + sources = [ "unittest/common/interfaces/distributeddb_interfaces_relational_ext_test.cpp" ] +} + distributeddb_unittest("DistributedDBCommonTest") { sources = [ "unittest/common/common/distributeddb_common_test.cpp" ] } @@ -812,6 +818,7 @@ group("unittest") { ":DistributedDBInterfacesNBUnpublishTest", ":DistributedDBInterfacesQueryDBTest", ":DistributedDBInterfacesRegisterSyncDBTest", + ":DistributedDBInterfacesRelationalExtTest", ":DistributedDBInterfacesRelationalRoutinesTest", ":DistributedDBInterfacesRelationalSyncTest", ":DistributedDBInterfacesSchemaDatabaseUpgradeTest", diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp index 1685bbc1..7ccaf5da 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_log_test.cpp @@ -15,6 +15,7 @@ #include +#include "cloud_store_types.h" #include "log_table_manager_factory.h" #include "native_sqlite.h" #include "split_device_log_table_manager.h" @@ -58,7 +59,8 @@ void DistributedDBInterfacesLogTest::TearDown() HWTEST_F(DistributedDBInterfacesLogTest, DBFactoryTest001, TestSize.Level1) { DistributedTableMode mode = DistributedTableMode::COLLABORATION; - auto tableManager = LogTableManagerFactory::GetTableManager(mode); + TableSyncType tableSyncType = TableSyncType::DEVICE_COOPERATION; + auto tableManager = LogTableManagerFactory::GetTableManager(mode, tableSyncType); EXPECT_TRUE(tableManager != nullptr); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_ext_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_ext_test.cpp new file mode 100644 index 00000000..9a24320e --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_ext_test.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "db_common.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "relational_store_manager.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { +constexpr const char *DB_SUFFIX = ".db"; +constexpr const char *STORE_ID = "Relational_Store_ID"; +std::string g_dbDir; +std::string g_testDir; +DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + +constexpr int E_OK = 0; +constexpr int E_ERROR = 1; +const int WAIT_TIME = 1000; // 1000ms +constexpr static uint64_t TO_100_NS = 10; // 1us to 100ns +const uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000; + +class DistributedDBInterfacesRelationalExtTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp() override; + void TearDown() override; +}; + +void DistributedDBInterfacesRelationalExtTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +void DistributedDBInterfacesRelationalExtTest::TearDownTestCase(void) +{ +} + +void DistributedDBInterfacesRelationalExtTest::SetUp() +{ +} + +void DistributedDBInterfacesRelationalExtTest::TearDown() +{ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +static int GetCurrentSysTimeIn100Ns(uint64_t &outTime) +{ + struct timeval rawTime; + int errCode = gettimeofday(&rawTime, nullptr); + if (errCode < 0) { + return -E_ERROR; + } + outTime = static_cast(rawTime.tv_sec) * MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS + + static_cast(rawTime.tv_usec); + outTime *= TO_100_NS; + return E_OK; +} + +/** + * @tc.name: GetRawSysTimeTest001 + * @tc.desc: Test get_raw_sys_time has been registered in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalExtTest, GetRawSysTimeTest001, TestSize.Level0) +{ + const std::string sql = "select get_raw_sys_time();"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime] (sqlite3_stmt *stmt) { + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(static_cast(sqlite3_column_int64(stmt, 0) - curTime) < diff); + return OK; + }), SQLITE_OK); + + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void PrepareData(const std::string &tableName, bool primaryKeyIsRowId) +{ + /** + * @tc.steps:step1. create db, create table. + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + std::string sql; + if (primaryKeyIsRowId) { + sql = "create table " + tableName + "(rowid INTEGER primary key, id int, name TEXT);"; + } else { + sql = "create table " + tableName + "(rowid int, id int, name TEXT, PRIMARY KEY(id, name));"; + } + + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + + /** + * @tc.steps:step2. create distributed table. + * @tc.expected: step2. return ok. + */ + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + EXPECT_EQ(delegate->CreateDistributedTable(tableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_mgr.CloseStore(delegate), OK); + delegate = nullptr; +} + +/** + * @tc.name: InsertTriggerTest001 + * @tc.desc: Test insert trigger in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalExtTest, InsertTriggerTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData(tableName, false); + + /** + * @tc.steps:step2. insert data into sync_data_tmp. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. select data from log table. + * @tc.expected: step3. return ok. + */ + sql = "select * from " + DBConstant::RELATIONAL_PREFIX + tableName + "_log;"; + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + + int resultCount = 0; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql, nullptr, [curTime, &resultCount] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is rowid + std::string device = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index + int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(wtimestamp - timestamp < diff); + EXPECT_TRUE(static_cast(curTime - timestamp) < diff); + EXPECT_EQ(sqlite3_column_int(stmt, 5), 2); // 5 is column index, flag == 2 + resultCount++; + return OK; + }), SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void UpdateTriggerTest(bool primaryKeyIsRowId) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData(tableName, primaryKeyIsRowId); + + /** + * @tc.steps:step2. insert data into sync_data_tmp. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. update data. + * @tc.expected: step3. return ok. + */ + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + sql = "update " + tableName + " set name = 'lisi';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step4. select data from log table. + * @tc.expected: step4. return ok. + */ + sql = "select * from " + DBConstant::RELATIONAL_PREFIX + tableName + "_log;"; + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + + int resultCnt = 0; + std::function sqliteCallBack = [curTime, primaryKeyIsRowId, &resultCnt] (sqlite3_stmt *stmt) { + if (!primaryKeyIsRowId && resultCnt == 0) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), -1); + EXPECT_EQ(sqlite3_column_int(stmt, 5), 3); // 5 is column index, flag == 3 + } else { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), 2); // 2 is rowid + EXPECT_EQ(sqlite3_column_int(stmt, 5), 2); // 5 is column index, flag == 2 + } + + std::string device = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index + EXPECT_EQ(oriDevice, ""); + + int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index + int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(timestamp - wtimestamp > diff); + EXPECT_TRUE(static_cast(curTime - timestamp) < diff); + + resultCnt++; + return OK; + }; + + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql, nullptr, sqliteCallBack), SQLITE_OK); + if (primaryKeyIsRowId) { + EXPECT_EQ(resultCnt, 1); + } else { + EXPECT_EQ(resultCnt, 2); // 2 is log records count + } + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +/** + * @tc.name: UpdateTriggerTest001 + * @tc.desc: Test update trigger in sqlite for primary key is not row id + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalExtTest, UpdateTriggerTest001, TestSize.Level0) +{ + UpdateTriggerTest(false); +} + +/** + * @tc.name: UpdateTriggerTest002 + * @tc.desc: Test update trigger in sqlite for primary key is row id + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalExtTest, UpdateTriggerTest002, TestSize.Level0) +{ + UpdateTriggerTest(true); +} + +/** + * @tc.name: DeleteTriggerTest001 + * @tc.desc: Test delete trigger in sqlite + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalExtTest, DeleteTriggerTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData(tableName, true); + + /** + * @tc.steps:step2. insert data into sync_data_tmp. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = "insert into " + tableName + " VALUES(2, 1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step3. delete data. + * @tc.expected: step3. return ok. + */ + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); + sql = "delete from " + tableName + " where name = 'zhangsan';"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + + /** + * @tc.steps:step4. select data from log table. + * @tc.expected: step4. return ok. + */ + sql = "select * from " + DBConstant::RELATIONAL_PREFIX + tableName + "_log;"; + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeIn100Ns(curTime); + EXPECT_EQ(errCode, E_OK); + + int resultCount = 0; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql, nullptr, + [curTime, &resultCount] (sqlite3_stmt *stmt) { + EXPECT_EQ(sqlite3_column_int64(stmt, 0), -1); + EXPECT_EQ(sqlite3_column_int(stmt, 5), 3); // 5 is column index, flag == 3 + + std::string device = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, device), E_OK); + EXPECT_EQ(device, ""); + std::string oriDevice = ""; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 2, oriDevice), E_OK); // 2 is column index, + EXPECT_EQ(oriDevice, ""); + + int64_t timestamp = sqlite3_column_int64(stmt, 3); // 3 is column index + int64_t wtimestamp = sqlite3_column_int64(stmt, 4); // 4 is column index + int64_t diff = MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS * TO_100_NS; + EXPECT_TRUE(timestamp - wtimestamp > diff); + EXPECT_TRUE(static_cast(curTime - timestamp) < diff); + + resultCount++; + return OK; + }), SQLITE_OK); + EXPECT_EQ(resultCount, 1); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp index a974f4a7..4d9a77dd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp @@ -82,6 +82,33 @@ namespace { void FakeOldVersionDB(sqlite3 *db) { + std::string dropLogTable = "drop table naturalbase_rdb_aux_student_1_log;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, dropLogTable), SQLITE_OK); + dropLogTable = "drop table naturalbase_rdb_aux_sync_data_log;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, dropLogTable), SQLITE_OK); + + std::string createLogTable = "CREATE TABLE naturalbase_rdb_aux_student_1_log(" \ + "data_key INT NOT NULL," \ + "device BLOB," \ + "ori_device BLOB," \ + "timestamp INT NOT NULL," \ + "wtimestamp INT NOT NULL," \ + "flag INT NOT NULL," \ + "hash_key BLOB NOT NULL," \ + "PRIMARY KEY(hash_key));"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, createLogTable), SQLITE_OK); + + createLogTable = "CREATE TABLE naturalbase_rdb_aux_sync_data_log(" \ + "data_key INT NOT NULL," \ + "device BLOB," \ + "ori_device BLOB," \ + "timestamp INT NOT NULL," \ + "wtimestamp INT NOT NULL," \ + "flag INT NOT NULL," \ + "hash_key BLOB NOT NULL," \ + "PRIMARY KEY(hash_key));"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, createLogTable), SQLITE_OK); + std::string dropTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_student_1_ON_UPDATE;"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, dropTrigger), SQLITE_OK); @@ -525,7 +552,7 @@ HWTEST_F(DistributedDBInterfacesRelationalSyncTest, UpgradeTriggerTest001, TestS " flag=0x03 WHERE hash_key=calc_hash(OLD.'id') AND flag&0x02=0x02;\n" "\t INSERT OR REPLACE INTO naturalbase_rdb_aux_student_1_log VALUES (NEW.rowid, '', '', get_sys_time(0), " "get_last_time(), CASE WHEN (calc_hash(NEW.'id') != calc_hash(NEW.'id')) " \ - "THEN 0x02 ELSE 0x22 END, calc_hash(NEW.'id'));\n" + "THEN 0x02 ELSE 0x22 END, calc_hash(NEW.'id'), '');\n" "END"; EXPECT_TRUE(resultTrigger == expectTrigger); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp index 52e3b789..016d9a9f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -34,72 +34,71 @@ using namespace DistributedDBUnitTest; using namespace std; namespace { - constexpr const char* DB_SUFFIX = ".db"; - constexpr const char* STORE_ID = "Relational_Store_ID"; - std::string g_testDir; - std::string g_dbDir; - DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); - - const std::string DEVICE_A = "real_device"; - const std::string DEVICE_B = "deviceB"; - VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr; - RelationalVirtualDevice *g_deviceB = nullptr; - - const std::string NORMAL_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS sync_data(" \ - "key BLOB NOT NULL UNIQUE," \ - "value BLOB," \ - "timestamp INT NOT NULL," \ - "flag INT NOT NULL," \ - "device BLOB," \ - "ori_device BLOB," \ - "hash_key BLOB PRIMARY KEY NOT NULL," \ - "w_timestamp INT," \ - "UNIQUE(device, ori_device));" \ - "CREATE INDEX key_index ON sync_data (key, flag);"; - - const std::string SIMPLE_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS t1(a INT, b TEXT)"; - - const std::string CREATE_TABLE_SQL_NO_PRIMARY_KEY = "CREATE TABLE IF NOT EXISTS sync_data(" \ - "key BLOB NOT NULL UNIQUE," \ - "value BLOB," \ - "timestamp INT NOT NULL," \ - "flag INT NOT NULL," \ - "device BLOB," \ - "ori_device BLOB," \ - "hash_key BLOB NOT NULL," \ - "w_timestamp INT," \ - "UNIQUE(device, ori_device));" \ - "CREATE INDEX key_index ON sync_data (key, flag);"; - - const std::string UNSUPPORTED_FIELD_TABLE_SQL = "CREATE TABLE IF NOT EXISTS test('$.ID' INT, val BLOB);"; - - const std::string COMPOSITE_PRIMARY_KEY_TABLE_SQL = R"(CREATE TABLE workers ( - worker_id INTEGER, - last_name VARCHAR NOT NULL, - first_name VARCHAR, - join_date DATE, - PRIMARY KEY (last_name, first_name) - );)"; - - const std::string INSERT_SYNC_DATA_SQL = "INSERT OR REPLACE INTO sync_data (key, timestamp, flag, hash_key) " - "VALUES('KEY', 123456789, 1, 'HASH_KEY');"; - - const std::string INVALID_TABLE_FIELD_SQL = "create table if not exists t1 ('1 = 1; --' int primary key, b blob)"; - - void PrepareVirtualDeviceEnv(const std::string &tableName, const std::string &dbPath, - const std::vector &remoteDeviceVec) - { - sqlite3 *db = RelationalTestUtils::CreateDataBase(dbPath); - ASSERT_NE(db, nullptr); - TableInfo tableInfo; - SQLiteUtils::AnalysisSchema(db, tableName, tableInfo); - for (const auto &dev : remoteDeviceVec) { - std::vector fieldInfoList = tableInfo.GetFieldInfos(); - dev->SetLocalFieldInfo(fieldInfoList); - dev->SetTableInfo(tableInfo); - } - EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +constexpr const char* DB_SUFFIX = ".db"; +constexpr const char* STORE_ID = "Relational_Store_ID"; +std::string g_testDir; +std::string g_dbDir; +DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + +const std::string DEVICE_A = "real_device"; +const std::string DEVICE_B = "deviceB"; +VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr; +RelationalVirtualDevice *g_deviceB = nullptr; + +const std::string NORMAL_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS sync_data(" \ + "key BLOB NOT NULL UNIQUE," \ + "value BLOB," \ + "timestamp INT NOT NULL," \ + "flag INT NOT NULL," \ + "device BLOB," \ + "ori_device BLOB," \ + "hash_key BLOB PRIMARY KEY NOT NULL," \ + "w_timestamp INT," \ + "UNIQUE(device, ori_device));" \ + "CREATE INDEX key_index ON sync_data(key, flag);"; + +const std::string SIMPLE_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS t1(a INT, b TEXT)"; + +const std::string CREATE_TABLE_SQL_NO_PRIMARY_KEY = "CREATE TABLE IF NOT EXISTS sync_data(" \ + "key BLOB NOT NULL UNIQUE," \ + "value BLOB," \ + "timestamp INT NOT NULL," \ + "flag INT NOT NULL," \ + "device BLOB," \ + "ori_device BLOB," \ + "hash_key BLOB NOT NULL," \ + "w_timestamp INT," \ + "UNIQUE(device, ori_device));" \ + "CREATE INDEX key_index ON sync_data (key, flag);"; + +const std::string UNSUPPORTED_FIELD_TABLE_SQL = "CREATE TABLE IF NOT EXISTS test('$.ID' INT, val BLOB);"; + +const std::string COMPOSITE_PRIMARY_KEY_TABLE_SQL = R"(CREATE TABLE workers ( + worker_id INTEGER, + last_name VARCHAR NOT NULL, + first_name VARCHAR, + join_date DATE, + PRIMARY KEY (last_name, first_name) + );)"; + +const std::string INSERT_SYNC_DATA_SQL = "INSERT OR REPLACE INTO sync_data (key, timestamp, flag, hash_key) " + "VALUES('KEY', 123456789, 1, 'HASH_KEY');"; + +const std::string INVALID_TABLE_FIELD_SQL = "create table if not exists t1 ('1 = 1; --' int primary key, b blob)"; + +void PrepareVirtualDeviceEnv(const std::string &tableName, const std::string &dbPath, + const std::vector &remoteDeviceVec) +{ + sqlite3 *db = RelationalTestUtils::CreateDataBase(dbPath); + ASSERT_NE(db, nullptr); + TableInfo tableInfo; + SQLiteUtils::AnalysisSchema(db, tableName, tableInfo); + for (const auto &dev : remoteDeviceVec) { + std::vector fieldInfoList = tableInfo.GetFieldInfos(); + dev->SetLocalFieldInfo(fieldInfoList); + dev->SetTableInfo(tableInfo); } + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } class DistributedDBInterfacesRelationalTest : public testing::Test { @@ -156,14 +155,7 @@ void DistributedDBInterfacesRelationalTest::TearDown(void) } } -/** - * @tc.name: RelationalStoreTest001 - * @tc.desc: Test open store and create distributed db - * @tc.type: FUNC - * @tc.require: AR000GK58F - * @tc.author: lianhuix - */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize.Level1) +void NoramlCreateDistributedTableTest(TableSyncType tableSyncType) { /** * @tc.steps:step1. Prepare db file @@ -185,11 +177,11 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize EXPECT_EQ(status, OK); ASSERT_NE(delegate, nullptr); - status = delegate->CreateDistributedTable("sync_data"); + status = delegate->CreateDistributedTable("sync_data", tableSyncType); EXPECT_EQ(status, OK); // test create same table again - status = delegate->CreateDistributedTable("sync_data"); + status = delegate->CreateDistributedTable("sync_data", tableSyncType); EXPECT_EQ(status, OK); status = g_mgr.CloseStore(delegate); @@ -216,6 +208,30 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize EXPECT_EQ(status, OK); } +/** + * @tc.name: RelationalStoreTest001 + * @tc.desc: Test open store and create distributed db with DEVICE_COOPERATION type + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001, TestSize.Level1) +{ + NoramlCreateDistributedTableTest(DistributedDB::DEVICE_COOPERATION); +} + +/** + * @tc.name: RelationalStoreTest001 + * @tc.desc: Test open store and create distributed db with CLOUD_COOPERATION type + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest001_1, TestSize.Level1) +{ + NoramlCreateDistributedTableTest(DistributedDB::CLOUD_COOPERATION); +} + /** * @tc.name: RelationalStoreTest002 * @tc.desc: Test open store with invalid path or store ID @@ -299,14 +315,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest003, TestSize ASSERT_EQ(delegate, nullptr); } -/** - * @tc.name: RelationalStoreTest004 - * @tc.desc: Test create distributed table with over limit - * @tc.type: FUNC - * @tc.require: AR000GK58F - * @tc.author: lianhuix - */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004, TestSize.Level1) +void CreateDistributedTableOverLimitTest(TableSyncType tableSyncTpe) { /** * @tc.steps:step1. Prepare db file with multiple tables @@ -316,7 +325,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004, TestSize ASSERT_NE(db, nullptr); EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); const int tableCount = DBConstant::MAX_DISTRIBUTED_TABLE_COUNT + 10; // 10: additional size for test abnormal scene - for (int i=0; iCreateDistributedTable("TEST_" + std::to_string(i)), OK); + EXPECT_EQ(delegate->CreateDistributedTable("TEST_" + std::to_string(i), tableSyncTpe), OK); } else { - EXPECT_NE(delegate->CreateDistributedTable("TEST_" + std::to_string(i)), OK); + EXPECT_NE(delegate->CreateDistributedTable("TEST_" + std::to_string(i), tableSyncTpe), OK); } } @@ -349,13 +358,30 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004, TestSize } /** - * @tc.name: RelationalStoreTest005 - * @tc.desc: Test create distributed table with invalid table name + * @tc.name: RelationalStoreTest004 + * @tc.desc: Test create distributed table with over limit for DEVICE_COOPERATION type * @tc.type: FUNC * @tc.require: AR000GK58F * @tc.author: lianhuix */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize.Level1) +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004, TestSize.Level1) +{ + CreateDistributedTableOverLimitTest(DistributedDB::DEVICE_COOPERATION); +} + +/** + * @tc.name: RelationalStoreTest004 + * @tc.desc: Test create distributed table with over limit for CLOUD_COOPERATION type + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest004_1, TestSize.Level1) +{ + CreateDistributedTableOverLimitTest(DistributedDB::CLOUD_COOPERATION); +} + +void CreateDistributedTableInvalidArgsTest(TableSyncType tableSyncType) { /** * @tc.steps:step1. Prepare db file @@ -379,21 +405,25 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize * @tc.steps:step3. Create distributed table with invalid table name * @tc.expected: step3. Create distributed table failed. */ - EXPECT_NE(delegate->CreateDistributedTable(DBConstant::SYSTEM_TABLE_PREFIX + "_tmp"), OK); + EXPECT_NE(delegate->CreateDistributedTable(DBConstant::SYSTEM_TABLE_PREFIX + "_tmp", tableSyncType), OK); - EXPECT_EQ(delegate->CreateDistributedTable("Handle-J@^."), INVALID_ARGS); + EXPECT_EQ(delegate->CreateDistributedTable("Handle-J@^.", tableSyncType), INVALID_ARGS); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", + static_cast(DistributedDB::DEVICE_COOPERATION - 1)), INVALID_ARGS); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", + static_cast(DistributedDB::CLOUD_COOPERATION + 1)), INVALID_ARGS); EXPECT_EQ(RelationalTestUtils::ExecSql(db, INVALID_TABLE_FIELD_SQL), SQLITE_OK); - EXPECT_EQ(delegate->CreateDistributedTable("t1"), NOT_SUPPORT); + EXPECT_EQ(delegate->CreateDistributedTable("t1", tableSyncType), NOT_SUPPORT); /** * @tc.steps:step4. Create distributed table temp table or not exist table * @tc.expected: step4. Create distributed table failed. */ - EXPECT_EQ(delegate->CreateDistributedTable("child"), NOT_FOUND); + EXPECT_EQ(delegate->CreateDistributedTable("child", tableSyncType), NOT_FOUND); std::string tempTableSql = "CREATE TEMP TABLE child(x, y, z)"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, tempTableSql), SQLITE_OK); - EXPECT_EQ(delegate->CreateDistributedTable("child"), NOT_FOUND); + EXPECT_EQ(delegate->CreateDistributedTable("child", tableSyncType), NOT_FOUND); /** * @tc.steps:step5. Close store @@ -405,13 +435,30 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize } /** - * @tc.name: RelationalStoreTest006 - * @tc.desc: Test create distributed table with non primary key schema + * @tc.name: RelationalStoreTest005 + * @tc.desc: Test create distributed table with invalid table name or invalid table sync type * @tc.type: FUNC * @tc.require: AR000GK58F * @tc.author: lianhuix */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize.Level1) +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize.Level1) +{ + CreateDistributedTableInvalidArgsTest(DistributedDB::DEVICE_COOPERATION); +} + +/** + * @tc.name: RelationalStoreTest005 + * @tc.desc: Test create distributed table with invalid table name or invalid table sync type + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005_1, TestSize.Level1) +{ + CreateDistributedTableInvalidArgsTest(DistributedDB::CLOUD_COOPERATION); +} + +void CreateDistributedTableNonPrimaryKeyTest(TableSyncType tableSyncType) { /** * @tc.steps:step1. Prepare db file @@ -433,10 +480,10 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize ASSERT_NE(delegate, nullptr); /** - * @tc.steps:step3. Create distributed table with invalid table name - * @tc.expected: step3. Create distributed table failed. + * @tc.steps:step3. Create distributed table with valid table name + * @tc.expected: step3. Create distributed table success. */ - EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", tableSyncType), OK); /** * @tc.steps:step4. Close store @@ -455,13 +502,30 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize } /** - * @tc.name: RelationalStoreTest007 - * @tc.desc: Test create distributed table with table has invalid field name + * @tc.name: RelationalStoreTest006 + * @tc.desc: Test create distributed table with non primary key schema * @tc.type: FUNC * @tc.require: AR000GK58F * @tc.author: lianhuix */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest007, TestSize.Level1) +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize.Level1) +{ + CreateDistributedTableNonPrimaryKeyTest(DistributedDB::DEVICE_COOPERATION); +} + +/** + * @tc.name: RelationalStoreTest006 + * @tc.desc: Test create distributed table with non primary key schema + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006_1, TestSize.Level1) +{ + CreateDistributedTableNonPrimaryKeyTest(DistributedDB::CLOUD_COOPERATION); +} + +void CreateDistributedTableInvalidFieldTest(TableSyncType tableSyncType) { sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); ASSERT_NE(db, nullptr); @@ -474,19 +538,36 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest007, TestSize EXPECT_EQ(status, OK); ASSERT_NE(delegate, nullptr); - EXPECT_EQ(delegate->CreateDistributedTable("test"), NOT_SUPPORT); + EXPECT_EQ(delegate->CreateDistributedTable("test", tableSyncType), NOT_SUPPORT); status = g_mgr.CloseStore(delegate); EXPECT_EQ(status, OK); } /** - * @tc.name: RelationalStoreTest008 - * @tc.desc: Test create distributed table with table has composite primary keys + * @tc.name: RelationalStoreTest007 + * @tc.desc: Test create distributed table with table has invalid field name * @tc.type: FUNC * @tc.require: AR000GK58F * @tc.author: lianhuix */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest008, TestSize.Level1) +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest007, TestSize.Level1) +{ + CreateDistributedTableInvalidFieldTest(DistributedDB::DEVICE_COOPERATION); +} + +/** + * @tc.name: RelationalStoreTest007 + * @tc.desc: Test create distributed table with table has invalid field name + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest007_1, TestSize.Level1) +{ + CreateDistributedTableInvalidFieldTest(DistributedDB::CLOUD_COOPERATION); +} + +void CreateDistributedTableCompositePKTest(TableSyncType tableSyncType, int expectCode) { sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); ASSERT_NE(db, nullptr); @@ -499,19 +580,36 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest008, TestSize EXPECT_EQ(status, OK); ASSERT_NE(delegate, nullptr); - EXPECT_EQ(delegate->CreateDistributedTable("workers"), NOT_SUPPORT); + EXPECT_EQ(delegate->CreateDistributedTable("workers", tableSyncType), expectCode); status = g_mgr.CloseStore(delegate); EXPECT_EQ(status, OK); } /** - * @tc.name: RelationalStoreTest009 - * @tc.desc: Test create distributed table with table has history data + * @tc.name: RelationalStoreTest008 + * @tc.desc: Test create distributed table with table has composite primary keys for DEVICE_COOPERATION * @tc.type: FUNC * @tc.require: AR000GK58F * @tc.author: lianhuix */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest009, TestSize.Level1) +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest008, TestSize.Level1) +{ + CreateDistributedTableCompositePKTest(DistributedDB::DEVICE_COOPERATION, NOT_SUPPORT); +} + +/** + * @tc.name: RelationalStoreTest008 + * @tc.desc: Test create distributed table with table has composite primary keys for CLOUD_COOPERATION + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest008_1, TestSize.Level1) +{ + CreateDistributedTableCompositePKTest(DistributedDB::CLOUD_COOPERATION, OK); +} + +void CreateDistributedTableWithHistoryDataTest(TableSyncType tableSyncType) { sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); ASSERT_NE(db, nullptr); @@ -530,9 +628,31 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest009, TestSize EXPECT_EQ(status, OK); } +/** + * @tc.name: RelationalStoreTest009 + * @tc.desc: Test create distributed table with table has history data for DEVICE_COOPERATION + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest009, TestSize.Level1) +{ + CreateDistributedTableWithHistoryDataTest(DistributedDB::DEVICE_COOPERATION); +} + +/** + * @tc.name: RelationalStoreTest009 + * @tc.desc: Test create distributed table with table has history data for CLOUD_COOPERATION + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest009_1, TestSize.Level1) +{ + CreateDistributedTableWithHistoryDataTest(DistributedDB::CLOUD_COOPERATION); +} -namespace { -void TableModifyTest(const std::string &modifySql, DBStatus expect) +void TableModifyTest(const std::string &modifySql, TableSyncType tableSyncType, DBStatus expect) { /** * @tc.steps:step1. Prepare db file @@ -560,7 +680,7 @@ void TableModifyTest(const std::string &modifySql, DBStatus expect) * @tc.steps:step3. Create distributed table * @tc.expected: step3. Create distributed table OK. */ - EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", tableSyncType), OK); /** * @tc.steps:step4. Upgrade table with modifySql @@ -572,7 +692,7 @@ void TableModifyTest(const std::string &modifySql, DBStatus expect) * @tc.steps:step5. Create distributed table again * @tc.expected: step5. Create distributed table return expect. */ - EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), expect); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", tableSyncType), expect); /** * @tc.steps:step6. Close store @@ -582,7 +702,6 @@ void TableModifyTest(const std::string &modifySql, DBStatus expect) EXPECT_EQ(status, OK); EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } -} /** * @tc.name: RelationalTableModifyTest001 @@ -593,7 +712,8 @@ void TableModifyTest(const std::string &modifySql, DBStatus expect) */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, TestSize.Level1) { - TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL DEFAULT 123;", OK); + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL DEFAULT 123;", + DistributedDB::DEVICE_COOPERATION, OK); } /** @@ -605,7 +725,8 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, Te */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, TestSize.Level1) { - TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL;", SCHEMA_MISMATCH); + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL;", + DistributedDB::DEVICE_COOPERATION, SCHEMA_MISMATCH); } /** @@ -617,17 +738,50 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, Te */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest003, TestSize.Level1) { - TableModifyTest("ALTER TABLE sync_data DROP COLUMN w_timestamp;", SCHEMA_MISMATCH); + TableModifyTest("ALTER TABLE sync_data DROP COLUMN w_timestamp;", + DistributedDB::DEVICE_COOPERATION, SCHEMA_MISMATCH); } /** - * @tc.name: RelationalTableModifyTest004 - * @tc.desc: Test upgrade distributed table with device table exists + * @tc.name: RelationalTableModifyTest001 + * @tc.desc: Test modify distributed table with compatible upgrade * @tc.type: FUNC - * @tc.require: AR000GK58F - * @tc.author: lianhuix + * @tc.require: + * @tc.author: zhangshijie */ -HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, TestSize.Level1) +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001_1, TestSize.Level1) +{ + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL DEFAULT 123;", + DistributedDB::CLOUD_COOPERATION, OK); +} + +/** + * @tc.name: RelationalTableModifyTest002 + * @tc.desc: Test modify distributed table with incompatible upgrade + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002_1, TestSize.Level1) +{ + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL;", + DistributedDB::CLOUD_COOPERATION, SCHEMA_MISMATCH); +} + +/** + * @tc.name: RelationalTableModifyTest003 + * @tc.desc: Test modify distributed table with incompatible upgrade + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest003_1, TestSize.Level1) +{ + TableModifyTest("ALTER TABLE sync_data DROP COLUMN w_timestamp;", + DistributedDB::CLOUD_COOPERATION, SCHEMA_MISMATCH); +} + +void UpgradeDistributedTableTest(TableSyncType tableSyncType) { /** * @tc.steps:step1. Prepare db file @@ -654,7 +808,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, Te * @tc.steps:step3. Create distributed table * @tc.expected: step3. Create distributed table OK. */ - EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", tableSyncType), OK); /** * @tc.steps:step4. Upgrade table @@ -672,7 +826,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, Te * @tc.steps:step5. Create distributed table again * @tc.expected: step5. Create distributed table return expect. */ - EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", tableSyncType), OK); /** * @tc.steps:step6. Close store @@ -683,6 +837,30 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, Te EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } +/** + * @tc.name: RelationalTableModifyTest004 + * @tc.desc: Test upgrade distributed table with device table exists + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, TestSize.Level1) +{ + UpgradeDistributedTableTest(DistributedDB::DEVICE_COOPERATION); +} + +/** + * @tc.name: RelationalTableModifyTest004 + * @tc.desc: Test upgrade distributed table with device table exists + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004_1, TestSize.Level1) +{ + UpgradeDistributedTableTest(DistributedDB::CLOUD_COOPERATION); +} + /** * @tc.name: RelationalTableModifyTest005 * @tc.desc: Test modify distributed table with compatible upgrade @@ -692,7 +870,21 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest004, Te */ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest005, TestSize.Level1) { - TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field STRING NOT NULL DEFAULT 'asdf';", OK); + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field STRING NOT NULL DEFAULT 'asdf';", + DistributedDB::DEVICE_COOPERATION, OK); +} + +/** + * @tc.name: RelationalTableModifyTest005 + * @tc.desc: Test modify distributed table with compatible upgrade + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest005_1, TestSize.Level1) +{ + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field STRING NOT NULL DEFAULT 'asdf';", + DistributedDB::CLOUD_COOPERATION, OK); } /** @@ -755,7 +947,6 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest00 EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); } -namespace { struct TableT1 { int a; std::string b; @@ -794,7 +985,6 @@ void AddDeviceSchema(RelationalVirtualDevice *device, sqlite3 *db, const std::st device->SetLocalFieldInfo(table.GetFieldInfos()); device->SetTableInfo(table); } -} /** * @tc.name: RelationalRemoveDeviceDataTest002 @@ -916,6 +1106,7 @@ void TestRemoveDeviceDataWithCallback(bool removeAll) EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); RuntimeConfig::SetTranslateToDeviceIdCallback(nullptr); } + /** * @tc.name: RelationalRemoveDeviceDataTest003 * @tc.desc: Test remove all device data and sync again @@ -1114,40 +1305,40 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePressureTest0 } namespace { -void ProcessSync(RelationalStoreDelegate *delegate) -{ - std::vector devices = {DEVICE_B}; - Query query = Query::Select("create").EqualTo("create", 1); - DBStatus status = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, - [&devices](const std::map> &devicesMap) { - EXPECT_EQ(devicesMap.size(), devices.size()); - EXPECT_EQ(devicesMap.at(DEVICE_B)[0].status, OK); - }, true); - EXPECT_EQ(status, OK); + void ProcessSync(RelationalStoreDelegate *delegate) + { + std::vector devices = {DEVICE_B}; + Query query = Query::Select("create").EqualTo("create", 1); + DBStatus status = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + EXPECT_EQ(devicesMap.at(DEVICE_B)[0].status, OK); + }, true); + EXPECT_EQ(status, OK); - std::vector data; - g_deviceB->GetAllSyncData("create", data); - EXPECT_EQ(data.size(), 1u); - - VirtualRowData virtualRowData; - DataValue d1; - d1 = static_cast(2); // 2: test data - virtualRowData.objectData.PutDataValue("create", d1); - DataValue d2; - d2.SetText("hello"); - virtualRowData.objectData.PutDataValue("ddd", d2); - DataValue d3; - d3.SetText("hello"); - virtualRowData.objectData.PutDataValue("eee", d3); - virtualRowData.logInfo.timestamp = 1; - g_deviceB->PutData("create", {virtualRowData}); - status = delegate->Sync(devices, SyncMode::SYNC_MODE_PULL_ONLY, query, - [&devices](const std::map> &devicesMap) { - EXPECT_EQ(devicesMap.size(), devices.size()); - EXPECT_EQ(devicesMap.at(DEVICE_B)[0].status, OK); - }, true); - EXPECT_EQ(status, OK); -} + std::vector data; + g_deviceB->GetAllSyncData("create", data); + EXPECT_EQ(data.size(), 1u); + + VirtualRowData virtualRowData; + DataValue d1; + d1 = static_cast(2); // 2: test data + virtualRowData.objectData.PutDataValue("create", d1); + DataValue d2; + d2.SetText("hello"); + virtualRowData.objectData.PutDataValue("ddd", d2); + DataValue d3; + d3.SetText("hello"); + virtualRowData.objectData.PutDataValue("eee", d3); + virtualRowData.logInfo.timestamp = 1; + g_deviceB->PutData("create", {virtualRowData}); + status = delegate->Sync(devices, SyncMode::SYNC_MODE_PULL_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + EXPECT_EQ(devicesMap.at(DEVICE_B)[0].status, OK); + }, true); + EXPECT_EQ(status, OK); + } } /** @@ -1164,7 +1355,7 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, SqliteKeyWordTest001, TestSize.L EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); std::string tableSql = "CREATE TABLE IF NOT EXISTS 'create' ('create' INTEGER PRIMARY KEY, b 'CREATE', " \ - "c TEXT DEFAULT 'DEFAULT', UNIQUE(b, c))"; + "c TEXT DEFAULT 'DEFAULT', UNIQUE(b, c))"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, tableSql), SQLITE_OK); std::string indexSql = "CREATE INDEX IF NOT EXISTS 'index' on 'create' (b)"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, indexSql), SQLITE_OK); @@ -1231,4 +1422,128 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, GetDistributedTableName001, Test devTableName = RelationalStoreManager::GetDistributedTableName("", tableName); EXPECT_EQ(devTableName, DBConstant::RELATIONAL_PREFIX + tableName + "_"); RuntimeConfig::SetTranslateToDeviceIdCallback(nullptr); +} + +/** + * @tc.name: CloudRelationalStoreTest001 + * @tc.desc: Test create distributed table in cloud table sync type + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare db file + * @tc.expected: step1. Return OK. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. open relational store, create distributed table with CLOUD_COOPERATION + * @tc.expected: step2. Return OK. + */ + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + + status = delegate->CreateDistributedTable("sync_data", DistributedDB::CLOUD_COOPERATION); + EXPECT_EQ(status, OK); + + /** + * @tc.steps:step3. open relational store, create distributed table with CLOUD_COOPERATION again + * @tc.expected: step3. Return OK. + */ + status = delegate->CreateDistributedTable("sync_data", DistributedDB::CLOUD_COOPERATION); + EXPECT_EQ(status, OK); + + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); +} + +/** + * @tc.name: CloudRelationalStoreTest002 + * @tc.desc: Test create distributed table in diff table sync type for the same table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare db file + * @tc.expected: step1. Return OK. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. open relational store, create distributed table with DEVICE_COOPERATION + * @tc.expected: step2. Return OK. + */ + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + + status = delegate->CreateDistributedTable("sync_data", DistributedDB::DEVICE_COOPERATION); + EXPECT_EQ(status, OK); + + /** + * @tc.steps:step3. create distributed table with CLOUD_COOPERATION again + * @tc.expected: step3. Return TYPE_MISMATCH. + */ + status = delegate->CreateDistributedTable("sync_data", DistributedDB::CLOUD_COOPERATION); + EXPECT_EQ(status, TYPE_MISMATCH); + + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + delegate = nullptr; + + /** + * @tc.steps:step4. drop table sync_data and create again + * @tc.expected: step4. Return OK. + */ + db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + const std::string dropSql = "drop table sync_data;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, dropSql), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step5. open relational store, create distributed table with CLOUD_COOPERATION + * @tc.expected: step5. Return OK. + */ + status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + + db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + EXPECT_EQ(delegate->CreateDistributedTable("sync_data", DistributedDB::CLOUD_COOPERATION), OK); + + /** + * @tc.steps:step6. create distributed table with DEVICE_COOPERATION again + * @tc.expected: step6. Return TYPE_MISMATCH. + */ + status = delegate->CreateDistributedTable("sync_data", DistributedDB::DEVICE_COOPERATION); + EXPECT_EQ(status, TYPE_MISMATCH); + + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + delegate = nullptr; +} } \ No newline at end of file -- Gitee