diff --git a/services/distributeddataservice/libs/distributeddb/BUILD.gn b/services/distributeddataservice/libs/distributeddb/BUILD.gn index 2ccb0157535f71c18e73321ad8a105192fe1641b..48d81beae207700d4ff664b86b2401035824a9ac 100755 --- a/services/distributeddataservice/libs/distributeddb/BUILD.gn +++ b/services/distributeddataservice/libs/distributeddb/BUILD.gn @@ -66,6 +66,7 @@ ohos_shared_library("distributeddb") { sources = [ "common/src/auto_launch.cpp", "common/src/data_compression.cpp", + "common/src/data_value.cpp", "common/src/db_ability.cpp", "common/src/db_common.cpp", "common/src/db_constant.cpp", @@ -91,6 +92,7 @@ ohos_shared_library("distributeddb") { "common/src/relational/relational_schema_object.cpp", "common/src/runtime_context.cpp", "common/src/runtime_context_impl.cpp", + "common/src/schema_constant.cpp", "common/src/schema_object.cpp", "common/src/schema_utils.cpp", "common/src/semaphore_utils.cpp", @@ -122,7 +124,7 @@ ohos_shared_library("distributeddb") { "interfaces/src/kv_store_nb_delegate_impl.cpp", "interfaces/src/kv_store_result_set_impl.cpp", "interfaces/src/kv_store_snapshot_delegate_impl.cpp", - "interfaces/src/relational/data_value.cpp", + "interfaces/src/relational/relational_store_changed_data_impl.cpp", "interfaces/src/relational/relational_store_delegate_impl.cpp", "interfaces/src/relational/relational_store_manager.cpp", "interfaces/src/relational/relational_store_sqlite_ext.cpp", @@ -217,7 +219,9 @@ ohos_shared_library("distributeddb") { "syncer/src/single_ver_data_message_schedule.cpp", "syncer/src/single_ver_data_packet.cpp", "syncer/src/single_ver_data_sync.cpp", + "syncer/src/single_ver_kv_sync_task_context.cpp", "syncer/src/single_ver_kv_syncer.cpp", + "syncer/src/single_ver_relational_sync_task_context.cpp", "syncer/src/single_ver_relational_syncer.cpp", "syncer/src/single_ver_serialize_manager.cpp", "syncer/src/single_ver_sync_engine.cpp", diff --git a/services/distributeddataservice/libs/distributeddb/common/include/auto_launch.h b/services/distributeddataservice/libs/distributeddb/common/include/auto_launch.h index 53bed5681e2f487dc18cd85579147386e6e97d61..32fba1c509a430d4b322b19c17176a008bf56cc5 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/auto_launch.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/auto_launch.h @@ -19,12 +19,16 @@ #include #include #include -#include "types_export.h" -#include "kv_store_observer.h" -#include "kvdb_properties.h" +#include "auto_launch_export.h" +#include "db_properties.h" #include "ikvdb_connection.h" #include "icommunicator_aggregator.h" -#include "auto_launch_export.h" +#include "kv_store_observer.h" +#include "kvdb_properties.h" +#include "types_export.h" +#include "relational_store_connection.h" +#include "relationaldb_properties.h" +#include "store_observer.h" namespace DistributedDB { enum class AutoLaunchItemState { @@ -35,19 +39,27 @@ enum class AutoLaunchItemState { IDLE, }; +enum class DBType { + DB_KV = 0, + DB_RELATION, + DB_INVALID, +}; + struct AutoLaunchItem { - KvDBProperties properties; + std::shared_ptr propertiesPtr; AutoLaunchNotifier notifier; KvStoreObserver *observer = nullptr; int conflictType = 0; KvStoreNbConflictNotifier conflictNotifier; - IKvDBConnection *conn = nullptr; + void *conn = nullptr; KvDBObserverHandle *observerHandle = nullptr; bool isWriteOpenNotifiered = false; AutoLaunchItemState state = AutoLaunchItemState::UN_INITIAL; bool isDisable = false; bool inObserver = false; bool isAutoSync = true; + DBType type = DBType::DB_INVALID; + StoreObserver *storeObserver = nullptr; }; class AutoLaunch { @@ -67,23 +79,24 @@ public: void GetAutoLaunchSyncDevices(const std::string &identifier, std::vector &devices) const; - void SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback); + void SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback, DBType type); - static int GetAutoLaunchProperties(const AutoLaunchParam ¶m, KvDBProperties &properties); + static int GetAutoLaunchProperties(const AutoLaunchParam ¶m, const DBType &openType, + std::shared_ptr &propertiesPtr); -private: +protected: int EnableKvStoreAutoLaunchParmCheck(AutoLaunchItem &autoLaunchItem, const std::string &identifier); - int GetConnectionInEnable(AutoLaunchItem &autoLaunchItem, const std::string &identifier); + int GetKVConnectionInEnable(AutoLaunchItem &autoLaunchItem, const std::string &identifier); - IKvDBConnection *GetOneConnection(const KvDBProperties &properties, int &errCode); + static int OpenOneConnection(AutoLaunchItem &autoLaunchItem); // we will return errCode, if errCode != E_OK - int CloseConnectionStrict(AutoLaunchItem &autoLaunchItem); + static int CloseConnectionStrict(AutoLaunchItem &autoLaunchItem); // before ReleaseDatabaseConnection, if errCode != E_OK, we not return, we try close more - void TryCloseConnection(AutoLaunchItem &autoLaunchItem); + virtual void TryCloseConnection(AutoLaunchItem &autoLaunchItem); int RegisterObserverAndLifeCycleCallback(AutoLaunchItem &autoLaunchItem, const std::string &identifier, bool isExt); @@ -104,7 +117,7 @@ private: void ReceiveUnknownIdentifierCallBackTask(const std::string &identifier); - void CloseNotifier(const AutoLaunchItem &autoLaunchItem); + static void CloseNotifier(const AutoLaunchItem &autoLaunchItem); void ConnectionLifeCycleCallback(const std::string &identifier); @@ -122,7 +135,28 @@ private: void ExtConnectionLifeCycleCallbackTask(const std::string &identifier); - int SetConflictNotifier(IKvDBConnection *conn, int conflictType, const KvStoreNbConflictNotifier ¬ifier); + static int SetConflictNotifier(AutoLaunchItem &autoLaunchItem); + + int ExtAutoLaunchRequestCallBack(const std::string &identifier, AutoLaunchParam ¶m, DBType &openType); + + static int GetAutoLaunchKVProperties(const AutoLaunchParam ¶m, + const std::shared_ptr &propertiesPtr); + + static int GetAutoLaunchRelationProperties(const AutoLaunchParam ¶m, + const std::shared_ptr &propertiesPtr); + + static int OpenKvConnection(AutoLaunchItem &autoLaunchItem); + + static int OpenRelationalConnection(AutoLaunchItem &autoLaunchItem); + + int RegisterLifeCycleCallback(AutoLaunchItem &autoLaunchItem, const std::string &identifier, + bool isExt); + + static int PragmaAutoSync(AutoLaunchItem &autoLaunchItem); + + void TryCloseKvConnection(AutoLaunchItem &autoLaunchItem); + + void TryCloseRelationConnection(AutoLaunchItem &autoLaunchItem); mutable std::mutex dataLock_; mutable std::mutex communicatorLock_; @@ -132,7 +166,7 @@ private: std::condition_variable cv_; std::mutex extLock_; - AutoLaunchRequestCallback autoLaunchRequestCallback_; + std::map autoLaunchRequestCallbackMap_; std::map extItemMap_; }; } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/data_value.h b/services/distributeddataservice/libs/distributeddb/common/include/data_value.h similarity index 90% rename from services/distributeddataservice/libs/distributeddb/interfaces/include/data_value.h rename to services/distributeddataservice/libs/distributeddb/common/include/data_value.h index ed5add66725a1e99b5ef765a90c2864c640f77b3..ae53ab5b695a7038ba1bd12b06cc623c09a23bc9 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/data_value.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/data_value.h @@ -63,9 +63,9 @@ public: // move constructor DataValue(DataValue &&dataValue) noexcept; DataValue &operator=(DataValue &&dataValue) noexcept; - DataValue &operator=(const bool &boolVal); - DataValue &operator=(const int64_t &intVal); - DataValue &operator=(const double &doubleVal); + DataValue &operator=(bool boolVal); + DataValue &operator=(int64_t intVal); + DataValue &operator=(double doubleVal); DataValue &operator=(const Blob &blob); DataValue &operator=(const std::string &string); int Set(Blob *&blob); @@ -79,7 +79,10 @@ public: int GetInt64(int64_t &outVal) const; int GetDouble(double &outVal) const; int GetBlob(Blob *&outVal) const; + int SetBlob(const Blob &val); int GetBlob(Blob &outVal) const; + int SetText(const std::string &val); + int SetText(const uint8_t *val, uint32_t length); int GetText(std::string &outVal) const; void ResetValue(); int GetBlobLength(uint32_t &length) const; @@ -104,6 +107,7 @@ public: int GetString(const std::string &fieldName, std::string &outValue) const; int GetBlob(const std::string &fieldName, Blob &blob) const; void PutDataValue(const std::string &fieldName, const DataValue &value); + int GetDataValue(const std::string &fieldName, DataValue &value) const; private: mutable std::map fieldData; }; diff --git a/services/distributeddataservice/libs/distributeddb/common/include/db_common.h b/services/distributeddataservice/libs/distributeddb/common/include/db_common.h index 3dedbdd0dfd1f067c875f0c9d4838df13fcafa39..e9faf72cd587d2e3152833fac4cd62c591d426b2 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/db_common.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/db_common.h @@ -19,7 +19,7 @@ #include #include #include "db_types.h" -#include "types.h" +#include "store_types.h" #include "kvdb_properties.h" namespace DistributedDB { @@ -54,6 +54,10 @@ public: const std::string &storeId); static std::string StringMasking(const std::string &oriStr, size_t remain = 3); // remain 3 unmask + + static std::string GetDistributedTableName(const std::string &device, const std::string &tableName); + + static void GetDeviceFromName(const std::string &deviceTableName, std::string &deviceHash, std::string &tableName); }; // Define short macro substitute for original long expression for convenience of using diff --git a/services/distributeddataservice/libs/distributeddb/common/include/db_constant.h b/services/distributeddataservice/libs/distributeddb/common/include/db_constant.h index ca7403d54a9b62296153b397995d59f70d6f89bb..1d56d55f6ed0ac78fca3c4cb0ea681614d23efae 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/db_constant.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/db_constant.h @@ -122,6 +122,10 @@ public: static constexpr uint64_t MAX_LOG_SIZE_LOW = 0x400000ULL; // 4MB static constexpr uint64_t MAX_LOG_SIZE_DEFAULT = 0x40000000ULL; // 1GB + static constexpr int DEF_LIFE_CYCLE_TIME = 60000; // 60S + + static const int RELATIONAL_LOG_TABLE_FIELD_NUM = 7; // field num is relational distributed log table + // For relational static const std::string RELATIONAL_PREFIX; static const std::string TIMESTAMP_ALIAS; diff --git a/services/distributeddataservice/libs/distributeddb/common/include/db_errno.h b/services/distributeddataservice/libs/distributeddb/common/include/db_errno.h index d76ab568fddca1b877c47a53c9e8b187757f45c9..c2bfadeda849b609ef30d8be5ad6698f081ddb6a 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/db_errno.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/db_errno.h @@ -138,10 +138,16 @@ constexpr int E_VALUE_MISMATCH_FEILD_COUNT = (E_BASE + 182); // Value mismatch s constexpr int E_VALUE_MISMATCH_FEILD_TYPE = (E_BASE + 183); // Value mismatch schema in field type constexpr int E_VALUE_MISMATCH_CONSTRAINT = (E_BASE + 184); // Value mismatch schema in constraint constexpr int E_VALUE_MISMATCH_OTHER_REASON = (E_BASE + 185); // Value mismatch schema in other reason +constexpr int E_RELATIONAL_TABLE_EQUAL = (E_BASE + 186); // In table is same +constexpr int E_RELATIONAL_TABLE_COMPATIBLE = (E_BASE + 187); // In table is compatible +constexpr int E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE = (E_BASE + 188); // In table has more fields with default value +constexpr int E_RELATIONAL_TABLE_INCOMPATIBLE = (E_BASE + 189); // In table is incompatible // Num 200+ is reserved for fixed value errno, which should not be changed between time // Message with errorNo of Feedback-type is generated by CommunicatorAggregator without data part(No deserial if exist) constexpr int E_FEEDBACK_UNKNOWN_MESSAGE = (E_BASE + 200); // Unknown message feedback from remote device constexpr int E_FEEDBACK_COMMUNICATOR_NOT_FOUND = (E_BASE + 201); // Communicator not found feedback from remote device +constexpr int E_DISTRIBUTED_SCHEMA_NOT_FOUND = (E_BASE + 202); // Schema was not found in relational distributed tables +constexpr int E_DISTRIBUTED_SCHEMA_CHANGED = (E_BASE + 203); // Schema has change when do sync } // namespace DistributedDB #endif // DISTRIBUTEDDB_ERRNO_H diff --git a/services/distributeddataservice/libs/distributeddb/common/include/parcel.h b/services/distributeddataservice/libs/distributeddb/common/include/parcel.h index 7658f860dcb43a67a02e477aa86eb10754fb84aa..fb42ce19bb8be2a50974f78f6aa7bd4ee346f4b3 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/parcel.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/parcel.h @@ -40,6 +40,8 @@ public: uint32_t ReadBool(bool &data); int WriteInt(int data); uint32_t ReadInt(int &val); + int WriteUInt8(uint8_t data); + uint32_t ReadUInt8(uint8_t &val); int WriteDouble(double data); uint32_t ReadDouble(double &val); int WriteInt64(int64_t data); @@ -77,13 +79,13 @@ public: len = HostToNet(len); if (bufPtr_ == nullptr || stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_) { LOGE("[WriteVector] bufPtr:%d, stepLen:%llu, totalLen:%llu, parcelLen:%llu", - bufPtr_ != nullptr, stepLen, totalLen_, parcelLen_); + bufPtr_ != nullptr, ULL(stepLen), ULL(totalLen_), ULL(parcelLen_)); isError_ = true; return -E_PARSE_FAIL; } errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &len, sizeof(uint32_t)); if (errCode != EOK) { - LOGE("[ReadVector] totalLen:%llu, parcelLen:%llu", totalLen_, parcelLen_); + LOGE("[ReadVector] totalLen:%llu, parcelLen:%llu", ULL(totalLen_), ULL(parcelLen_)); isError_ = true; return -E_SECUREC_ERROR; } @@ -106,7 +108,7 @@ public: } if (bufPtr_ == nullptr || parcelLen_ + sizeof(uint32_t) > totalLen_ || sizeof(T) > INT32_MAX) { LOGE("[ReadVector] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu", - bufPtr_ != nullptr, totalLen_, parcelLen_, sizeof(T)); + bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T)); isError_ = true; return 0; } @@ -119,7 +121,8 @@ public: } uint64_t stepLen = static_cast(len) * sizeof(T) + sizeof(uint32_t); if (stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_) { - LOGE("[ReadVector] stepLen:%llu, totalLen:%llu, parcelLen:%llu", stepLen, totalLen_, parcelLen_); + LOGE("[ReadVector] stepLen:%llu, totalLen:%llu, parcelLen:%llu", ULL(stepLen), ULL(totalLen_), + ULL(parcelLen_)); isError_ = true; return 0; } @@ -140,6 +143,7 @@ public: void EightByteAlign(); // Avoid reading a single data type across 8 bytes static uint32_t GetBoolLen(); static uint32_t GetIntLen(); + static uint32_t GetUInt8Len(); static uint32_t GetUInt32Len(); static uint32_t GetUInt64Len(); static uint32_t GetInt64Len(); @@ -189,7 +193,7 @@ uint32_t Parcel::ReadInteger(T &integer) } if (bufPtr_ == nullptr || parcelLen_ + sizeof(T) > totalLen_) { LOGE("[ReadInteger] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu", - bufPtr_ != nullptr, totalLen_, parcelLen_, sizeof(T)); + bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T)); isError_ = true; return 0; } @@ -208,14 +212,14 @@ int Parcel::WriteInteger(T integer) } T inData = HostToNet(integer); if (parcelLen_ + sizeof(T) > totalLen_) { - LOGE("[WriteInteger] totalLen:%llu, parcelLen:%llu, sizeof(T):%zu", totalLen_, parcelLen_, sizeof(T)); + LOGE("[WriteInteger] totalLen:%llu, parcelLen:%llu, sizeof(T):%zu", ULL(totalLen_), ULL(parcelLen_), sizeof(T)); isError_ = true; return -E_PARSE_FAIL; } errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &inData, sizeof(T)); if (errCode != EOK) { LOGE("[WriteInteger] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu", - bufPtr_ != nullptr, totalLen_, parcelLen_, sizeof(T)); + bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T)); isError_ = true; return -E_SECUREC_ERROR; } diff --git a/services/distributeddataservice/libs/distributeddb/common/include/relational/relational_schema_object.h b/services/distributeddataservice/libs/distributeddb/common/include/relational/relational_schema_object.h index d13b4c1658296818ed7c27fd26f8b6bad7e35490..767d219d222224f67f5bb81fddcc683b830e3689 100644 --- a/services/distributeddataservice/libs/distributeddb/common/include/relational/relational_schema_object.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/relational/relational_schema_object.h @@ -16,10 +16,10 @@ #define RELATIONAL_SCHEMA_OBJECT_H #ifdef RELATIONAL_STORE #include -#include "parcel.h" -#include "schema.h" #include "data_value.h" #include "json_object.h" +#include "parcel.h" +#include "schema.h" namespace DistributedDB { using CompositeFields = std::vector; @@ -45,6 +45,8 @@ public: // return field define string like ("fieldName": "MY INT(21), NOT NULL, DEFAULT 123") std::string ToAttributeString() const; + + int CompareWithField(const FieldInfo &inField) const; private: std::string fieldName_; std::string dataType_; // Type may be null @@ -78,10 +80,20 @@ public: void AddTrigger(const std::string &triggerName); std::string ToTableInfoString() const; void SetDevId(const std::string &devId); + + int CompareWithTable(const TableInfo &inTableInfo) const; + std::map GetSchemaDefine() const; + std::string GetFieldName(uint32_t cid) const; // cid begin with 0 + bool IsValid() const; + private: void AddFieldDefineString(std::string &attrStr) const; void AddUniqueDefineString(std::string &attrStr) const; void AddIndexDefineString(std::string &attrStr) const; + + int CompareWithTableFields(const std::map &inTableFields) const; + int CompareWithTableIndex(const std::map &inTableIndex) const; + std::string tableName_; std::string devId_; bool autoInc_ = false; // only 'INTEGER PRIMARY KEY' could be defined as 'AUTOINCREMENT' @@ -92,23 +104,27 @@ private: std::map indexDefines_; std::vector triggers_; JsonObject ToJsonObject() const; + mutable std::vector fieldNames_; }; class RelationalSyncOpinion { public: - int CalculateParcelLen(uint32_t softWareVersion) const; - int Serialize(Parcel &parcel, uint32_t softWareVersion) const; - int Deserialization(const Parcel &parcel); - const SyncOpinion &GetTableOpinion(const std::string& tableName) const; + uint32_t CalculateParcelLen(uint32_t softWareVersion) const; + int SerializeData(Parcel &parcel, uint32_t softWareVersion) const; + static int DeserializeData(Parcel &parcel, RelationalSyncOpinion &opinion); + SyncOpinion GetTableOpinion(const std::string& tableName) const; + const std::map &GetOpinions() const; void AddSyncOpinion(const std::string &tableName, const SyncOpinion &opinion); private: std::map opinions_; + static const uint32_t SYNC_OPINION_VERSION = 1; }; class RelationalSyncStrategy { public: - const SyncStrategy &GetTableStrategy(const std::string &tableName) const; + SyncStrategy GetTableStrategy(const std::string &tableName) const; void AddSyncStrategy(const std::string &tableName, const SyncStrategy &strategy); + const std::map &GetStrategies() const; private: std::map strategies_; }; @@ -136,8 +152,12 @@ public: void AddRelationalTable(const TableInfo& tb); + void RemoveRelationalTable(const std::string &tableName); + const std::map &GetTables() const; + std::vector GetTableNames() const; + TableInfo GetTable(const std::string& tableName) const; private: @@ -159,8 +179,10 @@ private: int ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTablePrimaryKey(const JsonObject &inJsonObject, TableInfo &resultTable); + void GenerateSchemaString(); + bool isValid_ = false; // set to true after parse success from string or add at least one relational table - SchemaType schemaType_ = SchemaType::NONE; // Default NONE + SchemaType schemaType_ = SchemaType::RELATIVE; // Default RELATIVE std::string schemaString_; // The minified and valid schemaString std::string schemaVersion_; std::map tables_; diff --git a/services/distributeddataservice/libs/distributeddb/common/include/runtime_context.h b/services/distributeddataservice/libs/distributeddb/common/include/runtime_context.h index ac76d7a6d9da43d02f6b025ac0b264a2be2e5de8..cb20a79510b2d6d59940049e09b9192fe9c17805 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/runtime_context.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/runtime_context.h @@ -20,14 +20,15 @@ #include #include -#include "macro_utils.h" -#include "notification_chain.h" +#include "auto_launch.h" +#include "auto_launch_export.h" #include "icommunicator_aggregator.h" #include "iprocess_system_api_adapter.h" -#include "types_export.h" #include "kv_store_observer.h" #include "kvdb_properties.h" -#include "auto_launch_export.h" +#include "macro_utils.h" +#include "notification_chain.h" +#include "types_export.h" namespace DistributedDB { using TimerId = uint64_t; @@ -85,7 +86,7 @@ public: virtual void GetAutoLaunchSyncDevices(const std::string &identifier, std::vector &devices) const = 0; - virtual void SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) = 0; + virtual void SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback, DBType type) = 0; virtual NotificationChain::Listener *RegisterLockStatusLister(const LockStatusNotifier &action, int &errCode) = 0; @@ -105,6 +106,11 @@ public: // Notify TIME_CHANGE_EVENT. virtual void NotifyTimeStampChanged(TimeOffset offset) const = 0; + + virtual void SetStoreStatusNotifier(const StoreStatusNotifier ¬ifier) = 0; + + virtual void NotifyDatabaseStatusChange(const std::string &userId, const std::string &appId, const std::string &storeId, + const std::string &deviceId, bool onlineStatus) = 0; protected: RuntimeContext() = default; virtual ~RuntimeContext() {} diff --git a/services/distributeddataservice/libs/distributeddb/common/include/schema.h b/services/distributeddataservice/libs/distributeddb/common/include/schema.h index c5670b1c7e6f5bbb8055098784b58daf0be7319b..dffc432ba1880bbee764011c259c03ecaa4c6bd1 100644 --- a/services/distributeddataservice/libs/distributeddb/common/include/schema.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/schema.h @@ -17,7 +17,6 @@ #define SCHEMA_H #include -#include namespace DistributedDB { // SchemaType::NONE represent for KV database which do not have schema. Only invalid SchemaObject is NONE type. @@ -29,11 +28,21 @@ enum class SchemaType : uint8_t { RELATIVE = 3, UNRECOGNIZED = 4 }; + +inline SchemaType ReadSchemaType(uint8_t inType) +{ + if (inType >= static_cast(SchemaType::UNRECOGNIZED)) { + return SchemaType::UNRECOGNIZED; + } + return static_cast(inType); +} + struct SyncOpinion { bool permitSync = false; bool requirePeerConvert = false; bool checkOnReceive = false; }; + struct SyncStrategy { bool permitSync = false; bool convertOnSend = false; diff --git a/services/distributeddataservice/libs/distributeddb/common/include/schema_constant.h b/services/distributeddataservice/libs/distributeddb/common/include/schema_constant.h new file mode 100644 index 0000000000000000000000000000000000000000..1fe1403124e301210b86196e9c792b696e87d620 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/common/include/schema_constant.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 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 SCHEMA_CONSTANT_H +#define SCHEMA_CONSTANT_H + +#include + +// This header is supposed to be included only in source files. Do not include it in any header files. +namespace DistributedDB { +class SchemaConstant final { +public : + static const std::string KEYWORD_SCHEMA_VERSION; + static const std::string KEYWORD_SCHEMA_MODE; + static const std::string KEYWORD_SCHEMA_DEFINE; + static const std::string KEYWORD_SCHEMA_INDEXES; + static const std::string KEYWORD_SCHEMA_SKIPSIZE; + static const std::string KEYWORD_SCHEMA_TYPE; + static const std::string KEYWORD_SCHEMA_TABLE; + static const std::string KEYWORD_INDEX; // For FlatBuffer-Schema + + static const std::string KEYWORD_MODE_STRICT; + static const std::string KEYWORD_MODE_COMPATIBLE; + + static const std::string KEYWORD_TYPE_BOOL; + static const std::string KEYWORD_TYPE_INTEGER; + static const std::string KEYWORD_TYPE_LONG; + static const std::string KEYWORD_TYPE_DOUBLE; + static const std::string KEYWORD_TYPE_STRING; + + static const std::string KEYWORD_ATTR_NOT_NULL; + static const std::string KEYWORD_ATTR_DEFAULT; + static const std::string KEYWORD_ATTR_VALUE_NULL; + static const std::string KEYWORD_ATTR_VALUE_TRUE; + static const std::string KEYWORD_ATTR_VALUE_FALSE; + + static const std::string KEYWORD_TYPE_RELATIVE; + static const std::string SCHEMA_SUPPORT_VERSION; + static const std::string SCHEMA_SUPPORT_VERSION_V2; + + static const uint32_t SCHEMA_META_FEILD_COUNT_MAX; + static const uint32_t SCHEMA_META_FEILD_COUNT_MIN; + static const uint32_t SCHEMA_FEILD_NAME_LENGTH_MAX; + static const uint32_t SCHEMA_FEILD_NAME_LENGTH_MIN; + static const uint32_t SCHEMA_FEILD_NAME_COUNT_MAX; + static const uint32_t SCHEMA_FEILD_NAME_COUNT_MIN; + static const uint32_t SCHEMA_FEILD_PATH_DEPTH_MAX; + static const uint32_t SCHEMA_INDEX_COUNT_MAX; + static const uint32_t SCHEMA_STRING_SIZE_LIMIT; + static const uint32_t SCHEMA_DEFAULT_STRING_SIZE_LIMIT; + static const uint32_t SCHEMA_SKIPSIZE_MAX; + + static const uint32_t SECURE_BYTE_ALIGN; +}; +} // namespace DistributedDB +#endif // SCHEMA_CONSTANT_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/common/include/schema_object.h b/services/distributeddataservice/libs/distributeddb/common/include/schema_object.h index 48621c087bc37a14f9cab56d3d79c2306253fe0f..2049882e1626f16f4316d5c1af7c60a4214ce042 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/schema_object.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/schema_object.h @@ -23,8 +23,9 @@ #endif // OMIT_FLATBUFFER #include "db_types.h" #include "macro_utils.h" -#include "value_object.h" +#include "relational_schema_object.h" #include "schema.h" +#include "value_object.h" namespace DistributedDB { using IndexName = FieldPath; @@ -56,6 +57,9 @@ public: ~SchemaObject() = default; SchemaObject(const SchemaObject &); SchemaObject& operator=(const SchemaObject &); +#ifdef RELATIONAL_STORE + SchemaObject(const TableInfo &tableInfo); // The construct func can only be used for query. +#endif // RELATIONAL_STORE // Move constructor and move assignment is not need currently SchemaObject(SchemaObject &&) = delete; diff --git a/services/distributeddataservice/libs/distributeddb/common/include/schema_utils.h b/services/distributeddataservice/libs/distributeddb/common/include/schema_utils.h index 8848b9188668d24c79a28fb9737cf2cd2df8f7b6..0f353c28a7447bf908a508ad978f7dbfc374cf1e 100755 --- a/services/distributeddataservice/libs/distributeddb/common/include/schema_utils.h +++ b/services/distributeddataservice/libs/distributeddb/common/include/schema_utils.h @@ -21,48 +21,6 @@ // This header is supposed to be included only in source files. Do not include it in any header files. namespace DistributedDB { -const std::string KEYWORD_SCHEMA_VERSION = "SCHEMA_VERSION"; -const std::string KEYWORD_SCHEMA_MODE = "SCHEMA_MODE"; -const std::string KEYWORD_SCHEMA_DEFINE = "SCHEMA_DEFINE"; -const std::string KEYWORD_SCHEMA_INDEXES = "SCHEMA_INDEXES"; -const std::string KEYWORD_SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; -const std::string KEYWORD_SCHEMA_TYPE = "SCHEMA_TYPE"; -const std::string KEYWORD_SCHEMA_TABLE = "TABLES"; -const std::string KEYWORD_INDEX = "INDEX"; // For FlatBuffer-Schema - -const std::string KEYWORD_MODE_STRICT = "STRICT"; -const std::string KEYWORD_MODE_COMPATIBLE = "COMPATIBLE"; - -const std::string KEYWORD_TYPE_BOOL = "BOOL"; -const std::string KEYWORD_TYPE_INTEGER = "INTEGER"; -const std::string KEYWORD_TYPE_LONG = "LONG"; -const std::string KEYWORD_TYPE_DOUBLE = "DOUBLE"; -const std::string KEYWORD_TYPE_STRING = "STRING"; - -const std::string KEYWORD_ATTR_NOT_NULL = "NOT NULL"; -const std::string KEYWORD_ATTR_DEFAULT = "DEFAULT"; -const std::string KEYWORD_ATTR_VALUE_NULL = "null"; -const std::string KEYWORD_ATTR_VALUE_TRUE = "true"; -const std::string KEYWORD_ATTR_VALUE_FALSE = "false"; - -const std::string KEYWORD_TYPE_RELATIVE = "RELATIVE"; - -const uint32_t SCHEMA_META_FEILD_COUNT_MAX = 5; -const uint32_t SCHEMA_META_FEILD_COUNT_MIN = 3; -const uint32_t SCHEMA_FEILD_NAME_LENGTH_MAX = 64; -const uint32_t SCHEMA_FEILD_NAME_LENGTH_MIN = 1; -const uint32_t SCHEMA_FEILD_NAME_COUNT_MAX = 256; -const uint32_t SCHEMA_FEILD_NAME_COUNT_MIN = 1; -const uint32_t SCHEMA_FEILD_PATH_DEPTH_MAX = 4; -const uint32_t SCHEMA_INDEX_COUNT_MAX = 32; -const uint32_t SCHEMA_STRING_SIZE_LIMIT = 524288; // 512K -const uint32_t SCHEMA_DEFAULT_STRING_SIZE_LIMIT = 4096; // 4K -const uint32_t SCHEMA_SKIPSIZE_MAX = 4194302; // 4M - 2 Bytes -const std::string SCHEMA_SUPPORT_VERSION = "1.0"; -const std::string SCHEMA_SUPPORT_VERSION_V2 = "2.0"; - -const uint32_t SECURE_BYTE_ALIGN = 8; // 8 bytes align - class SchemaUtils { public: // Check if any invalid exist, parse it into SchemaAttribute if totally valid and return E_OK @@ -75,7 +33,8 @@ public: // Check if any invalid exist, parse it into FieldPath if totally valid and return E_OK // Each fieldName of the fieldPath will be check valid as well. Path depth will be check. // Prefix and postfix spaces or tabs is allowed. Prefix $. can be not exist. - static int ParseAndCheckFieldPath(const std::string &inPathString, FieldPath &outPath); + // Parameter permitPrefix means whether $. prefix is permited. If not, return E_SCHEMA_PARSE_FAIL. + static int ParseAndCheckFieldPath(const std::string &inPathString, FieldPath &outPath, bool permitPrefix = true); // Return E_OK if it is totally valid. Prefix and postfix spaces or tabs is not allowed. static int CheckFieldName(const FieldName &inName); diff --git a/services/distributeddataservice/libs/distributeddb/common/src/auto_launch.cpp b/services/distributeddataservice/libs/distributeddb/common/src/auto_launch.cpp index b55ad13d8edc6ee87200c1162e0a29e36d85f920..e08cca0fa09168b97f0d19461d608a919bd84585 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/auto_launch.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/auto_launch.cpp @@ -25,6 +25,8 @@ #include "kvdb_pragma.h" #include "log_print.h" #include "param_check_utils.h" +#include "relational_store_instance.h" +#include "relational_store_changed_data_impl.h" #include "runtime_context.h" #include "semaphore_utils.h" #include "sync_able_kvdb_connection.h" @@ -136,14 +138,16 @@ int AutoLaunch::EnableKvStoreAutoLaunch(const KvDBProperties &properties, AutoLa { LOGI("[AutoLaunch] EnableKvStoreAutoLaunch"); std::string identifier = properties.GetStringProp(KvDBProperties::IDENTIFIER_DATA, ""); - AutoLaunchItem autoLaunchItem { properties, notifier, option.observer, option.conflictType, option.notifier }; + std::shared_ptr ptr = std::make_shared(properties); + AutoLaunchItem autoLaunchItem { ptr, notifier, option.observer, option.conflictType, option.notifier }; autoLaunchItem.isAutoSync = option.isAutoSync; + autoLaunchItem.type = DBType::DB_KV; int errCode = EnableKvStoreAutoLaunchParmCheck(autoLaunchItem, identifier); if (errCode != E_OK) { LOGE("[AutoLaunch] EnableKvStoreAutoLaunch failed errCode:%d", errCode); return errCode; } - errCode = GetConnectionInEnable(autoLaunchItem, identifier); + errCode = GetKVConnectionInEnable(autoLaunchItem, identifier); if (errCode == E_OK) { LOGI("[AutoLaunch] EnableKvStoreAutoLaunch ok"); } else { @@ -152,19 +156,21 @@ int AutoLaunch::EnableKvStoreAutoLaunch(const KvDBProperties &properties, AutoLa return errCode; } -int AutoLaunch::GetConnectionInEnable(AutoLaunchItem &autoLaunchItem, const std::string &identifier) +int AutoLaunch::GetKVConnectionInEnable(AutoLaunchItem &autoLaunchItem, const std::string &identifier) { - LOGI("[AutoLaunch] GetConnectionInEnable"); + LOGI("[AutoLaunch] GetKVConnectionInEnable"); int errCode; - autoLaunchItem.conn = KvDBManager::GetDatabaseConnection(autoLaunchItem.properties, errCode, false); + std::shared_ptr properties = + std::static_pointer_cast(autoLaunchItem.propertiesPtr); + autoLaunchItem.conn = KvDBManager::GetDatabaseConnection(*properties, errCode, false); if (errCode == -E_ALREADY_OPENED) { - LOGI("[AutoLaunch] GetConnectionInEnable user already getkvstore by self"); + LOGI("[AutoLaunch] GetKVConnectionInEnable user already getkvstore by self"); std::lock_guard autoLock(dataLock_); autoLaunchItemMap_[identifier].state = AutoLaunchItemState::IDLE; return E_OK; } if (autoLaunchItem.conn == nullptr) { - LOGE("[AutoLaunch] GetConnectionInEnable GetDatabaseConnection errCode:%d", errCode); + LOGE("[AutoLaunch] GetKVConnectionInEnable GetDatabaseConnection errCode:%d", errCode); std::lock_guard autoLock(dataLock_); autoLaunchItemMap_.erase(identifier); return errCode; @@ -175,10 +181,11 @@ int AutoLaunch::GetConnectionInEnable(AutoLaunchItem &autoLaunchItem, const std: isEmpty = onlineDevices_.empty(); } if (isEmpty) { - LOGI("[AutoLaunch] GetConnectionInEnable no online device, ReleaseDatabaseConnection"); - errCode = KvDBManager::ReleaseDatabaseConnection(autoLaunchItem.conn); + LOGI("[AutoLaunch] GetKVConnectionInEnable no online device, ReleaseDatabaseConnection"); + IKvDBConnection *kvConn = static_cast(autoLaunchItem.conn); + errCode = KvDBManager::ReleaseDatabaseConnection(kvConn); if (errCode != E_OK) { - LOGE("[AutoLaunch] GetConnectionInEnable ReleaseDatabaseConnection failed errCode:%d", errCode); + LOGE("[AutoLaunch] GetKVConnectionInEnable ReleaseDatabaseConnection failed errCode:%d", errCode); std::lock_guard autoLock(dataLock_); autoLaunchItemMap_.erase(identifier); return errCode; @@ -193,9 +200,9 @@ int AutoLaunch::GetConnectionInEnable(AutoLaunchItem &autoLaunchItem, const std: autoLaunchItemMap_[identifier].state = AutoLaunchItemState::IDLE; autoLaunchItemMap_[identifier].conn = autoLaunchItem.conn; autoLaunchItemMap_[identifier].observerHandle = autoLaunchItem.observerHandle; - LOGI("[AutoLaunch] GetConnectionInEnable RegisterObserverAndLifeCycleCallback ok"); + LOGI("[AutoLaunch] GetKVConnectionInEnable RegisterObserverAndLifeCycleCallback ok"); } else { - LOGE("[AutoLaunch] GetConnectionInEnable RegisterObserverAndLifeCycleCallback err, do CloseConnection"); + LOGE("[AutoLaunch] GetKVConnectionInEnable RegisterObserverAndLifeCycleCallback err, do CloseConnection"); TryCloseConnection(autoLaunchItem); // do nothing if failed std::lock_guard autoLock(dataLock_); autoLaunchItemMap_.erase(identifier); @@ -211,20 +218,21 @@ int AutoLaunch::CloseConnectionStrict(AutoLaunchItem &autoLaunchItem) LOGI("[AutoLaunch] CloseConnectionStrict conn is nullptr, do nothing"); return E_OK; } - int errCode = autoLaunchItem.conn->RegisterLifeCycleCallback(nullptr); + IKvDBConnection *kvConn = static_cast(autoLaunchItem.conn); + int errCode = kvConn->RegisterLifeCycleCallback(nullptr); if (errCode != E_OK) { LOGE("[AutoLaunch] CloseConnectionStrict RegisterLifeCycleCallback failed errCode:%d", errCode); return errCode; } if (autoLaunchItem.observerHandle != nullptr) { - errCode = autoLaunchItem.conn->UnRegisterObserver(autoLaunchItem.observerHandle); + errCode = kvConn->UnRegisterObserver(autoLaunchItem.observerHandle); if (errCode != E_OK) { LOGE("[AutoLaunch] CloseConnectionStrict UnRegisterObserver failed errCode:%d", errCode); return errCode; } autoLaunchItem.observerHandle = nullptr; } - errCode = KvDBManager::ReleaseDatabaseConnection(autoLaunchItem.conn); + errCode = KvDBManager::ReleaseDatabaseConnection(kvConn); if (errCode != E_OK) { LOGE("[AutoLaunch] CloseConnectionStrict ReleaseDatabaseConnection failed errCode:%d", errCode); } @@ -235,24 +243,16 @@ int AutoLaunch::CloseConnectionStrict(AutoLaunchItem &autoLaunchItem) void AutoLaunch::TryCloseConnection(AutoLaunchItem &autoLaunchItem) { LOGI("[AutoLaunch] TryCloseConnection"); - if (autoLaunchItem.conn == nullptr) { - LOGI("[AutoLaunch] TryCloseConnection conn is nullptr, do nothing"); - return; - } - int errCode = autoLaunchItem.conn->RegisterLifeCycleCallback(nullptr); - if (errCode != E_OK) { - LOGE("[AutoLaunch] TryCloseConnection RegisterLifeCycleCallback failed errCode:%d", errCode); - } - if (autoLaunchItem.observerHandle != nullptr) { - errCode = autoLaunchItem.conn->UnRegisterObserver(autoLaunchItem.observerHandle); - if (errCode != E_OK) { - LOGE("[AutoLaunch] TryCloseConnection UnRegisterObserver failed errCode:%d", errCode); - } - autoLaunchItem.observerHandle = nullptr; - } - errCode = KvDBManager::ReleaseDatabaseConnection(autoLaunchItem.conn); - if (errCode != E_OK) { - LOGE("[AutoLaunch] TryCloseConnection ReleaseDatabaseConnection failed errCode:%d", errCode); + switch (autoLaunchItem.type) { + case DBType::DB_KV: + TryCloseKvConnection(autoLaunchItem); + break; + case DBType::DB_RELATION: + TryCloseRelationConnection(autoLaunchItem); + break; + default: + LOGD("[AutoLaunch] Unknown type[%d] when try to close connection", autoLaunchItem.type); + break; } } @@ -264,51 +264,57 @@ int AutoLaunch::RegisterObserverAndLifeCycleCallback(AutoLaunchItem &autoLaunchI return errCode; } LOGI("[AutoLaunch] RegisterObserver ok"); - if (isExt) { - errCode = autoLaunchItem.conn->RegisterLifeCycleCallback(std::bind( - &AutoLaunch::ExtConnectionLifeCycleCallback, this, std::placeholders::_1)); - } else { - errCode = autoLaunchItem.conn->RegisterLifeCycleCallback(std::bind(&AutoLaunch::ConnectionLifeCycleCallback, - this, std::placeholders::_1)); - } + + errCode = RegisterLifeCycleCallback(autoLaunchItem, identifier, isExt); if (errCode != E_OK) { LOGE("[AutoLaunch] RegisterLifeCycleCallback failed, errCode:%d", errCode); return errCode; } LOGI("[AutoLaunch] RegisterLifeCycleCallback ok"); - errCode = SetConflictNotifier(autoLaunchItem.conn, autoLaunchItem.conflictType, autoLaunchItem.conflictNotifier); + errCode = SetConflictNotifier(autoLaunchItem); if (errCode != E_OK) { LOGE("[AutoLaunch] SetConflictNotifier failed, errCode:%d", errCode); return errCode; } - bool enAutoSync = autoLaunchItem.isAutoSync; - errCode = static_cast(autoLaunchItem.conn)->Pragma(PRAGMA_AUTO_SYNC, - static_cast(&enAutoSync)); - if (errCode != E_OK) { - LOGE("[AutoLaunch] PRAGMA_AUTO_SYNC failed, errCode:%d", errCode); - return errCode; - } - LOGI("[AutoLaunch] set PRAGMA_AUTO_SYNC ok, enAutoSync=%d", enAutoSync); - return errCode; + return PragmaAutoSync(autoLaunchItem); } int AutoLaunch::RegisterObserver(AutoLaunchItem &autoLaunchItem, const std::string &identifier, bool isExt) { - LOGI("[AutoLaunch] RegisterObserver"); if (autoLaunchItem.conn == nullptr) { LOGE("[AutoLaunch] autoLaunchItem.conn is nullptr"); return -E_INTERNAL_ERROR; } + LOGI("[AutoLaunch] RegisterObserver type=%d", autoLaunchItem.type); + if (autoLaunchItem.type == DBType::DB_RELATION) { + RelationalStoreConnection *conn = static_cast(autoLaunchItem.conn); + conn->RegisterObserverAction([autoLaunchItem](const std::string &changedDevice) { + RelationalStoreChangedDataImpl data(changedDevice); + if (autoLaunchItem.propertiesPtr != nullptr) { + data.SetStoreProperty({ + autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::USER_ID, ""), + autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::APP_ID, ""), + autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::STORE_ID, "") + }); + } + if (autoLaunchItem.storeObserver) { + LOGD("begin to observer onchange, changedDevice=%s", STR_MASK(changedDevice)); + autoLaunchItem.storeObserver->OnChange(data); + } + }); + return E_OK; + } int errCode; Key key; KvDBObserverHandle *observerHandle = nullptr; + IKvDBConnection *kvConn = static_cast(autoLaunchItem.conn); if (isExt) { - observerHandle = autoLaunchItem.conn->RegisterObserver(OBSERVER_CHANGES_FOREIGN, key, + observerHandle = kvConn->RegisterObserver(OBSERVER_CHANGES_FOREIGN, key, std::bind(&AutoLaunch::ExtObserverFunc, this, std::placeholders::_1, identifier), errCode); } else { - observerHandle = autoLaunchItem.conn->RegisterObserver(OBSERVER_CHANGES_FOREIGN, key, + observerHandle = kvConn->RegisterObserver(OBSERVER_CHANGES_FOREIGN, key, std::bind(&AutoLaunch::ObserverFunc, this, std::placeholders::_1, identifier), errCode); } @@ -341,9 +347,12 @@ void AutoLaunch::ObserverFunc(const KvDBCommitNotifyData ¬ifyData, const std: autoLaunchItem.observer = autoLaunchItemMap_[identifier].observer; autoLaunchItem.isWriteOpenNotifiered = autoLaunchItemMap_[identifier].isWriteOpenNotifiered; autoLaunchItem.notifier = autoLaunchItemMap_[identifier].notifier; - userId = autoLaunchItemMap_[identifier].properties.GetStringProp(KvDBProperties::USER_ID, ""); - appId = autoLaunchItemMap_[identifier].properties.GetStringProp(KvDBProperties::APP_ID, ""); - storeId = autoLaunchItemMap_[identifier].properties.GetStringProp(KvDBProperties::STORE_ID, ""); + + std::shared_ptr properties = + std::static_pointer_cast(autoLaunchItemMap_[identifier].propertiesPtr); + userId = properties->GetStringProp(KvDBProperties::USER_ID, ""); + appId = properties->GetStringProp(KvDBProperties::APP_ID, ""); + storeId = properties->GetStringProp(KvDBProperties::STORE_ID, ""); } if (autoLaunchItem.observer != nullptr) { LOGI("[AutoLaunch] do user observer"); @@ -440,9 +449,9 @@ void AutoLaunch::GetAutoLaunchSyncDevices(const std::string &identifier, std::ve void AutoLaunch::CloseNotifier(const AutoLaunchItem &autoLaunchItem) { if (autoLaunchItem.notifier) { - std::string userId = autoLaunchItem.properties.GetStringProp(KvDBProperties::USER_ID, ""); - std::string appId = autoLaunchItem.properties.GetStringProp(KvDBProperties::APP_ID, ""); - std::string storeId = autoLaunchItem.properties.GetStringProp(KvDBProperties::STORE_ID, ""); + std::string userId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::USER_ID, ""); + std::string appId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::APP_ID, ""); + std::string storeId = autoLaunchItem.propertiesPtr->GetStringProp(DBProperties::STORE_ID, ""); LOGI("[AutoLaunch] CloseNotifier do autoLaunchItem.notifier"); autoLaunchItem.notifier(userId, appId, storeId, AutoLaunchStatus::WRITE_CLOSED); LOGI("[AutoLaunch] CloseNotifier do autoLaunchItem.notifier finished"); @@ -499,16 +508,17 @@ void AutoLaunch::ConnectionLifeCycleCallback(const std::string &identifier) } } -IKvDBConnection *AutoLaunch::GetOneConnection(const KvDBProperties &properties, int &errCode) +int AutoLaunch::OpenOneConnection(AutoLaunchItem &autoLaunchItem) { LOGI("[AutoLaunch] GetOneConnection"); - IKvDBConnection *conn = KvDBManager::GetDatabaseConnection(properties, errCode, false); - if (errCode == -E_ALREADY_OPENED) { - LOGI("[AutoLaunch] GetOneConnection user already getkvstore by self"); - } else if (conn == nullptr) { - LOGE("[AutoLaunch] GetOneConnection GetDatabaseConnection failed errCode:%d", errCode); + switch (autoLaunchItem.type) { + case DBType::DB_KV: + return OpenKvConnection(autoLaunchItem); + case DBType::DB_RELATION: + return OpenRelationalConnection(autoLaunchItem); + default: + return -E_INVALID_ARGS; } - return conn; } void AutoLaunch::OnlineCallBack(const std::string &device, bool isConnect) @@ -570,8 +580,7 @@ void AutoLaunch::GetConnInDoOpenMap(std::map &doOpe SemaphoreUtils sema(1 - doOpenMap.size()); for (auto &iter : doOpenMap) { int errCode = RuntimeContext::GetInstance()->ScheduleTask([&sema, &iter, this] { - int ret; - iter.second.conn = GetOneConnection(iter.second.properties, ret); + int ret = OpenOneConnection(iter.second); LOGI("[AutoLaunch] GetConnInDoOpenMap GetOneConnection errCode:%d\n", ret); if (iter.second.conn == nullptr) { sema.SendSemaphore(); @@ -623,8 +632,7 @@ void AutoLaunch::ReceiveUnknownIdentifierCallBackTask(const std::string &identif std::lock_guard autoLock(dataLock_); autoLaunchItem = autoLaunchItemMap_[identifier]; } - int errCode; - autoLaunchItem.conn = GetOneConnection(autoLaunchItem.properties, errCode); + int errCode = OpenOneConnection(autoLaunchItem); LOGI("[AutoLaunch] ReceiveUnknownIdentifierCallBack GetOneConnection errCode:%d\n", errCode); if (autoLaunchItem.conn == nullptr) { std::lock_guard autoLock(dataLock_); @@ -691,30 +699,28 @@ EXT: return AutoLaunchExt(identifier); } -void AutoLaunch::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) +void AutoLaunch::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback, DBType type) { - LOGI("[AutoLaunch] SetAutoLaunchRequestCallback"); + LOGI("[AutoLaunch] SetAutoLaunchRequestCallback type[%d]", type); std::lock_guard lock(extLock_); - autoLaunchRequestCallback_ = callback; + if (callback) { + autoLaunchRequestCallbackMap_[type] = callback; + } else if (autoLaunchRequestCallbackMap_.find(type) != autoLaunchRequestCallbackMap_.end()) { + autoLaunchRequestCallbackMap_.erase(type); + } } int AutoLaunch::AutoLaunchExt(const std::string &identifier) { AutoLaunchParam param; - { - std::lock_guard lock(extLock_); - if (!autoLaunchRequestCallback_) { - LOGI("[AutoLaunch] autoLaunchRequestCallback_ is nullptr"); - return -E_NOT_FOUND; // not E_OK is ok for communicator - } - bool needOpen = autoLaunchRequestCallback_(identifier, param); - if (!needOpen) { - LOGI("[AutoLaunch] autoLaunchRequestCallback_ is not need open"); - return -E_NOT_FOUND; // not E_OK is ok for communicator - } + DBType openType = DBType::DB_INVALID; + int errCode = ExtAutoLaunchRequestCallBack(identifier, param, openType); + if (errCode != E_OK) { + return errCode; // not E_OK is ok for communicator } - KvDBProperties properties; - int errCode = AutoLaunch::GetAutoLaunchProperties(param, properties); + + std::shared_ptr ptr; + errCode = AutoLaunch::GetAutoLaunchProperties(param, openType, ptr); if (errCode != E_OK) { LOGE("[AutoLaunch] AutoLaunchExt param check fail errCode:%d", errCode); if (!param.notifier) { @@ -728,9 +734,11 @@ int AutoLaunch::AutoLaunchExt(const std::string &identifier) } return errCode; } - AutoLaunchItem autoLaunchItem{properties, param.notifier, param.option.observer, param.option.conflictType, + AutoLaunchItem autoLaunchItem{ptr, param.notifier, param.option.observer, param.option.conflictType, param.option.notifier}; autoLaunchItem.isAutoSync = param.option.isAutoSync; + autoLaunchItem.type = openType; + autoLaunchItem.storeObserver = param.option.storeObserver; errCode = RuntimeContext::GetInstance()->ScheduleTask(std::bind(&AutoLaunch::AutoLaunchExtTask, this, identifier, autoLaunchItem)); if (errCode != E_OK) { @@ -749,8 +757,7 @@ void AutoLaunch::AutoLaunchExtTask(const std::string identifier, AutoLaunchItem } extItemMap_[identifier] = autoLaunchItem; } - int errCode; - autoLaunchItem.conn = GetOneConnection(autoLaunchItem.properties, errCode); + int errCode = OpenOneConnection(autoLaunchItem); LOGI("[AutoLaunch] AutoLaunchExtTask GetOneConnection errCode:%d", errCode); if (autoLaunchItem.conn == nullptr) { std::lock_guard autoLock(extLock_); @@ -803,9 +810,9 @@ void AutoLaunch::ExtObserverFunc(const KvDBCommitNotifyData ¬ifyData, const s } } - std::string userId = autoLaunchItem.properties.GetStringProp(KvDBProperties::USER_ID, ""); - std::string appId = autoLaunchItem.properties.GetStringProp(KvDBProperties::APP_ID, ""); - std::string storeId = autoLaunchItem.properties.GetStringProp(KvDBProperties::STORE_ID, ""); + std::string userId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::USER_ID, ""); + std::string appId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::APP_ID, ""); + std::string storeId = autoLaunchItem.propertiesPtr->GetStringProp(KvDBProperties::STORE_ID, ""); int retCode = RuntimeContext::GetInstance()->ScheduleTask([notifier, userId, appId, storeId] { LOGI("[AutoLaunch] ExtObserverFunc do user notifier WRITE_OPENED"); notifier(userId, appId, storeId, AutoLaunchStatus::WRITE_OPENED); @@ -836,31 +843,35 @@ void AutoLaunch::ExtConnectionLifeCycleCallbackTask(const std::string &identifie return; } autoLaunchItem = extItemMap_[identifier]; + extItemMap_.erase(identifier); } LOGI("[AutoLaunch] ExtConnectionLifeCycleCallbackTask do CloseConnection"); TryCloseConnection(autoLaunchItem); // do nothing if failed - { - std::lock_guard lock(extLock_); - autoLaunchItem = extItemMap_[identifier]; - extItemMap_.erase(identifier); - } if (autoLaunchItem.isWriteOpenNotifiered) { CloseNotifier(autoLaunchItem); } } -int AutoLaunch::SetConflictNotifier(IKvDBConnection *conn, int conflictType, const KvStoreNbConflictNotifier ¬ifier) +int AutoLaunch::SetConflictNotifier(AutoLaunchItem &autoLaunchItem) { + if (autoLaunchItem.type != DBType::DB_KV) { + LOGD("[AutoLaunch] Current Type[%d] Not Support ConflictNotifier Now", autoLaunchItem.type); + return E_OK; + } + + IKvDBConnection *kvConn = static_cast(autoLaunchItem.conn); + int conflictType = autoLaunchItem.conflictType; + const KvStoreNbConflictNotifier ¬ifier = autoLaunchItem.conflictNotifier; if (conflictType == 0) { return E_OK; } int errCode; if (!notifier) { - errCode = conn->SetConflictNotifier(conflictType, nullptr); + errCode = kvConn->SetConflictNotifier(conflictType, nullptr); goto END; } - errCode = conn->SetConflictNotifier(conflictType, + errCode = kvConn->SetConflictNotifier(conflictType, [conflictType, notifier](const KvDBCommitNotifyData &data) { int resultCode; const std::list entries = data.GetCommitConflicts(resultCode); @@ -888,7 +899,28 @@ END: return errCode; } -int AutoLaunch::GetAutoLaunchProperties(const AutoLaunchParam ¶m, KvDBProperties &properties) +int AutoLaunch::GetAutoLaunchProperties(const AutoLaunchParam ¶m, const DBType &openType, + std::shared_ptr &propertiesPtr) +{ + switch (openType) { + case DBType::DB_KV: { + propertiesPtr = std::make_shared(); + std::shared_ptr kvPtr = std::static_pointer_cast(propertiesPtr); + return GetAutoLaunchKVProperties(param, kvPtr); + } + case DBType::DB_RELATION: { + propertiesPtr = std::make_shared(); + std::shared_ptr rdbPtr = + std::static_pointer_cast(propertiesPtr); + return GetAutoLaunchRelationProperties(param, rdbPtr); + } + default: + return -E_INVALID_ARGS; + } +} + +int AutoLaunch::GetAutoLaunchKVProperties(const AutoLaunchParam ¶m, + const std::shared_ptr &propertiesPtr) { SchemaObject schemaObject; std::string canonicalDir; @@ -898,25 +930,185 @@ int AutoLaunch::GetAutoLaunchProperties(const AutoLaunchParam ¶m, KvDBProper } if (param.option.isEncryptedDb) { - properties.SetPassword(param.option.cipher, param.option.passwd); - } - properties.SetStringProp(KvDBProperties::DATA_DIR, canonicalDir); - properties.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, param.option.createIfNecessary); - properties.SetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, param.option.createDirByStoreIdOnly); - properties.SetBoolProp(KvDBProperties::MEMORY_MODE, false); - properties.SetBoolProp(KvDBProperties::ENCRYPTED_MODE, param.option.isEncryptedDb); - properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); - properties.SetSchema(schemaObject); + propertiesPtr->SetPassword(param.option.cipher, param.option.passwd); + } + propertiesPtr->SetStringProp(KvDBProperties::DATA_DIR, canonicalDir); + propertiesPtr->SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, param.option.createIfNecessary); + propertiesPtr->SetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, param.option.createDirByStoreIdOnly); + propertiesPtr->SetBoolProp(KvDBProperties::MEMORY_MODE, false); + propertiesPtr->SetBoolProp(KvDBProperties::ENCRYPTED_MODE, param.option.isEncryptedDb); + propertiesPtr->SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + propertiesPtr->SetSchema(schemaObject); if (RuntimeContext::GetInstance()->IsProcessSystemApiAdapterValid()) { - properties.SetIntProp(KvDBProperties::SECURITY_LABEL, param.option.secOption.securityLabel); - properties.SetIntProp(KvDBProperties::SECURITY_FLAG, param.option.secOption.securityFlag); + propertiesPtr->SetIntProp(KvDBProperties::SECURITY_LABEL, param.option.secOption.securityLabel); + propertiesPtr->SetIntProp(KvDBProperties::SECURITY_FLAG, param.option.secOption.securityFlag); } - properties.SetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); + propertiesPtr->SetBoolProp(KvDBProperties::COMPRESS_ON_SYNC, param.option.isNeedCompressOnSync); if (param.option.isNeedCompressOnSync) { - properties.SetIntProp(KvDBProperties::COMPRESSION_RATE, + propertiesPtr->SetIntProp(KvDBProperties::COMPRESSION_RATE, ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate)); } - DBCommon::SetDatabaseIds(properties, param.appId, param.userId, param.storeId); + DBCommon::SetDatabaseIds(*propertiesPtr, param.appId, param.userId, param.storeId); + return E_OK; +} + +int AutoLaunch::GetAutoLaunchRelationProperties(const AutoLaunchParam ¶m, + const std::shared_ptr &propertiesPtr) +{ + if (!ParamCheckUtils::CheckStoreParameter(param.storeId, param.appId, param.userId)) { + LOGE("[AutoLaunch] CheckStoreParameter is invalid."); + return -E_INVALID_ARGS; + } + propertiesPtr->SetStringProp(RelationalDBProperties::DATA_DIR, param.path); + propertiesPtr->SetIdentifier(param.userId, param.appId, param.storeId); + return E_OK; +} + +int AutoLaunch::ExtAutoLaunchRequestCallBack(const std::string &identifier, AutoLaunchParam ¶m, DBType &openType) +{ + std::lock_guard lock(extLock_); + if (autoLaunchRequestCallbackMap_.empty()) { + LOGI("[AutoLaunch] autoLaunchRequestCallbackMap_ is empty"); + return -E_NOT_FOUND; // not E_OK is ok for communicator + } + + bool needOpen = false; + for (const auto &[type, callBack] : autoLaunchRequestCallbackMap_) { + needOpen = callBack(identifier, param); + if (needOpen) { + openType = type; + break; + } + } + + if (!needOpen) { + LOGI("[AutoLaunch] autoLaunchRequestCallback is not need open"); + return -E_NOT_FOUND; // not E_OK is ok for communicator + } + // inner error happened + if (openType >= DBType::DB_INVALID) { + LOGW("[AutoLaunch] Unknown DB Type, Ignore the open request"); + return -E_NOT_FOUND; // not E_OK is ok for communicator + } return E_OK; } + +int AutoLaunch::OpenKvConnection(AutoLaunchItem &autoLaunchItem) +{ + std::shared_ptr properties = + std::static_pointer_cast(autoLaunchItem.propertiesPtr); + int errCode = E_OK; + IKvDBConnection *conn = KvDBManager::GetDatabaseConnection(*properties, errCode, false); + if (errCode == -E_ALREADY_OPENED) { + LOGI("[AutoLaunch] GetOneConnection user already getkvstore by self"); + } else if (conn == nullptr) { + LOGE("[AutoLaunch] GetOneConnection GetDatabaseConnection failed errCode:%d", errCode); + } + autoLaunchItem.conn = conn; + return errCode; +} + +int AutoLaunch::OpenRelationalConnection(AutoLaunchItem &autoLaunchItem) +{ + std::shared_ptr properties = + std::static_pointer_cast(autoLaunchItem.propertiesPtr); + int errCode = E_OK; + auto conn = RelationalStoreInstance::GetDatabaseConnection(*properties, errCode); + if (errCode == -E_ALREADY_OPENED) { + LOGI("[AutoLaunch] GetOneConnection user already openstore by self"); + } else if (conn == nullptr) { + LOGE("[AutoLaunch] GetOneConnection GetDatabaseConnection failed errCode:%d", errCode); + } + autoLaunchItem.conn = conn; + return errCode; +} + +int AutoLaunch::RegisterLifeCycleCallback(AutoLaunchItem &autoLaunchItem, const std::string &identifier, + bool isExt) +{ + int errCode = E_OK; + DatabaseLifeCycleNotifier notifier; + if (isExt) { + notifier = std::bind( + &AutoLaunch::ExtConnectionLifeCycleCallback, this, std::placeholders::_1); + } else { + notifier = std::bind(&AutoLaunch::ConnectionLifeCycleCallback, + this, std::placeholders::_1); + } + switch (autoLaunchItem.type) { + case DBType::DB_KV: + errCode = static_cast(autoLaunchItem.conn)->RegisterLifeCycleCallback(notifier); + break; + case DBType::DB_RELATION: + errCode = + static_cast(autoLaunchItem.conn)->RegisterLifeCycleCallback(notifier); + break; + default: + LOGD("[AutoLaunch] Unknown Type[%d]", autoLaunchItem.type); + break; + } + return errCode; +} + +int AutoLaunch::PragmaAutoSync(AutoLaunchItem &autoLaunchItem) +{ + int errCode = E_OK; + if (autoLaunchItem.type != DBType::DB_KV) { + LOGD("[AutoLaunch] Current Type[%d] Not Support AutoSync Now", autoLaunchItem.type); + return errCode; + } + + bool enAutoSync = autoLaunchItem.isAutoSync; + errCode = static_cast(autoLaunchItem.conn)->Pragma(PRAGMA_AUTO_SYNC, + static_cast(&enAutoSync)); + if (errCode != E_OK) { + LOGE("[AutoLaunch] PRAGMA_AUTO_SYNC failed, errCode:%d", errCode); + return errCode; + } + LOGI("[AutoLaunch] set PRAGMA_AUTO_SYNC ok, enAutoSync=%d", enAutoSync); + return errCode; +} + +void AutoLaunch::TryCloseKvConnection(AutoLaunchItem &autoLaunchItem) +{ + LOGI("[AutoLaunch] TryCloseKvConnection"); + if (autoLaunchItem.conn == nullptr) { + LOGI("[AutoLaunch] TryCloseKvConnection conn is nullptr, do nothing"); + return; + } + IKvDBConnection *kvConn = static_cast(autoLaunchItem.conn); + int errCode = kvConn->RegisterLifeCycleCallback(nullptr); + if (errCode != E_OK) { + LOGE("[AutoLaunch] TryCloseKvConnection RegisterLifeCycleCallback failed errCode:%d", errCode); + } + if (autoLaunchItem.observerHandle != nullptr) { + errCode = kvConn->UnRegisterObserver(autoLaunchItem.observerHandle); + if (errCode != E_OK) { + LOGE("[AutoLaunch] TryCloseKvConnection UnRegisterObserver failed errCode:%d", errCode); + } + autoLaunchItem.observerHandle = nullptr; + } + errCode = KvDBManager::ReleaseDatabaseConnection(kvConn); + if (errCode != E_OK) { + LOGE("[AutoLaunch] TryCloseKvConnection ReleaseDatabaseConnection failed errCode:%d", errCode); + } +} + +void AutoLaunch::TryCloseRelationConnection(AutoLaunchItem &autoLaunchItem) +{ + LOGI("[AutoLaunch] TryCloseRelationConnection"); + if (autoLaunchItem.conn == nullptr) { + LOGI("[AutoLaunch] TryCloseRelationConnection conn is nullptr, do nothing"); + return; + } + RelationalStoreConnection *rdbConn = static_cast(autoLaunchItem.conn); + int errCode = rdbConn->RegisterLifeCycleCallback(nullptr); + if (errCode != E_OK) { + LOGE("[AutoLaunch] TryCloseRelationConnection RegisterLifeCycleCallback failed errCode:%d", errCode); + } + errCode = rdbConn->Close(); + if (errCode != E_OK) { + LOGE("[AutoLaunch] TryCloseRelationConnection close connection failed errCode:%d", errCode); + } +} } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/data_value.cpp b/services/distributeddataservice/libs/distributeddb/common/src/data_value.cpp similarity index 87% rename from services/distributeddataservice/libs/distributeddb/interfaces/src/relational/data_value.cpp rename to services/distributeddataservice/libs/distributeddb/common/src/data_value.cpp index 96e70dd485d804dcf879de268d9012a319b9b578..c5c1da5ff0ba6fa2d5c6a85c4a30406d09fc6bfa 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/data_value.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/data_value.cpp @@ -74,11 +74,11 @@ int Blob::WriteBlob(const uint8_t *ptrArray, const uint32_t &size) if (ptr_ == nullptr) { return -E_OUT_OF_MEMORY; } - size_ = size; errno_t errCode = memcpy_s(ptr_, size, ptrArray, size); if (errCode != EOK) { return -E_SECUREC_ERROR; } + size_ = size; return E_OK; } @@ -98,17 +98,8 @@ DataValue::DataValue(const DataValue &dataValue) } DataValue::DataValue(DataValue &&dataValue) noexcept - :type_(dataValue.type_), value_(dataValue.value_) { - switch (type_) { - case StorageType::STORAGE_TYPE_BLOB: - case StorageType::STORAGE_TYPE_TEXT: - dataValue.value_.blobPtr = nullptr; - break; - default: - break; - } - dataValue.ResetValue(); + *this = std::move(dataValue); } DataValue &DataValue::operator=(const DataValue &dataValue) @@ -119,17 +110,17 @@ DataValue &DataValue::operator=(const DataValue &dataValue) ResetValue(); switch (dataValue.type_) { case StorageType::STORAGE_TYPE_BOOL: - dataValue.GetBool(this->value_.bValue); + (void)dataValue.GetBool(this->value_.bValue); break; case StorageType::STORAGE_TYPE_INTEGER: - dataValue.GetInt64(this->value_.iValue); + (void)dataValue.GetInt64(this->value_.iValue); break; case StorageType::STORAGE_TYPE_REAL: - dataValue.GetDouble(this->value_.dValue); + (void)dataValue.GetDouble(this->value_.dValue); break; case StorageType::STORAGE_TYPE_BLOB: case StorageType::STORAGE_TYPE_TEXT: - dataValue.GetBlob(this->value_.blobPtr); + (void)dataValue.GetBlob(this->value_.blobPtr); break; default: break; @@ -157,7 +148,7 @@ DataValue &DataValue::operator=(DataValue &&dataValue) noexcept return *this; } -DataValue &DataValue::operator=(const bool &boolVal) +DataValue &DataValue::operator=(bool boolVal) { ResetValue(); type_ = StorageType::STORAGE_TYPE_BOOL; @@ -165,7 +156,7 @@ DataValue &DataValue::operator=(const bool &boolVal) return *this; } -DataValue &DataValue::operator=(const int64_t &intVal) +DataValue &DataValue::operator=(int64_t intVal) { ResetValue(); type_ = StorageType::STORAGE_TYPE_INTEGER; @@ -173,7 +164,7 @@ DataValue &DataValue::operator=(const int64_t &intVal) return *this; } -DataValue &DataValue::operator=(const double &doubleVal) +DataValue &DataValue::operator=(double doubleVal) { ResetValue(); type_ = StorageType::STORAGE_TYPE_REAL; @@ -183,18 +174,7 @@ DataValue &DataValue::operator=(const double &doubleVal) DataValue &DataValue::operator=(const Blob &blob) { - ResetValue(); - if (blob.GetSize() <= 0) { - return *this; - } - value_.blobPtr = new (std::nothrow) Blob(); - if (value_.blobPtr == nullptr) { - return *this; - } - type_ = StorageType::STORAGE_TYPE_BLOB; - if (blob.GetSize() > 0) { - value_.blobPtr->WriteBlob(blob.GetData(), blob.GetSize()); - } + (void)SetBlob(blob); return *this; } @@ -213,13 +193,7 @@ int DataValue::Set(Blob *&blob) DataValue &DataValue::operator=(const std::string &string) { - ResetValue(); - value_.blobPtr = new (std::nothrow) Blob(); - if (value_.blobPtr == nullptr) { - return *this; - } - type_ = StorageType::STORAGE_TYPE_TEXT; - value_.blobPtr->WriteBlob(reinterpret_cast(string.c_str()), string.size()); + (void)SetText(string); return *this; } @@ -297,6 +271,24 @@ int DataValue::GetBlob(Blob *&outVal) const return outVal->WriteBlob(value_.blobPtr->GetData(), value_.blobPtr->GetSize()); } +int DataValue::SetBlob(const Blob &val) +{ + ResetValue(); + if (val.GetSize() <= 0) { + return E_OK; + } + value_.blobPtr = new(std::nothrow) Blob(); + if (value_.blobPtr == nullptr) { + return -E_OUT_OF_MEMORY; + } + type_ = StorageType::STORAGE_TYPE_BLOB; + int errCode = E_OK; + if (val.GetSize() > 0) { + errCode = value_.blobPtr->WriteBlob(val.GetData(), val.GetSize()); + } + return errCode; +} + int DataValue::GetBlob(Blob &outVal) const { if (type_ != StorageType::STORAGE_TYPE_BLOB && type_ != StorageType::STORAGE_TYPE_TEXT) { @@ -305,6 +297,22 @@ int DataValue::GetBlob(Blob &outVal) const return outVal.WriteBlob(value_.blobPtr->GetData(), value_.blobPtr->GetSize()); } +int DataValue::SetText(const std::string &val) +{ + return SetText(reinterpret_cast(val.c_str()), val.length()); +} + +int DataValue::SetText(const uint8_t *val, uint32_t length) +{ + ResetValue(); + value_.blobPtr = new(std::nothrow) Blob(); + if (value_.blobPtr == nullptr) { + return -E_OUT_OF_MEMORY; + } + type_ = StorageType::STORAGE_TYPE_TEXT; + return value_.blobPtr->WriteBlob(val, length); +} + int DataValue::GetText(std::string &outValue) const { if (type_ != StorageType::STORAGE_TYPE_TEXT) { @@ -312,6 +320,10 @@ int DataValue::GetText(std::string &outValue) const } const uint8_t *data = value_.blobPtr->GetData(); uint32_t len = value_.blobPtr->GetSize(); + if (len == 0) { + outValue = ""; + return E_OK; + } outValue.resize(len); outValue.assign(data, data + len); return E_OK; @@ -436,5 +448,14 @@ void ObjectData::PutDataValue(const std::string &fieldName, const DataValue &val { fieldData[fieldName] = value; } + +int ObjectData::GetDataValue(const std::string &fieldName, DataValue &value) const +{ + if (fieldData.find(fieldName) == fieldData.end()) { + return -E_NOT_FOUND; + } + value = fieldData[fieldName]; + return E_OK; +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp b/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp index c04b394063b5c0bffd71fc286d4dbb051f6bb093..80847f13bd16132bd92ee49f51d2f78a26717267 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/db_common.cpp @@ -311,4 +311,21 @@ std::string DBCommon::StringMasking(const std::string &oriStr, size_t remain) } return oriStr; } + +std::string DBCommon::GetDistributedTableName(const std::string &device, const std::string &tableName) +{ + std::string deviceHashHex = DBCommon::TransferStringToHex(DBCommon::TransferHashString(device)); + return DBConstant::RELATIONAL_PREFIX + tableName + "_" + deviceHashHex; +} + +void DBCommon::GetDeviceFromName(const std::string &deviceTableName, std::string &deviceHash, std::string &tableName) +{ + std::size_t found = deviceTableName.rfind('_'); + if (found != std::string::npos && found + 1 < deviceTableName.length() && + found > DBConstant::RELATIONAL_PREFIX.length()) { + deviceHash = deviceTableName.substr(found + 1); + tableName = deviceTableName.substr(DBConstant::RELATIONAL_PREFIX.length(), + found - DBConstant::RELATIONAL_PREFIX.length()); + } +} } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/common/src/db_constant.cpp b/services/distributeddataservice/libs/distributeddb/common/src/db_constant.cpp index eb90c8a4a93eced1848ae0709995c13f90e3546b..35f3cf65e32659c7c84cceb6c48636d642c81941 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/db_constant.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/db_constant.cpp @@ -65,6 +65,6 @@ const std::string DBConstant::TRIGGER_REFERENCES_OLD = "OLD."; const std::string DBConstant::UPDATE_META_FUNC = "update_meta_within_trigger"; const std::string DBConstant::SYSTEM_TABLE_PREFIX = "naturalbase_rdb_"; -const std::string DBConstant::RELATIONAL_PREFIX = SYSTEM_TABLE_PREFIX + "aux_"; -const std::string DBConstant::TIMESTAMP_ALIAS = RELATIONAL_PREFIX + "timestamp"; +const std::string DBConstant::RELATIONAL_PREFIX = "naturalbase_rdb_aux_"; +const std::string DBConstant::TIMESTAMP_ALIAS = "naturalbase_rdb_aux_timestamp"; } \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/common/src/flatbuffer_schema.cpp b/services/distributeddataservice/libs/distributeddb/common/src/flatbuffer_schema.cpp index 7adade66406f61b185ab37828c25d24b04c5cbfc..d1eb269e4b3aeed4631b777cb1a1c7bf41c76a9d 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/flatbuffer_schema.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/flatbuffer_schema.cpp @@ -16,6 +16,7 @@ #include "schema_object.h" #include #include +#include "schema_constant.h" #include "schema_utils.h" #include "db_errno.h" #include "log_print.h" @@ -54,7 +55,8 @@ bool SchemaObject::FlatBufferSchema::IsFlatBufferSchema(const std::string &inOri LOGE("[FBSchema][Is] OriSchema empty."); return false; } - if (inOriginal.size() >= SCHEMA_STRING_SIZE_LIMIT * 2) { // Base64 encode will not exceed 2 times original binary + if (inOriginal.size() >= SchemaConstant::SCHEMA_STRING_SIZE_LIMIT * 2) { + // Base64 encode will not exceed 2 times original binary LOGE("[FBSchema][Is] OriSchemaSize=%zu too large even after base64 encode.", inOriginal.size()); return false; } @@ -482,19 +484,19 @@ int SchemaObject::FlatBufferSchema::ParseCheckRootTableAttribute(const reflectio return -E_SCHEMA_PARSE_FAIL; } - auto versionAttr = rootTableAttr->LookupByKey(KEYWORD_SCHEMA_VERSION.c_str()); + auto versionAttr = rootTableAttr->LookupByKey(SchemaConstant::KEYWORD_SCHEMA_VERSION.c_str()); if (!AttributeExistAndHasValue(versionAttr)) { LOGE("[FBSchema][ParseRootAttr] No SCHEMA_VERSION attribute or no value."); return -E_SCHEMA_PARSE_FAIL; } - if (SchemaUtils::Strip(versionAttr->value()->str()) != SCHEMA_SUPPORT_VERSION) { + if (SchemaUtils::Strip(versionAttr->value()->str()) != SchemaConstant::SCHEMA_SUPPORT_VERSION) { LOGE("[FBSchema][ParseRootAttr] Unexpect SCHEMA_VERSION=%s.", versionAttr->value()->c_str()); return -E_SCHEMA_PARSE_FAIL; } - owner_.schemaVersion_ = SCHEMA_SUPPORT_VERSION; - description_ += (KEYWORD_SCHEMA_VERSION + "=" + SCHEMA_SUPPORT_VERSION + ";"); + owner_.schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION; + description_ += (SchemaConstant::KEYWORD_SCHEMA_VERSION + "=" + SchemaConstant::SCHEMA_SUPPORT_VERSION + ";"); - auto skipsizeAttr = rootTableAttr->LookupByKey(KEYWORD_SCHEMA_SKIPSIZE.c_str()); + auto skipsizeAttr = rootTableAttr->LookupByKey(SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE.c_str()); if (!AttributeExistAndHasValue(skipsizeAttr)) { LOGI("[FBSchema][ParseRootAttr] No SCHEMA_SKIPSIZE attribute or no value."); owner_.schemaSkipSize_ = 0; // Default skipsize value @@ -503,12 +505,12 @@ int SchemaObject::FlatBufferSchema::ParseCheckRootTableAttribute(const reflectio std::string skipsizeStr = SchemaUtils::Strip(skipsizeAttr->value()->str()); int skipsizeInt = std::atoi(skipsizeStr.c_str()); // std::stoi will throw exception if (std::to_string(skipsizeInt) != skipsizeStr || skipsizeInt < 0 || - static_cast(skipsizeInt) > SCHEMA_SKIPSIZE_MAX) { + static_cast(skipsizeInt) > SchemaConstant::SCHEMA_SKIPSIZE_MAX) { LOGE("[FBSchema][ParseRootAttr] Unexpect SCHEMA_SKIPSIZE value=%s.", skipsizeAttr->value()->c_str()); return -E_SCHEMA_PARSE_FAIL; } owner_.schemaSkipSize_ = static_cast(skipsizeInt); - description_ += (KEYWORD_SCHEMA_SKIPSIZE + "=" + skipsizeStr + ";"); + description_ += (SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE + "=" + skipsizeStr + ";"); return E_OK; } @@ -547,12 +549,12 @@ int SchemaObject::FlatBufferSchema::ParseCheckRootTableDefine(const reflection:: } } uint32_t fieldPathCount = 0; - for (uint32_t depth = ROOT_DEFINE_DEPTH; depth < SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { + for (uint32_t depth = ROOT_DEFINE_DEPTH; depth < SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { if (owner_.schemaDefine_.count(depth) != 0) { fieldPathCount += owner_.schemaDefine_[depth].size(); } } - if (fieldPathCount > SCHEMA_FEILD_NAME_COUNT_MAX) { + if (fieldPathCount > SchemaConstant::SCHEMA_FEILD_NAME_COUNT_MAX) { LOGE("[FBSchema][ParseRootDefine] FieldPath count=%u exceed the limitation.", fieldPathCount); return -E_SCHEMA_PARSE_FAIL; } @@ -594,7 +596,7 @@ bool CheckFieldTypeSupport(const reflection::Type &inType, bool isRootField) int SchemaObject::FlatBufferSchema::ParseCheckFieldInfo(const reflection::Schema &schema, const reflection::Field &field, const FieldPath &path, RawIndexInfos &indexCollect) { - if (path.empty() || path.size() > SCHEMA_FEILD_PATH_DEPTH_MAX) { + if (path.empty() || path.size() > SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) { LOGE("[FBSchema][ParseField] FieldPath size=%zu invalid.", path.size()); return -E_SCHEMA_PARSE_FAIL; } @@ -642,7 +644,7 @@ void SchemaObject::FlatBufferSchema::CollectRawIndexInfos(const reflection::Fiel if (fieldAttr == nullptr) { return; } - auto indexAttr = fieldAttr->LookupByKey(KEYWORD_INDEX.c_str()); + auto indexAttr = fieldAttr->LookupByKey(SchemaConstant::KEYWORD_INDEX.c_str()); if (indexAttr == nullptr) { return; } @@ -656,7 +658,7 @@ void SchemaObject::FlatBufferSchema::CollectRawIndexInfos(const reflection::Fiel int SchemaObject::FlatBufferSchema::ParseCheckStructDefine(const reflection::Schema &schema, const reflection::Field &field, const FieldPath &path) { - if (path.size() >= SCHEMA_FEILD_PATH_DEPTH_MAX) { + if (path.size() >= SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) { LOGE("[FBSchema][ParseStruct] Struct define at depth limitation."); return -E_SCHEMA_PARSE_FAIL; } @@ -753,7 +755,7 @@ int SchemaObject::FlatBufferSchema::ParseCheckIndexes(const RawIndexInfos &index } description_ += ("INDEX=" + entry.first + ";"); } - if (owner_.schemaIndexes_.size() > SCHEMA_INDEX_COUNT_MAX) { + if (owner_.schemaIndexes_.size() > SchemaConstant::SCHEMA_INDEX_COUNT_MAX) { LOGE("[FBSchema][ParseIndex] Index count=%zu exceed limitation.", owner_.schemaIndexes_.size()); return -E_SCHEMA_PARSE_FAIL; } diff --git a/services/distributeddataservice/libs/distributeddb/common/src/json_object.cpp b/services/distributeddataservice/libs/distributeddb/common/src/json_object.cpp index 7e9b2b470ac6b90db2dc1c30ddb9107db77dceea..595dde63ae4c30ed7b985198c5b6281d7071797e 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/json_object.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/json_object.cpp @@ -403,7 +403,7 @@ int JsonObject::GetArrayContentOfStringOrStringArray(const FieldPath &inPath, int errCode = E_OK; const Json::Value &valueNode = GetJsonValueByFieldPath(inPath, errCode); if (errCode != E_OK) { - LOGE("[Json][GetArrayContent] Get JsonValue Fail=%d.", errCode); + LOGW("[Json][GetArrayContent] Get JsonValue Fail=%d.", errCode); return errCode; } if (valueNode.type() != Json::ValueType::arrayValue) { diff --git a/services/distributeddataservice/libs/distributeddb/common/src/parcel.cpp b/services/distributeddataservice/libs/distributeddb/common/src/parcel.cpp index e02f8685d6066707a921bea88557c6c335a73ba3..794a07116c79274f8daeb6775315c52e1f9c7400 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/parcel.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/parcel.cpp @@ -48,32 +48,16 @@ bool Parcel::IsError() const int Parcel::WriteBool(bool data) { - const uint32_t boolLen = GetBoolLen(); - if (isError_ || parcelLen_ + boolLen > totalLen_) { - isError_ = true; - return -E_PARSE_FAIL; - } - errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &data, sizeof(bool)); - if (errCode != EOK) { - isError_ = true; - return -E_SECUREC_ERROR; - } - bufPtr_ += boolLen; - parcelLen_ += boolLen; - return E_OK; + uint8_t value = data ? 1 : 0; + return WriteUInt8(value); } uint32_t Parcel::ReadBool(bool &val) { - const uint32_t boolLen = GetBoolLen(); - if (isError_ || parcelLen_ + boolLen > totalLen_) { - isError_ = true; - return -E_PARSE_FAIL; - } - val = *(reinterpret_cast(bufPtr_)); - bufPtr_ += boolLen; - parcelLen_ += boolLen; - return boolLen; + uint8_t intVal = 0; + uint32_t len = ReadUInt8(intVal); + val = intVal == 1 ? true : false; + return len; } int Parcel::WriteInt(int32_t data) @@ -86,6 +70,15 @@ uint32_t Parcel::ReadInt(int32_t &val) return ReadInteger(val); } +int Parcel::WriteUInt8(uint8_t data) +{ + return WriteInteger(data); +} + +uint32_t Parcel::ReadUInt8(uint8_t &val) +{ + return ReadInteger(val); +} int Parcel::WriteDouble(double data) { @@ -434,7 +427,12 @@ uint32_t Parcel::ReadBlob(char *buffer, uint32_t bufLen) uint32_t Parcel::GetBoolLen() { - return GetEightByteAlign(sizeof(bool)); + return GetUInt8Len(); +} + +uint32_t Parcel::GetUInt8Len() +{ + return sizeof(uint8_t); } uint32_t Parcel::GetIntLen() diff --git a/services/distributeddataservice/libs/distributeddb/common/src/query.cpp b/services/distributeddataservice/libs/distributeddb/common/src/query.cpp index 5204d1921dc91248fd520aab2ac5c37b1d1c166c..49cbdea95d4e6dac2aeb42305ab3a1c37926e555 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/query.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/query.cpp @@ -60,6 +60,12 @@ Query &Query::SuggestIndex(const std::string &indexName) return *this; } +Query &Query::InKeys(const std::set &keys) +{ + queryExpression_.InKeys(keys); + return *this; +} + Query &Query::OrderBy(const std::string &field, bool isAsc) { queryExpression_.OrderBy(field, isAsc); diff --git a/services/distributeddataservice/libs/distributeddb/common/src/query_expression.cpp b/services/distributeddataservice/libs/distributeddb/common/src/query_expression.cpp index 20e6988d6e7a43da66a25f807804377b9aaa72c8..f8dadf3992d312d3ac5d822d9160162697d71352 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/query_expression.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/query_expression.cpp @@ -186,6 +186,13 @@ void QueryExpression::QueryBySuggestIndex(const std::string &indexName) suggestIndex_ = indexName; } +void QueryExpression::InKeys(const std::set &keys) +{ + queryInfo_.emplace_back(QueryObjNode{QueryObjType::IN_KEYS, std::string(), QueryValueType::VALUE_TYPE_NULL, + std::vector()}); + keys_ = keys; +} + const std::list &QueryExpression::GetQueryExpression() { if (!GetErrFlag()) { @@ -212,7 +219,7 @@ const std::string &QueryExpression::GetTableName() return tableName_; } -bool QueryExpression::IsTableNameSpacified() const +bool QueryExpression::IsTableNameSpecified() const { return isTableNameSpecified_; } @@ -222,6 +229,11 @@ std::string QueryExpression::GetSuggestIndex() const return suggestIndex_; } +const std::set &QueryExpression::GetKeys() const +{ + return keys_; +} + void QueryExpression::BeginGroup() { queryInfo_.emplace_back(QueryObjNode{QueryObjType::BEGIN_GROUP, std::string(), @@ -241,6 +253,7 @@ void QueryExpression::Reset() prefixKey_.clear(); prefixKey_.shrink_to_fit(); suggestIndex_.clear(); + keys_.clear(); } void QueryExpression::SetErrFlag(bool flag) diff --git a/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp b/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp index 285221bd424b88a8c3b79028085535d006508ec9..aa6e334372d3a969e9545786be33099e9f1c4ccb 100644 --- a/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/relational/relational_schema_object.cpp @@ -13,10 +13,12 @@ * limitations under the License. */ #ifdef RELATIONAL_STORE +#include "relational_schema_object.h" + #include #include "json_object.h" -#include "relational_schema_object.h" +#include "schema_constant.h" #include "schema_utils.h" namespace DistributedDB { @@ -94,19 +96,32 @@ void FieldInfo::SetColumnId(int cid) cid_ = cid; } -// return field define string like ("fieldName": "MY INT(21), NOT NULL, DEFAULT 123") std::string FieldInfo::ToAttributeString() const { std::string attrStr = "\"" + fieldName_ + "\": {"; + attrStr += "\"COLUMN_ID\":" + std::to_string(cid_) + ","; attrStr += "\"TYPE\":\"" + dataType_ + "\","; - attrStr += "\"NOT_NULL\":" + std::string(isNotNull_ ? "true" : "false") + ","; + attrStr += "\"NOT_NULL\":" + std::string(isNotNull_ ? "true" : "false"); if (hasDefaultValue_) { + attrStr += ","; attrStr += "\"DEFAULT\":\"" + defaultValue_ + "\""; } attrStr += "}"; return attrStr; } +int FieldInfo::CompareWithField(const FieldInfo &inField) const +{ + if (fieldName_ != inField.GetFieldName() || dataType_ != inField.GetDataType() || + isNotNull_ != inField.IsNotNull()) { + return false; + } + if (hasDefaultValue_ && inField.HasDefaultValue()) { + return defaultValue_ == inField.GetDefaultValue(); + } + return hasDefaultValue_ == inField.HasDefaultValue(); +} + const std::string &TableInfo::GetTableName() const { return tableName_; @@ -148,6 +163,30 @@ const std::map &TableInfo::GetFields() const return fields_; } +std::string TableInfo::GetFieldName(uint32_t cid) const +{ + if (cid >= fields_.size()) { + return {}; + } + if (!fieldNames_.empty() && fieldNames_.size() == fields_.size()) { + return fieldNames_.at(cid); + } + fieldNames_.resize(fields_.size()); + if (fieldNames_.size() != fields_.size()) { + LOGE("GetField error, alloc memory failed."); + return {}; + } + for (const auto &[fieldName, fieldInfo] : fields_) { + fieldNames_.at(fieldInfo.GetColumnId()) = fieldName; + } + return fieldNames_.at(cid); +} + +bool TableInfo::IsValid() const +{ + return !tableName_.empty(); +} + void TableInfo::AddField(const FieldInfo &field) { fields_[field.GetFieldName()] = field; @@ -220,14 +259,14 @@ void TableInfo::AddUniqueDefineString(std::string &attrStr) const } attrStr += R"("UNIQUE": [)"; for (auto itUniqueDefine = uniqueDefines_.begin(); itUniqueDefine != uniqueDefines_.end(); ++itUniqueDefine) { - attrStr += "\""; + attrStr += "[\""; for (auto itField = (*itUniqueDefine).begin(); itField != (*itUniqueDefine).end(); ++itField) { attrStr += *itField; if (itField != (*itUniqueDefine).end() - 1) { - attrStr += ", "; + attrStr += "\",\""; } } - attrStr += "\""; + attrStr += "\"]"; if (itUniqueDefine != uniqueDefines_.end() - 1) { attrStr += ","; } @@ -240,16 +279,16 @@ void TableInfo::AddIndexDefineString(std::string &attrStr) const if (indexDefines_.empty()) { return; } - attrStr += R"("INDEX": {)"; + attrStr += R"(,"INDEX": {)"; for (auto itIndexDefine = indexDefines_.begin(); itIndexDefine != indexDefines_.end(); ++itIndexDefine) { - attrStr += "\"" + (*itIndexDefine).first + "\": \""; + attrStr += "\"" + (*itIndexDefine).first + "\": [\""; for (auto itField = itIndexDefine->second.begin(); itField != itIndexDefine->second.end(); ++itField) { attrStr += *itField; if (itField != itIndexDefine->second.end() - 1) { - attrStr += ","; + attrStr += "\",\""; } } - attrStr += "\""; + attrStr += "\"]"; if (itIndexDefine != std::prev(indexDefines_.end(), 1)) { attrStr += ","; } @@ -267,6 +306,85 @@ void TableInfo::SetDevId(const std::string &devId) devId_ = devId; } +int TableInfo::CompareWithTable(const TableInfo &inTableInfo) const +{ + if (tableName_ != inTableInfo.GetTableName()) { + LOGW("[Relational][Compare] Table name is not same"); + return -E_RELATIONAL_TABLE_INCOMPATIBLE; + } + + if (primaryKey_ != inTableInfo.GetPrimaryKey()) { + LOGW("[Relational][Compare] Table primary key is not same"); + return -E_RELATIONAL_TABLE_INCOMPATIBLE; + } + + int fieldCompareResult = CompareWithTableFields(inTableInfo.GetFields()); + if (fieldCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) { + LOGW("[Relational][Compare] Compare table fields with in table, %d", fieldCompareResult); + return -E_RELATIONAL_TABLE_INCOMPATIBLE; + } + + int indexCompareResult = CompareWithTableIndex(inTableInfo.GetIndexDefine()); + return (fieldCompareResult == -E_RELATIONAL_TABLE_EQUAL) ? indexCompareResult : fieldCompareResult; +} + +int TableInfo::CompareWithTableFields(const std::map &inTableFields) const +{ + auto itLocal = fields_.begin(); + auto itInTable = inTableFields.begin(); + int errCode = -E_RELATIONAL_TABLE_EQUAL; + while (itLocal != fields_.end() && itInTable != inTableFields.end()) { + if (itLocal->first == itInTable->first) { // Same field + if (!itLocal->second.CompareWithField(itInTable->second)) { // Compare field + LOGW("[Relational][Compare] Table field is incompatible"); // not compatible + return -E_RELATIONAL_TABLE_INCOMPATIBLE; + } + itLocal++; // Compare next field + } else { // Assume local table fields is a subset of in table + if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) { // Upgrade field not compatible + LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value."); + return -E_RELATIONAL_TABLE_INCOMPATIBLE; + } + errCode = -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE; + } + itInTable++; // Next in table field + } + + if (itLocal != fields_.end()) { + LOGW("[Relational][Compare] Table field is missing"); + return -E_RELATIONAL_TABLE_INCOMPATIBLE; + } + + if (itInTable == inTableFields.end()) { + return errCode; + } + + while (itInTable != inTableFields.end()) { + if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) { + LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value."); + return -E_RELATIONAL_TABLE_INCOMPATIBLE; + } + itInTable++; + } + return -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE; +} + +int TableInfo::CompareWithTableIndex(const std::map &inTableIndex) const +{ + // Index comparison results do not affect synchronization decisions + auto itLocal = indexDefines_.begin(); + auto itInTable = inTableIndex.begin(); + while (itLocal != indexDefines_.end() && itInTable != inTableIndex.end()) { + if (itLocal->first != itInTable->first || itLocal->second != itInTable->second) { + return -E_RELATIONAL_TABLE_COMPATIBLE; + } + itLocal++; + itInTable++; + } + return (itLocal == indexDefines_.end() && itInTable == inTableIndex.end()) ? -E_RELATIONAL_TABLE_EQUAL : + -E_RELATIONAL_TABLE_COMPATIBLE; +} + namespace { std::string VectorJoin(const CompositeFields &fields, char con) { @@ -303,6 +421,7 @@ JsonObject TableInfo::ToJsonObject() const std::string TableInfo::ToTableInfoString() const { std::string attrStr; + attrStr += "{"; attrStr += R"("NAME": ")" + tableName_ + "\","; AddFieldDefineString(attrStr); attrStr += R"("AUTOINCREMENT": )"; @@ -313,30 +432,116 @@ std::string TableInfo::ToTableInfoString() const } AddUniqueDefineString(attrStr); if (!primaryKey_.empty()) { - attrStr += R"("PRIMARY_KEY": ")" + primaryKey_ + "\","; + attrStr += R"("PRIMARY_KEY": ")" + primaryKey_ + "\""; } AddIndexDefineString(attrStr); + attrStr += "}"; return attrStr; } -int RelationalSyncOpinion::CalculateParcelLen(uint32_t softWareVersion) const +std::map TableInfo::GetSchemaDefine() const +{ + std::map schemaDefine; + for (const auto &[fieldName, fieldInfo] : GetFields()) { + FieldValue defaultValue; + defaultValue.stringValue = fieldInfo.GetDefaultValue(); + schemaDefine[std::vector { fieldName }] = SchemaAttribute { + .type = FieldType::LEAF_FIELD_NULL, // For relational schema, the json field type is unimportant. + .isIndexable = true, // For relational schema, all field is indexable. + .hasNotNullConstraint = fieldInfo.IsNotNull(), + .hasDefaultValue = fieldInfo.HasDefaultValue(), + .defaultValue = defaultValue, + .customFieldType = {} + }; + } + return schemaDefine; +} + +namespace { + const std::string MAGIC = "relational_opinion"; +} + +uint32_t RelationalSyncOpinion::CalculateParcelLen(uint32_t softWareVersion) const { - return E_OK; + uint64_t len = Parcel::GetStringLen(MAGIC); + len += Parcel::GetUInt32Len(); + len += Parcel::GetUInt32Len(); + len = Parcel::GetEightByteAlign(len); + for (const auto &it : opinions_) { + len += Parcel::GetStringLen(it.first); + len += Parcel::GetUInt32Len(); + len += Parcel::GetUInt32Len(); + len = Parcel::GetEightByteAlign(len); + } + if (len > UINT32_MAX) { + return 0; + } + return static_cast(len); } -int RelationalSyncOpinion::Serialize(Parcel &parcel, uint32_t softWareVersion) const +int RelationalSyncOpinion::SerializeData(Parcel &parcel, uint32_t softWareVersion) const { - return E_OK; + (void)parcel.WriteString(MAGIC); + (void)parcel.WriteUInt32(SYNC_OPINION_VERSION); + (void)parcel.WriteUInt32(static_cast(opinions_.size())); + (void)parcel.EightByteAlign(); + for (const auto &it : opinions_) { + (void)parcel.WriteString(it.first); + (void)parcel.WriteUInt32(it.second.permitSync); + (void)parcel.WriteUInt32(it.second.requirePeerConvert); + (void)parcel.EightByteAlign(); + } + return parcel.IsError() ? -E_INVALID_ARGS : E_OK; } -int RelationalSyncOpinion::Deserialization(const Parcel &parcel) +int RelationalSyncOpinion::DeserializeData(Parcel &parcel, RelationalSyncOpinion &opinion) { - return E_OK; + if (!parcel.IsContinueRead()) { + return E_OK; + } + std::string magicStr; + (void)parcel.ReadString(magicStr); + if (magicStr != MAGIC) { + LOGE("Deserialize sync opinion failed while read MAGIC string [%s]", magicStr.c_str()); + return -E_INVALID_ARGS; + } + uint32_t version; + (void)parcel.ReadUInt32(version); + if (version != SYNC_OPINION_VERSION) { + LOGE("Not support sync opinion version: %u", version); + return -E_NOT_SUPPORT; + } + uint32_t opinionSize; + (void)parcel.ReadUInt32(opinionSize); + (void)parcel.EightByteAlign(); + for (uint32_t i = 0; i < opinionSize; i++) { + std::string tableName; + SyncOpinion tableOpinion; + (void)parcel.ReadString(tableName); + uint32_t permitSync; + (void)parcel.ReadUInt32(permitSync); + tableOpinion.permitSync = static_cast(permitSync); + uint32_t requirePeerConvert; + (void)parcel.ReadUInt32(requirePeerConvert); + tableOpinion.requirePeerConvert = static_cast(requirePeerConvert); + (void)parcel.EightByteAlign(); + opinion.AddSyncOpinion(tableName, tableOpinion); + } + return parcel.IsError() ? -E_INVALID_ARGS : E_OK; +} + +SyncOpinion RelationalSyncOpinion::GetTableOpinion(const std::string &tableName) const +{ + auto it = opinions_.find(tableName); + if (it == opinions_.end()) { + return {}; + } + return it->second; } -const SyncOpinion &RelationalSyncOpinion::GetTableOpinion(const std::string &tableName) const +const std::map &RelationalSyncOpinion::GetOpinions() const { - return opinions_.at(tableName); + return opinions_; } void RelationalSyncOpinion::AddSyncOpinion(const std::string &tableName, const SyncOpinion &opinion) @@ -344,9 +549,13 @@ void RelationalSyncOpinion::AddSyncOpinion(const std::string &tableName, const S opinions_[tableName] = opinion; } -const SyncStrategy &RelationalSyncStrategy::GetTableStrategy(const std::string &tableName) const +SyncStrategy RelationalSyncStrategy::GetTableStrategy(const std::string &tableName) const { - return strategies_.at(tableName); + auto it = strategies_.find(tableName); + if (it == strategies_.end()) { + return {}; + } + return it->second; } void RelationalSyncStrategy::AddSyncStrategy(const std::string &tableName, const SyncStrategy &strategy) @@ -354,16 +563,99 @@ void RelationalSyncStrategy::AddSyncStrategy(const std::string &tableName, const strategies_[tableName] = strategy; } -RelationalSyncOpinion RelationalSchemaObject::MakeLocalSyncOpinion( - const RelationalSchemaObject &localSchema, const std::string &remoteSchema, uint8_t remoteSchemaType) +const std::map &RelationalSyncStrategy::GetStrategies() const { - return RelationalSyncOpinion(); + return strategies_; } -RelationalSyncStrategy RelationalSchemaObject::ConcludeSyncStrategy( - const RelationalSyncOpinion &localOpinion, const RelationalSyncOpinion &remoteOpinion) +RelationalSyncOpinion RelationalSchemaObject::MakeLocalSyncOpinion(const RelationalSchemaObject &localSchema, + const std::string &remoteSchema, uint8_t remoteSchemaType) { - return RelationalSyncStrategy(); + SchemaType localType = localSchema.GetSchemaType(); + SchemaType remoteType = ReadSchemaType(remoteSchemaType); + + if (remoteType == SchemaType::UNRECOGNIZED) { + LOGW("[RelationalSchema][opinion] Remote schema type %d is unrecognized.", remoteSchemaType); + return {}; + } + + if (remoteType != SchemaType::RELATIVE) { + LOGW("[RelationalSchema][opinion] Not support sync with schema type: local-type=[%d] remote-type=[%d]", + SchemaUtils::SchemaTypeString(localType).c_str(), SchemaUtils::SchemaTypeString(remoteType).c_str()); + return {}; + } + + if (!localSchema.IsSchemaValid()) { + LOGW("[RelationalSchema][opinion] Local schema is not valid"); + return {}; + } + + RelationalSchemaObject remoteSchemaObj; + int errCode = remoteSchemaObj.ParseFromSchemaString(remoteSchema); + if (errCode != E_OK) { + LOGW("[RelationalSchema][opinion] Parse remote schema failed %d, remote schema type %s", errCode, + SchemaUtils::SchemaTypeString(remoteType).c_str()); + return {}; + } + + RelationalSyncOpinion opinion; + for (const auto &it : localSchema.GetTables()) { + if (remoteSchemaObj.GetTable(it.first).GetTableName() != it.first) { + LOGW("[RelationalSchema][opinion] Table was missing in remote schema"); + continue; + } + // remote table is compatible(equal or upgrade) based on local table, permit sync and don't need check + errCode = it.second.CompareWithTable(remoteSchemaObj.GetTable(it.first)); + if (errCode != -E_RELATIONAL_TABLE_INCOMPATIBLE) { + opinion.AddSyncOpinion(it.first, {true, false, false}); + continue; + } + // local table is compatible upgrade based on remote table, permit sync and need check + errCode = remoteSchemaObj.GetTable(it.first).CompareWithTable(it.second); + if (errCode != -E_RELATIONAL_TABLE_INCOMPATIBLE) { + opinion.AddSyncOpinion(it.first, {true, false, true}); + continue; + } + // local table is incompatible with remote table mutually, don't permit sync and need check + LOGW("[RelationalSchema][opinion] Local table is incompatible with remote table mutually."); + opinion.AddSyncOpinion(it.first, {false, true, true}); + } + + return opinion; +} + +RelationalSyncStrategy RelationalSchemaObject::ConcludeSyncStrategy(const RelationalSyncOpinion &localOpinion, + const RelationalSyncOpinion &remoteOpinion) +{ + RelationalSyncStrategy syncStrategy; + for (const auto &itLocal : localOpinion.GetOpinions()) { + if (remoteOpinion.GetOpinions().find(itLocal.first) == remoteOpinion.GetOpinions().end()) { + LOGW("[RelationalSchema][Strategy] Table opinion is not found from remote."); + continue; + } + + SyncStrategy strategy; + SyncOpinion localTableOpinion = itLocal.second; + SyncOpinion remoteTableOpinion = remoteOpinion.GetTableOpinion(itLocal.first); + + strategy.permitSync = (localTableOpinion.permitSync || remoteTableOpinion.permitSync); + + bool convertConflict = (localTableOpinion.requirePeerConvert && remoteTableOpinion.requirePeerConvert); + if (convertConflict) { + // Should not both need peer convert + strategy.permitSync = false; + } + // No peer convert required means local side has convert capability, convert locally takes precedence + strategy.convertOnSend = (!localTableOpinion.requirePeerConvert); + strategy.convertOnReceive = remoteTableOpinion.requirePeerConvert; + + strategy.checkOnReceive = localTableOpinion.checkOnReceive; + LOGI("[RelationalSchema][Strategy] PermitSync=%d, SendConvert=%d, ReceiveConvert=%d, ReceiveCheck=%d.", + strategy.permitSync, strategy.convertOnSend, strategy.convertOnReceive, strategy.checkOnReceive); + syncStrategy.AddSyncStrategy(itLocal.first, strategy); + } + + return syncStrategy; } bool RelationalSchemaObject::IsSchemaValid() const @@ -387,7 +679,7 @@ int RelationalSchemaObject::ParseFromSchemaString(const std::string &inSchemaStr return -E_NOT_PERMIT; } - if (inSchemaString.size() > SCHEMA_STRING_SIZE_LIMIT) { + if (inSchemaString.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT) { LOGE("[RelationalSchema][Parse] SchemaSize=%zu Too Large.", inSchemaString.size()); return -E_INVALID_ARGS; } @@ -410,9 +702,35 @@ int RelationalSchemaObject::ParseFromSchemaString(const std::string &inSchemaStr return E_OK; } +void RelationalSchemaObject::GenerateSchemaString() +{ + schemaString_ = {}; + schemaString_ += "{"; + schemaString_ += R"("SCHEMA_VERSION":"2.0",)"; + schemaString_ += R"("SCHEMA_TYPE":"RELATIVE",)"; + schemaString_ += R"("TABLES":[)"; + for (auto it = tables_.begin(); it != tables_.end(); it++) { + if (it != tables_.begin()) { + schemaString_ += ","; + } + schemaString_ += it->second.ToTableInfoString(); + } + schemaString_ += R"(])"; + schemaString_ += "}"; +} + void RelationalSchemaObject::AddRelationalTable(const TableInfo &tb) { tables_[tb.GetTableName()] = tb; + isValid_ = true; + GenerateSchemaString(); +} + + +void RelationalSchemaObject::RemoveRelationalTable(const std::string &tableName) +{ + tables_.erase(tableName); + GenerateSchemaString(); } const std::map &RelationalSchemaObject::GetTables() const @@ -420,6 +738,15 @@ const std::map &RelationalSchemaObject::GetTables() cons return tables_; } +std::vector RelationalSchemaObject::GetTableNames() const +{ + std::vector tableNames; + for (const auto &it : tables_) { + tableNames.emplace_back(it.first); + } + return tableNames; +} + TableInfo RelationalSchemaObject::GetTable(const std::string &tableName) const { auto it = tables_.find(tableName); @@ -446,8 +773,11 @@ int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &f bool isNecessary, FieldValue &fieldValue) { if (!inJsonObject.IsFieldPathExist(FieldPath {fieldName})) { - LOGW("[RelationalSchema][Parse] Get schema %s not exist. isNecessary: %d", fieldName.c_str(), isNecessary); - return isNecessary ? -E_SCHEMA_PARSE_FAIL : -E_NOT_FOUND; + if (isNecessary) { + LOGE("[RelationalSchema][Parse] Get schema %s not exist. isNecessary: %d", fieldName.c_str(), isNecessary); + return -E_SCHEMA_PARSE_FAIL; + } + return -E_NOT_FOUND; } FieldType fieldType; @@ -487,30 +817,30 @@ int RelationalSchemaObject::ParseRelationalSchema(const JsonObject &inJsonObject int RelationalSchemaObject::ParseCheckSchemaVersionMode(const JsonObject &inJsonObject) { FieldValue fieldValue; - int errCode = GetMemberFromJsonObject(inJsonObject, KEYWORD_SCHEMA_VERSION, FieldType::LEAF_FIELD_STRING, - true, fieldValue); + int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_VERSION, + FieldType::LEAF_FIELD_STRING, true, fieldValue); if (errCode != E_OK) { return errCode; } - if (SchemaUtils::Strip(fieldValue.stringValue) != SCHEMA_SUPPORT_VERSION_V2) { + if (SchemaUtils::Strip(fieldValue.stringValue) != SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) { LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_VERSION=%s.", fieldValue.stringValue.c_str()); return -E_SCHEMA_PARSE_FAIL; } - schemaVersion_ = SCHEMA_SUPPORT_VERSION_V2; + schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION_V2; return E_OK; } int RelationalSchemaObject::ParseCheckSchemaType(const JsonObject &inJsonObject) { FieldValue fieldValue; - int errCode = GetMemberFromJsonObject(inJsonObject, KEYWORD_SCHEMA_TYPE, FieldType::LEAF_FIELD_STRING, - true, fieldValue); + int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_TYPE, + FieldType::LEAF_FIELD_STRING, true, fieldValue); if (errCode != E_OK) { return errCode; } - if (SchemaUtils::Strip(fieldValue.stringValue) != KEYWORD_TYPE_RELATIVE) { + if (SchemaUtils::Strip(fieldValue.stringValue) != SchemaConstant::KEYWORD_TYPE_RELATIVE) { LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_TYPE=%s.", fieldValue.stringValue.c_str()); return -E_SCHEMA_PARSE_FAIL; } @@ -521,7 +851,7 @@ int RelationalSchemaObject::ParseCheckSchemaType(const JsonObject &inJsonObject) int RelationalSchemaObject::ParseCheckSchemaTableDefine(const JsonObject &inJsonObject) { FieldType fieldType; - int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {KEYWORD_SCHEMA_TABLE}, fieldType); + int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, fieldType); if (errCode != E_OK) { LOGE("[RelationalSchema][Parse] Get schema TABLES fieldType failed: %d.", errCode); return -E_SCHEMA_PARSE_FAIL; @@ -532,7 +862,7 @@ int RelationalSchemaObject::ParseCheckSchemaTableDefine(const JsonObject &inJson return -E_SCHEMA_PARSE_FAIL; } std::vector tables; - errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{KEYWORD_SCHEMA_TABLE}, tables); + errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::KEYWORD_SCHEMA_TABLE}, tables); if (errCode != E_OK) { LOGE("[RelationalSchema][Parse] Get schema TABLES value failed: %d.", errCode); return -E_SCHEMA_PARSE_FAIL; @@ -570,7 +900,12 @@ int RelationalSchemaObject::ParseCheckTableInfo(const JsonObject &inJsonObject) if (errCode != E_OK) { return errCode; } - return ParseCheckTableIndex(inJsonObject, resultTable); + errCode = ParseCheckTableIndex(inJsonObject, resultTable); + if (errCode != E_OK) { + return errCode; + } + tables_[resultTable.GetTableName()] = resultTable; + return E_OK; } int RelationalSchemaObject::ParseCheckTableName(const JsonObject &inJsonObject, TableInfo &resultTable) @@ -608,7 +943,7 @@ int RelationalSchemaObject::ParseCheckTableDefine(const JsonObject &inJsonObject } FieldInfo fieldInfo; - fieldInfo.SetFieldName(field.first[0]); // 0 : first element in path + fieldInfo.SetFieldName(field.first[1]); // 1 : table name element in path errCode = ParseCheckTableFieldInfo(fieldObj, field.first, fieldInfo); if (errCode != E_OK) { LOGE("[RelationalSchema][Parse] Parse table field info failed. %d", errCode); @@ -620,24 +955,30 @@ int RelationalSchemaObject::ParseCheckTableDefine(const JsonObject &inJsonObject } int RelationalSchemaObject::ParseCheckTableFieldInfo(const JsonObject &inJsonObject, const FieldPath &path, - FieldInfo &table) + FieldInfo &field) { FieldValue fieldValue; - int errCode = GetMemberFromJsonObject(inJsonObject, "TYPE", FieldType::LEAF_FIELD_STRING, true, fieldValue); + int errCode = GetMemberFromJsonObject(inJsonObject, "COLUMN_ID", FieldType::LEAF_FIELD_INTEGER, true, fieldValue); if (errCode != E_OK) { return errCode; } - table.SetDataType(fieldValue.stringValue); + field.SetColumnId(fieldValue.integerValue); + + errCode = GetMemberFromJsonObject(inJsonObject, "TYPE", FieldType::LEAF_FIELD_STRING, true, fieldValue); + if (errCode != E_OK) { + return errCode; + } + field.SetDataType(fieldValue.stringValue); errCode = GetMemberFromJsonObject(inJsonObject, "NOT_NULL", FieldType::LEAF_FIELD_BOOL, true, fieldValue); if (errCode != E_OK) { return errCode; } - table.SetNotNull(fieldValue.boolValue); + field.SetNotNull(fieldValue.boolValue); errCode = GetMemberFromJsonObject(inJsonObject, "DEFAULT", FieldType::LEAF_FIELD_STRING, false, fieldValue); if (errCode == E_OK) { - table.SetDefaultValue(fieldValue.stringValue); + field.SetDefaultValue(fieldValue.stringValue); } else if (errCode != -E_NOT_FOUND) { return errCode; } @@ -659,6 +1000,9 @@ int RelationalSchemaObject::ParseCheckTableAutoInc(const JsonObject &inJsonObjec int RelationalSchemaObject::ParseCheckTableUnique(const JsonObject &inJsonObject, TableInfo &resultTable) { + if (!inJsonObject.IsFieldPathExist(FieldPath {"UNIQUE"})) { // UNIQUE is not necessary + return E_OK; + } std::vector uniqueArray; int errCode = inJsonObject.GetArrayContentOfStringOrStringArray(FieldPath {"UNIQUE"}, uniqueArray); if (errCode != E_OK) { @@ -681,6 +1025,9 @@ int RelationalSchemaObject::ParseCheckTablePrimaryKey(const JsonObject &inJsonOb int RelationalSchemaObject::ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable) { + if (!inJsonObject.IsFieldPathExist(FieldPath {"INDEX"})) { // INDEX is not necessary + return E_OK; + } std::map tableFields; int errCode = inJsonObject.GetSubFieldPathAndType(FieldPath {"INDEX"}, tableFields); if (errCode != E_OK) { diff --git a/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.cpp b/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.cpp index faaa671e6eef7b97f307b16696a0bf68beb9d934..10ab3e063a2f92b3e24b3e037e0a5b2f4d6c4e32 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.cpp @@ -398,9 +398,9 @@ void RuntimeContextImpl::GetAutoLaunchSyncDevices(const std::string &identifier, return autoLaunch_.GetAutoLaunchSyncDevices(identifier, devices); } -void RuntimeContextImpl::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) +void RuntimeContextImpl::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback, DBType type) { - autoLaunch_.SetAutoLaunchRequestCallback(callback); + autoLaunch_.SetAutoLaunchRequestCallback(callback, type); } NotificationChain::Listener *RuntimeContextImpl::RegisterLockStatusLister(const LockStatusNotifier &action, @@ -575,4 +575,23 @@ bool RuntimeContextImpl::IsCommunicatorAggregatorValid() const } return true; } + +void RuntimeContextImpl::SetStoreStatusNotifier(const StoreStatusNotifier ¬ifier) +{ + std::unique_lock writeLock(databaseStatusCallbackMutex_); + databaseStatusNotifyCallback_ = notifier; + LOGI("SetStoreStatusNotifier ok"); +} + +void RuntimeContextImpl::NotifyDatabaseStatusChange(const std::string &userId, const std::string &appId, + const std::string &storeId, const std::string &deviceId, bool onlineStatus) +{ + ScheduleTask([this, userId, appId, storeId, deviceId, onlineStatus] { + std::shared_lock autoLock(databaseStatusCallbackMutex_); + if (databaseStatusNotifyCallback_) { + LOGI("start notify database status:%d", onlineStatus); + databaseStatusNotifyCallback_(userId, appId, storeId, deviceId, onlineStatus); + } + }); +} } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.h b/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.h index 4d78e9261b8baafc926e4b6af8b144b8e9c5ce3c..ac645528d3f1abf3d5c59d35cbc88f8bb6f3115f 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.h +++ b/services/distributeddataservice/libs/distributeddb/common/src/runtime_context_impl.h @@ -76,7 +76,7 @@ public: void GetAutoLaunchSyncDevices(const std::string &identifier, std::vector &devices) const override; - void SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) override; + void SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback, DBType type) override; NotificationChain::Listener *RegisterLockStatusLister(const LockStatusNotifier &action, int &errCode) override; @@ -97,6 +97,11 @@ public: // Notify TIME_CHANGE_EVENT. void NotifyTimeStampChanged(TimeOffset offset) const override; + void SetStoreStatusNotifier(const StoreStatusNotifier ¬ifier) override; + + void NotifyDatabaseStatusChange(const std::string &userId, const std::string &appId, const std::string &storeId, + const std::string &deviceId, bool onlineStatus) override; + private: static constexpr int MAX_TP_THREADS = 10; // max threads of the task pool. static constexpr int MIN_TP_THREADS = 1; // min threads of the task pool. @@ -142,6 +147,9 @@ private: std::shared_ptr systemApiAdapter_; mutable std::mutex lockStatusLock_; // Mutex for lockStatusObserver_. LockStatusObserver *lockStatusObserver_; + + mutable std::shared_mutex databaseStatusCallbackMutex_{}; + StoreStatusNotifier databaseStatusNotifyCallback_; }; } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/common/src/schema_constant.cpp b/services/distributeddataservice/libs/distributeddb/common/src/schema_constant.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d833a7eeb3fd8f0bde96ffc744dacc29b5b6f776 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/common/src/schema_constant.cpp @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 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 "schema_constant.h" + +namespace DistributedDB { +const std::string SchemaConstant::KEYWORD_SCHEMA_VERSION = "SCHEMA_VERSION"; +const std::string SchemaConstant::KEYWORD_SCHEMA_MODE = "SCHEMA_MODE"; +const std::string SchemaConstant::KEYWORD_SCHEMA_DEFINE = "SCHEMA_DEFINE"; +const std::string SchemaConstant::KEYWORD_SCHEMA_INDEXES = "SCHEMA_INDEXES"; +const std::string SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE = "SCHEMA_SKIPSIZE"; +const std::string SchemaConstant::KEYWORD_SCHEMA_TYPE = "SCHEMA_TYPE"; +const std::string SchemaConstant::KEYWORD_SCHEMA_TABLE = "TABLES"; +const std::string SchemaConstant::KEYWORD_INDEX = "INDEX"; // For FlatBuffer-Schema + +const std::string SchemaConstant::KEYWORD_MODE_STRICT = "STRICT"; +const std::string SchemaConstant::KEYWORD_MODE_COMPATIBLE = "COMPATIBLE"; + +const std::string SchemaConstant::KEYWORD_TYPE_BOOL = "BOOL"; +const std::string SchemaConstant::KEYWORD_TYPE_INTEGER = "INTEGER"; +const std::string SchemaConstant::KEYWORD_TYPE_LONG = "LONG"; +const std::string SchemaConstant::KEYWORD_TYPE_DOUBLE = "DOUBLE"; +const std::string SchemaConstant::KEYWORD_TYPE_STRING = "STRING"; + +const std::string SchemaConstant::KEYWORD_ATTR_NOT_NULL = "NOT NULL"; +const std::string SchemaConstant::KEYWORD_ATTR_DEFAULT = "DEFAULT"; +const std::string SchemaConstant::KEYWORD_ATTR_VALUE_NULL = "null"; +const std::string SchemaConstant::KEYWORD_ATTR_VALUE_TRUE = "true"; +const std::string SchemaConstant::KEYWORD_ATTR_VALUE_FALSE = "false"; + +const std::string SchemaConstant::KEYWORD_TYPE_RELATIVE = "RELATIVE"; +const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION = "1.0"; +const std::string SchemaConstant::SCHEMA_SUPPORT_VERSION_V2 = "2.0"; + +const uint32_t SchemaConstant::SCHEMA_META_FEILD_COUNT_MAX = 5; +const uint32_t SchemaConstant::SCHEMA_META_FEILD_COUNT_MIN = 3; +const uint32_t SchemaConstant::SCHEMA_FEILD_NAME_LENGTH_MAX = 64; +const uint32_t SchemaConstant::SCHEMA_FEILD_NAME_LENGTH_MIN = 1; +const uint32_t SchemaConstant::SCHEMA_FEILD_NAME_COUNT_MAX = 256; +const uint32_t SchemaConstant::SCHEMA_FEILD_NAME_COUNT_MIN = 1; +const uint32_t SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX = 4; +const uint32_t SchemaConstant::SCHEMA_INDEX_COUNT_MAX = 32; +const uint32_t SchemaConstant::SCHEMA_STRING_SIZE_LIMIT = 524288; // 512K +const uint32_t SchemaConstant::SCHEMA_DEFAULT_STRING_SIZE_LIMIT = 4096; // 4K +const uint32_t SchemaConstant::SCHEMA_SKIPSIZE_MAX = 4194302; // 4M - 2 Bytes + +const uint32_t SchemaConstant::SECURE_BYTE_ALIGN = 8; // 8 bytes align +} // namespace DistributedDB + diff --git a/services/distributeddataservice/libs/distributeddb/common/src/schema_object.cpp b/services/distributeddataservice/libs/distributeddb/common/src/schema_object.cpp index 6470c54ca8594c5c98a2122c70ef0566abe2c473..8dc67aa172f69f4d1cdec27e09d7887c7ad973f9 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/schema_object.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/schema_object.cpp @@ -17,6 +17,7 @@ #include "schema_utils.h" #include "db_errno.h" #include "log_print.h" +#include "schema_constant.h" namespace DistributedDB { namespace { @@ -80,16 +81,6 @@ std::string SchemaObject::GenerateExtractSQL(SchemaType inSchemaType, const Fiel return resultSql; } -namespace { -inline SchemaType ReadSchemaType(uint8_t inType) -{ - if (inType >= static_cast(SchemaType::UNRECOGNIZED)) { - return SchemaType::UNRECOGNIZED; - } - return static_cast(inType); -} -} - // Some principle in current version describe below. (Relative-type will be introduced in future but not involved now) // 1. PermitSync: Be false may because schemaType-unrecognized, schemaType-different, schema-unparsable, // schemaVersion-unrecognized, schema-incompatible, and so on. @@ -197,6 +188,17 @@ SchemaObject& SchemaObject::operator=(const SchemaObject &other) return *this; } +#ifdef RELATIONAL_STORE +SchemaObject::SchemaObject(const TableInfo &tableInfo) : flatbufferSchema_(*this) +{ + isValid_ = true; + schemaType_ = SchemaType::NONE; // Default NONE + schemaVersion_ = "1.0"; + SchemaDefine schemaDefine = tableInfo.GetSchemaDefine(); + schemaDefine_.insert({ 0, schemaDefine }); +} +#endif // RELATIONAL_STORE + int SchemaObject::ParseFromSchemaString(const std::string &inSchemaString) { if (isValid_) { @@ -211,7 +213,7 @@ int SchemaObject::ParseFromSchemaString(const std::string &inSchemaString) LOGD("[Schema][Parse] FlatBuffer-Type, Decode before=%zu, after=%zu.", inSchemaString.size(), decoded.size()); } const std::string &oriSchema = ((estimateType == SchemaType::FLATBUFFER) ? decoded : inSchemaString); - if (oriSchema.size() > SCHEMA_STRING_SIZE_LIMIT) { + if (oriSchema.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT) { LOGE("[Schema][Parse] SchemaSize=%zu Too Large.", oriSchema.size()); return -E_INVALID_ARGS; } @@ -403,7 +405,7 @@ int SchemaObject::VerifyValue(ValueSource sourceType, const RawValue &inValue) c RawValue rawValue; std::vector cache; - if (schemaSkipSize_ % SECURE_BYTE_ALIGN == 0) { + if (schemaSkipSize_ % SchemaConstant::SECURE_BYTE_ALIGN == 0) { rawValue = {inValue.first + schemaSkipSize_, inValue.second - schemaSkipSize_}; } else { cache.assign(inValue.first + schemaSkipSize_, inValue.first + inValue.second); @@ -436,7 +438,7 @@ int SchemaObject::ExtractValue(ValueSource sourceType, RawString inPath, const R RawValue rawValue; std::vector *tempCache = nullptr; // A temporary cache for use when input cache can not hold. - if (schemaSkipSize_ % SECURE_BYTE_ALIGN == 0) { + if (schemaSkipSize_ % SchemaConstant::SECURE_BYTE_ALIGN == 0) { rawValue = {inValue.first + schemaSkipSize_, inValue.second - schemaSkipSize_}; } else if ((cache != nullptr) && (cache->size() >= (inValue.second - schemaSkipSize_))) { // Do not expand the cache if it can not hold @@ -496,25 +498,26 @@ int CheckOptionalMetaFieldCountAndType(const std::map &met { uint32_t indexMetaFieldCount = 0; uint32_t skipSizeMetaFieldCount = 0; - if (metaFieldPathType.count(FieldPath{KEYWORD_SCHEMA_INDEXES}) != 0) { + if (metaFieldPathType.count(FieldPath{SchemaConstant::KEYWORD_SCHEMA_INDEXES}) != 0) { indexMetaFieldCount++; - FieldType type = metaFieldPathType.at(FieldPath{KEYWORD_SCHEMA_INDEXES}); + FieldType type = metaFieldPathType.at(FieldPath{SchemaConstant::KEYWORD_SCHEMA_INDEXES}); if (type != FieldType::LEAF_FIELD_ARRAY) { LOGE("[Schema][CheckMeta] Expect SCHEMA_INDEXES type ARRAY but %s.", SchemaUtils::FieldTypeString(type).c_str()); return -E_SCHEMA_PARSE_FAIL; } } - if (metaFieldPathType.count(FieldPath{KEYWORD_SCHEMA_SKIPSIZE}) != 0) { + if (metaFieldPathType.count(FieldPath{SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE}) != 0) { skipSizeMetaFieldCount++; - FieldType type = metaFieldPathType.at(FieldPath{KEYWORD_SCHEMA_SKIPSIZE}); + FieldType type = metaFieldPathType.at(FieldPath{SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE}); if (type != FieldType::LEAF_FIELD_INTEGER) { LOGE("[Schema][CheckMeta] Expect SCHEMA_SKIPSIZE type INTEGER but %s.", SchemaUtils::FieldTypeString(type).c_str()); return -E_SCHEMA_PARSE_FAIL; } } - if (metaFieldPathType.size() != (SCHEMA_META_FEILD_COUNT_MIN + indexMetaFieldCount + skipSizeMetaFieldCount)) { + if (metaFieldPathType.size() != (SchemaConstant::SCHEMA_META_FEILD_COUNT_MIN + indexMetaFieldCount + + skipSizeMetaFieldCount)) { LOGE("[Schema][CheckMeta] Unrecognized metaField exist: total=%u, indexField=%u, skipSizeField=%u.", metaFieldPathType.size(), indexMetaFieldCount, skipSizeMetaFieldCount); return -E_SCHEMA_PARSE_FAIL; @@ -531,38 +534,38 @@ int SchemaObject::CheckMetaFieldCountAndType(const JsonObject& inJsonObject) con LOGE("[Schema][CheckMeta] GetSubFieldPathAndType fail, errCode=%d.", errCode); return errCode; } - if (metaFieldPathType.size() < SCHEMA_META_FEILD_COUNT_MIN || - metaFieldPathType.size() > SCHEMA_META_FEILD_COUNT_MAX) { + if (metaFieldPathType.size() < SchemaConstant::SCHEMA_META_FEILD_COUNT_MIN || + metaFieldPathType.size() > SchemaConstant::SCHEMA_META_FEILD_COUNT_MAX) { LOGE("[Schema][CheckMeta] Unexpected metafield count=%zu.", metaFieldPathType.size()); return -E_SCHEMA_PARSE_FAIL; } // Check KeyWord SCHEMA_VERSION - if (metaFieldPathType.count(FieldPath{KEYWORD_SCHEMA_VERSION}) == 0) { + if (metaFieldPathType.count(FieldPath{SchemaConstant::KEYWORD_SCHEMA_VERSION}) == 0) { LOGE("[Schema][CheckMeta] Expect metafield SCHEMA_VERSION but not find."); return -E_SCHEMA_PARSE_FAIL; } - FieldType type = metaFieldPathType.at(FieldPath{KEYWORD_SCHEMA_VERSION}); + FieldType type = metaFieldPathType.at(FieldPath{SchemaConstant::KEYWORD_SCHEMA_VERSION}); if (type != FieldType::LEAF_FIELD_STRING) { LOGE("[Schema][CheckMeta] Expect SCHEMA_VERSION type STRING but %s.", SchemaUtils::FieldTypeString(type).c_str()); return -E_SCHEMA_PARSE_FAIL; } // Check KeyWord SCHEMA_MODE - if (metaFieldPathType.count(FieldPath{KEYWORD_SCHEMA_MODE}) == 0) { + if (metaFieldPathType.count(FieldPath{SchemaConstant::KEYWORD_SCHEMA_MODE}) == 0) { LOGE("[Schema][CheckMeta] Expect metafield SCHEMA_MODE but not find."); return -E_SCHEMA_PARSE_FAIL; } - type = metaFieldPathType.at(FieldPath{KEYWORD_SCHEMA_MODE}); + type = metaFieldPathType.at(FieldPath{SchemaConstant::KEYWORD_SCHEMA_MODE}); if (type != FieldType::LEAF_FIELD_STRING) { LOGE("[Schema][CheckMeta] Expect SCHEMA_MODE type STRING but %s.", SchemaUtils::FieldTypeString(type).c_str()); return -E_SCHEMA_PARSE_FAIL; } // Check KeyWord SCHEMA_DEFINE - if (metaFieldPathType.count(FieldPath{KEYWORD_SCHEMA_DEFINE}) == 0) { + if (metaFieldPathType.count(FieldPath{SchemaConstant::KEYWORD_SCHEMA_DEFINE}) == 0) { LOGE("[Schema][CheckMeta] Expect metafield SCHEMA_DEFINE but not find."); return -E_SCHEMA_PARSE_FAIL; } - type = metaFieldPathType.at(FieldPath{KEYWORD_SCHEMA_DEFINE}); + type = metaFieldPathType.at(FieldPath{SchemaConstant::KEYWORD_SCHEMA_DEFINE}); if (type != FieldType::INTERNAL_FIELD_OBJECT) { // LEAF_FIELD_OBJECT indicate an empty object which is not allowed LOGE("[Schema][CheckMeta] Expect SCHEMA_DEFINE type INTERNAL_OBJECT but %s.", SchemaUtils::FieldTypeString(type).c_str()); @@ -576,28 +579,30 @@ int SchemaObject::ParseCheckSchemaVersionMode(const JsonObject& inJsonObject) { // Note: it has been checked in CheckMetaFieldCountAndType that SCHEMA_VERSION field exists and its type is string. FieldValue versionValue; - int errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath{KEYWORD_SCHEMA_VERSION}, versionValue); + int errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath{SchemaConstant::KEYWORD_SCHEMA_VERSION}, + versionValue); if (errCode != E_OK) { return -E_INTERNAL_ERROR; } - if (SchemaUtils::Strip(versionValue.stringValue) != SCHEMA_SUPPORT_VERSION) { + if (SchemaUtils::Strip(versionValue.stringValue) != SchemaConstant::SCHEMA_SUPPORT_VERSION) { LOGE("[Schema][ParseVerMode] Unexpected SCHEMA_VERSION=%s.", versionValue.stringValue.c_str()); return -E_SCHEMA_PARSE_FAIL; } - schemaVersion_ = SCHEMA_SUPPORT_VERSION; + schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION; // Note: it has been checked in CheckMetaFieldCountAndType that SCHEMA_MODE field exists and its type is string. FieldValue modeValue; - errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath{KEYWORD_SCHEMA_MODE}, modeValue); + errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath{SchemaConstant::KEYWORD_SCHEMA_MODE}, modeValue); if (errCode != E_OK) { return -E_INTERNAL_ERROR; } std::string modeStripped = SchemaUtils::Strip(modeValue.stringValue); - if (modeStripped != KEYWORD_MODE_STRICT && modeStripped != KEYWORD_MODE_COMPATIBLE) { + if (modeStripped != SchemaConstant::KEYWORD_MODE_STRICT && + modeStripped != SchemaConstant::KEYWORD_MODE_COMPATIBLE) { LOGE("[Schema][ParseVerMode] Unexpected SCHEMA_MODE=%s.", modeValue.stringValue.c_str()); return -E_SCHEMA_PARSE_FAIL; } - schemaMode_ = ((modeStripped == KEYWORD_MODE_STRICT) ? SchemaMode::STRICT : SchemaMode::COMPATIBLE); + schemaMode_ = ((modeStripped == SchemaConstant::KEYWORD_MODE_STRICT) ? SchemaMode::STRICT : SchemaMode::COMPATIBLE); return E_OK; } @@ -607,9 +612,9 @@ int SchemaObject::ParseCheckSchemaDefine(const JsonObject& inJsonObject) schemaDefine_.clear(); // Note: it has been checked in CheckMetaFieldCountAndType that SCHEMA_DEFINE field exists and its type is // internal-object. Nest path refer to those field with type internal object that has sub field. - std::set nestPathCurDepth{FieldPath{KEYWORD_SCHEMA_DEFINE}}; + std::set nestPathCurDepth{FieldPath{SchemaConstant::KEYWORD_SCHEMA_DEFINE}}; uint32_t fieldNameCount = 0; - for (uint32_t depth = 0; depth < SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { + for (uint32_t depth = 0; depth < SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { std::map subPathType; int errCode = inJsonObject.GetSubFieldPathAndType(nestPathCurDepth, subPathType); if (errCode != E_OK) { // Unlikely @@ -631,7 +636,7 @@ int SchemaObject::ParseCheckSchemaDefine(const JsonObject& inJsonObject) schemaDefine_[depth][FieldPath(++(subField.first.begin()), subField.first.end())] = attribute; // Deal with the nestpath and check depth limitation if (subField.second == FieldType::INTERNAL_FIELD_OBJECT) { - if (depth == SCHEMA_FEILD_PATH_DEPTH_MAX - 1) { // Minus 1 to be the boundary + if (depth == SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX - 1) { // Minus 1 to be the boundary LOGE("[Schema][ParseDefine] Path=%s is INTERNAL_FIELD_OBJECT but reach schema depth limitation.", SchemaUtils::FieldPathString(subField.first).c_str()); return -E_SCHEMA_PARSE_FAIL; @@ -644,7 +649,7 @@ int SchemaObject::ParseCheckSchemaDefine(const JsonObject& inJsonObject) break; } } - if (fieldNameCount > SCHEMA_FEILD_NAME_COUNT_MAX) { + if (fieldNameCount > SchemaConstant::SCHEMA_FEILD_NAME_COUNT_MAX) { // Check Field Count Here LOGE("[Schema][ParseDefine] FieldName count=%u exceed the limitation.", fieldNameCount); return -E_SCHEMA_PARSE_FAIL; @@ -706,19 +711,19 @@ int SchemaObject::ParseCheckSchemaIndexes(const JsonObject& inJsonObject) // Clear schemaIndexes_ to recover from a fail parse schemaIndexes_.clear(); // No SCHEMA_INDEXES field is allowed - if (!inJsonObject.IsFieldPathExist(FieldPath{KEYWORD_SCHEMA_INDEXES})) { + if (!inJsonObject.IsFieldPathExist(FieldPath{SchemaConstant::KEYWORD_SCHEMA_INDEXES})) { LOGD("[Schema][ParseIndex] No SCHEMA_INDEXES Field."); return E_OK; } // The type of SCHEMA_INDEXES field has been checked in CheckMetaFieldCountAndType to be an array // If not all members of the array are string type or string-array, this call will return error std::vector> oriIndexArray; - int errCode = inJsonObject.GetArrayContentOfStringOrStringArray(FieldPath{KEYWORD_SCHEMA_INDEXES}, oriIndexArray); + int errCode = inJsonObject.GetArrayContentOfStringOrStringArray(FieldPath{SchemaConstant::KEYWORD_SCHEMA_INDEXES}, oriIndexArray); if (errCode != E_OK) { LOGE("[Schema][ParseIndex] GetArrayContent Fail, errCode=%d.", errCode); return -E_SCHEMA_PARSE_FAIL; } - if (oriIndexArray.size() > SCHEMA_INDEX_COUNT_MAX) { + if (oriIndexArray.size() > SchemaConstant::SCHEMA_INDEX_COUNT_MAX) { LOGE("[Schema][ParseIndex] Index(Ori) count=%zu exceed limitation.", oriIndexArray.size()); return -E_SCHEMA_PARSE_FAIL; } @@ -734,17 +739,18 @@ int SchemaObject::ParseCheckSchemaIndexes(const JsonObject& inJsonObject) int SchemaObject::ParseCheckSchemaSkipSize(const JsonObject& inJsonObject) { // No SCHEMA_SKIPSIZE field is allowed - if (!inJsonObject.IsFieldPathExist(FieldPath{KEYWORD_SCHEMA_SKIPSIZE})) { + if (!inJsonObject.IsFieldPathExist(FieldPath{SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE})) { LOGD("[Schema][ParseSkipSize] No SCHEMA_SKIPSIZE Field."); return E_OK; } // The type of SCHEMA_SKIPSIZE field has been checked in CheckMetaFieldCountAndType to be an INTEGER FieldValue skipSizeValue; - int errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath{KEYWORD_SCHEMA_SKIPSIZE}, skipSizeValue); + int errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath{SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE}, skipSizeValue); if (errCode != E_OK) { return -E_INTERNAL_ERROR; } - if (skipSizeValue.integerValue < 0 || static_cast(skipSizeValue.integerValue) > SCHEMA_SKIPSIZE_MAX) { + if (skipSizeValue.integerValue < 0 || + static_cast(skipSizeValue.integerValue) > SchemaConstant::SCHEMA_SKIPSIZE_MAX) { LOGE("[Schema][ParseSkipSize] Unexpected SCHEMA_SKIPSIZE=%d.", skipSizeValue.integerValue); return -E_SCHEMA_PARSE_FAIL; } @@ -764,7 +770,7 @@ int SchemaObject::ParseCheckEachIndexFromStringArray(const std::vector SCHEMA_FEILD_PATH_DEPTH_MAX) { + if (eachPath.size() == 0 || eachPath.size() > SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) { LOGE("[Schema][ParseEachIndex] Root not indexable or path=%s depth exceed limit.", eachPathStr.c_str()); return -E_SCHEMA_PARSE_FAIL; } @@ -846,7 +852,7 @@ int SchemaObject::CompareSchemaSkipSize(const SchemaObject &newSchema) const int SchemaObject::CompareSchemaDefine(const SchemaObject &newSchema) const { bool isEqualExactly = true; - for (uint32_t depth = 0; depth < SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { + for (uint32_t depth = 0; depth < SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { SchemaDefine emptyDefine; const SchemaDefine &defineInOldSchema = (schemaDefine_.count(depth) == 0 ? emptyDefine : schemaDefine_.at(depth)); @@ -1158,7 +1164,7 @@ inline std::string ValueFieldType(const std::map &subPathT int SchemaObject::CheckValue(const ValueObject &inValue, std::set &lackingPaths) const { std::set nestPathCurDepth{FieldPath()}; // Empty path represent root path - for (uint32_t depth = 0; depth < SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { + for (uint32_t depth = 0; depth < SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) { if (schemaDefine_.count(depth) == 0 || schemaDefine_.at(depth).empty()) { // No schema define in this depth break; } diff --git a/services/distributeddataservice/libs/distributeddb/common/src/schema_utils.cpp b/services/distributeddataservice/libs/distributeddb/common/src/schema_utils.cpp index c1fe1fe961308bdbe95808690deed0bdf3af82c1..d854afe8f9b1e375af9e96e5e4d216bfb7454de4 100755 --- a/services/distributeddataservice/libs/distributeddb/common/src/schema_utils.cpp +++ b/services/distributeddataservice/libs/distributeddb/common/src/schema_utils.cpp @@ -20,17 +20,18 @@ #include #include "db_errno.h" #include "log_print.h" +#include "schema_constant.h" namespace DistributedDB { namespace { // Currently supported types const std::map FIELD_TYPE_DIC = { - {KEYWORD_TYPE_BOOL, FieldType::LEAF_FIELD_BOOL}, - {KEYWORD_TYPE_INTEGER, FieldType::LEAF_FIELD_INTEGER}, - {KEYWORD_TYPE_LONG, FieldType::LEAF_FIELD_LONG}, - {KEYWORD_TYPE_DOUBLE, FieldType::LEAF_FIELD_DOUBLE}, - {KEYWORD_TYPE_STRING, FieldType::LEAF_FIELD_STRING}, + {SchemaConstant::KEYWORD_TYPE_BOOL, FieldType::LEAF_FIELD_BOOL}, + {SchemaConstant::KEYWORD_TYPE_INTEGER, FieldType::LEAF_FIELD_INTEGER}, + {SchemaConstant::KEYWORD_TYPE_LONG, FieldType::LEAF_FIELD_LONG}, + {SchemaConstant::KEYWORD_TYPE_DOUBLE, FieldType::LEAF_FIELD_DOUBLE}, + {SchemaConstant::KEYWORD_TYPE_STRING, FieldType::LEAF_FIELD_STRING}, }; bool IsLegalFieldCharacter(char character) @@ -76,11 +77,13 @@ int SchemaUtils::MakeTrans(const std::string &oriContent, size_t &pos) { if (isspace(oriContent[pos])) { return COLUMN_BLANK; - } else if (oriContent.compare(pos, KEYWORD_ATTR_NOT_NULL.size(), KEYWORD_ATTR_NOT_NULL) == 0) { - pos = pos + KEYWORD_ATTR_NOT_NULL.size() - 1; + } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_NOT_NULL.size(), + SchemaConstant::KEYWORD_ATTR_NOT_NULL) == 0) { + pos = pos + SchemaConstant::KEYWORD_ATTR_NOT_NULL.size() - 1; return COLUMN_NOT_NULL; - } else if (oriContent.compare(pos, KEYWORD_ATTR_DEFAULT.size(), KEYWORD_ATTR_DEFAULT) == 0) { - pos = pos + KEYWORD_ATTR_DEFAULT.size() - 1; + } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_DEFAULT.size(), + SchemaConstant::KEYWORD_ATTR_DEFAULT) == 0) { + pos = pos + SchemaConstant::KEYWORD_ATTR_DEFAULT.size() - 1; return COLUMN_DEFAULT; } else if (std::isalnum(oriContent[pos]) || oriContent[pos] == '\'' || oriContent[pos] == '+' || oriContent[pos] == '-') { @@ -108,7 +111,7 @@ int SchemaUtils::SplitSchemaAttribute(const std::string &inAttrString, std::vect if (state == 1) { // state 1 :Indicates that only type information is currently available outAttrString[0].push_back(inAttrString[i]); } else if (state == 3) { // state 3 :Gets the NOT_NULL keyword - outAttrString[1] = KEYWORD_ATTR_NOT_NULL; + outAttrString[1] = SchemaConstant::KEYWORD_ATTR_NOT_NULL; } else if (state == 7) { // state 7 :Contains complete information // Get default string. Now transfer matrix can ensure > 1, but you should pay attention when fix it outAttrString[2] = inAttrString.substr(i - 1); @@ -129,10 +132,10 @@ int SchemaUtils::SplitSchemaAttribute(const std::string &inAttrString, std::vect int SchemaUtils::TransToBool(const std::string &defaultContent, SchemaAttribute &outAttr) { // Have been trim - if (defaultContent.compare(KEYWORD_ATTR_VALUE_TRUE) == 0) { + if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_TRUE) == 0) { outAttr.defaultValue.boolValue = true; return E_OK; - } else if (defaultContent.compare(KEYWORD_ATTR_VALUE_FALSE) == 0) { + } else if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_FALSE) == 0) { outAttr.defaultValue.boolValue = false; return E_OK; } @@ -145,7 +148,7 @@ int SchemaUtils::TransToString(const std::string &defaultContent, SchemaAttribut // Have been trim, Strip leading and trailing ' if (defaultContent.size() > 1 && defaultContent.front() == '\'' && defaultContent.back() == '\'') { outAttr.defaultValue.stringValue = defaultContent.substr(1, defaultContent.size() - 2); - if (outAttr.defaultValue.stringValue.size() > SCHEMA_DEFAULT_STRING_SIZE_LIMIT) { + if (outAttr.defaultValue.stringValue.size() > SchemaConstant::SCHEMA_DEFAULT_STRING_SIZE_LIMIT) { return -E_SCHEMA_PARSE_FAIL; } return E_OK; @@ -241,10 +244,10 @@ int SchemaUtils::TransToDouble(const std::string &defaultContent, SchemaAttribut int SchemaUtils::TransformDefaultValue(std::string &defaultContent, SchemaAttribute &outAttr) { TrimFiled(defaultContent); - if (defaultContent.compare(KEYWORD_ATTR_VALUE_NULL) == 0 && outAttr.hasNotNullConstraint) { + if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_NULL) == 0 && outAttr.hasNotNullConstraint) { LOGE("NOT NULL and DEFAULT null Simultaneously"); return -E_SCHEMA_PARSE_FAIL; - } else if (defaultContent.compare(KEYWORD_ATTR_VALUE_NULL) == 0) { + } else if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_NULL) == 0) { outAttr.hasDefaultValue = false; return E_OK; } @@ -366,7 +369,7 @@ int CheckDollarDotPrefix(const std::string &inPathStr, bool &hasPrefix) } } -int SchemaUtils::ParseAndCheckFieldPath(const std::string &inPathString, FieldPath &outPath) +int SchemaUtils::ParseAndCheckFieldPath(const std::string &inPathString, FieldPath &outPath, bool permitPrefix) { std::string tempInPathString = inPathString; TrimFiled(tempInPathString); @@ -376,6 +379,12 @@ int SchemaUtils::ParseAndCheckFieldPath(const std::string &inPathString, FieldPa LOGE("CheckDollarDotPrefix Fail."); return errCode; } + + if (!permitPrefix && hasPrefix) { + LOGE("Not permit $. prefix."); + return -E_SCHEMA_PARSE_FAIL; + } + if (!hasPrefix) { tempInPathString = std::string("$.") + tempInPathString; } @@ -390,7 +399,7 @@ int SchemaUtils::ParseAndCheckFieldPath(const std::string &inPathString, FieldPa curPos = nextPointPos; } - if (outPath.size() > SCHEMA_FEILD_PATH_DEPTH_MAX) { + if (outPath.size() > SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) { LOGE("Parse Schema Index depth illegality!"); return -E_SCHEMA_PARSE_FAIL; } @@ -406,7 +415,7 @@ int SchemaUtils::ParseAndCheckFieldPath(const std::string &inPathString, FieldPa int SchemaUtils::CheckFieldName(const FieldName &inName) { - if (inName.empty() || inName.size() > SCHEMA_FEILD_NAME_LENGTH_MAX) { + if (inName.empty() || inName.size() > SchemaConstant::SCHEMA_FEILD_NAME_LENGTH_MAX) { LOGE("Schema FieldName have invalid size!"); return -E_SCHEMA_PARSE_FAIL; } @@ -466,6 +475,7 @@ std::string SchemaUtils::SchemaTypeString(SchemaType inType) {SchemaType::NONE, "NONE"}, {SchemaType::JSON, "JSON-SCHEMA"}, {SchemaType::FLATBUFFER, "FLATBUFFER-SCHEMA"}, + {SchemaType::RELATIVE, "RELATIVE"}, {SchemaType::UNRECOGNIZED, "UNRECOGNIZED"}, }; return schemaTypeMapString[inType]; diff --git a/services/distributeddataservice/libs/distributeddb/include/auto_launch_export.h b/services/distributeddataservice/libs/distributeddb/include/auto_launch_export.h index 4fba674560c566bb89bd14f08f733953daf16149..5001a858678125864fe8422433c777518f6c5667 100755 --- a/services/distributeddataservice/libs/distributeddb/include/auto_launch_export.h +++ b/services/distributeddataservice/libs/distributeddb/include/auto_launch_export.h @@ -19,6 +19,7 @@ #include "types_export.h" #include "kv_store_observer.h" #include "kv_store_nb_delegate.h" +#include "store_observer.h" namespace DistributedDB { struct AutoLaunchOption { @@ -38,6 +39,7 @@ struct AutoLaunchOption { bool isNeedCompressOnSync = false; uint8_t compressionRate = 100; // valid in [1, 100]. bool isAutoSync = true; + StoreObserver *storeObserver = nullptr; }; struct AutoLaunchParam { diff --git a/services/distributeddataservice/libs/distributeddb/include/query.h b/services/distributeddataservice/libs/distributeddb/include/query.h index 91271f6a3c281f647ae78394fc4108874e6e01bf..5480939c3007fa810773f19e7e042ff3919aa80a 100755 --- a/services/distributeddataservice/libs/distributeddb/include/query.h +++ b/services/distributeddataservice/libs/distributeddb/include/query.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "query_expression.h" #include "types_export.h" @@ -140,6 +141,8 @@ public: DB_API Query &SuggestIndex(const std::string &indexName); + DB_API Query &InKeys(const std::set &keys); + friend class GetQueryInfo; ~Query() = default; diff --git a/services/distributeddataservice/libs/distributeddb/include/query_expression.h b/services/distributeddataservice/libs/distributeddb/include/query_expression.h index 48084148c535dee01e8856da4ecf0c95ae9a1ca4..a864c611146411eadbb0309ac7f7381fb5bfaf72 100755 --- a/services/distributeddataservice/libs/distributeddb/include/query_expression.h +++ b/services/distributeddataservice/libs/distributeddb/include/query_expression.h @@ -19,6 +19,7 @@ #include #include #include +#include #include "types_export.h" @@ -57,6 +58,7 @@ enum class QueryObjType : uint32_t { LIMIT = 0x0701, ORDERBY, SUGGEST_INDEX = 0x0801, + IN_KEYS = 0x0901, }; struct QueryObjNode { @@ -114,10 +116,13 @@ public: void SetTableName(const std::string &tableName); const std::string &GetTableName(); - bool IsTableNameSpacified() const; + bool IsTableNameSpecified() const; std::string GetSuggestIndex() const; + const std::set &GetKeys() const; + void InKeys(const std::set &keys); + const std::list &GetQueryExpression(); void SetErrFlag(bool flag); @@ -133,6 +138,7 @@ private: std::string suggestIndex_; std::string tableName_; bool isTableNameSpecified_; + std::set keys_; }; // specialize for double diff --git a/services/distributeddataservice/libs/distributeddb/include/types_export.h b/services/distributeddataservice/libs/distributeddb/include/types_export.h index 6e474e73408006ca43080e5547e87961be9f6e98..97687358a762008594a89e0f05923dc63b9a6a05 100755 --- a/services/distributeddataservice/libs/distributeddb/include/types_export.h +++ b/services/distributeddataservice/libs/distributeddb/include/types_export.h @@ -119,6 +119,9 @@ using PermissionCheckCallback = std::function; +using StoreStatusNotifier = std::function; // status, 1: online, 0: offline + enum AutoLaunchStatus { WRITE_OPENED = 1, WRITE_CLOSED = 2, diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/intercepted_data.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/intercepted_data.h index 85c49cef5e79e5b5fa698945fe3a74847b924f29..9d6fa2cfec81185c6927576aed95be52fc5fc46f 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/intercepted_data.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/intercepted_data.h @@ -17,7 +17,7 @@ #define INTERCEPTED_DATA_H #include -#include "types.h" +#include "store_types.h" #include "types_export.h" namespace DistributedDB { diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_communicator.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_communicator.h index 94228dbab33c191d5d22e875cf568d57c21ef6d9..f2dd6163c216e8a519232042999869237fa1b228 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_communicator.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_communicator.h @@ -20,7 +20,7 @@ #include #include #include -#include "types.h" +#include "store_types.h" namespace DistributedDB { // The DeviceInfos may contain other fields(Can only be auxiliary information) besides identifier field in the future. diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_system_api_adapter.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_system_api_adapter.h index 7a0ede831802b893444a05424b7c249d38a1c47d..3a3b14de6dcdac3e5f8082f7fbd28d4c9905f366 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_system_api_adapter.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/iprocess_system_api_adapter.h @@ -18,7 +18,7 @@ #include #include -#include "types.h" +#include "store_types.h" namespace DistributedDB { using OnAccessControlledEvent = std::function; diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_changed_data.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_changed_data.h index ce63ef04e2856894941c4a6c72ffc213ab80793a..65f84a41965185653920a046ea4c9d62c42a92ac 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_changed_data.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_changed_data.h @@ -17,7 +17,7 @@ #define KV_STORE_CHANGED_DATA_H #include -#include "types.h" +#include "store_types.h" namespace DistributedDB { class KvStoreChangedData { diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate.h index 93be3e10dac7c747d70b7a7d3be03da8f9269d53..5194ac455d4004c67a6e84e0ff8a00922e428934 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate.h @@ -19,7 +19,7 @@ #include #include -#include "types.h" +#include "store_types.h" #include "kv_store_observer.h" #include "kv_store_snapshot_delegate.h" diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h index e1613e077368482d9992193c09d402c8ed6b8a60..16c5e1f095664ed112558757e6649a7688874c84 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h @@ -25,7 +25,7 @@ #include "kv_store_delegate.h" #endif #include "kv_store_nb_delegate.h" -#include "types.h" +#include "store_types.h" #include "iprocess_communicator.h" #include "iprocess_system_api_adapter.h" #include "auto_launch_export.h" @@ -102,6 +102,8 @@ public: DB_API static DBStatus SetProcessSystemAPIAdapter(const std::shared_ptr &adapter); + DB_API static void SetStoreStatusNotifier(const StoreStatusNotifier ¬ifier); + private: // Check if the dataDir is safe arg. diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_errno.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_errno.h index 364df4b0fad11176475144d644a2c49dd9de3dbd..4cb150f59a06d3cdc8f5a3c01df5e249c1ed948c 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_errno.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_errno.h @@ -16,7 +16,7 @@ #ifndef KV_STORE_ERRNO_H #define KV_STORE_ERRNO_H -#include "types.h" +#include "store_types.h" namespace DistributedDB { // Transfer the db error code to the DBStatus. diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_conflict_data.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_conflict_data.h index 80138261506b81253d32490d508476ef1eac2a9f..9ce4317d8f3a5f0ff9819a67d1eb4a1bfd3732f6 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_conflict_data.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_conflict_data.h @@ -16,7 +16,7 @@ #ifndef KV_STORE_NB_CONFLICT_DATA_H #define KV_STORE_NB_CONFLICT_DATA_H -#include "types.h" +#include "store_types.h" namespace DistributedDB { enum KvStoreNbConflictType { diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h index cae441e22b54b321ff9d59c73f122d855adbf66b..2215b370d4474b2ee3a507d143ceae1726c81ea8 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h @@ -20,7 +20,7 @@ #include #include -#include "types.h" +#include "store_types.h" #include "kv_store_observer.h" #include "kv_store_nb_conflict_data.h" #include "kv_store_result_set.h" diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_result_set.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_result_set.h index afb0e8aa7f9a70b22f224c6238662ce0b07979e1..68a72de1d31dd002b2c75e7d8d4cd00104e4d4bc 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_result_set.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_result_set.h @@ -16,7 +16,7 @@ #ifndef KV_STORE_RESULT_SET_H #define KV_STORE_RESULT_SET_H -#include "types.h" +#include "store_types.h" namespace DistributedDB { class KvStoreResultSet { diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_snapshot_delegate.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_snapshot_delegate.h index f13b4531a8b3ffa82531991834d9b4d15e1f58e5..3053e7ff5f6d08e60454e3b3cfcd1663a5c563a0 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_snapshot_delegate.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/kv_store_snapshot_delegate.h @@ -19,7 +19,7 @@ #include #include -#include "types.h" +#include "store_types.h" namespace DistributedDB { class KvStoreSnapshotDelegate { diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h index fbf038564aa8476dc32b4d2dd0015ae3b7c0244e..448d22642e0ebc3dddd6c8b6bc77bab8cf4684f5 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h @@ -19,7 +19,8 @@ #include #include "query.h" -#include "types.h" +#include "store_types.h" +#include "store_observer.h" namespace DistributedDB { class RelationalStoreDelegate { @@ -27,22 +28,18 @@ public: DB_API virtual ~RelationalStoreDelegate() = default; struct Option { + StoreObserver *observer = nullptr; // split mode }; - DB_API virtual DBStatus Pragma(PragmaCmd cmd, PragmaData ¶mData) = 0; - - DB_API virtual DBStatus RemoveDeviceData(const std::string &device) = 0; - DB_API virtual DBStatus CreateDistributedTable(const std::string &tableName) = 0; DB_API virtual DBStatus Sync(const std::vector &devices, SyncMode mode, - SyncStatusCallback &onComplete, bool wait) = 0; + const Query &query, const SyncStatusCallback &onComplete, bool wait) = 0; - DB_API virtual DBStatus Sync(const std::vector &devices, SyncMode mode, - const Query &query, SyncStatusCallback &onComplete, bool wait) = 0; + DB_API virtual DBStatus RemoveDeviceData(const std::string &device) = 0; - DB_API virtual DBStatus RemoveDevicesData(const std::string &tableName, const std::string &device) = 0; + DB_API virtual DBStatus RemoveDeviceData(const std::string &device, const std::string &tableName) = 0; }; } // namespace DistributedDB #endif // RELATIONAL_STORE_DELEGATE_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_manager.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_manager.h index 6a06e4878ef612a2814f9211c917260ee7d31903..9be7b6e69465a47be4f545ac0f1e87396318812b 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_manager.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_manager.h @@ -14,18 +14,20 @@ */ #ifndef RELATIONAL_STORE_MANAGER_H #define RELATIONAL_STORE_MANAGER_H - #include #include #include #include "auto_launch_export.h" #include "relational_store_delegate.h" -#include "types.h" +#include "store_types.h" namespace DistributedDB { class RelationalStoreManager final { public: + // Only calculate the table name with device hash, no guarantee for the table exists + DB_API static std::string GetDistributedTableName(const std::string &device, const std::string &tableName); + DB_API RelationalStoreManager(const std::string &appId, const std::string &userId); DB_API ~RelationalStoreManager() = default; @@ -39,8 +41,6 @@ public: DB_API DBStatus CloseStore(RelationalStoreDelegate *store); - DB_API DBStatus DeleteStore(const std::string &path); - DB_API static void SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback); DB_API static std::string GetRelationalStoreIdentifier(const std::string &userId, const std::string &appId, diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h index ab7ed71177c4682d0ee79421260aa1b30fe28097..59f4d534236c2b4a1255f25991fa5b8c18585b49 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/relational_store_sqlite_ext.h @@ -14,17 +14,18 @@ */ #ifndef RELATIONAL_STORE_EXT_H #define RELATIONAL_STORE_EXT_H -#ifdef RELATIONAL_STORE #define SQLITE3_HW_EXPORT_SYMBOLS +// using the "sqlite3sym.h" in OHOS +#ifndef USE_SQLITE_SYMBOLS #include "sqlite3.h" -#include "types.h" +#else +#include "sqlite3sym.h" +#endif // We extend the original purpose of the "sqlite3ext.h". struct sqlite3_api_routines_relational { - int (*close)(sqlite3*); - int (*close_v2)(sqlite3*); int (*open)(const char *, sqlite3 **); int (*open16)(const void *, sqlite3 **); int (*open_v2)(const char *, sqlite3 **, int, const char *); @@ -32,16 +33,6 @@ struct sqlite3_api_routines_relational { extern const struct sqlite3_api_routines_relational *sqlite3_export_relational_symbols; -#ifdef sqlite3_close -#undef sqlite3_close -#endif -#define sqlite3_close sqlite3_export_relational_symbols->close - -#ifdef sqlite3_close_v2 -#undef sqlite3_close_v2 -#endif -#define sqlite3_close_v2 sqlite3_export_relational_symbols->close_v2 - #ifdef sqlite3_open #undef sqlite3_open #endif @@ -57,5 +48,4 @@ extern const struct sqlite3_api_routines_relational *sqlite3_export_relational_s #endif #define sqlite3_open_v2 sqlite3_export_relational_symbols->open_v2 -#endif #endif // RELATIONAL_STORE_EXT_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/runtime_config.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/runtime_config.h index b21c7dba80724fde3813fcfc037ae6e3c5072f19..517ffd5f9b37e8cc3f09d37808bf34d96a26ea4b 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/runtime_config.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/runtime_config.h @@ -21,7 +21,7 @@ #include "iprocess_communicator.h" #include "iprocess_system_api_adapter.h" -#include "types.h" +#include "store_types.h" namespace DistributedDB { class RuntimeConfig final { public: diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/store_changed_data.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/store_changed_data.h new file mode 100644 index 0000000000000000000000000000000000000000..46ff59907d01f68c5f1cc54509d6f0d5c23d9a22 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/store_changed_data.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2022 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 STORE_CHANGED_DATA_H +#define STORE_CHANGED_DATA_H + +#include +#include "store_types.h" + +namespace DistributedDB { +struct StoreProperty { + std::string userId; + std::string appId; + std::string storeId; +}; +class StoreChangedData { +public: + StoreChangedData() {} + DB_API virtual ~StoreChangedData() {} + + // Interface for Getting the device whose data changed. + DB_API virtual const std::string GetDataChangeDevice() const = 0; + + // Interface for Getting the store whose data changed. + DB_API virtual void GetStoreProperty(StoreProperty &storeProperty) const = 0; +}; +} // namespace DistributedDB + +#endif // STORE_CHANGED_DATA_H diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/store_observer.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/store_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..6072bbc694668ce585cee25cb21605691865c33e --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/relational/store_observer.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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 STORE_OBSERVER_H +#define STORE_OBSERVER_H + +#include "store_changed_data.h" + +namespace DistributedDB { +class StoreObserver { +public: + virtual ~StoreObserver() {} + + // Databa change callback + virtual void OnChange(const StoreChangedData &data) = 0; +}; +} // namespace DistributedDB + +#endif // STORE_OBSERVER_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/include/types.h b/services/distributeddataservice/libs/distributeddb/interfaces/include/store_types.h similarity index 96% rename from services/distributeddataservice/libs/distributeddb/interfaces/include/types.h rename to services/distributeddataservice/libs/distributeddb/interfaces/include/store_types.h index 8012f771d3078cdafec7c6a8a929c49487c8e653..2a121192a5bd3891555539f93ee07ac711acbf6c 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/include/types.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/include/store_types.h @@ -57,8 +57,8 @@ enum DBStatus { SCHEMA_VIOLATE_VALUE, // Values already exist in dbFile do not match new schema INTERCEPT_DATA_FAIL, // Interceptor push data failed. LOG_OVER_LIMITS, // Log size is over the limits. - RELATIONAL_SCHEMA_NOT_FOUND, // the sync table is not a relational table - RELATIONAL_SCHEMA_CHANGED, // the schema was changed + DISTRIBUTED_SCHEMA_NOT_FOUND, // the sync table is not a distributed table + DISTRIBUTED_SCHEMA_CHANGED, // the schema was changed }; struct KvStoreConfig { diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/intercepted_data_impl.h b/services/distributeddataservice/libs/distributeddb/interfaces/src/intercepted_data_impl.h index 6e548d72e2ceac993588c9a8d446ff739b0b90a3..30fefe4bbefea8beff25eb154a596efe9aedf1f3 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/intercepted_data_impl.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/intercepted_data_impl.h @@ -23,7 +23,7 @@ #include "intercepted_data.h" #include "macro_utils.h" #include "single_ver_kv_entry.h" -#include "types.h" +#include "store_types.h" #include "types_export.h" namespace DistributedDB { diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_impl.h b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_impl.h index 9cf8b57520134dbe2d298c566e5a1129cafea30b..b2fcdea73758ae5eb97ff3b35597380b1731c763 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_impl.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_impl.h @@ -21,7 +21,7 @@ #include #include -#include "types.h" +#include "store_types.h" #include "ikvdb_connection.h" #include "ikvdb_factory.h" #include "kv_store_delegate.h" diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp index a0c0cde7c605527c830aac943e2355fefd342225..53b8aae7298280f3a75a36bdd51fad195d225146 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp @@ -526,14 +526,15 @@ DBStatus KvStoreDelegateManager::EnableKvStoreAutoLaunch(const std::string &user return DB_ERROR; } AutoLaunchParam param{ userId, appId, storeId, option, notifier }; - KvDBProperties properties; - int errCode = AutoLaunch::GetAutoLaunchProperties(param, properties); + std::shared_ptr ptr = std::make_shared(); + int errCode = AutoLaunch::GetAutoLaunchProperties(param, DBType::DB_KV, ptr); if (errCode != E_OK) { LOGE("[KvStoreManager] Enable auto launch failed:%d", errCode); return TransferDBErrno(errCode); } - errCode = RuntimeContext::GetInstance()->EnableKvStoreAutoLaunch(properties, notifier, option); + std::shared_ptr kvPtr = std::static_pointer_cast(ptr); + errCode = RuntimeContext::GetInstance()->EnableKvStoreAutoLaunch(*kvPtr, notifier, option); if (errCode != E_OK) { LOGE("[KvStoreManager] Enable auto launch failed:%d", errCode); return TransferDBErrno(errCode); @@ -562,7 +563,7 @@ DBStatus KvStoreDelegateManager::DisableKvStoreAutoLaunch(const std::string &use void KvStoreDelegateManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) { - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBType::DB_KV); } std::string KvStoreDelegateManager::GetKvStoreIdentifier(const std::string &userId, const std::string &appId, @@ -578,4 +579,9 @@ DBStatus KvStoreDelegateManager::SetProcessSystemAPIAdapter(const std::shared_pt { return TransferDBErrno(RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter)); } + +void KvStoreDelegateManager::SetStoreStatusNotifier(const StoreStatusNotifier ¬ifier) +{ + RuntimeContext::GetInstance()->SetStoreStatusNotifier(notifier); +} } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_errno.cpp b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_errno.cpp index 492ea201197898a30ca755875632c9b67fd1a7fb..27ce5fb42ad7b670d17eeb27c6d194acfcaf6c31 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_errno.cpp +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_errno.cpp @@ -53,6 +53,8 @@ namespace { { -E_SECURITY_OPTION_CHECK_ERROR, SECURITY_OPTION_CHECK_ERROR }, { -E_INTERCEPT_DATA_FAIL, INTERCEPT_DATA_FAIL }, { -E_LOG_OVER_LIMITS, LOG_OVER_LIMITS }, + { -E_DISTRIBUTED_SCHEMA_NOT_FOUND, DISTRIBUTED_SCHEMA_NOT_FOUND}, + { -E_DISTRIBUTED_SCHEMA_CHANGED, DISTRIBUTED_SCHEMA_CHANGED}, }; } diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp index 9c346ccdcca8cbdf0312758cd2b8686a6b15de2b..c2af67c2397450da9eb96a4bd25cb34eacb10e0a 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp @@ -24,7 +24,7 @@ #include "db_errno.h" #include "db_types.h" #include "param_check_utils.h" -#include "types.h" +#include "store_types.h" #include "kvdb_pragma.h" #include "kvdb_manager.h" #include "kv_store_errno.h" diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h index 35606772fd9120ef6ece995eba3b5a3ae3f1a4cd..cac5fbaab8a827bba71bf5d6e0df696f05c69cb5 100755 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.h @@ -21,7 +21,7 @@ #include #include -#include "types.h" +#include "store_types.h" #include "db_types.h" #include "ikvdb_connection.h" #include "kv_store_nb_conflict_data.h" diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_changed_data_impl.cpp b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_changed_data_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75270211db98d62832bca20a03c266f91f7e0f07 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_changed_data_impl.cpp @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022 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 "relational_store_changed_data_impl.h" + +namespace DistributedDB { +RelationalStoreChangedDataImpl::~RelationalStoreChangedDataImpl() +{ +} + +DB_API const std::string RelationalStoreChangedDataImpl::GetDataChangeDevice() const +{ + std::lock_guard lock(mutex_); + // add get changedDevice_ code; + return changedDevice_; +} + +DB_API void RelationalStoreChangedDataImpl::GetStoreProperty(StoreProperty &storeProperty) const +{ + std::lock_guard lock(mutex_); + storeProperty = storeProperty_; +} + +void RelationalStoreChangedDataImpl::SetStoreProperty(const StoreProperty &storeProperty) +{ + std::lock_guard lock(mutex_); + storeProperty_ = storeProperty; +} +} // namespace DistributedDB + diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_changed_data_impl.h b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_changed_data_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..bce7f93c1a1f5602835c5d83e8415d563a7c88c6 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_changed_data_impl.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022 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 RELATION_STORE_CHANGED_DATA_IMPL_H +#define RELATION_STORE_CHANGED_DATA_IMPL_H + +#include +#include "macro_utils.h" +#include "store_changed_data.h" + +namespace DistributedDB { +class RelationalStoreChangedDataImpl : public StoreChangedData { +public: + explicit RelationalStoreChangedDataImpl(const std::string &changedDevice) : changedDevice_(changedDevice) {} + virtual ~RelationalStoreChangedDataImpl(); + + DISABLE_COPY_ASSIGN_MOVE(RelationalStoreChangedDataImpl); + + const std::string GetDataChangeDevice() const override; + + void GetStoreProperty(StoreProperty &storeProperty) const override; + + void SetStoreProperty(const StoreProperty &storeProperty); +private: + mutable std::mutex mutex_; + mutable std::string changedDevice_; + StoreProperty storeProperty_; +}; +} // namespace DistributedDB + +#endif // RELATION_STORE_CHANGED_DATA_IMPL_H + diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index a4d279cdf3c532b9f56f57b0d3de9be96d1ea439..d8ec715a32c9730201787bfda345934462de9cb7 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -30,27 +30,16 @@ RelationalStoreDelegateImpl::RelationalStoreDelegateImpl(RelationalStoreConnecti RelationalStoreDelegateImpl::~RelationalStoreDelegateImpl() { if (!releaseFlag_) { - LOGF("[KvStoreNbDelegate] Can't release directly"); + LOGF("[RelationalStore Delegate] Can't release directly"); return; } conn_ = nullptr; }; -DBStatus RelationalStoreDelegateImpl::Pragma(PragmaCmd cmd, PragmaData ¶mData) -{ - return NOT_SUPPORT; -} - -DBStatus RelationalStoreDelegateImpl::Sync(const std::vector &devices, SyncMode mode, - SyncStatusCallback &onComplete, bool wait) -{ - return NOT_SUPPORT; -} - DBStatus RelationalStoreDelegateImpl::RemoveDeviceData(const std::string &device) { - return NOT_SUPPORT; + return RemoveDeviceData(device, {}); } DBStatus RelationalStoreDelegateImpl::CreateDistributedTable(const std::string &tableName) @@ -74,7 +63,7 @@ DBStatus RelationalStoreDelegateImpl::CreateDistributedTable(const std::string & } DBStatus RelationalStoreDelegateImpl::Sync(const std::vector &devices, SyncMode mode, - const Query &query, SyncStatusCallback &onComplete, bool wait) + const Query &query, const SyncStatusCallback &onComplete, bool wait) { if (conn_ == nullptr) { LOGE("Invalid connection for operation!"); @@ -91,9 +80,24 @@ DBStatus RelationalStoreDelegateImpl::Sync(const std::vector &devic return OK; } -DBStatus RelationalStoreDelegateImpl::RemoveDevicesData(const std::string &tableName, const std::string &device) +DBStatus RelationalStoreDelegateImpl::RemoveDeviceData(const std::string &device, const std::string &tableName) { - return NOT_SUPPORT; + if (conn_ == nullptr) { + LOGE("Invalid connection for operation!"); + return DB_ERROR; + } + + if (device.empty()) { + LOGE("[RelationalStore Delegate] Remove device data with unspecified device name."); + return INVALID_ARGS; + } + + int errCode = conn_->RemoveDeviceData(device, tableName); + if (errCode != E_OK) { + LOGW("[RelationalStore Delegate] remove device data failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; } DBStatus RelationalStoreDelegateImpl::Close() @@ -104,7 +108,7 @@ DBStatus RelationalStoreDelegateImpl::Close() int errCode = conn_->Close(); if (errCode == -E_BUSY) { - LOGW("[KvStoreDelegate] busy for close"); + LOGW("[RelationalStore Delegate] busy for close"); return BUSY; } if (errCode != E_OK) { @@ -112,7 +116,7 @@ DBStatus RelationalStoreDelegateImpl::Close() return TransferDBErrno(errCode); } - LOGI("[KvStoreDelegate] Close"); + LOGI("[RelationalStore Delegate] Close"); conn_ = nullptr; return OK; } diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h index 76eb8defe22dff8f5b09518c5ed274a181b1e6aa..2a151f20db77041fec2ae9e56cb101e6f54b7ea7 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h @@ -29,22 +29,18 @@ public: DISABLE_COPY_ASSIGN_MOVE(RelationalStoreDelegateImpl); - DBStatus Pragma(PragmaCmd cmd, PragmaData ¶mData) override; - - DBStatus Sync(const std::vector &devices, SyncMode mode, - SyncStatusCallback &onComplete, bool wait) override; - DBStatus Sync(const std::vector &devices, SyncMode mode, - const Query &query, SyncStatusCallback &onComplete, bool wait) override; + const Query &query, const SyncStatusCallback &onComplete, bool wait) override; DBStatus RemoveDeviceData(const std::string &device) override; DBStatus CreateDistributedTable(const std::string &tableName) override; - DBStatus RemoveDevicesData(const std::string &tableName, const std::string &device) override; + DBStatus RemoveDeviceData(const std::string &device, const std::string &tableName) override; // For connection DBStatus Close(); + void SetReleaseFlag(bool flag); private: diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp index a72f5667a91668b6d85810b137bc3550eb6891a3..2b207ebb881dc1c625790b2cf4cbfa333cbc8a52 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp @@ -24,6 +24,7 @@ #include "log_print.h" #include "db_errno.h" #include "kv_store_errno.h" +#include "relational_store_changed_data_impl.h" #include "relational_store_delegate_impl.h" #include "runtime_context.h" #include "platform_specific.h" @@ -93,6 +94,14 @@ DB_API DBStatus RelationalStoreManager::OpenStore(const std::string &path, const conn->Close(); return DB_ERROR; } + conn->RegisterObserverAction([option, storeId, this](const std::string &changedDevice) { + RelationalStoreChangedDataImpl data(changedDevice); + data.SetStoreProperty({userId_, appId_, storeId}); + if (option.observer) { + LOGD("begin to observer onchange, changedDevice=%s", STR_MASK(changedDevice)); + option.observer->OnChange(data); + } + }); return OK; } @@ -114,69 +123,17 @@ DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store) return OK; } -static int RemoveFile(const std::string &fileName) -{ - if (!OS::CheckPathExistence(fileName)) { - return E_OK; - } - - if (OS::RemoveFile(fileName.c_str()) != E_OK) { - LOGE("Remove file failed:%d", errno); - return -E_REMOVE_FILE; - } - return E_OK; -} - -static int RemoveDB(const std::string &path) -{ - if (RemoveFile(path) != E_OK) { - LOGE("Remove the db file failed:%d", errno); - return -E_REMOVE_FILE; - } - - std::string dbFile = path + "-wal"; - if (RemoveFile(dbFile) != E_OK) { - LOGE("Remove the wal file failed:%d", errno); - return -E_REMOVE_FILE; - } - - dbFile = path + "-shm"; - if (RemoveFile(dbFile) != E_OK) { - LOGE("Remove the shm file failed:%d", errno); - return -E_REMOVE_FILE; - } - return E_OK; -} - -DBStatus RelationalStoreManager::DeleteStore(const std::string &path) +std::string RelationalStoreManager::GetDistributedTableName(const std::string &device, const std::string &tableName) { - if (path.empty()) { - LOGE("Invalid store info for deleting"); - return INVALID_ARGS; - } - - std::string identifier = userId_ + "-" + appId_ + "-" + path; - std::string hashIdentifier = DBCommon::TransferHashString(identifier); - - auto *manager = RelationalStoreInstance::GetInstance(); - int errCode = manager->CheckDatabaseFileStatus(hashIdentifier); - if (errCode != E_OK) { - LOGE("The store is busy!"); - return BUSY; - } - - // RemoveDB - errCode = RemoveDB(path); - if (errCode == E_OK) { - LOGI("Database deleted successfully!"); - return OK; + if (device.empty() || tableName.empty()) { + return {}; } - LOGE("Delete the kv store error:%d", errCode); - return TransferDBErrno(errCode); + return DBCommon::GetDistributedTableName(device, tableName); } void RelationalStoreManager::SetAutoLaunchRequestCallback(const AutoLaunchRequestCallback &callback) { + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(callback, DBType::DB_RELATION); } std::string RelationalStoreManager::GetRelationalStoreIdentifier(const std::string &userId, const std::string &appId, diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index 70209f45d85909b8baf3fbd954161fa279189e9d..92421716da3213b66520650538dacc77c11af4f7 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -12,48 +12,370 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifdef RELATIONAL_STORE -#include "sqlite_utils.h" -#include "log_print.h" -using namespace DistributedDB; -// namespace DistributedDB { -// We extend the original purpose of the "sqlite3ext.h". -SQLITE_API int sqlite3_close_relational(sqlite3* db) + +#include +#include +#include +#include +#include + +// using the "sqlite3sym.h" in OHOS +#ifndef USE_SQLITE_SYMBOLS +#include "sqlite3.h" +#else +#include "sqlite3sym.h" +#endif + +namespace { +constexpr int E_OK = 0; +constexpr int E_ERROR = 1; + +class ValueHashCalc { +public: + ValueHashCalc() {}; + ~ValueHashCalc() + { + delete context_; + context_ = nullptr; + } + + int Initialize() + { + context_ = new (std::nothrow) SHA256_CTX; + if (context_ == nullptr) { + return -E_ERROR; + } + + int errCode = SHA256_Init(context_); + if (errCode == 0) { + return -E_ERROR; + } + return E_OK; + } + + int Update(const std::vector &value) + { + if (context_ == nullptr) { + return -E_ERROR; + } + int errCode = SHA256_Update(context_, value.data(), value.size()); + if (errCode == 0) { + return -E_ERROR; + } + return E_OK; + } + + int GetResult(std::vector &value) + { + if (context_ == nullptr) { + return -E_ERROR; + } + + value.resize(SHA256_DIGEST_LENGTH); + int errCode = SHA256_Final(value.data(), context_); + if (errCode == 0) { + return -E_ERROR; + } + + return E_OK; + } + +private: + SHA256_CTX *context_ = nullptr; +}; + + +const uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000; + +using TimeStamp = uint64_t; +using TimeOffset = int64_t; + +class TimeHelper { +public: + constexpr static int64_t BASE_OFFSET = 10000LL * 365LL * 24LL * 3600LL * 1000LL * 1000LL * 10L; // 10000 year 100ns + + constexpr static int64_t MAX_VALID_TIME = BASE_OFFSET * 2; // 20000 year 100ns + + constexpr static uint64_t TO_100_NS = 10; // 1us to 100ns + + constexpr static TimeStamp INVALID_TIMESTAMP = 0; + + // Get current system time + static TimeStamp GetSysCurrentTime() + { + uint64_t curTime = 0; + int errCode = GetCurrentSysTimeInMicrosecond(curTime); + if (errCode != E_OK) { + return INVALID_TIMESTAMP; + } + + std::lock_guard lock(systemTimeLock_); + // If GetSysCurrentTime in 1us, we need increase the currentIncCount_ + if (curTime == lastSystemTimeUs_) { + // if the currentIncCount_ has been increased MAX_INC_COUNT, keep the currentIncCount_ + if (currentIncCount_ < MAX_INC_COUNT) { + currentIncCount_++; + } + } else { + lastSystemTimeUs_ = curTime; + currentIncCount_ = 0; + } + return (curTime * TO_100_NS) + currentIncCount_; // Currently TimeStamp is uint64_t + } + + // Init the TimeHelper + static void Initialize(TimeStamp maxTimeStamp) + { + std::lock_guard lock(lastLocalTimeLock_); + if (lastSystemTimeUs_ < maxTimeStamp) { + lastSystemTimeUs_ = maxTimeStamp; + } + } + + static TimeStamp GetTime(TimeOffset TimeOffset) + { + TimeStamp currentSysTime = GetSysCurrentTime(); + TimeStamp currentLocalTime = currentSysTime + TimeOffset; + std::lock_guard lock(lastLocalTimeLock_); + if (currentLocalTime <= lastLocalTime_ || currentLocalTime > MAX_VALID_TIME) { + lastLocalTime_++; + currentLocalTime = lastLocalTime_; + } else { + lastLocalTime_ = currentLocalTime; + } + return currentLocalTime; + } + +private: + static int GetCurrentSysTimeInMicrosecond(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); + return E_OK; + } + + static std::mutex systemTimeLock_; + static TimeStamp lastSystemTimeUs_; + static TimeStamp currentIncCount_; + static const uint64_t MAX_INC_COUNT = 9; // last bit from 0-9 + + static TimeStamp lastLocalTime_; + static std::mutex lastLocalTimeLock_; +}; + +std::mutex TimeHelper::systemTimeLock_; +TimeStamp TimeHelper::lastSystemTimeUs_ = 0; +TimeStamp TimeHelper::currentIncCount_ = 0; +TimeStamp TimeHelper::lastLocalTime_ = 0; +std::mutex TimeHelper::lastLocalTimeLock_; + +struct TransactFunc { + void (*xFunc)(sqlite3_context*, int, sqlite3_value**) = nullptr; + void (*xStep)(sqlite3_context*, int, sqlite3_value**) = nullptr; + void (*xFinal)(sqlite3_context*) = nullptr; + void(*xDestroy)(void*) = nullptr; +}; + +int RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func) { - ::LOGD("### my sqlite3_close_relational!"); - return sqlite3_close(db); + if (db == nullptr) { + return -E_ERROR; + } + return sqlite3_create_function_v2(db, funcName.c_str(), nArg, SQLITE_UTF8 | SQLITE_DETERMINISTIC, uData, + func.xFunc, func.xStep, func.xFinal, func.xDestroy); } -SQLITE_API int sqlite3_close_v2_relational(sqlite3* db) +int CalcValueHash(const std::vector &value, std::vector &hashValue) { - ::LOGD("### my sqlite3_close_v2_relational!"); - return sqlite3_close_v2(db); + ValueHashCalc hashCalc; + int errCode = hashCalc.Initialize(); + if (errCode != E_OK) { + return -E_ERROR; + } + + errCode = hashCalc.Update(value); + if (errCode != E_OK) { + return -E_ERROR; + } + + errCode = hashCalc.GetResult(hashValue); + if (errCode != E_OK) { + return -E_ERROR; + } + + return E_OK; +} + +void CalcHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + // 1 means that the function only needs one parameter, namely key + if (ctx == nullptr || argc != 1 || argv == nullptr) { + return; + } + auto keyBlob = static_cast(sqlite3_value_blob(argv[0])); + if (keyBlob == nullptr) { + sqlite3_result_error(ctx, "Parameters is invalid.", -1); + return; + } + int blobLen = sqlite3_value_bytes(argv[0]); + std::vector value(keyBlob, keyBlob + blobLen); + std::vector hashValue; + int errCode = CalcValueHash(value, hashValue); + if (errCode != E_OK) { + sqlite3_result_error(ctx, "Get hash value error.", -1); + return; + } + sqlite3_result_blob(ctx, hashValue.data(), hashValue.size(), SQLITE_TRANSIENT); + return; +} + +int RegisterCalcHash(sqlite3 *db) +{ + TransactFunc func; + func.xFunc = &CalcHashKey; + return RegisterFunction(db, "calc_hash", 1, nullptr, func); +} + +void GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 1 || argv == nullptr) { // 1: function need one parameter + return; + } + int timeOffset = static_cast(sqlite3_value_int64(argv[0])); + sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetTime(timeOffset)); +} + +int RegisterGetSysTime(sqlite3 *db) +{ + TransactFunc func; + func.xFunc = &GetSysTime; + return RegisterFunction(db, "get_sys_time", 1, nullptr, func); +} + +int ResetStatement(sqlite3_stmt *&stmt) +{ + if (stmt == nullptr || sqlite3_finalize(stmt) != SQLITE_OK) { + return -E_ERROR; + } + stmt = nullptr; + return E_OK; +} + +int GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&stmt) +{ + int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, nullptr); + if (errCode != SQLITE_OK) { + (void)ResetStatement(stmt); + return -E_ERROR; + } + return E_OK; +} + +int StepWithRetry(sqlite3_stmt *stmt) +{ + if (stmt == nullptr) { + return -E_ERROR; + } + int errCode = sqlite3_step(stmt); + if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) { + return -E_ERROR; + } + return errCode; +} + +int GetColumnTestValue(sqlite3_stmt *stmt, int index, std::string &value) +{ + if (stmt == nullptr) { + return -E_ERROR; + } + const unsigned char *val = sqlite3_column_text(stmt, index); + value = (val != nullptr) ? std::string(reinterpret_cast(val)) : std::string(); + return E_OK; +} + +int GetCurrentMaxTimeStamp(sqlite3 *db, TimeStamp &maxTimestamp) +{ + if (db == nullptr) { + return -E_ERROR; + } + std::string checkTableSql = "SELECT name FROM sqlite_master WHERE type = 'table' AND " \ + "name LIKE 'naturalbase_rdb_aux_%_log';"; + sqlite3_stmt *checkTableStmt = nullptr; + int errCode = GetStatement(db, checkTableSql, checkTableStmt); + if (errCode != E_OK) { + return -E_ERROR; + } + while ((errCode = StepWithRetry(checkTableStmt)) != SQLITE_DONE) { + std::string logTablename; + GetColumnTestValue(checkTableStmt, 0, logTablename); + if (logTablename.empty()) { + continue; + } + + std::string getMaxTimestampSql = "SELECT MAX(timestamp) FROM " + logTablename + ";"; + sqlite3_stmt *getTimeStmt = nullptr; + errCode = GetStatement(db, getMaxTimestampSql, getTimeStmt); + if (errCode != E_OK) { + continue; + } + errCode = StepWithRetry(getTimeStmt); + if (errCode != SQLITE_ROW) { + ResetStatement(getTimeStmt); + continue; + } + TimeStamp tableMaxTimestamp = sqlite3_column_int64(getTimeStmt, 0); + maxTimestamp = (maxTimestamp > tableMaxTimestamp) ? maxTimestamp : tableMaxTimestamp; + ResetStatement(getTimeStmt); + } + ResetStatement(checkTableStmt); + return E_OK; +} } SQLITE_API int sqlite3_open_relational(const char *filename, sqlite3 **ppDb) { int err = sqlite3_open(filename, ppDb); - DistributedDB::SQLiteUtils::RegisterCalcHash(*ppDb); - DistributedDB::SQLiteUtils::RegisterGetSysTime(*ppDb); - ::LOGD("### my sqlite3_open!"); + if (err != SQLITE_OK) { + return err; + } + TimeStamp currentMaxTimestamp = 0; + (void)GetCurrentMaxTimeStamp(*ppDb, currentMaxTimestamp); + TimeHelper::Initialize(currentMaxTimestamp); + RegisterCalcHash(*ppDb); + RegisterGetSysTime(*ppDb); return err; } SQLITE_API int sqlite3_open16_relational(const void *filename, sqlite3 **ppDb) { int err = sqlite3_open16(filename, ppDb); - DistributedDB::SQLiteUtils::RegisterCalcHash(*ppDb); - DistributedDB::SQLiteUtils::RegisterGetSysTime(*ppDb); - ::LOGD("### my sqlite3_open16!"); + if (err != SQLITE_OK) { + return err; + } + TimeStamp currentMaxTimestamp = 0; + (void)GetCurrentMaxTimeStamp(*ppDb, currentMaxTimestamp); + TimeHelper::Initialize(currentMaxTimestamp); + RegisterCalcHash(*ppDb); + RegisterGetSysTime(*ppDb); return err; } SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs) { int err = sqlite3_open_v2(filename, ppDb, flags, zVfs); - DistributedDB::SQLiteUtils::RegisterCalcHash(*ppDb); - DistributedDB::SQLiteUtils::RegisterGetSysTime(*ppDb); - ::LOGD("### my sqlite3_open_v2!"); + if (err != SQLITE_OK) { + return err; + } + TimeStamp currentMaxTimestamp = 0; + (void)GetCurrentMaxTimeStamp(*ppDb, currentMaxTimestamp); + TimeHelper::Initialize(currentMaxTimestamp); + RegisterCalcHash(*ppDb); + RegisterGetSysTime(*ppDb); return err; } @@ -68,8 +390,6 @@ SQLITE_API int sqlite3_open_v2_relational(const char *filename, sqlite3 **ppDb, #endif struct sqlite3_api_routines_relational { - int (*close)(sqlite3*); - int (*close_v2)(sqlite3*); int (*open)(const char *, sqlite3 **); int (*open16)(const void *, sqlite3 **); int (*open_v2)(const char *, sqlite3 **, int, const char *); @@ -78,14 +398,10 @@ struct sqlite3_api_routines_relational { typedef struct sqlite3_api_routines_relational sqlite3_api_routines_relational; static const sqlite3_api_routines_relational sqlite3HwApis = { #ifdef SQLITE_DISTRIBUTE_RELATIONAL - sqlite3_close_relational, - sqlite3_close_v2_relational, sqlite3_open_relational, sqlite3_open16_relational, sqlite3_open_v2_relational #else - 0, - 0, 0, 0, 0 @@ -93,6 +409,4 @@ static const sqlite3_api_routines_relational sqlite3HwApis = { }; EXPORT_SYMBOLS const sqlite3_api_routines_relational *sqlite3_export_relational_symbols = &sqlite3HwApis; -#endif - #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h index e9e6562b4c671d80676734d5f2d97977c8120817..66fec6748fc9c6dae10f19a1eac9d96f87a35577 100644 --- a/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h +++ b/services/distributeddataservice/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h @@ -17,11 +17,14 @@ #ifdef RELATIONAL_STORE #include "relational_db_sync_interface.h" +#include "relationaldb_properties.h" +#include "runtime_context.h" #include "sqlite_single_relational_storage_engine.h" #include "sqlite_single_ver_relational_continue_token.h" namespace DistributedDB { +using RelationalObserverAction = std::function; class RelationalSyncAbleStorage : public RelationalDBSyncInterface, public virtual RefObject { public: explicit RelationalSyncAbleStorage(StorageEngine *engine); @@ -90,21 +93,29 @@ public: int LocalDataChanged(int notifyEvent, std::vector &queryObj) override; - int SchemaChanged(int notifyEvent) override; - - int InterceptData(std::vector &entries, - const std::string &sourceID, const std::string &targetID) const override + int InterceptData(std::vector &entries, const std::string &sourceID, + const std::string &targetID) const override { return E_OK; } - int CheckAndInitQueryCondition(QueryObject &query) const override - { - return E_OK; - } + int CheckAndInitQueryCondition(QueryObject &query) const override; + void RegisterObserverAction(const RelationalObserverAction &action); + void TriggerObserverAction(const std::string &deviceName); + + int CreateDistributedDeviceTable(const std::string &device, const RelationalSyncStrategy &syncStrategy) override; + + int RegisterSchemaChangedCallback(const std::function &callback) override; + + void NotifySchemaChanged(); + + void RegisterHeartBeatListener(const std::function &listener); + + int GetCompressionAlgo(std::set &algorithmSet) const override; private: - SQLiteSingleVerRelationalStorageExecutor *GetHandle(bool isWrite, int &errCode, OperatePerm perm) const; + SQLiteSingleVerRelationalStorageExecutor *GetHandle(bool isWrite, int &errCode, + OperatePerm perm = OperatePerm::NORMAL_PERM) const; void ReleaseHandle(SQLiteSingleVerRelationalStorageExecutor *&handle) const; int SetMaxTimeStamp(TimeStamp timestamp); @@ -121,6 +132,13 @@ private: TimeStamp currentMaxTimeStamp_ = 0; KvDBProperties properties; mutable std::mutex maxTimeStampMutex_; + + std::function onSchemaChanged_; + mutable std::mutex onSchemaChangedMutex_; + std::mutex dataChangeDeviceMutex_; + RelationalObserverAction dataChangeDeviceCallback_; + std::function heartBeatListener_; + mutable std::mutex heartBeatMutex_; }; } // namespace DistributedDB #endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb.h b/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb.h index 1aa687b9800c3e1e7878a680bd2aeefd61cd21f0..09327426a7ff825b39d135f5f4628e20af589c9a 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb.h @@ -57,6 +57,8 @@ public: virtual void EnableAutonomicUpgrade() = 0; virtual int CheckIntegrity() const = 0; + + virtual std::string GetStorePath() const = 0; }; } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb_connection.h b/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb_connection.h index 75406272927c240fa6a6cdba2aa97806c4339549..09f0e5ec7d4de4c043d5a841f8eeb6647ffff08d 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb_connection.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/ikvdb_connection.h @@ -19,7 +19,7 @@ #include #include -#include "types.h" +#include "store_types.h" #include "db_types.h" #include "macro_utils.h" #include "query.h" diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/kvdb_pragma.h b/services/distributeddataservice/libs/distributeddb/storage/include/kvdb_pragma.h index 5759240efee9b17e49adc3ebf98c36d9e8090745..4b6698b0867bd80478d79e939cb853e5fdd50625 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/include/kvdb_pragma.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/kvdb_pragma.h @@ -20,7 +20,7 @@ #include #include -#include "types.h" +#include "store_types.h" #include "query_sync_object.h" namespace DistributedDB { diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/relational_db_sync_interface.h b/services/distributeddataservice/libs/distributeddb/storage/include/relational_db_sync_interface.h index 94749dba30aee2f7f38472f548f733f02786599d..81e8fb3d84133d6fecf6b28575b3f77d19f146d4 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/include/relational_db_sync_interface.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/relational_db_sync_interface.h @@ -37,7 +37,9 @@ public: virtual int LocalDataChanged(int notifyEvent, std::vector &queryObj) = 0; - virtual int SchemaChanged(int notifyEvent) = 0; + virtual int CreateDistributedDeviceTable(const std::string &device, const RelationalSyncStrategy &syncStrategy) = 0; + + virtual int RegisterSchemaChangedCallback(const std::function &callback) = 0; }; } #endif // RELATIONAL_STORE diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/relational_store_connection.h b/services/distributeddataservice/libs/distributeddb/storage/include/relational_store_connection.h index f3dd78fc6c5dfe110fad022cac221d4076b67aa5..be53b2c6cc243c4a710256fffd3853c7758e19cd 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/include/relational_store_connection.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/relational_store_connection.h @@ -26,7 +26,7 @@ namespace DistributedDB { class IRelationalStore; - +using RelationalObserverAction = std::function; class RelationalStoreConnection : public virtual RefObject { public: struct SyncInfo { @@ -53,8 +53,12 @@ public: virtual int CreateDistributedTable(const std::string &tableName) = 0; virtual int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) = 0; + virtual int RemoveDeviceData(const std::string &device) = 0; + virtual int RemoveDeviceData(const std::string &device, const std::string &tableName) = 0; + virtual void RegisterObserverAction(const RelationalObserverAction &action) = 0; + protected: - // Get the stashed 'KvDB_ pointer' without ref. + // Get the stashed 'RelationalDB_ pointer' without ref. template DerivedDBType *GetDB() const { diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/relationaldb_properties.h b/services/distributeddataservice/libs/distributeddb/storage/include/relationaldb_properties.h index 4877e7220343a4d11111b67925624b4b7ed902c1..2b60fede5473ae2537aafa7911d4cf67573f4db9 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/include/relationaldb_properties.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/relationaldb_properties.h @@ -14,7 +14,7 @@ */ #ifndef RELATIONALDB_PROPERTIES_H #define RELATIONALDB_PROPERTIES_H - +#ifdef RELATIONAL_STORE #include #include #include @@ -41,4 +41,5 @@ private: RelationalSchemaObject schema_; }; } +#endif #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/single_ver_kvdb_sync_interface.h b/services/distributeddataservice/libs/distributeddb/storage/include/single_ver_kvdb_sync_interface.h index 1cca304b6ed674ff3f034566a190a2cab67c1965..fe56452bbf3fc0de445e5c9f1d98f270bd1828bb 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/include/single_ver_kvdb_sync_interface.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/single_ver_kvdb_sync_interface.h @@ -33,10 +33,6 @@ public: ~SingleVerKvDBSyncInterface() override = default; virtual SchemaObject GetSchemaInfo() const = 0; - - virtual bool CheckCompatible(const std::string &schema) const = 0; - - virtual int GetCompressionAlgo(std::set &algorithmSet) const = 0; }; } diff --git a/services/distributeddataservice/libs/distributeddb/storage/include/sync_generic_interface.h b/services/distributeddataservice/libs/distributeddb/storage/include/sync_generic_interface.h index 6068081113e839d5200c564017f1ae33f2dfb4d0..600e1c3a84ff5b0e3dd87492d375279d22cc4c34 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/include/sync_generic_interface.h +++ b/services/distributeddataservice/libs/distributeddb/storage/include/sync_generic_interface.h @@ -129,6 +129,16 @@ public: { return -E_NOT_SUPPORT; } + + virtual int GetCompressionAlgo(std::set &algorithmSet) const + { + return -E_NOT_SUPPORT; + } + + virtual bool CheckCompatible(const std::string &schema) const + { + return false; + } }; } #endif // SYNC_GENERIC_INTERFACE_H diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.cpp index f55194374d9d32125e4aa18dd1ca17d1e9f0fbed..57ab81714b3382a3b42cf0d03f6aead65de42279 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.cpp @@ -15,6 +15,7 @@ #ifdef RELATIONAL_STORE #include "data_transformer.h" +#include "db_common.h" #include "db_errno.h" #include "log_print.h" #include "parcel.h" @@ -66,15 +67,12 @@ int DataTransformer::SerializeDataItem(const RowDataWithLog &data, return errCode; } const LogInfo &logInfo = data.logInfo; - errCode = SerializeHashKey(dataItem.hashKey, logInfo.hashKey); - if (errCode != E_OK) { - return errCode; - } dataItem.timeStamp = logInfo.timestamp; dataItem.dev = logInfo.device; dataItem.origDev = logInfo.originDev; dataItem.writeTimeStamp = logInfo.wTimeStamp; dataItem.flag = logInfo.flag; + dataItem.hashKey = logInfo.hashKey; return E_OK; } @@ -90,15 +88,12 @@ int DataTransformer::DeSerializeDataItem(const DataItem &dataItem, OptRowDataWit } LogInfo &logInfo = data.logInfo; - errCode = DeSerializeHashKey(dataItem.hashKey, logInfo.hashKey); - if (errCode != E_OK) { - return errCode; - } logInfo.timestamp = dataItem.timeStamp; logInfo.device = dataItem.dev; logInfo.originDev = dataItem.origDev; logInfo.wTimeStamp = dataItem.writeTimeStamp; logInfo.flag = dataItem.flag; + logInfo.hashKey = dataItem.hashKey; return E_OK; } @@ -120,16 +115,11 @@ uint32_t DataTransformer::CalDataValueLength(const DataValue &dataValue) uint32_t length = 0; switch (dataValue.GetType()) { case StorageType::STORAGE_TYPE_BLOB: + case StorageType::STORAGE_TYPE_TEXT: (void)dataValue.GetBlobLength(length); length = Parcel::GetEightByteAlign(length); length += Parcel::GetUInt32Len(); // record data length break; - case StorageType::STORAGE_TYPE_TEXT: { - std::string str; - (void)dataValue.GetText(str); - length = Parcel::GetStringLen(str); - break; - } default: break; } @@ -224,24 +214,6 @@ int DeSerializeDoubleValue(DataValue &dataValue, Parcel &parcel) return E_OK; } -int SerializeTextValue(const DataValue &dataValue, Parcel &parcel) -{ - std::string val; - (void)dataValue.GetText(val); - return parcel.WriteString(val); -} - -int DeSerializeTextValue(DataValue &dataValue, Parcel &parcel) -{ - std::string val; - (void)parcel.ReadString(val); - if (parcel.IsError()) { - return -E_PARSE_FAIL; - } - dataValue = val; - return E_OK; -} - int SerializeBlobValue(const DataValue &dataValue, Parcel &parcel) { Blob val; @@ -257,12 +229,12 @@ int SerializeBlobValue(const DataValue &dataValue, Parcel &parcel) return parcel.WriteBlob(reinterpret_cast(val.GetData()), size); } -int DeSerializeBlobValue(DataValue &dataValue, Parcel &parcel) +int DeSerializeBlobByType(DataValue &dataValue, Parcel &parcel, StorageType type) { - Blob val; uint32_t blobLength = 0; (void)parcel.ReadUInt32(blobLength); if (blobLength == 0) { + dataValue.ResetValue(); return E_OK; } char array[blobLength]; @@ -270,13 +242,34 @@ int DeSerializeBlobValue(DataValue &dataValue, Parcel &parcel) if (parcel.IsError()) { return -E_PARSE_FAIL; } - int errCode = val.WriteBlob(reinterpret_cast(array), blobLength); - if (errCode == E_OK) { - dataValue = val; + int errCode = -E_NOT_SUPPORT; + if (type == StorageType::STORAGE_TYPE_TEXT) { + errCode = dataValue.SetText(reinterpret_cast(array), blobLength); + } else if (type == StorageType::STORAGE_TYPE_BLOB) { + Blob val; + errCode = val.WriteBlob(reinterpret_cast(array), blobLength); + if (errCode == E_OK) { + errCode = dataValue.SetBlob(val); + } } return errCode; } +int DeSerializeBlobValue(DataValue &dataValue, Parcel &parcel) +{ + return DeSerializeBlobByType(dataValue, parcel, StorageType::STORAGE_TYPE_BLOB); +} + +int SerializeTextValue(const DataValue &dataValue, Parcel &parcel) +{ + return SerializeBlobValue(dataValue, parcel); +} + +int DeSerializeTextValue(DataValue &dataValue, Parcel &parcel) +{ + return DeSerializeBlobByType(dataValue, parcel, StorageType::STORAGE_TYPE_TEXT); +} + struct FunctionEntry { std::function serializeFunc; std::function deSerializeFunc; @@ -340,8 +333,6 @@ int DataTransformer::DeSerializeValue(const Value &value, OptRowData &optionalDa std::vector valueList; for (const auto &fieldInfo : remoteFieldInfo) { DataValue dataValue; - LOGD("[DataTransformer][DeSerializeValue] start deSerialize %s type %d", - fieldInfo.GetFieldName().c_str(), fieldInfo.GetStorageType()); uint32_t type = 0; parcel.ReadUInt32(type); auto iter = typeFuncMap.find(static_cast(type)); @@ -367,23 +358,5 @@ int DataTransformer::DeSerializeValue(const Value &value, OptRowData &optionalDa } return E_OK; } - -int DataTransformer::SerializeHashKey(Key &key, const std::string &hashKey) -{ - uint32_t len = Parcel::GetStringLen(hashKey); - key.resize(len, 0); - if (key.size() != len) { - return -E_OUT_OF_MEMORY; - } - Parcel parcel(key.data(), len); - return parcel.WriteString(hashKey); -} - -int DataTransformer::DeSerializeHashKey(const Key &key, std::string &hashKey) -{ - Parcel parcel(const_cast(key.data()), key.size()); - (void)parcel.ReadString(hashKey); - return parcel.IsError() ? -E_PARSE_FAIL : E_OK; -} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.h b/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.h index 51a7d8510e7ca0cb36ec2486abb46916c3b2eab8..c21185009ae7c6505d03dc198e162db56b105cc4 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/data_transformer.h @@ -33,7 +33,7 @@ struct LogInfo { TimeStamp timestamp = 0; TimeStamp wTimeStamp = 0; uint64_t flag = 0; - std::string hashKey; // primary key hash value + Key hashKey; // primary key hash value }; struct RowDataWithLog { @@ -72,10 +72,7 @@ public: const std::vector &localFieldInfo, std::vector &indexMapping); private: - static int SerializeHashKey(Key &key, const std::string &hashKey); static int SerializeValue(Value &value, const RowData &rowData, const std::vector &fieldInfoList); - - static int DeSerializeHashKey(const Key &key, std::string &hashKey); static int DeSerializeValue(const Value &value, OptRowData &optionalData, const std::vector &remoteFieldInfo, std::vector &indexMapping); diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.cpp index 9802edf55ac5dc0c0f6e41b35e1cccffc6887e2c..e19fbaf4a62b44522ae5884df3e2eae44ce4b85c 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.cpp @@ -398,4 +398,9 @@ std::string GenericKvDB::GetStoreIdOnlyIdentifier(const KvDBProperties &properti std::string hashStoreDir = DBCommon::TransferStringToHex(hashStoreId); return hashStoreDir; } + +std::string GenericKvDB::GetStorePath() const +{ + return properties_.GetStringProp(KvDBProperties::DATA_DIR, ""); +} } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.h b/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.h index 5cacf01892d305b7b7ab2128f3e9873ee11f0c51..31d580a9bbe2af6f959a0b0b65b07146b98801ff 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/generic_kvdb.h @@ -21,7 +21,7 @@ #include #include -#include "types.h" +#include "store_types.h" #include "version.h" #include "ikvdb.h" #include "generic_kvdb_connection.h" @@ -128,6 +128,8 @@ public: int CheckIntegrity() const override; + std::string GetStorePath() const override; + protected: // Create a connection object, no DB ref increased. virtual GenericKvDBConnection *NewConnection(int &errCode) = 0; diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/irelational_store.h b/services/distributeddataservice/libs/distributeddb/storage/src/irelational_store.h index a9714e556139794d230c69c96d84cf45007b7a37..1340ca6d7833de3e15f5cb8ddb792c0d2863a79d 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/irelational_store.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/irelational_store.h @@ -37,6 +37,8 @@ public: // Create a db connection. virtual RelationalStoreConnection *GetDBConnection(int &errCode) = 0; + + virtual std::string GetStorePath() const = 0; }; } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_manager.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_manager.cpp index 8d8d560741bc49127ce09c8f7d7807ec2259fd4a..aeff440e5759025da83689a50f5a75df84fef33a 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_manager.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_manager.cpp @@ -266,9 +266,16 @@ IKvDBConnection *KvDBManager::GetDatabaseConnection(const KvDBProperties &proper LOGE("Failed to open the db:%d", errCode); } } else { - connection = kvDB->GetDBConnection(errCode); - if (connection == nullptr) { // not kill kvdb, Other operations like import may be used concurrently - LOGE("Failed to get the db connect for delegate:%d", errCode); + bool isMemoryDb = properties.GetBoolProp(KvDBProperties::MEMORY_MODE, false); + std::string canonicalDir = properties.GetStringProp(KvDBProperties::DATA_DIR, ""); + if (!isMemoryDb && (canonicalDir.empty() || canonicalDir != kvDB->GetStorePath())) { + LOGE("Failed to check store path, the input path does not match with cached store."); + errCode = -E_INVALID_ARGS; + } else { + connection = kvDB->GetDBConnection(errCode); + if (connection == nullptr) { // not kill kvdb, Other operations like import may be used concurrently + LOGE("Failed to get the db connect for delegate:%d", errCode); + } } RefObject::DecObjRef(kvDB); // restore the reference increased by the cache. kvDB = nullptr; diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_utils.h b/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_utils.h index da294afddc55c48a104d182800fda5ce819634ef..b55ac8dac228f448f4f0cd2e13619dd06cd28852 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_utils.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/kvdb_utils.h @@ -17,7 +17,7 @@ #define KVDB_UTILLS_H #include -#include "types.h" +#include "store_types.h" #include "macro_utils.h" namespace DistributedDB { diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/relational_store_instance.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/relational_store_instance.cpp index 366d78863fcc80e252f65c8a39afbdd356227c71..1f08bdb3d96114e7e50a19d9034a28462604563a 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/relational_store_instance.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/relational_store_instance.cpp @@ -156,6 +156,14 @@ RelationalStoreConnection *RelationalStoreInstance::GetDatabaseConnection(const return nullptr; } + std::string canonicalDir = properties.GetStringProp(KvDBProperties::DATA_DIR, ""); + if (canonicalDir.empty() || canonicalDir != db->GetStorePath()) { + LOGE("Failed to check store path, the input path does not match with cached store."); + errCode = -E_INVALID_ARGS; + RefObject::DecObjRef(db); + return nullptr; + } + auto connection = db->GetDBConnection(errCode); if (connection == nullptr) { // not kill db, Other operations like import may be used concurrently LOGE("Failed to get the db connect for delegate:%d", errCode); diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/relational_sync_able_storage.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/relational_sync_able_storage.cpp index 70418aa13a454d9b9e4f0e6d094bd8d88a0da9f3..67006005da0ff3f11d5634d47e85c51b5cb1b3c4 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/relational_sync_able_storage.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/relational_sync_able_storage.cpp @@ -14,8 +14,12 @@ */ #ifdef RELATIONAL_STORE #include "relational_sync_able_storage.h" -#include "platform_specific.h" + +#include "db_common.h" +#include "data_compression.h" #include "generic_single_ver_kv_entry.h" +#include "platform_specific.h" +#include "runtime_context.h" namespace DistributedDB { #define CHECK_STORAGE_ENGINE do { \ @@ -51,10 +55,11 @@ void RelationalSyncAbleStorage::DecRefCount() DecObjRef(this); } -// Get the identifier of this kvdb. +// Get the identifier of this rdb. std::vector RelationalSyncAbleStorage::GetIdentifier() const { - return {}; + std::string identifier = storageEngine_->GetIdentifier(); + return std::vector(identifier.begin(), identifier.end()); } // Get the max timestamp of all entries in database. @@ -91,6 +96,14 @@ void RelationalSyncAbleStorage::ReleaseHandle(SQLiteSingleVerRelationalStorageEx } StorageExecutor *databaseHandle = handle; storageEngine_->Recycle(databaseHandle); + std::function listener = nullptr; + { + std::lock_guard autoLock(heartBeatMutex_); + listener = heartBeatListener_; + } + if (listener) { + listener(); + } } // Get meta data associated with the given key. @@ -272,17 +285,13 @@ int RelationalSyncAbleStorage::GetSyncDataForQuerySync(std::vector &da goto ERROR; } - errCode = handle->SetTableInfo(token->GetQuery()); - if (errCode != E_OK) { - goto ERROR; - } - do { errCode = handle->GetSyncDataByQuery(dataItems, Parcel::GetAppendedLen(), dataSizeInfo, std::bind(&SQLiteSingleVerRelationalContinueToken::GetStatement, *token, - std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); + std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), + token->GetQuery().GetTableName()); if (errCode == -E_FINISHED) { token->FinishGetData(); errCode = token->IsGetAllDataFinished() ? E_OK : -E_UNFINISHED; @@ -308,7 +317,7 @@ int RelationalSyncAbleStorage::GetSyncData(QueryObject &query, const SyncTimeRan if (!timeRange.IsValid()) { return -E_INVALID_ARGS; } - + query.SetSchema(storageEngine_->GetSchemaRef()); auto token = new (std::nothrow) SQLiteSingleVerRelationalContinueToken(timeRange, query); if (token == nullptr) { LOGE("[SingleVerNStore] Allocate continue token failed."); @@ -375,17 +384,17 @@ int RelationalSyncAbleStorage::SaveSyncDataItems(const QueryObject &object, std: if (handle == nullptr) { return errCode; } - - errCode = handle->SetTableInfo(object); - if (errCode != E_OK) { - ReleaseHandle(handle); - return errCode; - } + QueryObject query = object; + query.SetSchema(storageEngine_->GetSchemaRef()); TimeStamp maxTimestamp = 0; - errCode = handle->SaveSyncItems(object, dataItems, deviceName, maxTimestamp); + errCode = handle->SaveSyncItems(query, dataItems, deviceName, maxTimestamp); if (errCode == E_OK) { (void)SetMaxTimeStamp(maxTimestamp); + // dataItems size > 0 now because already check befor + // all dataItems will write into db now, so need to observer notify here + // if some dataItems will not write into db in the future, observer notify here need change + TriggerObserverAction(deviceName); } ReleaseHandle(handle); @@ -414,7 +423,7 @@ int RelationalSyncAbleStorage::RemoveDeviceData(const std::string &deviceName, b RelationalSchemaObject RelationalSyncAbleStorage::GetSchemaInfo() const { - return RelationalSchemaObject(); + return storageEngine_->GetSchemaRef(); } int RelationalSyncAbleStorage::GetSecurityOption(SecurityOption &option) const @@ -455,9 +464,114 @@ int RelationalSyncAbleStorage::LocalDataChanged(int notifyEvent, std::vectorCreateDistributedDeviceTable(device, storageEngine_->GetSchemaRef().GetTable(table)); + if (errCode != E_OK) { + LOGE("Create distributed device table failed. %d", errCode); + break; + } + } + + ReleaseHandle(handle); + return errCode; +} + +int RelationalSyncAbleStorage::RegisterSchemaChangedCallback(const std::function &callback) +{ + std::lock_guard lock(onSchemaChangedMutex_); + onSchemaChanged_ = callback; + return E_OK; +} + +void RelationalSyncAbleStorage::NotifySchemaChanged() +{ + std::lock_guard lock(onSchemaChangedMutex_); + if (onSchemaChanged_) { + LOGD("Notify relational schema was changed"); + onSchemaChanged_(); + } +} +int RelationalSyncAbleStorage::GetCompressionAlgo(std::set &algorithmSet) const +{ + algorithmSet.clear(); + DataCompression::GetCompressionAlgo(algorithmSet); + return E_OK; +} + +void RelationalSyncAbleStorage::RegisterObserverAction(const RelationalObserverAction &action) +{ + std::lock_guard lock(dataChangeDeviceMutex_); + dataChangeDeviceCallback_ = action; +} + +void RelationalSyncAbleStorage::TriggerObserverAction(const std::string &deviceName) +{ + { + std::lock_guard lock(dataChangeDeviceMutex_); + if (!dataChangeDeviceCallback_) { + return; + } + } + IncObjRef(this); + int taskErrCode = RuntimeContext::GetInstance()->ScheduleTask([this, deviceName] { + std::lock_guard lock(dataChangeDeviceMutex_); + if (dataChangeDeviceCallback_) { + dataChangeDeviceCallback_(deviceName); + } + DecObjRef(this); + }); + if (taskErrCode != E_OK) { + LOGE("TriggerObserverAction scheduletask retCode=%d", taskErrCode); + DecObjRef(this); + } +} + +void RelationalSyncAbleStorage::RegisterHeartBeatListener(const std::function &listener) +{ + std::lock_guard autoLock(heartBeatMutex_); + heartBeatListener_ = listener; +} + +int RelationalSyncAbleStorage::CheckAndInitQueryCondition(QueryObject &query) const +{ + if (!query.IsQueryForRelationalDB()) { + LOGE("Not support for this query type."); + return -E_NOT_SUPPORT; + } + + RelationalSchemaObject schema = storageEngine_->GetSchemaRef(); + TableInfo table = schema.GetTable(query.GetTableName()); + if (table.GetTableName() != query.GetTableName()) { + LOGE("Query table is not a distributed table."); + return -E_DISTRIBUTED_SCHEMA_NOT_FOUND; + } + query.SetSchema(schema); + + int errCode = E_OK; + auto *handle = GetHandle(false, errCode); + if (handle == nullptr) { + return errCode; + } + + errCode = handle->CheckQueryObjectLegal(table, query); + if (errCode != E_OK) { + LOGE("Check relational query condition failed. %d", errCode); + } + + ReleaseHandle(handle); + return errCode; } } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/relationaldb_properties.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/relationaldb_properties.cpp index 3a87aafb5e5a8a7d829fdc8b3819b806409656e8..52d34820ac7319446ffef3295220483d93451252 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/relationaldb_properties.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/relationaldb_properties.cpp @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +#ifdef RELATIONAL_STORE #include "relationaldb_properties.h" namespace DistributedDB { @@ -37,3 +37,4 @@ RelationalSchemaObject RelationalDBProperties::GetSchema() const return schema_; } } +#endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.cpp index 8c465a1c83b019edcbe106885cde5ad06d10737c..16039fdc5f3009d53aa1b89e877e720a4fd88029 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.cpp @@ -36,6 +36,7 @@ QueryObject::QueryObject() hasOrderBy_(false), hasLimit_(false), hasPrefixKey_(false), + hasInKeys_(false), orderByCounts_(0) { } @@ -54,6 +55,8 @@ void QueryObject::GetAttrFromQueryObjNodes() hasOrderBy_ = true; } else if (symbolType == PREFIXKEY_SYMBOL) { hasPrefixKey_ = true; + } else if (symbolType == IN_KEYS_SYMBOL) { + hasInKeys_ = true; } } } @@ -65,6 +68,7 @@ QueryObject::QueryObject(const Query &query) hasOrderBy_(false), hasLimit_(false), hasPrefixKey_(false), + hasInKeys_(false), orderByCounts_(0) { QueryExpression queryExpressions = GetQueryInfo::GetQueryExpression(query); @@ -74,12 +78,15 @@ QueryObject::QueryObject(const Query &query) prefixKey_ = queryExpressions.GetPreFixKey(); suggestIndex_ = queryExpressions.GetSuggestIndex(); tableName_ = queryExpressions.GetTableName(); - isTableNameSpecified_ = queryExpressions.IsTableNameSpacified(); + isTableNameSpecified_ = queryExpressions.IsTableNameSpecified(); + keys_ = queryExpressions.GetKeys(); } -QueryObject::QueryObject(const std::list &queryObjNodes, const std::vector &prefixKey) +QueryObject::QueryObject(const std::list &queryObjNodes, const std::vector &prefixKey, + const std::set &keys) : queryObjNodes_(queryObjNodes), prefixKey_(prefixKey), + keys_(keys), isValid_(true), initialized_(false), limit_(INVALID_LIMIT), @@ -87,6 +94,7 @@ QueryObject::QueryObject(const std::list &queryObjNodes, const std hasOrderBy_(false), hasLimit_(false), hasPrefixKey_(false), + hasInKeys_(false), orderByCounts_(0) { GetAttrFromQueryObjNodes(); @@ -117,8 +125,8 @@ SqliteQueryHelper QueryObject::GetQueryHelper(int &errCode) if (errCode != E_OK) { return SqliteQueryHelper(QueryObjInfo{}); } - QueryObjInfo info {schema_, queryObjNodes_, prefixKey_, suggestIndex_, - orderByCounts_, isValid_, hasOrderBy_, hasLimit_, hasPrefixKey_, tableName_}; + QueryObjInfo info {schema_, queryObjNodes_, prefixKey_, suggestIndex_, keys_, + orderByCounts_, isValid_, hasOrderBy_, hasLimit_, hasPrefixKey_, tableName_, isTableNameSpecified_}; return SqliteQueryHelper {info}; // compiler RVO by default, and RVO is generally required after C++17 } @@ -168,6 +176,7 @@ void QueryObject::ClearNodesFlag() hasOrderBy_ = false; hasLimit_ = false; hasPrefixKey_ = false; + hasInKeys_ = false; orderByCounts_ = 0; } @@ -232,6 +241,16 @@ int QueryObject::ParseNode(const std::list::iterator &iter) } } else if (symbolType == SUGGEST_INDEX_SYMBOL) { return CheckSuggestIndexFormat(iter); + } else if (symbolType == IN_KEYS_SYMBOL) { + if (hasInKeys_) { + LOGE("Only filter by keys in once!!"); + return -E_INVALID_QUERY_FORMAT; + } + int errCode = CheckInKeys(); + if (errCode != E_OK) { + return errCode; + } + hasInKeys_ = true; } return E_OK; } @@ -241,13 +260,18 @@ int QueryObject::CheckLinkerBefore(const std::list::iterator &iter auto preIter = std::prev(iter, 1); SymbolType symbolType = SqliteQueryHelper::GetSymbolType(preIter->operFlag); if (symbolType != COMPARE_SYMBOL && symbolType != RELATIONAL_SYMBOL && symbolType != LOGIC_SYMBOL && - symbolType != RANGE_SYMBOL && symbolType != PREFIXKEY_SYMBOL) { + symbolType != RANGE_SYMBOL && symbolType != PREFIXKEY_SYMBOL && symbolType != IN_KEYS_SYMBOL) { LOGE("Must be a comparison operation before the connective! operFlag = %s", VNAME(preIter->operFlag)); return -E_INVALID_QUERY_FORMAT; } return E_OK; } +bool QueryObject::IsRelationalQuery() const +{ + return isTableNameSpecified_; +} + int QueryObject::CheckEqualFormat(const std::list::iterator &iter) const { if (!schema_.IsSchemaValid()) { @@ -256,7 +280,8 @@ int QueryObject::CheckEqualFormat(const std::list::iterator &iter) } FieldPath fieldPath; - int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath); + bool permitPrefix = !IsRelationalQuery(); // For relational query, $. prefix is not permitted. + int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath, permitPrefix); if (errCode != E_OK) { return -E_INVALID_QUERY_FIELD; } @@ -287,7 +312,14 @@ int QueryObject::CheckEqualFormat(const std::list::iterator &iter) int QueryObject::CheckLinkerFormat(const std::list::iterator &iter) const { - if (iter == queryObjNodes_.begin()) { + auto itPre = iter; + for (; itPre != queryObjNodes_.begin(); itPre = std::prev(itPre, 1)) { + SymbolType symbolType = SqliteQueryHelper::GetSymbolType(std::prev(itPre, 1)->operFlag); + if (symbolType != PREFIXKEY_SYMBOL && symbolType != IN_KEYS_SYMBOL) { + break; + } + } + if (itPre == queryObjNodes_.begin()) { LOGE("Connectives are not allowed in the first place!"); return -E_INVALID_QUERY_FORMAT; } @@ -322,7 +354,9 @@ int QueryObject::CheckOrderByFormat(const std::list::iterator &ite FieldType schemaFieldType; FieldPath fieldPath; - int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath); + + bool permitPrefix = !IsRelationalQuery(); // For relational query, $. prefix is not permitted. + int errCode = SchemaUtils::ParseAndCheckFieldPath(iter->fieldName, fieldPath, permitPrefix); if (errCode != E_OK) { return -E_INVALID_QUERY_FIELD; } @@ -352,7 +386,18 @@ int QueryObject::CheckLimitFormat(const std::list::iterator &iter) bool QueryObject::IsQueryOnlyByKey() const { return std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) { - return node.operFlag != QueryObjType::LIMIT && node.operFlag != QueryObjType::QUERY_BY_KEY_PREFIX; + return node.operFlag != QueryObjType::LIMIT && node.operFlag != QueryObjType::QUERY_BY_KEY_PREFIX && + node.operFlag != QueryObjType::IN_KEYS; + }); +} + +bool QueryObject::IsQueryForRelationalDB() const +{ + return isTableNameSpecified_ && + std::none_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) { + return node.operFlag != QueryObjType::EQUALTO && node.operFlag != QueryObjType::NOT_EQUALTO && + node.operFlag != QueryObjType::AND && node.operFlag != QueryObjType::OR && + node.operFlag != QueryObjType::ORDERBY && node.operFlag != QueryObjType::LIMIT; }); } @@ -365,5 +410,34 @@ bool QueryObject::Empty() const { return queryObjNodes_.empty(); } + +int QueryObject::CheckInKeys() const +{ + if (keys_.empty()) { + return -E_INVALID_ARGS; + } + if (keys_.size() > DBConstant::MAX_BATCH_SIZE) { + return -E_MAX_LIMITS; + } + for (const auto &key : keys_) { + if (key.empty() || key.size() > DBConstant::MAX_KEY_SIZE) { + return -E_INVALID_ARGS; + } + } + return E_OK; +} + +#ifdef RELATIONAL_STORE +int QueryObject::SetSchema(const RelationalSchemaObject &schemaObj) +{ + if (!isTableNameSpecified_) { + return -E_INVALID_ARGS; + } + const auto &tableInfo = schemaObj.GetTable(tableName_); + SchemaObject schema(tableInfo); + schema_ = schema; + return E_OK; +} +#endif } diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.h index b65ef70258fe0191fc7273b4ed5397657ed138e6..63108153085deac299fdc51c195bb977b0713459 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_object.h @@ -16,8 +16,10 @@ #define QUERY_OBJECT_H #include -#include "schema_object.h" + #include "query.h" +#include "relational_schema_object.h" +#include "schema_object.h" #include "sqlite_query_helper.h" namespace DistributedDB { @@ -26,7 +28,8 @@ public: QueryObject(); explicit QueryObject(const Query &query); // for query sync - QueryObject(const std::list &queryObjNodes, const std::vector &prefixKey); + QueryObject(const std::list &queryObjNodes, const std::vector &prefixKey, + const std::set &keys); virtual ~QueryObject(); int Init(); SqliteQueryHelper GetQueryHelper(int &errCode); @@ -41,6 +44,7 @@ public: void SetSchema(const SchemaObject &schema); bool IsQueryOnlyByKey() const; + bool IsQueryForRelationalDB() const; void SetTableName(const std::string &tableName) { @@ -58,12 +62,22 @@ public: int ParseQueryObjNodes(); bool Empty() const; + + bool HasInKeys() const + { + return hasInKeys_; + } + +#ifdef RELATIONAL_STORE + int SetSchema(const RelationalSchemaObject &schemaObj); // The interface can only be used in relational query. +#endif protected: std::list queryObjNodes_; std::vector prefixKey_; std::string tableName_ = "sync_data"; std::string suggestIndex_; + std::set keys_; bool isValid_ = true; @@ -81,6 +95,8 @@ private: int CheckLinkerBefore(const std::list::iterator &iter) const; void ClearNodesFlag(); void GetAttrFromQueryObjNodes(); + int CheckInKeys() const; + bool IsRelationalQuery() const; SchemaObject schema_; // used to check and parse schema filed int limit_; @@ -88,6 +104,7 @@ private: bool hasOrderBy_; bool hasLimit_; bool hasPrefixKey_; + bool hasInKeys_; int orderByCounts_; }; } diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp index 31b551677cf25ec1d314518bfc4d5c429b576db1..603f713626c351023b28cc804b0d7b475d189722 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp @@ -84,8 +84,9 @@ int DeSerializeDataObjNode(Parcel &parcel, QueryObjNode &objNode) QuerySyncObject::QuerySyncObject() {} -QuerySyncObject::QuerySyncObject(const std::list &queryObjNodes, const std::vector &prefixKey) - : QueryObject(queryObjNodes, prefixKey) +QuerySyncObject::QuerySyncObject(const std::list &queryObjNodes, const std::vector &prefixKey, + const std::set &keys) + : QueryObject(queryObjNodes, prefixKey, keys) {} QuerySyncObject::QuerySyncObject(const Query &query) @@ -95,12 +96,21 @@ QuerySyncObject::QuerySyncObject(const Query &query) QuerySyncObject::~QuerySyncObject() {} +uint32_t QuerySyncObject::GetVersion() const +{ + uint32_t version = QUERY_SYNC_OBJECT_VERSION_0; + if (isTableNameSpecified_ || !keys_.empty()) { + version = QUERY_SYNC_OBJECT_VERSION_1; + } + return version; +} + int QuerySyncObject::GetObjContext(ObjContext &objContext) const { if (!isValid_) { return -E_INVALID_QUERY_FORMAT; } - objContext.version = isTableNameSpecified_ ? QUERY_SYNC_OBJECT_VERSION_1 : QUERY_SYNC_OBJECT_VERSION_0; + objContext.version = GetVersion(); objContext.prefixKey.assign(prefixKey_.begin(), prefixKey_.end()); objContext.suggestIndex = suggestIndex_; objContext.queryObjNodes = queryObjNodes_; @@ -114,9 +124,6 @@ std::string QuerySyncObject::GetIdentify() const } // suggestionIndex is local attribute, do not need to be propagated to remote uint64_t len = Parcel::GetVectorCharLen(prefixKey_); - if (isTableNameSpecified_) { - len += Parcel::GetStringLen(tableName_); - } for (const QueryObjNode &node : queryObjNodes_) { if (node.operFlag == QueryObjType::LIMIT || node.operFlag == QueryObjType::ORDERBY || node.operFlag == QueryObjType::SUGGEST_INDEX) { @@ -129,14 +136,18 @@ std::string QuerySyncObject::GetIdentify() const } } + // QUERY_SYNC_OBJECT_VERSION_1 added. + len += isTableNameSpecified_ ? Parcel::GetStringLen(tableName_) : 0; + for (const auto &key : keys_) { + len += Parcel::GetVectorCharLen(key); + } + // QUERY_SYNC_OBJECT_VERSION_1 end. + std::vector buff(len, 0); // It will affect the hash result, the default value cannot be modified Parcel parcel(buff.data(), len); // The order needs to be consistent, otherwise it will affect the hash result (void)parcel.WriteVectorChar(prefixKey_); - if (isTableNameSpecified_) { - (void)parcel.WriteString(tableName_); - } for (const QueryObjNode &node : queryObjNodes_) { if (node.operFlag == QueryObjType::LIMIT || node.operFlag == QueryObjType::ORDERBY || node.operFlag == QueryObjType::SUGGEST_INDEX) { @@ -151,6 +162,15 @@ std::string QuerySyncObject::GetIdentify() const } } + // QUERY_SYNC_OBJECT_VERSION_1 added. + if (isTableNameSpecified_) { + (void)parcel.WriteString(tableName_); + } + for (const auto &key : keys_) { + (void)parcel.WriteVectorChar(key); + } + // QUERY_SYNC_OBJECT_VERSION_1 end. + if (parcel.IsError()) { return std::string(); } @@ -184,9 +204,6 @@ int QuerySyncObject::SerializeData(Parcel &parcel, uint32_t softWareVersion) (void)parcel.WriteUInt32(context.version); (void)parcel.WriteVectorChar(context.prefixKey); (void)parcel.WriteString(context.suggestIndex); - if (isTableNameSpecified_) { - (void)parcel.WriteString(tableName_); - } (void)parcel.WriteUInt32(context.queryObjNodes.size()); parcel.EightByteAlign(); @@ -197,6 +214,20 @@ int QuerySyncObject::SerializeData(Parcel &parcel, uint32_t softWareVersion) return errCode; } } + + // QUERY_SYNC_OBJECT_VERSION_1 added. + if (context.version >= QUERY_SYNC_OBJECT_VERSION_1) { + (void)parcel.WriteUInt32(static_cast(isTableNameSpecified_)); + if (isTableNameSpecified_) { + (void)parcel.WriteString(tableName_); + } + (void)parcel.WriteUInt32(keys_.size()); + for (const auto &key : keys_) { + (void)parcel.WriteVectorChar(key); + } + } + // QUERY_SYNC_OBJECT_VERSION_1 end. + if (parcel.IsError()) { // parcel almost success return -E_INVALID_ARGS; } @@ -204,6 +235,30 @@ int QuerySyncObject::SerializeData(Parcel &parcel, uint32_t softWareVersion) return E_OK; } +namespace { +int DeSerializeVersion1Data(uint32_t version, Parcel &parcel, std::string &tableName, std::set &keys) +{ + if (version >= QUERY_SYNC_OBJECT_VERSION_1) { + uint32_t isTblNameExist = 0; + (void)parcel.ReadUInt32(isTblNameExist); + if (isTblNameExist) { + (void)parcel.ReadString(tableName); + } + uint32_t keysSize = 0; + (void)parcel.ReadUInt32(keysSize); + if (keysSize > DBConstant::MAX_BATCH_SIZE) { + return -E_PARSE_FAIL; + } + for (uint32_t i = 0; i < keysSize; ++i) { + Key key; + (void)parcel.ReadVector(key); + keys.emplace(key); + } + } + return E_OK; +} +} + int QuerySyncObject::DeSerializeData(Parcel &parcel, QuerySyncObject &queryObj) { std::string magic; @@ -214,17 +269,13 @@ int QuerySyncObject::DeSerializeData(Parcel &parcel, QuerySyncObject &queryObj) ObjContext context; (void)parcel.ReadUInt32(context.version); - if (context.version > QUERY_SYNC_OBJECT_VERSION_1) { + if (context.version > QUERY_SYNC_OBJECT_VERSION_CURRENT) { LOGE("Parcel version and deserialize version not matched! ver=%u", context.version); return -E_VERSION_NOT_SUPPORT; } (void)parcel.ReadVectorChar(context.prefixKey); (void)parcel.ReadString(context.suggestIndex); - std::string tableName; - if (context.version == QUERY_SYNC_OBJECT_VERSION_1) { - parcel.ReadString(tableName); - } uint32_t nodesSize = 0; (void)parcel.ReadUInt32(nodesSize); @@ -241,11 +292,20 @@ int QuerySyncObject::DeSerializeData(Parcel &parcel, QuerySyncObject &queryObj) context.queryObjNodes.emplace_back(node); } + // QUERY_SYNC_OBJECT_VERSION_1 added. + std::string tableName; + std::set keys; + int errCode = DeSerializeVersion1Data(context.version, parcel, tableName, keys); + if (errCode != E_OK) { + return errCode; + } + // QUERY_SYNC_OBJECT_VERSION_1 end. + if (parcel.IsError()) { // almost success return -E_INVALID_ARGS; } - queryObj = QuerySyncObject(context.queryObjNodes, context.prefixKey); - if (context.version == QUERY_SYNC_OBJECT_VERSION_1) { + queryObj = QuerySyncObject(context.queryObjNodes, context.prefixKey, keys); + if (!tableName.empty()) { queryObj.SetTableName(tableName); } return E_OK; @@ -257,9 +317,6 @@ uint32_t QuerySyncObject::CalculateLen() const len += Parcel::GetUInt32Len(); // version len += Parcel::GetVectorCharLen(prefixKey_); len += Parcel::GetStringLen(suggestIndex_); - if (isTableNameSpecified_) { - len += Parcel::GetStringLen(tableName_); - } len += Parcel::GetUInt32Len(); // nodes size len = Parcel::GetEightByteAlign(len); for (const QueryObjNode &node : queryObjNodes_) { @@ -276,6 +333,18 @@ uint32_t QuerySyncObject::CalculateLen() const len += Parcel::GetInt64Len() + Parcel::GetStringLen(node.fieldValue[i].stringValue); } } + + // QUERY_SYNC_OBJECT_VERSION_1 added. + len += Parcel::GetUInt32Len(); // whether the table name exists. + if (isTableNameSpecified_) { + len += Parcel::GetStringLen(tableName_); + } + len += Parcel::GetUInt32Len(); // size of keys_ + for (const auto &key : keys_) { + len += Parcel::GetVectorCharLen(key); + } + // QUERY_SYNC_OBJECT_VERSION_1 end. + len = Parcel::GetEightByteAlign(len); if (len > INT32_MAX) { return 0; diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.h index 052b9ea29b5d6f4a51cd09f4920b77054170d2ab..7d8ca7630c1a2ea98a03dc2229c43e871ce39c2f 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/query_sync_object.h @@ -22,20 +22,23 @@ #include "parcel.h" namespace DistributedDB { -const uint32_t QUERY_SYNC_OBJECT_VERSION_0 = 0; // for kvDB -const uint32_t QUERY_SYNC_OBJECT_VERSION_1 = 1; // for relational DB, which need specify tableName +const uint32_t QUERY_SYNC_OBJECT_VERSION_0 = 0; +const uint32_t QUERY_SYNC_OBJECT_VERSION_1 = 1; // Add tableName_ and keys_. +const uint32_t QUERY_SYNC_OBJECT_VERSION_CURRENT = QUERY_SYNC_OBJECT_VERSION_1; // always point the last. struct ObjContext { uint32_t version = QUERY_SYNC_OBJECT_VERSION_0; // serialized struct version std::vector prefixKey{}; std::string suggestIndex{}; std::list queryObjNodes{}; + std::vector keys{}; }; class QuerySyncObject : public QueryObject { public: QuerySyncObject(); - QuerySyncObject(const std::list &queryObjNodes, const std::vector &prefixKey); + QuerySyncObject(const std::list &queryObjNodes, const std::vector &prefixKey, + const std::set &keys); explicit QuerySyncObject(const Query &query); ~QuerySyncObject() override; @@ -51,6 +54,7 @@ public: private: uint32_t CalculateLen() const; int GetObjContext(ObjContext &objContext) const; + uint32_t GetVersion() const; }; } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index fea33f026b00ad529322fd89f2a0b856f7ed62e9..ce86080300a24fe0ebf396c4dc15cee77afe98d1 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -25,7 +25,7 @@ namespace DistributedDB { namespace { constexpr const char *RELATIONAL_SCHEMA_KEY = "relational_schema"; - constexpr const char *LOG_TABLE_VERSION_KEY = "log_table_versoin"; + constexpr const char *LOG_TABLE_VERSION_KEY = "log_table_version"; constexpr const char *LOG_TABLE_VERSION_1 = "1.0"; } @@ -67,9 +67,10 @@ int SQLiteRelationalStore::InitStorageEngine(const RelationalDBProperties &prope { OpenDbProperties option; InitDataBaseOption(properties, option); + std::string identifier = properties.GetStringProp(DBProperties::IDENTIFIER_DATA, ""); StorageEngineAttr poolSize = {1, 1, 0, 16}; // at most 1 write 16 read. - int errCode = sqliteStorageEngine_->InitSQLiteStorageEngine(poolSize, option); + int errCode = sqliteStorageEngine_->InitSQLiteStorageEngine(poolSize, option, identifier); if (errCode != E_OK) { LOGE("Init the sqlite storage engine failed:%d", errCode); } @@ -82,6 +83,7 @@ void SQLiteRelationalStore::ReleaseResources() sqliteStorageEngine_->ClearEnginePasswd(); (void)StorageEngineManager::ReleaseStorageEngine(sqliteStorageEngine_); } + RefObject::DecObjRef(storageEngine_); } int SQLiteRelationalStore::CheckDBMode() @@ -118,12 +120,11 @@ int SQLiteRelationalStore::GetSchemaFromMeta() RelationalSchemaObject schema; errCode = schema.ParseFromSchemaString(schemaStr); if (errCode != E_OK) { - LOGE("Parse schema string from mata table failed."); + LOGE("Parse schema string from meta table failed."); return errCode; } - std::lock_guard lock(schemaMutex_); - properties_.SetSchema(schema); + sqliteStorageEngine_->SetSchema(schema); return E_OK; } @@ -131,7 +132,7 @@ int SQLiteRelationalStore::SaveSchemaToMeta() { const Key schemaKey(RELATIONAL_SCHEMA_KEY, RELATIONAL_SCHEMA_KEY + strlen(RELATIONAL_SCHEMA_KEY)); Value schemaVal; - DBCommon::StringToVector(properties_.GetSchema().ToSchemaString(), schemaVal); + DBCommon::StringToVector(sqliteStorageEngine_->GetSchemaRef().ToSchemaString(), schemaVal); int errCode = storageEngine_->PutMetaData(schemaKey, schemaVal); if (errCode != E_OK) { LOGE("Save relational schema to meta table failed. %d", errCode); @@ -142,19 +143,40 @@ int SQLiteRelationalStore::SaveSchemaToMeta() int SQLiteRelationalStore::SaveLogTableVersionToMeta() { LOGD("save log table version to meta table, key: %s, val: %s", LOG_TABLE_VERSION_KEY, LOG_TABLE_VERSION_1); - return E_OK; + const Key logVersionKey(LOG_TABLE_VERSION_KEY, LOG_TABLE_VERSION_KEY + strlen(LOG_TABLE_VERSION_KEY)); + Value logVersionVal(LOG_TABLE_VERSION_1, LOG_TABLE_VERSION_1 + strlen(LOG_TABLE_VERSION_1)); + int errCode = storageEngine_->PutMetaData(logVersionKey, logVersionVal); + if (errCode != E_OK) { + LOGE("save log table version to meta table failed. %d", errCode); + } + return errCode; } int SQLiteRelationalStore::CleanDistributedDeviceTable() { - return E_OK; + std::vector missingTables; + int errCode = sqliteStorageEngine_->CleanDistributedDeviceTable(missingTables); + if (errCode != E_OK) { + LOGE("Clean distributed device table failed. %d", errCode); + } + for (const auto &deviceTableName : missingTables) { + std::string deviceHash; + std::string tableName; + DBCommon::GetDeviceFromName(deviceTableName, deviceHash, tableName); + syncAbleEngine_->EraseDeviceWaterMark(deviceHash, false, tableName); + if (errCode != E_OK) { + LOGE("Erase water mark failed:%d", errCode); + return errCode; + } + } + return errCode; } int SQLiteRelationalStore::Open(const RelationalDBProperties &properties) { std::lock_guard lock(initalMutex_); if (isInitialized_) { - LOGD("[RelationalStore][Open] relational db was already inited."); + LOGD("[RelationalStore][Open] relational db was already initialized."); return E_OK; } @@ -179,6 +201,8 @@ int SQLiteRelationalStore::Open(const RelationalDBProperties &properties) break; } + syncAbleEngine_ = std::make_unique(storageEngine_); + errCode = CheckDBMode(); if (errCode != E_OK) { break; @@ -200,7 +224,6 @@ int SQLiteRelationalStore::Open(const RelationalDBProperties &properties) break; } - syncEngine_ = std::make_unique(storageEngine_); isInitialized_ = true; return E_OK; } while (false); @@ -244,7 +267,7 @@ void SQLiteRelationalStore::ReleaseHandle(SQLiteSingleVerRelationalStorageExecut int SQLiteRelationalStore::Sync(const ISyncer::SyncParma &syncParam) { - return syncEngine_->Sync(syncParam); + return syncAbleEngine_->Sync(syncParam); } // Called when a connection released. @@ -270,7 +293,7 @@ void SQLiteRelationalStore::DecreaseConnectionCounter() } // Sync Close - syncEngine_->Close(); + syncAbleEngine_->Close(); if (sqliteStorageEngine_ != nullptr) { delete sqliteStorageEngine_; @@ -299,26 +322,32 @@ void SQLiteRelationalStore::ReleaseDBConnection(RelationalStoreConnection *conne void SQLiteRelationalStore::WakeUpSyncer() { - syncEngine_->WakeUpSyncer(); + syncAbleEngine_->WakeUpSyncer(); } - int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName) { - int errCode = E_OK; - std::lock_guard lock(schemaMutex_); - auto schema = properties_.GetSchema(); - if (schema.GetTable(tableName).GetTableName() == tableName) { - LOGW("distributed table was already created."); - return E_OK; + bool schemaChanged = false; + int errCode = sqliteStorageEngine_->CreateDistributedTable(tableName, schemaChanged); + if (errCode != E_OK) { + LOGE("Create distributed table failed. %d", errCode); + } + if (schemaChanged) { + LOGD("Notify schema changed."); + storageEngine_->NotifySchemaChanged(); } + return errCode; +} - if (schema.GetTables().size() >= DBConstant::MAX_DISTRIBUTED_TABLE_COUNT) { - LOGW("The number of distributed tables is exceeds limit."); - return -E_MAX_LIMITS; +int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std::string &tableName) +{ + std::map tables = sqliteStorageEngine_->GetSchemaRef().GetTables(); + if (!tableName.empty() && tables.find(tableName) == tables.end()) { + LOGW("Remove device data with table name which is not a distributed table or not exist."); + return E_OK; } - LOGD("Create distributed table."); + int errCode = E_OK; auto *handle = GetHandle(true, errCode); if (handle == nullptr) { return errCode; @@ -330,20 +359,128 @@ int SQLiteRelationalStore::CreateDistributedTable(const std::string &tableName) return errCode; } - TableInfo table; - errCode = handle->CreateDistributedTable(tableName, table); + errCode = handle->DeleteDistributedDeviceTable(device, tableName); if (errCode != E_OK) { - LOGE("create distributed table failed. %d", errCode); + LOGE("delete device data failed. %d", errCode); (void)handle->Rollback(); ReleaseHandle(handle); return errCode; } - schema.AddRelationalTable(table); - properties_.SetSchema(schema); - (void)handle->Commit(); - + errCode = handle->Commit(); ReleaseHandle(handle); - return SaveSchemaToMeta(); + return (errCode != E_OK) ? errCode : syncAbleEngine_->EraseDeviceWaterMark(device, true, tableName); +} + +void SQLiteRelationalStore::RegisterObserverAction(const RelationalObserverAction &action) +{ + storageEngine_->RegisterObserverAction(action); +} + +int SQLiteRelationalStore::StopLifeCycleTimer() const +{ + auto runtimeCxt = RuntimeContext::GetInstance(); + if (runtimeCxt == nullptr) { + return -E_INVALID_ARGS; + } + if (lifeTimerId_ != 0) { + TimerId timerId = lifeTimerId_; + lifeTimerId_ = 0; + runtimeCxt->RemoveTimer(timerId, false); + } + return E_OK; +} + +int SQLiteRelationalStore::StartLifeCycleTimer(const DatabaseLifeCycleNotifier ¬ifier) const +{ + auto runtimeCxt = RuntimeContext::GetInstance(); + if (runtimeCxt == nullptr) { + return -E_INVALID_ARGS; + } + RefObject::IncObjRef(this); + TimerId timerId = 0; + int errCode = runtimeCxt->SetTimer(DBConstant::DEF_LIFE_CYCLE_TIME, + [this](TimerId id) -> int { + std::lock_guard lock(lifeCycleMutex_); + if (lifeCycleNotifier_) { + auto identifier = properties_.GetStringProp(DBProperties::IDENTIFIER_DATA, ""); + lifeCycleNotifier_(identifier); + } + return 0; + }, + [this]() { + int ret = RuntimeContext::GetInstance()->ScheduleTask([this]() { + RefObject::DecObjRef(this); + }); + if (ret != E_OK) { + LOGE("SQLiteSingleVerNaturalStore timer finalizer ScheduleTask, errCode %d", ret); + } + }, + timerId); + if (errCode != E_OK) { + lifeTimerId_ = 0; + LOGE("SetTimer failed:%d", errCode); + RefObject::DecObjRef(this); + return errCode; + } + + lifeCycleNotifier_ = notifier; + lifeTimerId_ = timerId; + return E_OK; +} + +int SQLiteRelationalStore::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) +{ + int errCode; + { + std::lock_guard lock(lifeCycleMutex_); + if (lifeTimerId_ != 0) { + errCode = StopLifeCycleTimer(); + if (errCode != E_OK) { + LOGE("Stop the life cycle timer failed:%d", errCode); + return errCode; + } + } + + if (!notifier) { + return E_OK; + } + errCode = StartLifeCycleTimer(notifier); + if (errCode != E_OK) { + LOGE("Register life cycle timer failed:%d", errCode); + return errCode; + } + } + auto listener = std::bind(&SQLiteRelationalStore::HeartBeat, this); + storageEngine_->RegisterHeartBeatListener(listener); + return errCode; +} + +void SQLiteRelationalStore::HeartBeat() const +{ + std::lock_guard lock(lifeCycleMutex_); + int errCode = ResetLifeCycleTimer(); + if (errCode != E_OK) { + LOGE("Heart beat for life cycle failed:%d", errCode); + } +} + +int SQLiteRelationalStore::ResetLifeCycleTimer() const +{ + if (lifeTimerId_ == 0) { + return E_OK; + } + auto lifeNotifier = lifeCycleNotifier_; + lifeCycleNotifier_ = nullptr; + int errCode = StopLifeCycleTimer(); + if (errCode != E_OK) { + LOGE("[Reset timer]Stop the life cycle timer failed:%d", errCode); + } + return StartLifeCycleTimer(lifeNotifier); +} + +std::string SQLiteRelationalStore::GetStorePath() const +{ + return properties_.GetStringProp(DBProperties::DATA_DIR, ""); } } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h index ebb3fb2b5949d83e2338887311b2f409eccfcd34..86245108531389da48e5377cd1cdbd19797ad92d 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h @@ -25,8 +25,10 @@ #include "isyncer.h" #include "sync_able_engine.h" #include "relational_sync_able_storage.h" +#include "runtime_context.h" namespace DistributedDB { +using RelationalObserverAction = std::function; class SQLiteRelationalStore : public IRelationalStore { public: SQLiteRelationalStore() = default; @@ -52,6 +54,14 @@ public: } int CreateDistributedTable(const std::string &tableName); + + int RemoveDeviceData(const std::string &device, const std::string &tableName); + + void RegisterObserverAction(const RelationalObserverAction &action); + int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier); + + std::string GetStorePath() const override; + private: void ReleaseResources(); @@ -65,8 +75,13 @@ private: int CleanDistributedDeviceTable(); + int StopLifeCycleTimer() const; + int StartLifeCycleTimer(const DatabaseLifeCycleNotifier ¬ifier) const; + void HeartBeat() const; + int ResetLifeCycleTimer() const; + // use for sync Interactive - std::unique_ptr syncEngine_ = nullptr; // For storage operate sync function + std::unique_ptr syncAbleEngine_ = nullptr; // For storage operate sync function // use ref obj same as kv RelationalSyncAbleStorage *storageEngine_ = nullptr; // For storage operate data SQLiteSingleRelationalStorageEngine *sqliteStorageEngine_ = nullptr; @@ -77,12 +92,16 @@ private: std::atomic connectionCount_ = 0; std::vector> closeNotifiers_; + mutable std::mutex schemaMutex_; RelationalDBProperties properties_; mutable std::mutex initalMutex_; bool isInitialized_ = false; - mutable std::mutex schemaMutex_; + // lifeCycle + mutable std::mutex lifeCycleMutex_; + mutable DatabaseLifeCycleNotifier lifeCycleNotifier_; + mutable TimerId lifeTimerId_; }; } // namespace DistributedDB #endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp index de529540bcc2f106bd9f018634fbc82fa80bfcb5..fe95c589ed94fa3cde9df6d194cd41dde42afe78 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp @@ -150,6 +150,26 @@ int SQLiteRelationalStoreConnection::CreateDistributedTable(const std::string &t return errCode; } +int SQLiteRelationalStoreConnection::RemoveDeviceData(const std::string &device) +{ + return RemoveDeviceData(device, {}); +} + +int SQLiteRelationalStoreConnection::RemoveDeviceData(const std::string &device, const std::string &tableName) +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, get DB failed!"); + return -E_INVALID_CONNECTION; + } + + int errCode = store->RemoveDeviceData(device, tableName); + if (errCode != E_OK) { + LOGE("[RelationalConnection] remove device data failed. %d", errCode); + } + return errCode; +} + int SQLiteRelationalStoreConnection::Pragma(int cmd, void *parameter) // reserve for interface function fix { return E_OK; @@ -183,6 +203,7 @@ int SQLiteRelationalStoreConnection::SyncToDevice(SyncInfo &info) int errCode = store->Sync(syncParam); if (errCode != E_OK) { DecObjRef(this); + return errCode; } } return E_OK; @@ -190,7 +211,18 @@ int SQLiteRelationalStoreConnection::SyncToDevice(SyncInfo &info) int SQLiteRelationalStoreConnection::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) { - return E_OK; + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, get executor failed!"); + return -E_INVALID_CONNECTION; + } + + return store->RegisterLifeCycleCallback(notifier); +} + +void SQLiteRelationalStoreConnection::RegisterObserverAction(const RelationalObserverAction &action) +{ + static_cast(store_)->RegisterObserverAction(action); } } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h index 552447e76e6ab4e6aae8ae70aa84d35df375cfe4..6094af02239baa89db721c9519dedf3e6f49d6d4 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h @@ -40,6 +40,10 @@ public: int CreateDistributedTable(const std::string &tableName) override; int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; + int RemoveDeviceData(const std::string &device) override; + int RemoveDeviceData(const std::string &device, const std::string &tableName) override; + void RegisterObserverAction(const RelationalObserverAction &action) override; + protected: int Pragma(int cmd, void *parameter) override; diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index 6ef4b916eda3dd8d12d30783bbbaeff0ca1ec604..4d6ef2abfcd3209ba35f4164f6000e9e97702615 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp @@ -15,10 +15,16 @@ #ifdef RELATIONAL_STORE #include "sqlite_single_relational_storage_engine.h" -#include "sqlite_single_ver_relational_storage_executor.h" +#include "db_common.h" #include "db_errno.h" +#include "sqlite_single_ver_relational_storage_executor.h" + namespace DistributedDB { +namespace { + constexpr const char *RELATIONAL_SCHEMA_KEY = "relational_schema"; +} + SQLiteSingleRelationalStorageEngine::SQLiteSingleRelationalStorageEngine() {}; SQLiteSingleRelationalStorageEngine::~SQLiteSingleRelationalStorageEngine() {}; @@ -57,6 +63,11 @@ int SQLiteSingleRelationalStorageEngine::CreateNewExecutor(bool isWrite, Storage return errCode; } do { + errCode = SQLiteUtils::SetPersistWalMode(db); + if (errCode != E_OK) { + break; + } + errCode = Upgrade(db); // cerate meta_data table. if (errCode != E_OK) { break; @@ -80,5 +91,179 @@ int SQLiteSingleRelationalStorageEngine::CreateNewExecutor(bool isWrite, Storage db = nullptr; return errCode; } + +int SQLiteSingleRelationalStorageEngine::ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor *&handle) +{ + if (handle == nullptr) { + return E_OK; + } + StorageExecutor *databaseHandle = handle; + Recycle(databaseHandle); + handle = nullptr; + return E_OK; +} + +void SQLiteSingleRelationalStorageEngine::SetSchema(const RelationalSchemaObject &schema) +{ + std::lock_guard lock(schemaMutex_); + schema_ = schema; +} + +const RelationalSchemaObject &SQLiteSingleRelationalStorageEngine::GetSchemaRef() const +{ + std::lock_guard lock(schemaMutex_); + return schema_; +} + +namespace { +int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, const RelationalSchemaObject &schema) +{ + const Key schemaKey(RELATIONAL_SCHEMA_KEY, RELATIONAL_SCHEMA_KEY + strlen(RELATIONAL_SCHEMA_KEY)); + Value schemaVal; + DBCommon::StringToVector(schema.ToSchemaString(), schemaVal); + int errCode = handle->PutKvData(schemaKey, schemaVal); // save schema to meta_data + if (errCode != E_OK) { + LOGE("Save schema to meta table failed. %d", errCode); + } + return errCode; +} +} + +int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName, bool &schemaChanged) +{ + std::lock_guard lock(schemaMutex_); + RelationalSchemaObject tmpSchema = schema_; + if (tmpSchema.GetTable(tableName).GetTableName() == tableName) { + LOGW("distributed table was already created."); + int errCode = UpgradeDistributedTable(tableName); + if (errCode != E_OK) { + LOGE("Upgrade distributed table failed. %d", errCode); + return errCode; + } + } + + if (tmpSchema.GetTables().size() >= DBConstant::MAX_DISTRIBUTED_TABLE_COUNT) { + LOGE("The number of distributed tables is exceeds limit."); + return -E_MAX_LIMITS; + } + + LOGD("Create distributed table."); + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, + errCode)); + if (handle == nullptr) { + return errCode; + } + + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + ReleaseExecutor(handle); + return errCode; + } + + TableInfo table; + errCode = handle->CreateDistributedTable(tableName, table); + if (errCode != E_OK) { + LOGE("create distributed table failed. %d", errCode); + (void)handle->Rollback(); + ReleaseExecutor(handle); + return errCode; + } + + tmpSchema.AddRelationalTable(table); + errCode = SaveSchemaToMetaTable(handle, tmpSchema); + if (errCode != E_OK) { + LOGE("Save schema to meta table for create distributed table failed. %d", errCode); + (void)handle->Rollback(); + ReleaseExecutor(handle); + return errCode; + } + + errCode = handle->Commit(); + if (errCode == E_OK) { + schema_ = tmpSchema; + schemaChanged = true; + } + ReleaseExecutor(handle); + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::UpgradeDistributedTable(const std::string &tableName) +{ + LOGD("Upgrade distributed table."); + RelationalSchemaObject tmpSchema = schema_; + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, + errCode)); + if (handle == nullptr) { + return errCode; + } + + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + ReleaseExecutor(handle); + return errCode; + } + + TableInfo newTable; + errCode = handle->UpgradeDistributedTable(tmpSchema.GetTable(tableName), newTable); + if (errCode != E_OK) { + LOGE("Upgrade distributed table failed. %d", errCode); + (void)handle->Rollback(); + ReleaseExecutor(handle); + return errCode; + } + + tmpSchema.AddRelationalTable(newTable); + errCode = SaveSchemaToMetaTable(handle, tmpSchema); + if (errCode != E_OK) { + LOGE("Save schema to meta table for upgrade distributed table failed. %d", errCode); + (void)handle->Rollback(); + ReleaseExecutor(handle); + return errCode; + } + + errCode = handle->Commit(); + if (errCode == E_OK) { + schema_ = tmpSchema; + } + ReleaseExecutor(handle); + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::CleanDistributedDeviceTable(std::vector &missingTables) +{ + int errCode = E_OK; + auto handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, + errCode)); + if (handle == nullptr) { + return errCode; + } + + std::lock_guard lock(schemaMutex_); + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + ReleaseExecutor(handle); + return errCode; + } + + errCode = handle->CheckAndCleanDistributedTable(schema_.GetTableNames(), missingTables); + if (errCode == E_OK) { + errCode = handle->Commit(); + if (errCode == E_OK) { + // Remove non-existent tables from the schema + for (const auto &tableName : missingTables) { + schema_.RemoveRelationalTable(tableName); + } + SaveSchemaToMetaTable(handle, schema_); // save schema to meta_data + } + } else { + LOGE("Check distributed table failed. %d", errCode); + (void)handle->Rollback(); + } + + ReleaseExecutor(handle); + return errCode; +} } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h index 7bb37460b82199c06a3b41a95629f51e5d2d2b78..d09014b6eef01ef6cdc16feab919ad63e42430f0 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h @@ -29,13 +29,30 @@ public: // Delete the copy and assign constructors DISABLE_COPY_ASSIGN_MOVE(SQLiteSingleRelationalStorageEngine); + void SetSchema(const RelationalSchemaObject &schema); + + const RelationalSchemaObject &GetSchemaRef() const; + + int CreateDistributedTable(const std::string &tableName, bool &schemaChanged); + + int CleanDistributedDeviceTable(std::vector &missingTables); + protected: StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *db, bool isWrite, bool isMemDb) override; int Upgrade(sqlite3 *db) override; int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) override; private: + // For executor. + int ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor *&handle); + + // For db. int RegisterFunction(sqlite3 *db) const; + + int UpgradeDistributedTable(const std::string &tableName); + + RelationalSchemaObject schema_; + mutable std::mutex schemaMutex_; }; } // namespace DistributedDB #endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp index 212b13f301e0b457e2d708a93dabca385c0368a6..cb78f27d8f3087b28e59109f2ec00ef23344ab54 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp @@ -123,6 +123,7 @@ SqliteQueryHelper::SqliteQueryHelper(const QueryObjInfo &info) prefixKey_(info.prefixKey_), suggestIndex_(info.suggestIndex_), tableName_(info.tableName_), + keys_(info.keys_), orderByCounts_(info.orderByCounts_), isValid_(info.isValid_), transformed_(false), @@ -130,7 +131,8 @@ SqliteQueryHelper::SqliteQueryHelper(const QueryObjInfo &info) hasLimit_(info.hasLimit_), isOrderByAppeared_(false), hasPrefixKey_(info.hasPrefixKey_), - isNeedOrderbyKey_(false) + isNeedOrderbyKey_(false), + isRelationalQuery_(info.isRelationalQuery_) {} SymbolType SqliteQueryHelper::GetSymbolType(const QueryObjType &queryObjType) @@ -147,7 +149,7 @@ bool SqliteQueryHelper::FilterSymbolToAddBracketLink(std::string &querySql, bool querySql += isNeedLink ? " AND (" : " ("; isNeedEndBracket = true; break; - } else if (symbolType == LOGIC_SYMBOL || symbolType == PREFIXKEY_SYMBOL) { + } else if (symbolType == LOGIC_SYMBOL || symbolType == PREFIXKEY_SYMBOL || symbolType == IN_KEYS_SYMBOL) { continue; } else { break; @@ -277,6 +279,7 @@ int SqliteQueryHelper::GetQuerySql(std::string &sql, bool onlyRowid) const std::string &querySqlForUse = (onlyRowid ? PRE_QUERY_ROWID_SQL : PRE_QUERY_KV_SQL); sql = AssembleSqlForSuggestIndex(querySqlForUse, FILTER_NATIVE_DATA_SQL); sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) "); + sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size())); if (transformed_) { LOGD("This query object has been parsed."); sql += querySql_; @@ -300,6 +303,7 @@ int SqliteQueryHelper::GetSyncDataCheckSql(std::string &sql) } sql = PRE_QUERY_ITEM_SQL + tableName_ + " WHERE hash_key=? AND (flag&0x01=0) "; sql += hasPrefixKey_ ? " AND (key>=? AND key<=?) " : ""; + sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size())); if (!transformed_) { errCode = ToQuerySql(); if (errCode != E_OK) { @@ -354,6 +358,7 @@ int SqliteQueryHelper::GetCountQuerySql(std::string &sql) } sql = AssembleSqlForSuggestIndex(PRE_GET_COUNT_SQL, FILTER_NATIVE_DATA_SQL); sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) "); + sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size())); sql += countSql_; return E_OK; } @@ -377,6 +382,12 @@ int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, const std::string index = 3; // begin from 3rd args } + errCode = BindKeysToStmt(keys_, statement, index); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(statement, true, errCode); + return errCode; + } + for (const QueryObjNode &objNode : queryObjNodes_) { errCode = BindFieldValue(statement, objNode, index); if (errCode != E_OK) { @@ -412,6 +423,11 @@ int SqliteQueryHelper::GetQuerySqlStatement(sqlite3 *dbHandle, bool onlyRowid, s index = 3; // begin from 3rd args } + errCode = BindKeysToStmt(keys_, statement, index); + if (errCode != E_OK) { + return errCode; + } + for (const QueryObjNode &objNode : queryObjNodes_) { errCode = BindFieldValue(statement, objNode, index); if (errCode != E_OK) { @@ -447,6 +463,11 @@ int SqliteQueryHelper::GetCountSqlStatement(sqlite3 *dbHandle, sqlite3_stmt *&co index = 3; // begin from 3rd args } + errCode = BindKeysToStmt(keys_, countStmt, index); + if (errCode != E_OK) { + return errCode; + } + for (const QueryObjNode &objNode : queryObjNodes_) { if (GetSymbolType(objNode.operFlag) == SPECIAL_SYMBOL) { continue; @@ -474,6 +495,7 @@ int SqliteQueryHelper::GetSyncDataQuerySql(std::string &sql, bool hasSubQuery) sql = AssembleSqlForSuggestIndex(PRE_QUERY_ITEM_SQL + tableName_ + " ", FILTER_REMOTE_QUERY); sql = !hasPrefixKey_ ? sql : (sql + " AND (key>=? AND key<=?) "); + sql = keys_.empty() ? sql : (sql + " AND " + MapKeysInToSql(keys_.size())); sql = hasSubQuery ? sql : (sql + " AND (timestamp>=? AND timestamp=? @@ -605,8 +633,7 @@ std::string SqliteQueryHelper::MapKeywordSymbolToSql(const QueryObjNode &queryNo if (!isOrderByAppeared_) { sql += "ORDER BY "; } - - sql += SqliteQueryHelper::MapCastFuncSql(queryNode); + sql += GetFieldShape(queryNode); sql += queryNode.fieldValue[0].boolValue ? "ASC," : "DESC,"; orderByCounts_--; if (orderByCounts_ == 0) { @@ -713,6 +740,15 @@ std::string SqliteQueryHelper::MapCastTypeSql(const FieldType &type) const } } +std::string SqliteQueryHelper::GetFieldShape(const QueryObjNode &queryNode, const std::string &accessStr) +{ + if (isRelationalQuery_) { + // For relational query, $. prefix is not permitted, so need not extract json. Return directly will be OK. + return queryNode.fieldName + " "; + } + return MapCastFuncSql(queryNode, accessStr); +} + int SqliteQueryHelper::ParseQueryExpression(const QueryObjNode &queryNode, std::string &querySql, const std::string &accessStr, bool placeholder) { @@ -723,7 +759,7 @@ int SqliteQueryHelper::ParseQueryExpression(const QueryObjNode &queryNode, std:: } if (symbolType == COMPARE_SYMBOL || symbolType == RELATIONAL_SYMBOL || symbolType == RANGE_SYMBOL) { - querySql += MapCastFuncSql(queryNode, accessStr); + querySql += GetFieldShape(queryNode, accessStr); querySql += MapRelationalSymbolToSql(queryNode, placeholder); } else if (symbolType == LOGIC_SYMBOL || symbolType == LINK_SYMBOL) { querySql += MapLogicSymbolToSql(queryNode); @@ -767,6 +803,19 @@ std::string SqliteQueryHelper::CheckAndFormatSuggestIndex() const return SchemaUtils::FieldPathString(indexName); } +std::string SqliteQueryHelper::MapKeysInSubCondition(const std::string &accessStr) const +{ + std::string resultStr = "hex(" + accessStr + "key) IN ("; + for (auto iter = keys_.begin(); iter != keys_.end(); iter++) { + if (iter != keys_.begin()) { + resultStr += ", "; + } + resultStr += "'" + DBCommon::VectorToHexString(*iter) + "' "; + } + resultStr += ")"; + return resultStr; +} + int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std::string &conditionStr) { if (queryObjNodes_.empty()) { @@ -777,7 +826,15 @@ int SqliteQueryHelper::GetSubscribeCondition(const std::string &accessStr, std:: if (hasPrefixKey_) { conditionStr += "(hex(" + accessStr + "key) LIKE '" + DBCommon::VectorToHexString(prefixKey_) + "%')"; } - bool isNeedEndBracket = FilterSymbolToAddBracketLink(conditionStr, hasPrefixKey_); + + if (!keys_.empty()) { + if (hasPrefixKey_) { + conditionStr += " AND "; + } + conditionStr += "(" + MapKeysInSubCondition(accessStr) + ")"; + } + + bool isNeedEndBracket = FilterSymbolToAddBracketLink(conditionStr, hasPrefixKey_ || !keys_.empty()); int errCode = E_OK; for (const QueryObjNode &objNode : queryObjNodes_) { SymbolType symbolType = GetSymbolType(objNode.operFlag); @@ -917,4 +974,33 @@ int SqliteQueryHelper::GetRelationalQueryStatement(sqlite3 *dbHandle, uint64_t b } return errCode; } + +std::string SqliteQueryHelper::MapKeysInToSql(size_t keysNum) const +{ + std::string resultSql = "key IN ("; + for (size_t i = 0; i < keysNum; i++) { + if (i != 0) { + resultSql += ", "; + } + resultSql += "? "; + } + resultSql += ") "; + return resultSql; +} + +int SqliteQueryHelper::BindKeysToStmt(std::set &keys, sqlite3_stmt *&statement, int &index) const +{ + if (!keys_.empty()) { + int errCode = E_OK; + for (const auto &key : keys) { + errCode = SQLiteUtils::BindBlobToStatement(statement, index, key); + if (errCode != E_OK) { + LOGE("[Query] Get statement when bind keys failed, errCode = %d", errCode); + return errCode; + } + index++; + } + } + return E_OK; +} } \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h index fc31888853fa6a535c5fe779b2cbf2acd76b067d..2bdf91c7564388fc7587fb6d431d1de85fa6c016 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.h @@ -16,6 +16,7 @@ #define SQLITE_QUERY_HELPER_H #include +#include #include #include @@ -32,12 +33,14 @@ struct QueryObjInfo { std::list queryObjNodes_; std::vector prefixKey_; std::string suggestIndex_; + std::set keys_; int orderByCounts_ = 0; // Record processing to which orderBy node bool isValid_ = true; bool hasOrderBy_ = false; bool hasLimit_ = false; bool hasPrefixKey_ = false; std::string tableName_; + bool isRelationalQuery_ = false; }; enum SymbolType : uint32_t { @@ -50,6 +53,7 @@ enum SymbolType : uint32_t { LINK_SYMBOL = 0x0600, // use to link relatonal symbol SPECIAL_SYMBOL = 0x0700, // need special precess and need at the last SUGGEST_INDEX_SYMBOL = 0x0800, + IN_KEYS_SYMBOL = 0x0900, }; class SqliteQueryHelper final { @@ -112,12 +116,19 @@ private: int BindTimeRange(sqlite3_stmt *&statement, int &index, uint64_t beginTime, uint64_t endTime) const; int BindObjNodes(sqlite3_stmt *&statement, int &index) const; int GetSubscribeCondition(const std::string &accessStr, std::string &conditionStr); + std::string MapKeysInToSql(size_t keysNum) const; + int BindKeysToStmt(std::set &keys, sqlite3_stmt *&countStmt, int &index) const; + + std::string MapKeysInSubCondition(const std::string &accessStr) const; // For InKeys. + // Return the left string of symbol in compare clause. + std::string GetFieldShape(const QueryObjNode &queryNode, const std::string &accessStr = ""); SchemaObject schema_; std::list queryObjNodes_; std::vector prefixKey_; std::string suggestIndex_; std::string tableName_; + std::set keys_; std::string querySql_; std::string countSql_; @@ -130,6 +141,7 @@ private: bool isOrderByAppeared_; bool hasPrefixKey_; bool isNeedOrderbyKey_; // The tag field is used for prefix query filtering key sorting + bool isRelationalQuery_; }; } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp index 1110153a52df5a5f91e8567a9e4702eb7ee132ae..797e9a93e1c22f4c1f79e3c0ab9e49e406cea350 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp @@ -42,7 +42,6 @@ namespace DistributedDB { } while (0) namespace { - constexpr int DEF_LIFE_CYCLE_TIME = 60000; // 60s constexpr int WAIT_DELEGATE_CALLBACK_TIME = 100; const std::string CREATE_DB_TIME = "createDBTime"; @@ -172,7 +171,7 @@ SQLiteSingleVerNaturalStore::SQLiteSingleVerNaturalStore() isReadOnly_(false), lifeCycleNotifier_(nullptr), lifeTimerId_(0), - autoLifeTime_(DEF_LIFE_CYCLE_TIME), + autoLifeTime_(DBConstant::DEF_LIFE_CYCLE_TIME), createDBTime_(0), dataInterceptor_(nullptr), maxLogSize_(DBConstant::MAX_LOG_SIZE_DEFAULT) diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp index 40a692b647d97de9d3cb1132928b073c9473c939..c5abe7bc4d1573ccb427c8fd305d882e29530087 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp @@ -21,7 +21,7 @@ #include "kvdb_pragma.h" #include "sqlite_single_ver_natural_store.h" #include "kvdb_observer_handle.h" -#include "types.h" +#include "store_types.h" #include "db_common.h" #include "sqlite_single_ver_result_set.h" #include "sqlite_single_ver_forward_cursor.h" diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp index fd765798715232a063e80d87fb07c0752dcab9d2..63e4029d94ca1ad2dbb63694c4a95fae80c6a349 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp @@ -25,7 +25,6 @@ SQLiteSingleVerRelationalStorageExecutor::SQLiteSingleVerRelationalStorageExecut int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedTable(const std::string &tableName, TableInfo &table) { if (dbHandle_ == nullptr) { - LOGE("[CreateDistributedTable] Begin transaction failed, dbHandle is null."); return -E_INVALID_DB; } @@ -62,12 +61,234 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedTable(const std:: // add trigger errCode = SQLiteUtils::AddRelationalLogTableTrigger(dbHandle_, table); if (errCode != E_OK) { - LOGE("[CreateDistributedTable] create log table failed"); + LOGE("[CreateDistributedTable] Add relational log table trigger failed."); return errCode; } return E_OK; } +int SQLiteSingleVerRelationalStorageExecutor::UpgradeDistributedTable(const TableInfo &tableInfo, + TableInfo &newTableInfo) +{ + if (dbHandle_ == nullptr) { + return -E_INVALID_DB; + } + + int errCode = SQLiteUtils::AnalysisSchema(dbHandle_, tableInfo.GetTableName(), newTableInfo); + if (errCode != E_OK) { + LOGE("[UpgradeDistributedTable] analysis table schema failed. %d", errCode); + return errCode; + } + + if (newTableInfo.GetCreateTableSql().find("WITHOUT ROWID") != std::string::npos) { + LOGE("[UpgradeDistributedTable] Not support create distributed table without rowid."); + return -E_NOT_SUPPORT; + } + + // new table should has same or compatible upgrade + errCode = tableInfo.CompareWithTable(newTableInfo); + if (errCode == -E_RELATIONAL_TABLE_INCOMPATIBLE) { + LOGE("[UpgradeDistributedTable] Not support with incompatible upgrade."); + return -E_SCHEMA_MISMATCH; + } + + errCode = AlterAuxTableForUpgrade(tableInfo, newTableInfo); + if (errCode != E_OK) { + LOGE("[UpgradeDistributedTable] Alter aux table for upgrade failed. %d", errCode); + } + + return errCode; +} + +namespace { +int GetDeviceTableName(sqlite3 *handle, const std::string &tableName, const std::string &device, + std::vector &deviceTables) +{ + if (device.empty() && tableName.empty()) { // device and table name should not both be empty + return -E_INVALID_ARGS; + } + std::string deviceHash = DBCommon::TransferStringToHex(DBCommon::TransferHashString(device)); + std::string devicePattern = device.empty() ? "%" : deviceHash; + std::string tablePattern = tableName.empty() ? "%" : tableName; + std::string deviceTableName = DBConstant::RELATIONAL_PREFIX + tablePattern + "_" + devicePattern; + + const std::string checkSql = "SELECT name FROM sqlite_master WHERE type='table' AND name LIKE '" + + deviceTableName + "';"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(handle, checkSql, stmt); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; + } + + do { + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + break; + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("Get table name failed. %d", errCode); + break; + } + std::string realTableName; + errCode = SQLiteUtils::GetColumnTextValue(stmt, 0, realTableName); // 0: table name result column index + if (errCode != E_OK || realTableName.empty()) { // sqlite might return a row with NULL + continue; + } + if (realTableName.rfind("_log") == (realTableName.length() - 4)) { // 4:suffix length of "_log" + continue; + } + deviceTables.emplace_back(realTableName); + } while (true); + + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} + +std::vector GetUpgradeFields(const TableInfo &oldTableInfo, const TableInfo &newTableInfo) +{ + std::vector fields; + auto itOld = oldTableInfo.GetFields().begin(); + auto itNew = newTableInfo.GetFields().begin(); + for (; itNew != newTableInfo.GetFields().end(); itNew++) { + if (itOld == oldTableInfo.GetFields().end() || itOld->first != itNew->first) { + fields.emplace_back(itNew->second); + continue; + } + itOld++; + } + return fields; +} + +int UpgradeFields(sqlite3 *db, const std::vector &tables, const std::vector &fields) +{ + if (db == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + for (auto table : tables) { + for (auto field : fields) { + std::string alterSql = "ALTER TABLE " + table + " ADD " + field.GetFieldName() + " " + + field.GetDataType() + ";"; + errCode = SQLiteUtils::ExecuteRawSQL(db, alterSql); + if (errCode != E_OK) { + LOGE("Alter table failed. %d", errCode); + break; + } + } + } + return errCode; +} + +std::map GetChangedIndexes(const TableInfo &oldTableInfo, const TableInfo &newTableInfo) +{ + std::map indexes; + auto itOld = oldTableInfo.GetIndexDefine().begin(); + auto itNew = newTableInfo.GetIndexDefine().begin(); + auto itOldEnd = oldTableInfo.GetIndexDefine().end(); + auto itNewEnd = newTableInfo.GetIndexDefine().end(); + + while (itOld != itOldEnd && itNew != itNewEnd) { + if (itOld->first == itNew->first) { + if (itOld->second != itNew->second) { + indexes.insert({itNew->first, itNew->second}); + } + itOld++; + itNew++; + } else if (itOld->first < itNew->first) { + indexes.insert({itOld->first,{}}); + itOld++; + } else if (itOld->first > itNew->first) { + indexes.insert({itNew->first, itNew->second}); + itNew++; + } + } + + while (itOld != itOldEnd) { + indexes.insert({itOld->first,{}}); + itOld++; + } + + while (itNew != itNewEnd) { + indexes.insert({itNew->first, itNew->second}); + itNew++; + } + + return indexes; +} + +int Upgradeindexes(sqlite3 *db, const std::vector &tables, + const std::map &indexes) +{ + if (db == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + for (const auto &table : tables) { + for (const auto &index : indexes) { + if (index.first.empty()) { + continue; + } + std::string realIndexName = table + "_" + index.first; + std::string deleteIndexSql = "DROP INDEX IF EXISTS " + realIndexName; + errCode = SQLiteUtils::ExecuteRawSQL(db, deleteIndexSql); + if (errCode != E_OK) { + LOGE("Drop index failed. %d", errCode); + return errCode; + } + + if (index.second.empty()) { // empty means drop index only + continue; + } + + auto it = index.second.begin(); + std::string indexDefine = *it++; + while (it != index.second.end()) { + indexDefine += ", " + *it++; + } + std::string createIndexSql = "CREATE INDEX IF NOT EXISTS " + realIndexName + " ON " + table + + "(" + indexDefine + ");"; + errCode = SQLiteUtils::ExecuteRawSQL(db, createIndexSql); + if (errCode != E_OK) { + LOGE("Create index failed. %d", errCode); + break; + } + } + } + return errCode; +} +} + +int SQLiteSingleVerRelationalStorageExecutor::AlterAuxTableForUpgrade(const TableInfo &oldTableInfo, + const TableInfo &newTableInfo) +{ + std::vector upgradeFields = GetUpgradeFields(oldTableInfo, newTableInfo); + std::map upgradeIndexces = GetChangedIndexes(oldTableInfo, newTableInfo); + std::vector deviceTables; + int errCode = GetDeviceTableName(dbHandle_, oldTableInfo.GetTableName(), {}, deviceTables); + if (errCode != E_OK) { + LOGE("Get device table name for alter table failed. %d", errCode); + return errCode; + } + + LOGD("Begin to alter table: upgrade fields[%d], indexces[%d], deviceTable[%d]", upgradeFields.size(), + upgradeIndexces.size(), deviceTables.size()); + errCode = UpgradeFields(dbHandle_, deviceTables, upgradeFields); + if (errCode != E_OK) { + LOGE("upgrade fields failed. %d", errCode); + return errCode; + } + + errCode = Upgradeindexes(dbHandle_, deviceTables, upgradeIndexces); + if (errCode != E_OK) { + LOGE("upgrade indexes failed. %d", errCode); + } + + return E_OK; +} + int SQLiteSingleVerRelationalStorageExecutor::StartTransaction(TransactType type) { if (dbHandle_ == nullptr) { @@ -102,9 +323,10 @@ int SQLiteSingleVerRelationalStorageExecutor::Rollback() return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::SetTableInfo(const QueryObject &query) +int SQLiteSingleVerRelationalStorageExecutor::SetTableInfo(const std::string &baseTbl) { - int errCode = SQLiteUtils::AnalysisSchema(dbHandle_, query.GetTableName(), table_); + table_ = {}; + int errCode = SQLiteUtils::AnalysisSchema(dbHandle_, baseTbl, table_); if (errCode != E_OK) { LOGE("[CreateDistributedTable] analysis table schema failed"); } @@ -237,15 +459,7 @@ static int GetLogData(sqlite3_stmt *logStatement, LogInfo &logInfo) logInfo.wTimeStamp = static_cast(sqlite3_column_int64(logStatement, 4)); // 4 means w_timestamp index logInfo.flag = static_cast(sqlite3_column_int64(logStatement, 5)); // 5 means flag index logInfo.flag &= (~DataItem::LOCAL_FLAG); - - std::vector hashKey; - errCode = SQLiteUtils::GetColumnBlobValue(logStatement, 6, hashKey); // 6 means hashKey index - if (errCode != E_OK) { - return errCode; - } - - logInfo.hashKey = std::string(hashKey.begin(), hashKey.end()); - return errCode; + return SQLiteUtils::GetColumnBlobValue(logStatement, 6, logInfo.hashKey); // 6 means hashKey index } static size_t GetDataItemSerialSize(DataItem &item, size_t appendLen) @@ -427,37 +641,15 @@ int SQLiteSingleVerRelationalStorageExecutor::PrepareForSavingLog(const QueryObj int SQLiteSingleVerRelationalStorageExecutor::PrepareForSavingData(const QueryObject &object, const std::string &deviceName, sqlite3_stmt *&statement) const { - // naturalbase_rdb_aux_userTableName_deviceHash - // tableName - std::string devName = DBCommon::TransferHashString(deviceName); - const std::string tableName = DBConstant::RELATIONAL_PREFIX + object.GetTableName() + "_" + - DBCommon::TransferStringToHex(devName); - TableInfo table; - int errCode = SQLiteUtils::AnalysisSchema(dbHandle_, tableName, table); - if (errCode == -E_NOT_FOUND) { - errCode = SQLiteUtils::CreateSameStuTable(dbHandle_, object.GetTableName(), tableName, false); - if (errCode == E_OK) { - errCode = SQLiteUtils::CloneIndexes(dbHandle_, object.GetTableName(), tableName); - } - } - - if (errCode != E_OK) { - LOGE("[PrepareForSavingData] analysis table schema failed"); - return errCode; - } - - std::string colName; + const std::string tableName = DBCommon::GetDistributedTableName(deviceName, object.GetTableName()); std::string dataFormat; - const std::map fields = table_.GetFields(); - for (const auto &field : fields) { - colName += field.first + ","; + for (size_t i = 0; i < table_.GetFields().size(); ++i) { dataFormat += "?,"; } - colName.pop_back(); dataFormat.pop_back(); - std::string sql = "INSERT OR REPLACE INTO " + tableName + " (" + colName + ") VALUES (" + dataFormat + ");"; - errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); + std::string sql = "INSERT OR REPLACE INTO " + tableName + " VALUES (" + dataFormat + ");"; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); if (errCode != E_OK) { LOGE("[info statement] Get statement fail!"); errCode = -E_INVALID_QUERY_FORMAT; @@ -466,11 +658,8 @@ int SQLiteSingleVerRelationalStorageExecutor::PrepareForSavingData(const QueryOb } int SQLiteSingleVerRelationalStorageExecutor::SaveSyncLog(sqlite3_stmt *statement, const DataItem &dataItem, - TimeStamp &maxTimestamp) + TimeStamp &maxTimestamp, int64_t rowid) { - Key hashKey; - (void)DBCommon::CalcValueHash(dataItem.key, hashKey); - std::string hash = std::string(hashKey.begin(), hashKey.end()); std::string sql = "select * from " + DBConstant::RELATIONAL_PREFIX + table_.GetTableName() + "_log where hash_key = ?;"; sqlite3_stmt *queryStmt = nullptr; @@ -479,11 +668,15 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncLog(sqlite3_stmt *statemen LOGE("[info statement] Get statement fail!"); return -E_INVALID_QUERY_FORMAT; } - SQLiteUtils::BindTextToStatement(queryStmt, 1, hash); + errCode = SQLiteUtils::BindBlobToStatement(queryStmt, 1, dataItem.hashKey); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(queryStmt, true, errCode); + return errCode; + } LogInfo logInfoGet; errCode = SQLiteUtils::StepWithRetry(queryStmt, isMemDb_); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { errCode = -E_NOT_FOUND; } else { errCode = GetLogData(queryStmt, logInfoGet); @@ -491,11 +684,9 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncLog(sqlite3_stmt *statemen SQLiteUtils::ResetStatement(queryStmt, true, errCode); LogInfo logInfoBind; - std::string key = std::string(dataItem.key.begin(), dataItem.key.end()); - logInfoBind.hashKey = hash; + logInfoBind.hashKey = dataItem.hashKey; logInfoBind.device = dataItem.dev; logInfoBind.timestamp = dataItem.timeStamp; - int dataKeyBind = -1; logInfoBind.flag = dataItem.flag; logInfoBind.wTimeStamp = maxTimestamp; @@ -509,13 +700,13 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncLog(sqlite3_stmt *statemen } // bind - SQLiteUtils::BindInt64ToStatement(statement, 1, dataKeyBind); // 1 means dataKey index + SQLiteUtils::BindInt64ToStatement(statement, 1, rowid); // 1 means dataKey index std::vector originDev(logInfoBind.originDev.begin(), logInfoBind.originDev.end()); SQLiteUtils::BindBlobToStatement(statement, 2, originDev); // 2 means ori_dev index SQLiteUtils::BindInt64ToStatement(statement, 3, logInfoBind.timestamp); // 3 means timestamp index SQLiteUtils::BindInt64ToStatement(statement, 4, logInfoBind.wTimeStamp); // 4 means w_timestamp index SQLiteUtils::BindInt64ToStatement(statement, 5, logInfoBind.flag); // 5 means flag index - SQLiteUtils::BindTextToStatement(statement, 6, logInfoBind.hashKey); // 6 means hashKey index + SQLiteUtils::BindBlobToStatement(statement, 6, logInfoBind.hashKey); // 6 means hashKey index errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { return E_OK; @@ -525,18 +716,26 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncLog(sqlite3_stmt *statemen int SQLiteSingleVerRelationalStorageExecutor::DeleteSyncDataItem(const DataItem &dataItem) { - std::string devName = DBCommon::TransferHashString(dataItem.dev); - const std::string tableName = DBConstant::RELATIONAL_PREFIX + table_.GetTableName() + "_" + - DBCommon::TransferStringToHex(devName); - std::string hashKey = std::string(dataItem.hashKey.begin(), dataItem.hashKey.end()); - std::string sql = "DELETE FROM " + tableName + " WHERE calc_hash(" + table_.GetPrimaryKey() + ")=" + hashKey + ";"; + const std::string tableName = DBCommon::GetDistributedTableName(dataItem.dev, table_.GetTableName()); + const std::string sql = "DELETE FROM " + tableName + " WHERE rowid IN (" + "SELECT data_key FROM " + DBConstant::RELATIONAL_PREFIX + table_.GetTableName() + "_log " + "WHERE hash_key=? AND device=? AND flag&0x01=0);"; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); if (errCode != E_OK) { LOGE("[info statement] Get statement fail!"); return -E_INVALID_QUERY_FORMAT; } - + errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, dataItem.hashKey); // 1 means hash_key index + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; + } + errCode = SQLiteUtils::BindTextToStatement(stmt, 2, dataItem.dev); // 2 means device index + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; + } errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb_); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { errCode = E_OK; @@ -545,7 +744,8 @@ int SQLiteSingleVerRelationalStorageExecutor::DeleteSyncDataItem(const DataItem return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItem(sqlite3_stmt *statement, const DataItem &dataItem) +int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItem(sqlite3_stmt *statement, const DataItem &dataItem, + int64_t &rowid) { if ((dataItem.flag & DataItem::DELETE_FLAG) != 0) { return DeleteSyncDataItem(dataItem); @@ -578,6 +778,7 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItem(sqlite3_stmt *sta errCode = SQLiteUtils::StepWithRetry(statement, isMemDb_); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + rowid = SQLiteUtils::GetLastRowId(dbHandle_); errCode = E_OK; } return errCode; @@ -586,6 +787,10 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItem(sqlite3_stmt *sta int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItems(const QueryObject &object, std::vector &dataItems, const std::string &deviceName, TimeStamp &maxTimestamp) { + const auto &baseTbl = object.GetTableName(); + if (!table_.IsValid() || table_.GetTableName() != baseTbl) { + SetTableInfo(baseTbl); + } sqlite3_stmt *statement = nullptr; int errCode = PrepareForSavingData(object, deviceName, statement); if (errCode != E_OK) { @@ -604,14 +809,18 @@ int SQLiteSingleVerRelationalStorageExecutor::SaveSyncDataItems(const QueryObjec if (item.neglect) { // Do not save this record if it is neglected continue; } - errCode = SaveSyncDataItem(statement, item); + + item.dev = deviceName; + int64_t rowid = -1; + errCode = SaveSyncDataItem(statement, item, rowid); if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("Save sync dataitem failed:%d.", errCode); break; } - item.dev = deviceName; - errCode = SaveSyncLog(logStmt, item, maxTimestamp); + errCode = SaveSyncLog(logStmt, item, maxTimestamp, rowid); if (errCode != E_OK) { + LOGE("Save sync log failed:%d.", errCode); break; } maxTimestamp = std::max(item.timeStamp, maxTimestamp); @@ -659,7 +868,6 @@ int SQLiteSingleVerRelationalStorageExecutor::GetDataItemForSync(sqlite3_stmt *s for (const auto &col: table_.GetFields()) { auto colType = col.second.GetStorageType(); auto colId = col.second.GetColumnId() + 7; // 7 means the count of log table's column. - LOGD("[GetDataItemForSync] field:%s type:%d cid:%d", col.second.GetFieldName().c_str(), colType, colId); DataValue value; errCode = GetDataValueByType(stmt, value, colType, colId); if (errCode != E_OK) { @@ -678,8 +886,12 @@ int SQLiteSingleVerRelationalStorageExecutor::GetDataItemForSync(sqlite3_stmt *s } int SQLiteSingleVerRelationalStorageExecutor::GetSyncDataByQuery(std::vector &dataItems, size_t appendLength, - const DataSizeSpecInfo &dataSizeInfo, std::function getStmt) + const DataSizeSpecInfo &dataSizeInfo, std::function getStmt, + const std::string &baseTbl) { + if (!table_.IsValid() || table_.GetTableName() != baseTbl) { + SetTableInfo(baseTbl); + } sqlite3_stmt *stmt = nullptr; bool isGettingDeletedData = false; int errCode = getStmt(dbHandle_, stmt, isGettingDeletedData); @@ -702,6 +914,11 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncDataByQuery(std::vector DBConstant::MAX_VALUE_SIZE) { + continue; + } + // If dataTotalSize value is bigger than blockSize value , reserve the surplus data item. dataTotalSize += GetDataItemSerialSize(item, appendLength); if ((dataTotalSize > dataSizeInfo.blockSize && !dataItems.empty()) || @@ -721,11 +938,151 @@ int SQLiteSingleVerRelationalStorageExecutor::CheckDBModeForRelational() { std::string journalMode; int errCode = SQLiteUtils::GetJournalMode(dbHandle_, journalMode); - if (errCode != E_OK || journalMode != "wal") { - LOGE("Not support journal mode %s for relational db, expect wal mode, %d", journalMode.c_str(), errCode); + + for (auto &c : journalMode) { // convert to lowercase + c = static_cast(std::tolower(c)); + } + + if (errCode == E_OK && journalMode != "wal") { + LOGE("Not support journal mode %s for relational db, expect wal mode.", journalMode.c_str()); return -E_NOT_SUPPORT; } - return E_OK; + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::DeleteDistributedDeviceTable(const std::string &device, + const std::string &tableName) +{ + std::vector deviceTables; + int errCode = GetDeviceTableName(dbHandle_, tableName, device, deviceTables); + if (errCode != E_OK) { + LOGE("Get device table name for alter table failed. %d", errCode); + return errCode; + } + + LOGD("Begin to delete device table: deviceTable[%d]", deviceTables.size()); + for (const auto &table : deviceTables) { + std::string deleteSql = "DROP TABLE IF EXISTS " + table + ";"; // drop the found table + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, deleteSql); + if (errCode != E_OK) { + LOGE("Delete device data failed. %d", errCode); + break; + } + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::DeleteDistributedLogTable(const std::string &tableName) +{ + if (tableName.empty()) { + return -E_INVALID_ARGS; + } + std::string logTableName = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; + std::string deleteSql = "DROP TABLE IF EXISTS " + logTableName + ";"; + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, deleteSql); + if (errCode != E_OK) { + LOGE("Delete distributed log table failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CheckAndCleanDistributedTable(const std::vector &tableNames, + std::vector &missingTables) +{ + if (tableNames.empty()) { + return E_OK; + } + const std::string checkSql = "SELECT name FROM sqlite_master WHERE type='table' AND name=?;"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, checkSql, stmt); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; + } + for (const auto &tableName : tableNames) { + errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName); // 1: tablename bind index + if (errCode != E_OK) { + LOGE("Bind table name to check distributed table statement failed. %d", errCode); + break; + } + + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // The table in schema was dropped + errCode = DeleteDistributedDeviceTable({}, tableName); // Clean the auxiliary tables for the dropped table + if (errCode != E_OK) { + LOGE("Delete device tables for missing distributed table failed. %d", errCode); + break; + } + errCode = DeleteDistributedLogTable(tableName); + if (errCode != E_OK) { + LOGE("Delete log tables for missing distributed table failed. %d", errCode); + break; + } + missingTables.emplace_back(tableName); + } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("Check distributed table failed. %s", errCode); + break; + } + errCode = E_OK; // Check result ok for distributed table is still exists + SQLiteUtils::ResetStatement(stmt, false, errCode); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + return CheckCorruptedStatus(errCode); +} + +int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedDeviceTable(const std::string &device, + const TableInfo &baseTbl) +{ + if (dbHandle_ == nullptr) { + return -E_INVALID_DB; + } + + if (device.empty() || !baseTbl.IsValid()) { + return -E_INVALID_ARGS; + } + + std::string deviceTableName = DBCommon::GetDistributedTableName(device, baseTbl.GetTableName()); + int errCode = SQLiteUtils::CreateSameStuTable(dbHandle_, baseTbl, deviceTableName); + if (errCode != E_OK) { + LOGE("Create device table failed. %d", errCode); + return errCode; + } + + errCode = SQLiteUtils::CloneIndexes(dbHandle_, baseTbl.GetTableName(), deviceTableName); + if (errCode != E_OK) { + LOGE("Copy index to device table failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CheckQueryObjectLegal(const TableInfo &table, QueryObject &query) +{ + if (dbHandle_ == nullptr) { + return -E_INVALID_DB; + } + + int errCode = E_OK; + SqliteQueryHelper helper = query.GetQueryHelper(errCode); + if (errCode != E_OK) { + LOGE("Get query helper for check query failed. %d", errCode); + return errCode; + } + + SyncTimeRange defaultTimeRange; + sqlite3_stmt *stmt = nullptr; + errCode = helper.GetRelationalQueryStatement(dbHandle_, defaultTimeRange.beginTime, defaultTimeRange.endTime, stmt); + if (errCode != E_OK) { + LOGE("Get query statement for check query failed. %d", errCode); + return errCode; + } + + errCode = SQLiteUtils::CheckSchemaChanged(stmt, table, DBConstant::RELATIONAL_LOG_TABLE_FIELD_NUM); + if (errCode != E_OK) { + LOGE("Check schema failed, schema was changed. %d", errCode); + } + + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; } } // namespace DistributedDB #endif diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h index ba0057ae17186556081e6f0c12097512a8692b0b..0bfa02f725f0943ab3cbe9dffff02d1945811346 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h @@ -35,15 +35,15 @@ public: int CreateDistributedTable(const std::string &tableName, TableInfo &table); + int UpgradeDistributedTable(const TableInfo &tableInfo, TableInfo &newTableInfo); + int StartTransaction(TransactType type); int Commit(); int Rollback(); - int SetTableInfo(const QueryObject &query); - // For Get sync data - int GetSyncDataByQuery(std::vector &dataItems, size_t appendLength, - const DataSizeSpecInfo &dataSizeInfo, std::function getStmt); + int GetSyncDataByQuery(std::vector &dataItems, size_t appendLength, const DataSizeSpecInfo &dataSizeInfo, + std::function getStmt, const std::string &baseTbl); // operation of meta data int GetKvData(const Key &key, Value &value) const; @@ -60,6 +60,16 @@ public: int CheckDBModeForRelational(); + int DeleteDistributedDeviceTable(const std::string &device, const std::string &tableName); + int DeleteDistributedLogTable(const std::string &tableName); + + int CheckAndCleanDistributedTable(const std::vector &tableNames, + std::vector &missingTables); + + int CreateDistributedDeviceTable(const std::string &device, const TableInfo &baseTbl); + + int CheckQueryObjectLegal(const TableInfo &table, QueryObject &query); + private: int PrepareForSyncDataByTime(TimeStamp begin, TimeStamp end, sqlite3_stmt *&statement, bool getDeletedData) const; @@ -68,14 +78,18 @@ private: int SaveSyncDataItems(const QueryObject &object, std::vector &dataItems, const std::string &deviceName, TimeStamp &timeStamp); - int SaveSyncDataItem(sqlite3_stmt *statement, const DataItem &dataItem); + int SaveSyncDataItem(sqlite3_stmt *statement, const DataItem &dataItem, int64_t &rowid); int DeleteSyncDataItem(const DataItem &dataItem); - int SaveSyncLog(sqlite3_stmt *statement, const DataItem &dataItem, TimeStamp &maxTimestamp); + int SaveSyncLog(sqlite3_stmt *statement, const DataItem &dataItem, TimeStamp &maxTimestamp, int64_t rowid); int PrepareForSavingData(const QueryObject &object, const std::string &deviceName, sqlite3_stmt *&statement) const; int PrepareForSavingLog(const QueryObject &object, const std::string &deviceName, sqlite3_stmt *&statement) const; + int AlterAuxTableForUpgrade(const TableInfo &oldTableInfo, const TableInfo &newTableInfo); + + int SetTableInfo(const std::string &baseTbl); + TableInfo table_; }; } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index e44a5572708d6486c2a6174474c71804158da0f0..df7ecaecb084723bb3a1096eab8f43f776e588f3 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -31,6 +31,7 @@ #include "log_print.h" #include "value_object.h" #include "schema_utils.h" +#include "schema_constant.h" #include "time_helper.h" #include "platform_specific.h" @@ -613,7 +614,8 @@ int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, Table table.AddTrigger(triggerName); } } else { - LOGW("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err); + LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err); + errCode = SQLiteUtils::MapSQLiteErrno(err); break; } } while (true); @@ -628,7 +630,7 @@ int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector -static std::string string_format(const std::string& format, Args ... args) +namespace { +std::string GetInsertTrigger(const TableInfo table) +{ + std::string insertTrigger = "CREATE TRIGGER IF NOT EXISTS "; + insertTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_INSERT AFTER INSERT \n"; + insertTrigger += "ON " + table.GetTableName() + "\n"; + insertTrigger += "BEGIN\n"; + insertTrigger += "\t INSERT OR REPLACE INTO "; + insertTrigger += DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; + insertTrigger += " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key)"; + insertTrigger += " VALUES (new.rowid, '" + table.GetDevId() + "', '" + table.GetDevId() + "',"; + insertTrigger += " get_sys_time(0), get_sys_time(0), 0x02,"; + insertTrigger += " calc_hash(new." + table.GetPrimaryKey() + "));\n"; + insertTrigger += "END;"; + return insertTrigger; +} + +std::string GetUpdateTrigger(const TableInfo table) { - auto size = static_cast(1024); // trigger string total len need < 1024 - auto buf = std::make_unique(size); - (void)sprintf_s(buf.get(), size, format.c_str(), args ...); - return std::string(buf.get(), buf.get() + size - 1); // We don't want the '\0' inside + std::string updateTrigger = "CREATE TRIGGER IF NOT EXISTS "; + updateTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_UPDATE AFTER UPDATE \n"; + updateTrigger += "ON " + table.GetTableName() + "\n"; + updateTrigger += "BEGIN\n"; + updateTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; + updateTrigger += " SET timestamp=get_sys_time(0), device='" + table.GetDevId() + "'"; + updateTrigger += " where hash_key=calc_hash(old." + table.GetPrimaryKey() + ") and flag&0x02=0x02;\n"; + updateTrigger += "END;"; + return updateTrigger; +} + +std::string GetDeleteTrigger(const TableInfo table) +{ + std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS "; + deleteTrigger += "naturalbase_rdb_" + table.GetTableName() + "_ON_DELETE BEFORE DELETE \n"; + deleteTrigger += "ON " + table.GetTableName() + "\n"; + deleteTrigger += "BEGIN\n"; + deleteTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; + deleteTrigger += " SET flag=0x03,timestamp=get_sys_time(0)"; + deleteTrigger += " where hash_key=calc_hash(old." + table.GetPrimaryKey() + ") and flag&0x02=0x02;\n"; + deleteTrigger += "END;"; + return deleteTrigger; +} } int SQLiteUtils::AddRelationalLogTableTrigger(sqlite3 *db, const TableInfo &table) { - std::string insertTrigger = - "CREATE TRIGGER IF NOT EXISTS naturalbase_rdb_%s_ON_INSERT AFTER INSERT \n" \ - "ON %s\n" \ - "BEGIN\n" \ - "\t INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "%s_log \ - (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key)" \ - "VALUES (new.rowid, '%s', '%s', get_sys_time(), get_sys_time(), 0x02, calc_hash(new.%s));\n" \ - "END;"; - insertTrigger = string_format(insertTrigger, table.GetTableName().c_str(), table.GetTableName().c_str(), - table.GetTableName().c_str(), table.GetDevId().c_str(), - table.GetDevId().c_str(), table.GetPrimaryKey().c_str()); - std::string updateTrigger = - "CREATE TRIGGER IF NOT EXISTS naturalbase_rdb_%s_ON_UPDATE AFTER UPDATE \n" \ - "ON %s\n" \ - "BEGIN\n" \ - "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + "%s_log SET timestamp=get_sys_time(), device='%s' \ - where hash_key=calc_hash(old.%s) and flag&0x10=0;\n" \ - "END;"; - updateTrigger = string_format(updateTrigger, table.GetTableName().c_str(), table.GetTableName().c_str(), - table.GetTableName().c_str(), table.GetDevId().c_str(), table.GetPrimaryKey().c_str()); - std::string deleteTrigger = - "CREATE TRIGGER IF NOT EXISTS naturalbase_rdb_%s_ON_DELETE BEFORE DELETE \n" \ - "ON %s\n" \ - "BEGIN\n" \ - "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + "%s_log set flag=0x03,timestamp=get_sys_time() \ - WHERE hash_key=calc_hash(old.%s);\n" \ - "END;"; - deleteTrigger = string_format(deleteTrigger, table.GetTableName().c_str(), - table.GetTableName().c_str(), table.GetTableName().c_str(), table.GetPrimaryKey().c_str()); - - std::vector sqls = {insertTrigger, updateTrigger, deleteTrigger}; - // add insert trigger - // add update trigger - // add delete trigger + std::vector sqls = {GetInsertTrigger(table), GetUpdateTrigger(table), GetDeleteTrigger(table)}; + // add insert,update,delete trigger for (const auto &sql : sqls) { int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); if (errCode != E_OK) { @@ -1392,14 +1380,26 @@ int SQLiteUtils::AddRelationalLogTableTrigger(sqlite3 *db, const TableInfo &tabl return E_OK; } -int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName, - bool isCopyData) +int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName) { - std::string sql = "create table IF NOT EXISTS " + newTableName + " as select * from " + oriTableName; - if (!isCopyData) { - sql += " where 1=0 "; + std::string sql = "CREATE TABLE IF NOT EXISTS " + newTableName + "("; + const std::map &fields = baseTbl.GetFields(); + for (uint32_t cid = 0; cid < fields.size(); ++cid) { + std::string fieldName = baseTbl.GetFieldName(cid); + sql += fieldName + " " + fields.at(fieldName).GetDataType(); + if (fields.at(fieldName).IsNotNull()) { + sql += " NOT NULL"; + } + if (fields.at(fieldName).HasDefaultValue()) { + sql += " DEFAULT " + fields.at(fieldName).GetDefaultValue(); + } + if (fieldName == baseTbl.GetPrimaryKey()) { + sql += " PRIMARY KEY"; + } + sql += ","; } - sql += ";"; + sql.pop_back(); + sql += ");"; int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); if (errCode != E_OK) { LOGE("[SQLite] execute create table sql failed"); @@ -1410,7 +1410,7 @@ int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const std::string &oriTableName int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName) { std::string sql = - "SELECT 'CREATE ' || CASE WHEN il.'unique' THEN 'UNIQUE ' ELSE '' END || 'INDEX ' || '" + + "SELECT 'CREATE ' || CASE WHEN il.'unique' THEN 'UNIQUE ' ELSE '' END || 'INDEX IF NOT EXISTS ' || '" + newTableName + "_' || il.name || ' ON ' || '" + newTableName + "' || '(' || GROUP_CONCAT(ii.name) || ');' " "FROM sqlite_master AS m," @@ -1421,7 +1421,7 @@ int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, cons sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, sql, stmt); if (errCode != E_OK) { - LOGE("[AnalysisSchema] Prepare the clone sql failed:%d", errCode); + LOGE("Prepare the clone sql failed:%d", errCode); return errCode; } @@ -1429,8 +1429,9 @@ int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, cons while (true) { errCode = SQLiteUtils::StepWithRetry(stmt, false); if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - const unsigned char *indexSql = sqlite3_column_text(stmt, 0); - sql += std::string(reinterpret_cast(indexSql)); + std::string indexSql; + (void)GetColumnTextValue(stmt, 0, indexSql); + sql += indexSql; continue; } if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { @@ -1443,7 +1444,6 @@ int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, cons if (errCode != E_OK) { return errCode; } - errCode = SQLiteUtils::ExecuteRawSQL(db, sql); if (errCode != E_OK) { LOGE("[SQLite] execute create table sql failed"); @@ -1733,10 +1733,10 @@ void SQLiteUtils::FlatBufferExtractByPath(sqlite3_context *ctx, int argc, sqlite namespace { constexpr uint32_t FLATBUFFER_MAX_CACHE_SIZE = 102400; // 100 KBytes -void FlatBufferCacheFree(std::vector *inCahce) +void FlatBufferCacheFree(std::vector *inCache) { - delete inCahce; - inCahce = nullptr; + delete inCache; + inCache = nullptr; } } @@ -1744,7 +1744,7 @@ void SQLiteUtils::FlatBufferExtractInnerFunc(sqlite3_context *ctx, const SchemaO RawString inPath) { // All parameter had already been check inside FlatBufferExtractByPath, only called by FlatBufferExtractByPath - if (schema.GetSkipSize() % SECURE_BYTE_ALIGN == 0) { + if (schema.GetSkipSize() % SchemaConstant::SECURE_BYTE_ALIGN == 0) { TypeValue outExtract; int errCode = schema.ExtractValue(ValueSource::FROM_DBFILE, inPath, inValue, outExtract, nullptr); if (errCode != E_OK) { @@ -2054,4 +2054,54 @@ int SQLiteUtils::CheckTableEmpty(sqlite3 *db, const std::string &tableName, bool SQLiteUtils::ResetStatement(stmt, true, errCode); return SQLiteUtils::MapSQLiteErrno(errCode); } + +int SQLiteUtils::SetPersistWalMode(sqlite3 *db) +{ + if (db == nullptr) { + return -E_INVALID_ARGS; + } + int opCode = 1; + int errCode = sqlite3_file_control(db, "main", SQLITE_FCNTL_PERSIST_WAL, &opCode); + if (errCode != SQLITE_OK) { + LOGE("Set persist wal mode failed. %d", errCode); + } + return SQLiteUtils::MapSQLiteErrno(errCode); +} + +int SQLiteUtils::CheckSchemaChanged(sqlite3_stmt *stmt, const TableInfo &table, int offset) +{ + if (stmt == nullptr) { + return -E_INVALID_ARGS; + } + + int columnNum = sqlite3_column_count(stmt); + if (columnNum - offset != static_cast(table.GetFields().size())) { + LOGE("Schema field number does not match."); + return -E_DISTRIBUTED_SCHEMA_CHANGED; + } + + auto fields = table.GetFields(); + for (int i = offset; i < columnNum; i++) { + const char *name = sqlite3_column_name(stmt, i); + std::string colName = (name == nullptr) ? std::string() : name; + const char *declType = sqlite3_column_decltype(stmt, i); + std::string colType = (declType == nullptr) ? std::string() : declType; + transform(colType.begin(), colType.end(), colType.begin(), ::tolower); + + auto it = fields.find(colName); + if (it == fields.end() || it->second.GetDataType() != colType) { + LOGE("Schema field define does not match."); + return -E_DISTRIBUTED_SCHEMA_CHANGED; + } + } + return E_OK; +} + +int64_t SQLiteUtils::GetLastRowId(sqlite3 *db) +{ + if (db == nullptr) { + return -1; + } + return sqlite3_last_insert_rowid(db); +} } // namespace DistributedDB \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index ea6478b62655c9191eb4c97e37627ffd49947363..eca6422802d54d442c8e5b273c003559c9bebbb0 100755 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -22,7 +22,7 @@ #include "db_types.h" #include "schema_object.h" -#include "types.h" +#include "store_types.h" #ifdef RELATIONAL_STORE #include "relational_schema_object.h" #endif @@ -37,7 +37,7 @@ struct TransactFunc { void (*xFunc)(sqlite3_context*, int, sqlite3_value**) = nullptr; void (*xStep)(sqlite3_context*, int, sqlite3_value**) = nullptr; void (*xFinal)(sqlite3_context*) = nullptr; - void(*xDestroy)(void*) = nullptr; + void (*xDestroy)(void*) = nullptr; }; namespace TriggerMode { @@ -118,8 +118,6 @@ public: static int GetJournalMode(sqlite3 *db, std::string &mode); - static int GetSynchronousMode(sqlite3 *db, int &mode); - static int SetUserVer(const OpenDbProperties &properties, int version); static int SetUserVer(sqlite3 *db, int version); @@ -169,8 +167,7 @@ public: static int AddRelationalLogTableTrigger(sqlite3 *db, const TableInfo &table); static int AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table); - static int CreateSameStuTable(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName, - bool isCopyData); + static int CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableNames); static int CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName); #endif @@ -182,6 +179,12 @@ public: static int CheckTableEmpty(sqlite3 *db, const std::string &tableName, bool &isEmpty); + static int SetPersistWalMode(sqlite3 *db); + + static int CheckSchemaChanged(sqlite3_stmt *stmt, const TableInfo &table, int offset); + + static int64_t GetLastRowId(sqlite3 *db); + private: static int CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal); diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.cpp b/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.cpp index 66c4735c4d2734d99503bde8fe357494a7a19f49..da5c9b02dd8cc15d87f40c2392ae9d84ee92b810 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.cpp +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.cpp @@ -86,12 +86,12 @@ uint64_t SyncAbleEngine::GetTimeStamp() return syncer_.GetTimeStamp(); } -int SyncAbleEngine::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) +int SyncAbleEngine::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName) { if (!started_) { StartSyncer(); } - return syncer_.EraseDeviceWaterMark(deviceId, isNeedHash); + return syncer_.EraseDeviceWaterMark(deviceId, isNeedHash, tableName); } // Start syncer diff --git a/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.h b/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.h index 08e2120303c4f149f984c0cc4e5195ddb9f4be85..e43d5194b661284e9b79703070e621f80a55ec92 100644 --- a/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.h +++ b/services/distributeddataservice/libs/distributeddb/storage/src/sync_able_engine.h @@ -46,7 +46,7 @@ public: // Get The current virtual timestamp uint64_t GetTimeStamp(); - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash); + int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName = ""); int GetLocalIdentity(std::string &outTarget); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/include/isyncer.h b/services/distributeddataservice/libs/distributeddb/syncer/include/isyncer.h index fe177b5d36d6047a40b15b9bd7331180c2956ac5..3adf6e63e76a90f3c8a3fbf929f1ae62553d345f 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/include/isyncer.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/include/isyncer.h @@ -23,7 +23,7 @@ #include "isync_interface.h" #include "types_export.h" #include "query_sync_object.h" -#include "types.h" +#include "store_types.h" namespace DistributedDB { class ISyncer { @@ -75,7 +75,8 @@ public: virtual void EnableAutoSync(bool enable) = 0; // delete specified device's watermark - virtual int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) = 0; + virtual int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, + const std::string &tableName = "") = 0; // Local data changed callback virtual void LocalDataChanged(int notifyEvent) = 0; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/include/sync_config.h b/services/distributeddataservice/libs/distributeddb/syncer/include/sync_config.h index 2d342a53b8693dcb28972e80dfc98861264912d4..aff11c4a70891f7280286395f798cfd49a6c2dcb 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/include/sync_config.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/include/sync_config.h @@ -34,10 +34,15 @@ current ability format: |DATABASE_COMPRESSION_ZLIB|ALLPREDICATEQUERY|SUBSCRIBEQUERY| */ constexpr AbilityItem DATABASE_COMPRESSION_ZLIB = {0, 1}; -constexpr AbilityItem ALLPREDICATEQUERY = {1, 1}; // offset: 0 + 1 -constexpr AbilityItem SUBSCRIBEQUERY = {2, 1}; // // offset: 1 + 1 +constexpr AbilityItem ALLPREDICATEQUERY = {1, 1}; // 0b10 {1: start at second bit, 1: 1 bit len} +constexpr AbilityItem SUBSCRIBEQUERY = {2, 1}; // 0b100 +constexpr AbilityItem INKEYS_QUERY = {3, 1}; // 0b1000 -const std::vector ABILITYBITS = {DATABASE_COMPRESSION_ZLIB, ALLPREDICATEQUERY, SUBSCRIBEQUERY}; +const std::vector ABILITYBITS = { + DATABASE_COMPRESSION_ZLIB, + ALLPREDICATEQUERY, + SUBSCRIBEQUERY, + INKEYS_QUERY}; const std::map COMPRESSALGOMAP = { {static_cast(CompressAlgorithm::ZLIB), DATABASE_COMPRESSION_ZLIB}, diff --git a/services/distributeddataservice/libs/distributeddb/syncer/include/syncer_proxy.h b/services/distributeddataservice/libs/distributeddb/syncer/include/syncer_proxy.h index b2b698e6e24de034228a9958989509d61dbac82b..52be0f72a07fc3557baa02ba5343b0221002091b 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/include/syncer_proxy.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/include/syncer_proxy.h @@ -60,7 +60,8 @@ public: void EnableAutoSync(bool enable) override; // delete specified device's watermark - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) override; + int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, + const std::string &tableName = "") override; // Local data changed callback void LocalDataChanged(int notifyEvent) override; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.cpp index f7a591fe378c8d638c94a7991090f32841cb9535..9e03dfef46e2fb339f1d8dd694be6a2f4f4c759e 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.cpp @@ -23,8 +23,10 @@ #include "db_common.h" #include "single_ver_kvdb_sync_interface.h" #include "single_ver_sync_task_context.h" +#include "single_ver_kv_sync_task_context.h" #ifdef RELATIONAL_STORE #include "relational_db_sync_interface.h" +#include "single_ver_relational_sync_task_context.h" #endif namespace DistributedDB { @@ -295,6 +297,7 @@ uint32_t AbilitySyncAckPacket::CalculateLen() const len += Parcel::GetUInt32Len(); // requirePeerConvert_ len += Parcel::GetUInt64Len(); // dbCreateTime_ len += DbAbility::CalculateLen(dbAbility_); // dbAbility_ + len += relationalSyncOpinion_.CalculateParcelLen(softwareVersion_); if (len > INT32_MAX) { LOGE("[AbilitySyncAckPacket][CalculateLen] err len:%llu", len); return 0; @@ -312,6 +315,16 @@ void AbilitySyncAckPacket::SetDbAbility(const DbAbility &dbAbility) dbAbility_ = dbAbility; } +void AbilitySyncAckPacket::SetRelationalSyncOpinion(const RelationalSyncOpinion &relationalSyncOpinion) +{ + relationalSyncOpinion_ = relationalSyncOpinion; +} + +RelationalSyncOpinion AbilitySyncAckPacket::GetRelationalSyncOpinion() const +{ + return relationalSyncOpinion_; +} + AbilitySync::AbilitySync() : communicator_(nullptr), storageInterface_(nullptr), @@ -387,8 +400,14 @@ int AbilitySync::AckRecv(const Message *message, ISyncTaskContext *context) std::string schema = packet->GetSchema(); if (remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_2_0) { HandleVersionV3AckSecOptionParam(packet, context); - SyncOpinion localSyncOpinion = HandleVersionV3AckSchemaParam(packet, schema, context); - bool permitSync = ((static_cast(context))->GetSyncStrategy()).permitSync; + AbilitySyncAckPacket ackPacket; + errCode = HandleVersionV3AckSchemaParam(packet, ackPacket, context, true); + if (errCode != E_OK) { + return errCode; + } + auto singleVerContext = static_cast(context); + auto query = singleVerContext->GetQuery(); + bool permitSync = (singleVerContext->GetSyncStrategy(query)).permitSync; if (!permitSync) { (static_cast(context))->SetTaskErrCode(-E_SCHEMA_MISMATCH); LOGE("[AbilitySync][AckRecv] scheme check failed"); @@ -403,13 +422,10 @@ int AbilitySync::AckRecv(const Message *message, ISyncTaskContext *context) } DbAbility remoteDbAbility = packet->GetDbAbility(); (static_cast(context))->SetDbAbility(remoteDbAbility); - SendAck(message, localSyncOpinion, AbilitySync::CHECK_SUCCESS, true); + (void)SendAck(message, AbilitySync::CHECK_SUCCESS, true, ackPacket); (static_cast(context))->SetIsSchemaSync(true); } else { - bool isCompatible = true; - if (IsSingleKvVer()) { - isCompatible = static_cast(storageInterface_)->CheckCompatible(schema); - } + bool isCompatible = static_cast(storageInterface_)->CheckCompatible(schema); if (!isCompatible) { (static_cast(context))->SetTaskErrCode(-E_SCHEMA_MISMATCH); LOGE("[AbilitySync][AckRecv] scheme check failed"); @@ -430,54 +446,21 @@ int AbilitySync::RequestRecv(const Message *message, ISyncTaskContext *context) if (packet == nullptr) { return -E_INVALID_ARGS; } - SyncOpinion localSyncOpinion; if (packet->GetSendCode() == -E_VERSION_NOT_SUPPORT) { - SendAck(message, localSyncOpinion, -E_VERSION_NOT_SUPPORT, false); + AbilitySyncAckPacket ackPacket; + (void)SendAck(message, -E_VERSION_NOT_SUPPORT, false, ackPacket); LOGI("[AbilitySync][RequestRecv] version can not support, remote version is %u", packet->GetProtocolVersion()); return -E_VERSION_NOT_SUPPORT; } std::string schema = packet->GetSchema(); - bool isCompatible = true; - if (IsSingleKvVer()) { - isCompatible = static_cast(storageInterface_)->CheckCompatible(schema); - } + bool isCompatible = static_cast(storageInterface_)->CheckCompatible(schema); if (!isCompatible) { (static_cast(context))->SetTaskErrCode(-E_SCHEMA_MISMATCH); } uint32_t remoteSoftwareVersion = packet->GetSoftwareVersion(); context->SetRemoteSoftwareVersion(remoteSoftwareVersion); - int ackCode; - if (remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_2_0) { - localSyncOpinion = HandleVersionV3RequestParam(packet, context, schema); - if (SecLabelCheck(packet)) { - ackCode = E_OK; - } else { - ackCode = -E_SECURITY_OPTION_CHECK_ERROR; - } - } else { - LOGI("[AbilitySync][RequestRecv] remote version = %u, CheckSchemaCompatible = %d", - remoteSoftwareVersion, isCompatible); - return SendAck(message, SchemaObject(), E_OK, localSyncOpinion, false); - } - if (ackCode == E_OK && remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_3_0) { - ackCode = metadata_->SetDbCreateTime(deviceId_, packet->GetDbCreateTime(), true); - } - LOGI("[AbilitySync][RequestRecv] remote dev=%s,ver=%u,schemaCompatible=%d", STR_MASK(deviceId_), - remoteSoftwareVersion, isCompatible); - return SendAck(message, localSyncOpinion, ackCode, false); -} - -int AbilitySync::SendAck(const Message *message, SyncOpinion &localSyncOpinion, int ackCode, bool isAckNotify) -{ -#ifdef RELATIONAL_STORE - if (IsSingleRelationalVer()) { - SchemaObject schemaObject; - return SendAck(message, schemaObject, ackCode, localSyncOpinion, isAckNotify); - } -#endif - SchemaObject schemaObject = static_cast(storageInterface_)->GetSchemaInfo(); - return SendAck(message, schemaObject, ackCode, localSyncOpinion, isAckNotify); + return HandleRequestRecv(message, context, isCompatible); } int AbilitySync::AckNotifyRecv(const Message *message, ISyncTaskContext *context) @@ -502,12 +485,17 @@ int AbilitySync::AckNotifyRecv(const Message *message, ISyncTaskContext *context std::string schema = packet->GetSchema(); uint32_t remoteSoftwareVersion = packet->GetSoftwareVersion(); context->SetRemoteSoftwareVersion(remoteSoftwareVersion); - SyncOpinion localSyncOpinion = HandleVersionV3AckSchemaParam(packet, schema, context); + AbilitySyncAckPacket sendPacket; + errCode = HandleVersionV3AckSchemaParam(packet, sendPacket, context, false); + int ackCode = errCode; LOGI("[AckNotifyRecv] receive dev = %s ack notify, remoteSoftwareVersion = %u, ackCode = %d", STR_MASK(deviceId_), remoteSoftwareVersion, errCode); - (static_cast(context))->SetIsSchemaSync(true); - (void)SendAck(message, SchemaObject(), AbilitySync::LAST_NOTIFY, localSyncOpinion, true); - return E_OK; + if (errCode == E_OK) { + (static_cast(context))->SetIsSchemaSync(true); + ackCode = AbilitySync::LAST_NOTIFY; + } + (void)SendAckWithEmptySchema(message, ackCode, true); + return errCode; } bool AbilitySync::GetAbilitySyncFinishedStatus() const @@ -546,27 +534,17 @@ bool AbilitySync::SecLabelCheck(const AbilitySyncRequestPacket *packet) const } } -SyncOpinion AbilitySync::HandleVersionV3RequestParam(const AbilitySyncRequestPacket *packet, ISyncTaskContext *context, +void AbilitySync::HandleVersionV3RequestParam(const AbilitySyncRequestPacket *packet, ISyncTaskContext *context, const std::string &remoteSchema) const { int32_t remoteSecLabel = packet->GetSecLabel(); int32_t remoteSecFlag = packet->GetSecFlag(); - SecurityOption secOption = {remoteSecLabel, remoteSecFlag}; DbAbility remoteDbAbility = packet->GetDbAbility(); (static_cast(context))->SetDbAbility(remoteDbAbility); - (static_cast(context))->SetRemoteSeccurityOption(secOption); + (static_cast(context))->SetRemoteSeccurityOption({remoteSecLabel, remoteSecFlag}); (static_cast(context))->SetReceivcPermitCheck(false); -#ifdef RELATIONAL_STORE - if (IsSingleRelationalVer()) { - return SyncOpinion{true, false, false}; - } -#endif - uint8_t remoteSchemaType = packet->GetSchemaType(); - SchemaObject localSchema = (static_cast(storageInterface_))->GetSchemaInfo(); - SyncOpinion localSyncOpinion = SchemaObject::MakeLocalSyncOpinion(localSchema, remoteSchema, remoteSchemaType); LOGI("[AbilitySync][HandleVersionV3RequestParam] remoteSecLabel = %d, remoteSecFlag = %d, remoteSchemaType = %u", - remoteSecLabel, remoteSecFlag, remoteSchemaType); - return localSyncOpinion; + remoteSecLabel, remoteSecFlag, packet->GetSchemaType()); } void AbilitySync::HandleVersionV3AckSecOptionParam(const AbilitySyncAckPacket *packet, @@ -580,26 +558,14 @@ void AbilitySync::HandleVersionV3AckSecOptionParam(const AbilitySyncAckPacket *p LOGI("[AbilitySync][AckRecv] remoteSecLabel = %d, remoteSecFlag = %d", remoteSecLabel, remoteSecFlag); } -SyncOpinion AbilitySync::HandleVersionV3AckSchemaParam(const AbilitySyncAckPacket *packet, - const std::string &remoteSchema, ISyncTaskContext *context) const +int AbilitySync::HandleVersionV3AckSchemaParam(const AbilitySyncAckPacket *recvPacket, + AbilitySyncAckPacket &sendPacket, ISyncTaskContext *context, bool sendOpinion) const { - bool permitSync = static_cast(packet->GetPermitSync()); - bool requirePeerConvert = static_cast(packet->GetRequirePeerConvert()); - SyncOpinion remoteOpinion = {permitSync, requirePeerConvert, true}; - uint8_t remoteSchemaType = packet->GetSchemaType(); -#ifdef RELATIONAL_STORE if (IsSingleRelationalVer()) { - auto localOpinion = SyncOpinion{true, false, false}; - SyncStrategy localStrategy = SchemaObject::ConcludeSyncStrategy(localOpinion, remoteOpinion); - (static_cast(context))->SetSyncStrategy(localStrategy); - return localOpinion; + return HandleRelationAckSchemaParam(recvPacket, sendPacket, context, sendOpinion); } -#endif - SchemaObject localSchema = (static_cast(storageInterface_))->GetSchemaInfo(); - SyncOpinion localOpinion = SchemaObject::MakeLocalSyncOpinion(localSchema, remoteSchema, remoteSchemaType); - SyncStrategy localStrategy = SchemaObject::ConcludeSyncStrategy(localOpinion, remoteOpinion); - (static_cast(context))->SetSyncStrategy(localStrategy); - return localOpinion; + HandleKvAckSchemaParam(recvPacket, context, sendPacket); + return E_OK; } void AbilitySync::GetPacketSecOption(SecurityOption &option) const @@ -698,44 +664,6 @@ int AbilitySync::DeSerialization(const uint8_t *buffer, uint32_t length, Message } } -#ifdef RELATIONAL_STORE -int AbilitySync::SendAck(const Message *inMsg, const ISchema &schemaObj, int ackCode, SyncOpinion localOpinion, - bool isAckNotify) -#else -int AbilitySync::SendAck(const Message *inMsg, const SchemaObject &schemaObj, int ackCode, SyncOpinion localOpinion, - bool isAckNotify) -#endif -{ - AbilitySyncAckPacket ackPacket; - int errCode = SetAbilityAckBodyInfo(ackPacket, schemaObj, ackCode, localOpinion, isAckNotify); - if (errCode != E_OK) { - return errCode; - } - Message *ackMessage = new (std::nothrow) Message(ABILITY_SYNC_MESSAGE); - if (ackMessage == nullptr) { - LOGE("[AbilitySync][SendAck] message create failed, may be memleak!"); - return -E_OUT_OF_MEMORY; - } - errCode = ackMessage->SetCopiedObject<>(ackPacket); - if (errCode != E_OK) { - LOGE("[AbilitySync][SendAck] SetCopiedObject failed, err %d", errCode); - delete ackMessage; - ackMessage = nullptr; - return errCode; - } - (!isAckNotify) ? ackMessage->SetMessageType(TYPE_RESPONSE) : ackMessage->SetMessageType(TYPE_NOTIFY); - ackMessage->SetTarget(deviceId_); - ackMessage->SetSessionId(inMsg->GetSessionId()); - ackMessage->SetSequenceId(inMsg->GetSequenceId()); - errCode = communicator_->SendMessage(deviceId_, ackMessage, false, SEND_TIME_OUT); - if (errCode != E_OK) { - LOGE("[AbilitySync][SendAck] SendPacket failed, err %d", errCode); - delete ackMessage; - ackMessage = nullptr; - } - return errCode; -} - int AbilitySync::RequestPacketCalculateLen(const Message *inMsg, uint32_t &len) { const AbilitySyncRequestPacket *packet = inMsg->GetObject(); @@ -803,6 +731,10 @@ int AbilitySync::AckPacketSerialization(uint8_t *buffer, uint32_t length, const if (parcel.IsError() || errCode != E_OK) { return -E_PARSE_FAIL; } + errCode = packet->GetRelationalSyncOpinion().SerializeData(parcel, SOFTWARE_VERSION_CURRENT); + if (parcel.IsError() || errCode != E_OK) { + return -E_PARSE_FAIL; + } return E_OK; } @@ -915,6 +847,13 @@ int AbilitySync::AckPacketDeSerializationTailPart(Parcel &parcel, AbilitySyncAck return errCode; } packet->SetDbAbility(remoteDbAbility); + RelationalSyncOpinion relationalSyncOpinion; + errCode = RelationalSyncOpinion::DeserializeData(parcel, relationalSyncOpinion); + if (errCode != E_OK) { + LOGE("[AbilitySync] ack packet DeSerializ RelationalSyncOpinion failed."); + return errCode; + } + packet->SetRelationalSyncOpinion(relationalSyncOpinion); return E_OK; } @@ -981,20 +920,16 @@ int AbilitySync::SetAbilityRequestBodyInfo(AbilitySyncRequestPacket &packet, uin SecurityOption option; GetPacketSecOption(option); std::string schemaStr; - uint32_t schemaType; + uint32_t schemaType = 0; if (IsSingleKvVer()) { SchemaObject schemaObj = (static_cast(storageInterface_))->GetSchemaInfo(); schemaStr = schemaObj.ToSchemaString(); schemaType = static_cast(schemaObj.GetSchemaType()); - } -#ifdef RELATIONAL_STORE - if (IsSingleRelationalVer()) { - // todo demo + } else if (IsSingleRelationalVer()) { auto schemaObj = (static_cast(storageInterface_))->GetSchemaInfo(); schemaStr = schemaObj.ToSchemaString(); - schemaType = 0; + schemaType = static_cast(schemaObj.GetSchemaType()); } -#endif DbAbility dbAbility; errCode = GetDbAbilityInfo(dbAbility); if (errCode != E_OK) { @@ -1021,19 +956,11 @@ int AbilitySync::SetAbilityRequestBodyInfo(AbilitySyncRequestPacket &packet, uin return E_OK; } -#ifdef RELATIONAL_STORE -int AbilitySync::SetAbilityAckBodyInfo(AbilitySyncAckPacket &ackPacket, const ISchema &schemaObj, int ackCode, - SyncOpinion localOpinion, bool isAckNotify) -#else -int AbilitySync::SetAbilityAckBodyInfo(AbilitySyncAckPacket &ackPacket, const SchemaObject &schemaObj, int ackCode, - SyncOpinion localOpinion, bool isAckNotify) -#endif +int AbilitySync::SetAbilityAckBodyInfo(AbilitySyncAckPacket &ackPacket, int ackCode, bool isAckNotify) const { int errCode = E_OK; ackPacket.SetProtocolVersion(ABILITY_SYNC_VERSION_V1); ackPacket.SetSoftwareVersion(SOFTWARE_VERSION_CURRENT); - ackPacket.SetSchema(schemaObj.ToSchemaString()); - ackPacket.SetSchemaType(static_cast(schemaObj.GetSchemaType())); if (!isAckNotify) { SecurityOption option; GetPacketSecOption(option); @@ -1056,9 +983,19 @@ int AbilitySync::SetAbilityAckBodyInfo(AbilitySyncAckPacket &ackPacket, const Sc ackPacket.SetDbAbility(dbAbility); } ackPacket.SetAckCode(ackCode); + return E_OK; +} + +void AbilitySync::SetAbilityAckSchemaInfo(AbilitySyncAckPacket &ackPacket, const ISchema &schemaObj) const +{ + ackPacket.SetSchema(schemaObj.ToSchemaString()); + ackPacket.SetSchemaType(static_cast(schemaObj.GetSchemaType())); +} + +void AbilitySync::SetAbilityAckSyncOpinionInfo(AbilitySyncAckPacket &ackPacket, SyncOpinion localOpinion) const +{ ackPacket.SetPermitSync(localOpinion.permitSync); ackPacket.SetRequirePeerConvert(localOpinion.requirePeerConvert); - return E_OK; } int AbilitySync::GetDbAbilityInfo(DbAbility &dbAbility) const @@ -1108,10 +1045,153 @@ bool AbilitySync::IsSingleKvVer() const { return storageInterface_->GetInterfaceType() == ISyncInterface::SYNC_SVD; } -#ifdef RELATIONAL_STORE bool AbilitySync::IsSingleRelationalVer() const { +#ifdef RELATIONAL_STORE return storageInterface_->GetInterfaceType() == ISyncInterface::SYNC_RELATION; -} +#elif + return false; #endif +} + +int AbilitySync::HandleRequestRecv(const Message *message, ISyncTaskContext *context, bool isCompatible) +{ + const AbilitySyncRequestPacket *packet = message->GetObject(); + if (packet == nullptr) { + return -E_INVALID_ARGS; + } + uint32_t remoteSoftwareVersion = packet->GetSoftwareVersion(); + int ackCode; + std::string schema = packet->GetSchema(); + if (remoteSoftwareVersion <= SOFTWARE_VERSION_RELEASE_2_0) { + LOGI("[AbilitySync][RequestRecv] remote version = %u, CheckSchemaCompatible = %d", + remoteSoftwareVersion, isCompatible); + return SendAckWithEmptySchema(message, E_OK, false); + } + HandleVersionV3RequestParam(packet, context, schema); + if (SecLabelCheck(packet)) { + ackCode = E_OK; + } else { + ackCode = -E_SECURITY_OPTION_CHECK_ERROR; + } + if (ackCode == E_OK && remoteSoftwareVersion > SOFTWARE_VERSION_RELEASE_3_0) { + ackCode = metadata_->SetDbCreateTime(deviceId_, packet->GetDbCreateTime(), true); + } + AbilitySyncAckPacket ackPacket; + if (IsSingleRelationalVer()) { + ackPacket.SetRelationalSyncOpinion(MakeRelationSyncOpnion(packet, schema)); + } else { + SetAbilityAckSyncOpinionInfo(ackPacket, MakeKvSyncOpnion(packet, schema)); + } + LOGI("[AbilitySync][RequestRecv] remote dev=%s,ver=%u,schemaCompatible=%d", STR_MASK(deviceId_), + remoteSoftwareVersion, isCompatible); + return SendAck(message, ackCode, false, ackPacket); +} + +int AbilitySync::SendAck(const Message *message, int ackCode, bool isAckNotify, AbilitySyncAckPacket &ackPacket) +{ + int errCode = SetAbilityAckBodyInfo(ackPacket, ackCode, isAckNotify); + if (errCode != E_OK) { + return errCode; + } + if (IsSingleRelationalVer()) { + auto schemaObj = (static_cast(storageInterface_))->GetSchemaInfo(); + SetAbilityAckSchemaInfo(ackPacket, schemaObj); + } else if(IsSingleKvVer()) { + SchemaObject schemaObject = static_cast(storageInterface_)->GetSchemaInfo(); + SetAbilityAckSchemaInfo(ackPacket, schemaObject); + } + return SendAck(message, ackPacket, isAckNotify); +} + +int AbilitySync::SendAckWithEmptySchema(const Message *message, int ackCode, + bool isAckNotify) +{ + AbilitySyncAckPacket ackPacket; + int errCode = SetAbilityAckBodyInfo(ackPacket, ackCode, isAckNotify); + if (errCode != E_OK) { + return errCode; + } + SetAbilityAckSchemaInfo(ackPacket, SchemaObject()); + return SendAck(message, ackPacket, isAckNotify); +} + +int AbilitySync::SendAck(const Message *inMsg, const AbilitySyncAckPacket &ackPacket, bool isAckNotify) +{ + Message *ackMessage = new (std::nothrow) Message(ABILITY_SYNC_MESSAGE); + if (ackMessage == nullptr) { + LOGE("[AbilitySync][SendAck] message create failed, may be memleak!"); + return -E_OUT_OF_MEMORY; + } + int errCode = ackMessage->SetCopiedObject<>(ackPacket); + if (errCode != E_OK) { + LOGE("[AbilitySync][SendAck] SetCopiedObject failed, err %d", errCode); + delete ackMessage; + ackMessage = nullptr; + return errCode; + } + (!isAckNotify) ? ackMessage->SetMessageType(TYPE_RESPONSE) : ackMessage->SetMessageType(TYPE_NOTIFY); + ackMessage->SetTarget(deviceId_); + ackMessage->SetSessionId(inMsg->GetSessionId()); + ackMessage->SetSequenceId(inMsg->GetSequenceId()); + errCode = communicator_->SendMessage(deviceId_, ackMessage, false, SEND_TIME_OUT); + if (errCode != E_OK) { + LOGE("[AbilitySync][SendAck] SendPacket failed, err %d", errCode); + delete ackMessage; + ackMessage = nullptr; + } + return errCode; +} + +SyncOpinion AbilitySync::MakeKvSyncOpnion(const AbilitySyncRequestPacket *packet, const std::string &remoteSchema) const +{ + uint8_t remoteSchemaType = packet->GetSchemaType(); + SchemaObject localSchema = (static_cast(storageInterface_))->GetSchemaInfo(); + SyncOpinion localSyncOpinion = SchemaObject::MakeLocalSyncOpinion(localSchema, remoteSchema, remoteSchemaType); + return localSyncOpinion; +} + +RelationalSyncOpinion AbilitySync::MakeRelationSyncOpnion(const AbilitySyncRequestPacket *packet, + const std::string &remoteSchema) const +{ + uint8_t remoteSchemaType = packet->GetSchemaType(); + RelationalSchemaObject localSchema = (static_cast(storageInterface_))->GetSchemaInfo(); + return RelationalSchemaObject::MakeLocalSyncOpinion(localSchema, remoteSchema, remoteSchemaType); +} + +void AbilitySync::HandleKvAckSchemaParam(const AbilitySyncAckPacket *recvPacket, + ISyncTaskContext *context, AbilitySyncAckPacket &sendPacket) const +{ + std::string remoteSchema = recvPacket->GetSchema(); + uint8_t remoteSchemaType = recvPacket->GetSchemaType(); + bool permitSync = static_cast(recvPacket->GetPermitSync()); + bool requirePeerConvert = static_cast(recvPacket->GetRequirePeerConvert()); + SyncOpinion remoteOpinion = {permitSync, requirePeerConvert, true}; + SchemaObject localSchema = (static_cast(storageInterface_))->GetSchemaInfo(); + SyncOpinion syncOpinion = SchemaObject::MakeLocalSyncOpinion(localSchema, remoteSchema, remoteSchemaType); + SyncStrategy localStrategy = SchemaObject::ConcludeSyncStrategy(syncOpinion, remoteOpinion); + SetAbilityAckSyncOpinionInfo(sendPacket, syncOpinion); + (static_cast(context))->SetSyncStrategy(localStrategy); +} + +int AbilitySync::HandleRelationAckSchemaParam(const AbilitySyncAckPacket *recvPacket, AbilitySyncAckPacket &sendPacket, + ISyncTaskContext *context, bool sendOpinion) const +{ + std::string remoteSchema = recvPacket->GetSchema(); + uint8_t remoteSchemaType = recvPacket->GetSchemaType(); + auto localSchema = (static_cast(storageInterface_))->GetSchemaInfo(); + auto localOpinion = RelationalSchemaObject::MakeLocalSyncOpinion(localSchema, remoteSchema, remoteSchemaType); + auto localStrategy = RelationalSchemaObject::ConcludeSyncStrategy(localOpinion, + recvPacket->GetRelationalSyncOpinion()); + (static_cast(context))->SetRelationalSyncStrategy(localStrategy); + int errCode = (static_cast(storageInterface_))-> + CreateDistributedDeviceTable(context->GetDeviceId(), localStrategy); + if (errCode != E_OK) { + LOGE("[AbilitySync][AckRecv] create distributed device table failed,errCode=%d", errCode); + } + if (sendOpinion) { + sendPacket.SetRelationalSyncOpinion(localOpinion); + } + return errCode; +} } // namespace DistributedDB \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.h b/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.h index a76f8dc62727f9d4ec5db76a30f9fdbe5474a312..e1fa1ad0cb8e28a7043e40723678cf9828d2f0ef 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/ability_sync.h @@ -117,6 +117,10 @@ public: void SetDbAbility(const DbAbility &dbAbility); + void SetRelationalSyncOpinion(const RelationalSyncOpinion &relationalSyncOpinion); + + RelationalSyncOpinion GetRelationalSyncOpinion() const; + private: uint32_t protocolVersion_; uint32_t softwareVersion_; @@ -129,6 +133,7 @@ private: uint32_t requirePeerConvert_; uint64_t dbCreateTime_; DbAbility dbAbility_; + RelationalSyncOpinion relationalSyncOpinion_; }; class AbilitySync { @@ -164,13 +169,6 @@ public: static int DeSerialization(const uint8_t *buffer, uint32_t length, Message *inMsg); // register to communicator private: -#ifdef RELATIONAL_STORE - int SendAck(const Message *inMsg, const ISchema &schemaObj, int ackCode, SyncOpinion localOpinion, - bool isAckNotify = false); -#else - int SendAck(const Message *inMsg, const SchemaObject &schemaObj, int ackCode, SyncOpinion localOpinion, - bool isAckNotify = false); -#endif static int RequestPacketSerialization(uint8_t *buffer, uint32_t length, const Message *inMsg); @@ -191,36 +189,51 @@ private: bool SecLabelCheck(const AbilitySyncRequestPacket *packet) const; - SyncOpinion HandleVersionV3RequestParam(const AbilitySyncRequestPacket *packet, ISyncTaskContext *context, + void HandleVersionV3RequestParam(const AbilitySyncRequestPacket *packet, ISyncTaskContext *context, const std::string &remoteSchema) const; void HandleVersionV3AckSecOptionParam(const AbilitySyncAckPacket *packet, ISyncTaskContext *context) const; - SyncOpinion HandleVersionV3AckSchemaParam(const AbilitySyncAckPacket *packet, const std::string &remoteSchema, - ISyncTaskContext *context) const; + int HandleVersionV3AckSchemaParam(const AbilitySyncAckPacket *recvPacket, + AbilitySyncAckPacket &sendPacket, ISyncTaskContext *context, bool sendOpinion) const; + + void HandleKvAckSchemaParam(const AbilitySyncAckPacket *recvPacket, + ISyncTaskContext *context, AbilitySyncAckPacket &sendPacket) const; + + int HandleRelationAckSchemaParam(const AbilitySyncAckPacket *recvPacket, + AbilitySyncAckPacket &sendPacket, ISyncTaskContext *context, bool sendOpinion) const; void GetPacketSecOption(SecurityOption &option) const; int SetAbilityRequestBodyInfo(AbilitySyncRequestPacket &packet, uint16_t remoteCommunicatorVersion) const; -#ifdef RELATIONAL_STORE - int SetAbilityAckBodyInfo(AbilitySyncAckPacket &ackPacket, const ISchema &schemaObj, int ackCode, - SyncOpinion localOpinion, bool isAckNotify); -#else - int SetAbilityAckBodyInfo(AbilitySyncAckPacket &ackPacket, const SchemaObject &schemaObj, int ackCode, - SyncOpinion localOpinion, bool isAckNotify); -#endif + int SetAbilityAckBodyInfo(AbilitySyncAckPacket &ackPacket, int ackCode, bool isAckNotify) const; + + void SetAbilityAckSchemaInfo(AbilitySyncAckPacket &ackPacket, const ISchema &schemaObj) const; + + void SetAbilityAckSyncOpinionInfo(AbilitySyncAckPacket &ackPacket, SyncOpinion localOpinion) const; int GetDbAbilityInfo(DbAbility &dbAbility) const; int AckMsgCheck(const Message *message, ISyncTaskContext *context) const; bool IsSingleKvVer() const; -#ifdef RELATIONAL_STORE + bool IsSingleRelationalVer() const; -#endif - int SendAck(const Message *message, SyncOpinion &localSyncOpinion, int ackCode, bool isAckNotify); + + int SendAck(const Message *message, int ackCode, bool isAckNotify, AbilitySyncAckPacket &ackPacket); + + int SendAckWithEmptySchema(const Message *message, int ackCode, bool isAckNotify); + + int SendAck(const Message *message, const AbilitySyncAckPacket &ackPacket, bool isAckNotify); + + int HandleRequestRecv(const Message *message, ISyncTaskContext *context, bool isCompatible); + + SyncOpinion MakeKvSyncOpnion(const AbilitySyncRequestPacket *packet, const std::string &remoteSchema) const; + + RelationalSyncOpinion MakeRelationSyncOpnion(const AbilitySyncRequestPacket *packet, + const std::string &remoteSchema) const; ICommunicator *communicator_; ISyncInterface *storageInterface_; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.cpp index dd6f1094c3bb30b4fd37ea3820cef637e44cb5df..a6da32f7717dd9f55979a82aa0a77f129dbbd40d 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.cpp @@ -189,7 +189,7 @@ int GenericSyncer::Sync(const SyncParma ¶m) int GenericSyncer::PrepareSync(const SyncParma ¶m, uint32_t syncId) { auto *operation = - new (std::nothrow) SyncOperation(syncId, param.devices, param.mode, param.onComplete, param.wait); + new (std::nothrow) SyncOperation(syncId, param.devices, param.mode, param.onComplete, param.wait); if (operation == nullptr) { SubQueuedSyncSize(); return -E_OUT_OF_MEMORY; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.h b/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.h index 47bd27ff538ef1e67e91663139311ac98ab2236d..5c4048e1b0bb85de8a9f279f4c4dc0a3853e25ac 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/generic_syncer.h @@ -88,12 +88,13 @@ public: // Inner function, Used for subscribe sync int Sync(const InternalSyncParma ¶m); -protected: // Remote data changed callback virtual void RemoteDataChanged(const std::string &device) = 0; virtual void RemoteDeviceOffline(const std::string &device) = 0; +protected: + // trigger query auto sync or auto subscribe // trigger auto subscribe only when subscribe task is failed triggered by remote db opened // it won't be triggered again when subscribe task success diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/isync_engine.h b/services/distributeddataservice/libs/distributeddb/syncer/src/isync_engine.h index f7db71ff924f94da86108709948df5aa5a01ba85..c073be6a13b59512a5c96c30434ec24b486205f1 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/isync_engine.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/isync_engine.h @@ -76,6 +76,8 @@ public: // Check if the Sync Engine is active, some times synchronization is not allowed virtual bool IsEngineActive() const = 0; + virtual void ResetAbilitySync() = 0; + protected: virtual ~ISyncEngine() {}; }; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.cpp index 41dd2e0cdcf74ab82b3d334e4b08f7dd0a5ab841..c60415b26688202815288fb761bc381cc19e0462 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.cpp @@ -145,14 +145,14 @@ TimeOffset Metadata::GetLocalTimeOffset() const return localTimeOffset; } -int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) +int Metadata::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName) { // try to erase all the waterMark // erase deleteSync recv waterMark WaterMark waterMark = 0; int errCodeDeleteSync = SetRecvDeleteSyncWaterMark(deviceId, waterMark); // erase querySync recv waterMark - int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId); + int errCodeQuerySync = ResetRecvQueryWaterMark(deviceId, tableName); // peerWaterMark must be erased at last int errCode = SavePeerWaterMark(deviceId, 0, isNeedHash); if (errCode != E_OK) { @@ -452,9 +452,9 @@ int Metadata::SetRecvDeleteSyncWaterMark(const DeviceID &deviceId, const WaterMa return querySyncWaterMarkHelper_.SetRecvDeleteSyncWaterMark(deviceId, waterMark); } -int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId) +int Metadata::ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName) { - return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId); + return querySyncWaterMarkHelper_.ResetRecvQueryWaterMark(deviceId, tableName); } void Metadata::GetDbCreateTime(const DeviceID &deviceId, uint64_t &outValue) diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.h b/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.h index c0d280b1225007199e826da9c5fa1bbf49060b30..0cbcbfa96c2c52b87662b8e4c77dce3927115548 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/meta_data.h @@ -58,7 +58,7 @@ public: TimeOffset GetLocalTimeOffset() const; - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash); + int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, const std::string &tableName = ""); void SetLastLocalTime(TimeStamp lastLocalTime); @@ -141,7 +141,7 @@ private: int LoadDeviceIdDataToMap(const Key &key); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName = ""); // store localTimeOffset in ram; if change, should add a lock first, change here and metadata, // then release lock diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.cpp index 669dff8434062b9301b6628edf5ec86fe7664f04..c75695a44a57679c24045f1c9528e7f1f55b9e73 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.cpp @@ -58,7 +58,8 @@ void MultiVerSyncer::EnableAutoSync(bool enable) } } -int MultiVerSyncer::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) +int MultiVerSyncer::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, + const std::string &tableName) { return -E_NOT_SUPPORT; } diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.h b/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.h index 97b9c6b027ce803f47cb6e2503b6af6f20bf5e67..9c93d4d9d5c0326fea7d269851cedfd735a3ea6b 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/multi_ver_syncer.h @@ -30,7 +30,8 @@ public: void EnableAutoSync(bool enable) override; // delete specified device's watermark - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) override; + int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, + const std::string &tableName = "") override; // Local data changed callback void LocalDataChanged(int notifyEvent) override; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp index 7227596e0d7321586de4f95ba3fc020ca642f77a..7884d46b0ab45646d2674117d0ceafb115f4c0ec 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp @@ -547,12 +547,18 @@ int QuerySyncWaterMarkHelper::RemoveLeastUsedQuerySyncItems(const std::vector autoLock(queryWaterMarkLock_); std::string prefixKeyStr = QUERY_SYNC_PREFIX_KEY + DBCommon::TransferHashString(deviceId); + if (!tableName.empty()) { + std::string hashTableName = DBCommon::TransferHashString(tableName); + std::string hexTableName = DBCommon::TransferStringToHex(hashTableName); + prefixKeyStr += hexTableName; + } + // remove in db Key prefixKey; DBCommon::StringToVector(prefixKeyStr, prefixKey); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h b/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h index e9f82e9a5f5ec0ed265779dc1c3d9dad6a993bb1..6491633ccd60a3333ccf6c56c5985ab4d8b8f78c 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/query_sync_water_mark_helper.h @@ -90,7 +90,7 @@ public: int RemoveLeastUsedQuerySyncItems(const std::vector &querySyncIds); // reset the waterMark to zero - int ResetRecvQueryWaterMark(const DeviceID &deviceId); + int ResetRecvQueryWaterMark(const DeviceID &deviceId, const std::string &tableName = ""); static std::string GetQuerySyncPrefixKey(); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.cpp index 443cd2ef490c9d5ef11c45e43c9c2aca7d3d95f2..d219bb9eb3376b32868410949101d5120d51ade6 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.cpp @@ -329,7 +329,7 @@ int SingleVerDataSync::GetUnsyncData(SingleVerSyncTaskContext *context, std::vec int errCode; WaterMark startMark = 0; SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; - GetLocalWaterMark(curType, GetQuerySyncId(context, context->GetQuery().GetIdentify()), context, startMark); + GetLocalWaterMark(curType, context->GetQuerySyncId(), context, startMark); WaterMark endMark = MAX_TIMESTAMP; if ((endMark == 0) || (startMark > endMark)) { return E_OK; @@ -435,7 +435,7 @@ SyncTimeRange SingleVerDataSync::GetSyncDataTimeRange(SyncType syncType, SingleV { WaterMark localMark = 0; WaterMark deleteMark = 0; - GetLocalWaterMark(syncType, GetQuerySyncId(context, context->GetQuery().GetIdentify()), context, localMark); + GetLocalWaterMark(syncType, context->GetQuerySyncId(), context, localMark); GetLocalDeleteSyncWaterMark(context, deleteMark); if (syncType != SyncType::QUERY_SYNC_TYPE) { return GetFullSyncDataTimeRange(inData, localMark, isUpdate); @@ -538,7 +538,7 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync WaterMark localMark = 0; int errCode = E_OK; const std::string &deviceId = context->GetDeviceId(); - std::string queryId = GetQuerySyncId(context, context->GetQuery().GetIdentify()); + std::string queryId = context->GetQuerySyncId(); if (syncType != SyncType::QUERY_SYNC_TYPE) { if (isCheckBeforUpdate) { GetLocalWaterMark(syncType, queryId, context, localMark); @@ -572,7 +572,7 @@ int SingleVerDataSync::SaveLocalWaterMark(SyncType syncType, const SingleVerSync if (isNeedUpdateDeleteMark) { LOGD("label=%s,dev=%s,deleteEndTime=%llu", label_.c_str(), STR_MASK(GetDeviceId()), dataTimeRange.deleteEndTime); - errCode = metadata_->SetSendDeleteSyncWaterMark(GetDeleteSyncId(context), dataTimeRange.deleteEndTime); + errCode = metadata_->SetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), dataTimeRange.deleteEndTime); } } if (errCode != E_OK) { @@ -599,7 +599,7 @@ void SingleVerDataSync::GetPeerDeleteSyncWaterMark(const DeviceID &deviceId, Wat void SingleVerDataSync::GetLocalDeleteSyncWaterMark(const SingleVerSyncTaskContext *context, WaterMark &waterMark) const { - metadata_->GetSendDeleteSyncWaterMark(GetDeleteSyncId(context), waterMark, context->IsAutoLiftWaterMark()); + metadata_->GetSendDeleteSyncWaterMark(context->GetDeleteSyncId(), waterMark, context->IsAutoLiftWaterMark()); } void SingleVerDataSync::GetLocalWaterMark(SyncType syncType, const std::string &queryIdentify, @@ -630,7 +630,7 @@ int SingleVerDataSync::RemoveDeviceDataHandle(SingleVerSyncTaskContext *context, SyncType curType = SyncOperation::GetSyncType(packet->GetMode()); WaterMark packetLocalMark = packet->GetLocalWaterMark(); WaterMark peerMark = 0; - GetPeerWaterMark(curType, GetQuerySyncId(context, packet->GetQueryId()), context->GetDeviceId(), peerMark); + GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), peerMark); isNeedClearRemoteData = ((packetLocalMark == 0) && (peerMark != 0)); } if (!isNeedClearRemoteData) { @@ -674,7 +674,7 @@ int SingleVerDataSync::DealRemoveDeviceDataByAck(SingleVerSyncTaskContext *conte isNeedClearRemoteData = ((localMark != 0) && (ackWaterMark == 0)); } else { WaterMark peerMark = 0; - GetPeerWaterMark(curType, GetQuerySyncId(context, context->GetQuery().GetIdentify()), + GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), peerMark); isNeedClearRemoteData = ((reserved[ACK_PACKET_RESERVED_INDEX_LOCAL_WATER_MARK] == 0) && (peerMark != 0)); } @@ -780,7 +780,7 @@ void SingleVerDataSync::FillDataRequestPacket(DataRequestPacket *packet, SingleV bool needCompressOnSync = false; uint8_t compressionRate = DBConstant::DEFAULT_COMPTRESS_RATE; (void)storage_->GetCompressionOption(needCompressOnSync, compressionRate); - std::string id = GetQuerySyncId(context, context->GetQuery().GetIdentify()); + std::string id = context->GetQuerySyncId(); GetLocalWaterMark(curType, id, context, localMark); GetPeerWaterMark(curType, id, context->GetDeviceId(), peerMark); GetLocalDeleteSyncWaterMark(context, deleteMark); @@ -801,7 +801,7 @@ void SingleVerDataSync::FillDataRequestPacket(DataRequestPacket *packet, SingleV packet->SetSessionId(context->GetRequestSessionId()); } packet->SetQuery(context->GetQuery()); - packet->SetQueryId(GetQuerySyncId(context, context->GetQuery().GetIdentify())); + packet->SetQueryId(context->GetQuerySyncId()); CompressAlgorithm curAlgo = context->ChooseCompressAlgo(); if (needCompressOnSync && curAlgo != CompressAlgorithm::NONE) { packet->SetCompressDataMark(); @@ -872,8 +872,8 @@ int SingleVerDataSync::RequestStart(SingleVerSyncTaskContext *context, int mode) void SingleVerDataSync::TranslateErrCodeIfNeed(int mode, uint32_t version, int &errCode) { // once get data occur E_EKEYREVOKED error, should also send request to remote dev to pull data. - if (SyncOperation::TransferSyncMode(mode) == SyncModeType::PUSH_AND_PULL && version > SOFTWARE_VERSION_RELEASE_2_0 - && errCode == -E_EKEYREVOKED) { + if (SyncOperation::TransferSyncMode(mode) == SyncModeType::PUSH_AND_PULL && + version > SOFTWARE_VERSION_RELEASE_2_0 && errCode == -E_EKEYREVOKED) { errCode = E_OK; } } @@ -918,9 +918,9 @@ int SingleVerDataSync::PullRequestStart(SingleVerSyncTaskContext *context) WaterMark peerMark = 0; WaterMark localMark = 0; WaterMark deleteMark = 0; - GetPeerWaterMark(syncType, GetQuerySyncId(context, context->GetQuery().GetIdentify()), + GetPeerWaterMark(syncType, context->GetQuerySyncId(), context->GetDeviceId(), peerMark); - GetLocalWaterMark(syncType, GetQuerySyncId(context, context->GetQuery().GetIdentify()), context, localMark); + GetLocalWaterMark(syncType, context->GetQuerySyncId(), context, localMark); GetLocalDeleteSyncWaterMark(context, deleteMark); uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); WaterMark endMark = context->GetEndMark(); @@ -931,7 +931,7 @@ int SingleVerDataSync::PullRequestStart(SingleVerSyncTaskContext *context) packet->SetEndWaterMark(endMark); packet->SetSessionId(context->GetRequestSessionId()); packet->SetQuery(context->GetQuery()); - packet->SetQueryId(GetQuerySyncId(context, context->GetQuery().GetIdentify())); + packet->SetQueryId(context->GetQuerySyncId()); packet->SetLastSequence(); SetPacketId(packet, context, version); @@ -1019,7 +1019,7 @@ void SingleVerDataSync::UpdatePeerWaterMark(SyncType syncType, const std::string if (peerDeletedWatermark != 0) { LOGD("label=%s,dev=%s,peerDeletedTime=%llu", label_.c_str(), STR_MASK(GetDeviceId()), peerDeletedWatermark); - errCode = metadata_->SetRecvDeleteSyncWaterMark(GetDeleteSyncId(context), peerDeletedWatermark); + errCode = metadata_->SetRecvDeleteSyncWaterMark(context->GetDeleteSyncId(), peerDeletedWatermark); } } if (errCode != E_OK) { @@ -1438,8 +1438,11 @@ int SingleVerDataSync::RunPermissionCheck(SingleVerSyncTaskContext *context, con // before add permissionCheck, PushStart packet and pullResponse packet do not setMode. flag = CHECK_FLAG_RECEIVE; } - int errCode = RuntimeContext::GetInstance()->RunPermissionCheck(userId, appId, storeId, context->GetDeviceId(), - flag); + int errCode = E_OK; + if (storage_->GetInterfaceType() != ISyncInterface::SYNC_RELATION) { + errCode = RuntimeContext::GetInstance()->RunPermissionCheck(userId, appId, storeId, context->GetDeviceId(), + flag); + } if (errCode != E_OK) { LOGE("[DataSync][RunPermissionCheck] check failed flag=%d,Label=%s,dev=%s", flag, label_.c_str(), STR_MASK(GetDeviceId())); @@ -1650,7 +1653,7 @@ bool SingleVerDataSync::WaterMarkErrHandle(SyncType syncType, SingleVerSyncTaskC WaterMark deletedMark = 0; GetPeerWaterMark(syncType, packet->GetQueryId(), context->GetDeviceId(), peerMark); if (syncType == SyncType::QUERY_SYNC_TYPE) { - GetPeerDeleteSyncWaterMark(GetDeleteSyncId(context), deletedMark); + GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), deletedMark); } if (syncType != SyncType::QUERY_SYNC_TYPE && packetLocalMark > peerMark) { LOGI("[DataSync][DataRequestRecv] packetLocalMark=%llu,current=%llu", packetLocalMark, peerMark); @@ -1687,7 +1690,12 @@ bool SingleVerDataSync::CheckPermitReceiveData(const SingleVerSyncTaskContext *c int SingleVerDataSync::CheckSchemaStrategy(SingleVerSyncTaskContext *context, const Message *message) { - SyncStrategy localStrategy = context->GetSyncStrategy(); + auto *packet = message->GetObject(); + if (packet == nullptr) { + return -E_INVALID_ARGS; + } + auto query = packet->GetQuery(); + SyncStrategy localStrategy = context->GetSyncStrategy(query); if (!context->GetIsSchemaSync()) { LOGE("[DataSync][CheckSchemaStrategy] isSchemaSync=%d check failed", context->GetIsSchemaSync()); (void)SendDataAck(context, message, -E_NEED_ABILITY_SYNC, 0); @@ -1769,7 +1777,7 @@ void SingleVerDataSync::SetAckPacket(DataAckPacket &ackPacket, SingleVerSyncTask // while recv is not E_OK, data is peerMark, reserve[2] is deletedPeerMark value if (curType == SyncType::QUERY_SYNC_TYPE && recvCode != WATER_MARK_INVALID) { WaterMark deletedPeerMark; - GetPeerDeleteSyncWaterMark(GetDeleteSyncId(context), deletedPeerMark); + GetPeerDeleteSyncWaterMark(context->GetDeleteSyncId(), deletedPeerMark); reserved.push_back(deletedPeerMark); // query sync mode, reserve[2] store deletedPeerMark value } ackPacket.SetReserved(reserved); @@ -1884,7 +1892,7 @@ void SingleVerDataSync::FillRequestReSendPacket(const SingleVerSyncTaskContext * { SyncType curType = (context->IsQuerySync()) ? SyncType::QUERY_SYNC_TYPE : SyncType::MANUAL_FULL_SYNC_TYPE; WaterMark peerMark = 0; - GetPeerWaterMark(curType, GetQuerySyncId(context, context->GetQuery().GetIdentify()), context->GetDeviceId(), + GetPeerWaterMark(curType, context->GetQuerySyncId(), context->GetDeviceId(), peerMark); uint32_t version = std::min(context->GetRemoteSoftwareVersion(), SOFTWARE_VERSION_CURRENT); // transer reSend mode, RESPONSE_PULL transfer to push or query push @@ -1907,7 +1915,7 @@ void SingleVerDataSync::FillRequestReSendPacket(const SingleVerSyncTaskContext * packet->SetEndWaterMark(context->GetEndMark()); packet->SetQuery(context->GetQuery()); } - packet->SetQueryId(GetQuerySyncId(context, context->GetQuery().GetIdentify())); + packet->SetQueryId(context->GetQuerySyncId()); if (version > SOFTWARE_VERSION_RELEASE_2_0) { std::vector reserved {reSendInfo.packetId}; packet->SetReserved(reserved); @@ -1962,6 +1970,10 @@ bool SingleVerDataSync::QuerySyncCheck(const SingleVerSyncTaskContext *context) LOGE("[SingleVerDataSync] remote version only support prefix key"); return false; } + if (context->GetQuery().HasInKeys() && + context->GetRemoteDbAbility().GetAbilityItem(INKEYS_QUERY) != SUPPORT_MARK) { + return false; + } return true; } @@ -2090,6 +2102,11 @@ int SingleVerDataSync::ControlCmdStartCheck(SingleVerSyncTaskContext *context) LOGE("[ControlCmdStartCheck] not support controlCmd"); return -E_INVALID_ARGS; } + if (context->GetMode() == SyncModeType::SUBSCRIBE_QUERY && + context->GetQuery().HasInKeys() && + context->GetRemoteDbAbility().GetAbilityItem(INKEYS_QUERY) != SUPPORT_MARK) { + return -E_NOT_SUPPORT; + } if ((context->GetMode() != SyncModeType::SUBSCRIBE_QUERY) || context->GetReceivcPermitCheck()) { return E_OK; } @@ -2355,30 +2372,6 @@ void SingleVerDataSync::ControlAckErrorHandle(const SingleVerSyncTaskContext *co } } -std::string SingleVerDataSync::GetQuerySyncId(const SingleVerSyncTaskContext *context, const std::string &queryId) const -{ - std::string id; -#ifdef RELATIONAL_STORE - if (storage_->GetInterfaceType() == ISyncInterface::SYNC_RELATION) { - id += context->GetQuery().GetRelationTableName(); - } -#endif - id += queryId; - return id; -} - -std::string SingleVerDataSync::GetDeleteSyncId(const SingleVerSyncTaskContext *context) const -{ - std::string id; - id += context->GetDeviceId(); -#ifdef RELATIONAL_STORE - if (storage_->GetInterfaceType() == ISyncInterface::SYNC_RELATION) { - id += context->GetQuery().GetRelationTableName(); - } -#endif - return id; -} - void SingleVerDataSync::PutDataMsg(Message *message) { return msgSchedule_.PutMsg(message); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.h index 8788197e7fa431f387f09ecc5463e116b80a260f..ea65bf4da4ab26bd04c61b0043d7d1a0a1de8576 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_data_sync.h @@ -297,9 +297,6 @@ protected: int SendControlAck(SingleVerSyncTaskContext *context, const Message *message, int32_t recvCode, uint32_t controlCmdType, const CommErrHandler &handler = nullptr); - std::string GetQuerySyncId(const SingleVerSyncTaskContext *context, const std::string &queryId) const; - std::string GetDeleteSyncId(const SingleVerSyncTaskContext *context) const; - uint32_t mtuSize_; SyncGenericInterface* storage_; ICommunicator* communicateHandle_; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_sync_task_context.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_sync_task_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1cfdf3350d45f2e680a941e2fd2012512ac35b01 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_sync_task_context.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2022 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 "single_ver_kv_sync_task_context.h" + +namespace DistributedDB { +SingleVerKvSyncTaskContext::SingleVerKvSyncTaskContext() + : SingleVerSyncTaskContext(), syncStrategy_{} +{} + +SingleVerKvSyncTaskContext::~SingleVerKvSyncTaskContext() +{ +} + +std::string SingleVerKvSyncTaskContext::GetQuerySyncId() const +{ + return query_.GetIdentify(); +} + +std::string SingleVerKvSyncTaskContext::GetDeleteSyncId() const +{ + return GetDeviceId(); +} + +void SingleVerKvSyncTaskContext::SetSyncStrategy(const SyncStrategy &strategy) +{ + syncStrategy_.permitSync = strategy.permitSync; + syncStrategy_.convertOnSend = strategy.convertOnSend; + syncStrategy_.convertOnReceive = strategy.convertOnReceive; + syncStrategy_.checkOnReceive = strategy.checkOnReceive; +} + +SyncStrategy SingleVerKvSyncTaskContext::GetSyncStrategy(QuerySyncObject &querySyncObject) const +{ + return syncStrategy_; +} +} \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_sync_task_context.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_sync_task_context.h new file mode 100644 index 0000000000000000000000000000000000000000..5d8b615defdbeb5112b486fc7e3cc40aa762da36 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_sync_task_context.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 SINGLE_VER_KV_SYNC_TASK_CONTEXT_H +#define SINGLE_VER_KV_SYNC_TASK_CONTEXT_H + +#include "single_ver_sync_task_context.h" + +namespace DistributedDB { +class SingleVerKvSyncTaskContext : public SingleVerSyncTaskContext { +public: + + explicit SingleVerKvSyncTaskContext(); + + DISABLE_COPY_ASSIGN_MOVE(SingleVerKvSyncTaskContext); + + std::string GetQuerySyncId() const override; + std::string GetDeleteSyncId() const override; + + void SetSyncStrategy(const SyncStrategy &strategy); + SyncStrategy GetSyncStrategy(QuerySyncObject &querySyncObject) const override; +protected: + ~SingleVerKvSyncTaskContext() override; + + SyncStrategy syncStrategy_; +}; +} +#endif // SINGLE_VER_KV_SYNC_TASK_CONTEXT_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp index d1c8732ac81e6bf41c1cb62c68bebf1f78ad76c2..dbfec0286571ca8ec9e2bebdd788a3ed7fd99832 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp @@ -28,8 +28,7 @@ namespace DistributedDB { SingleVerKVSyncer::SingleVerKVSyncer() - : autoSyncEnable_(false), - triggerSyncTask_(true) + : autoSyncEnable_(false), triggerSyncTask_(true) { } @@ -66,14 +65,6 @@ void SingleVerKVSyncer::EnableAutoSync(bool enable) } } -int SingleVerKVSyncer::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) -{ - if (metadata_ == nullptr) { - return -E_NOT_INIT; - } - return metadata_->EraseDeviceWaterMark(deviceId, isNeedHash); -} - // Local data changed callback void SingleVerKVSyncer::LocalDataChanged(int notifyEvent) { @@ -125,8 +116,11 @@ void SingleVerKVSyncer::LocalDataChanged(int notifyEvent) void SingleVerKVSyncer::RemoteDataChanged(const std::string &device) { LOGI("[SingleVerKVSyncer] device online dev %s", STR_MASK(device)); - // while remote db is online again, need to do abilitySync - static_cast(syncEngine_)->SetIsNeedResetAbilitySync(device, true); + std::string userId = syncInterface_->GetDbProperties().GetStringProp(KvDBProperties::USER_ID, ""); + std::string appId = syncInterface_->GetDbProperties().GetStringProp(KvDBProperties::APP_ID, ""); + std::string storeId = syncInterface_->GetDbProperties().GetStringProp(KvDBProperties::STORE_ID, ""); + RuntimeContext::GetInstance()->NotifyDatabaseStatusChange(userId, appId, storeId, device, true); + SingleVerSyncer::RemoteDataChanged(device); if (autoSyncEnable_) { RefObject::IncObjRef(syncEngine_); int retCode = RuntimeContext::GetInstance()->ScheduleTask([this, device] { diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.h index cb02a472c2bcc4cae744bccf3fc0d22b63397ef4..dc601ff0a714fd14cd83156f8c0e0fbb032158d9 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_kv_syncer.h @@ -27,9 +27,6 @@ public: // Enable auto sync function void EnableAutoSync(bool enable) override; - // delete specified device's watermark - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) override; - // Local data changed callback void LocalDataChanged(int notifyEvent) override; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_sync_task_context.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_sync_task_context.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cb818d21da84794ce6a87809f1c8750835839cd3 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_sync_task_context.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2022 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 "single_ver_relational_sync_task_context.h" +#include "db_common.h" + +#ifdef RELATIONAL_STORE +namespace DistributedDB { +SingleVerRelationalSyncTaskContext::SingleVerRelationalSyncTaskContext() + : SingleVerSyncTaskContext() +{} + +SingleVerRelationalSyncTaskContext::~SingleVerRelationalSyncTaskContext() +{ +} + +std::string SingleVerRelationalSyncTaskContext::GetQuerySyncId() const +{ + return querySyncId_; +} + +std::string SingleVerRelationalSyncTaskContext::GetDeleteSyncId() const +{ + return deleteSyncId_; +} + +void SingleVerRelationalSyncTaskContext::Clear() +{ + querySyncId_.clear(); + deleteSyncId_.clear(); + SingleVerSyncTaskContext::Clear(); +} + +void SingleVerRelationalSyncTaskContext::CopyTargetData(const ISyncTarget *target, const TaskParam &TaskParam) +{ + SingleVerSyncTaskContext::CopyTargetData(target, TaskParam); + std::string hashTableName = DBCommon::TransferHashString(query_.GetRelationTableName()); + std::string hexTableName = DBCommon::TransferStringToHex(hashTableName); + querySyncId_ = hexTableName + query_.GetIdentify(); // save as deviceId + hexTableName + queryId + deleteSyncId_ = GetDeviceId() + hexTableName; // save as deviceId + hexTableName +} + +void SingleVerRelationalSyncTaskContext::SetRelationalSyncStrategy(RelationalSyncStrategy strategy) +{ + relationalSyncStrategy_ = strategy; +} + +SyncStrategy SingleVerRelationalSyncTaskContext::GetSyncStrategy(QuerySyncObject &querySyncObject) const +{ + return relationalSyncStrategy_.GetTableStrategy(querySyncObject.GetRelationTableName()); +} +} +#endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_sync_task_context.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_sync_task_context.h new file mode 100644 index 0000000000000000000000000000000000000000..c1024fcb9cc9d278db1cd8836c360eb9b446272e --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_sync_task_context.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022 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 SINGLE_VER_RELATIONAL_SYNC_TASK_CONTEXT_H +#define SINGLE_VER_RELATIONAL_SYNC_TASK_CONTEXT_H + +#ifdef RELATIONAL_STORE +#include "single_ver_sync_task_context.h" + +namespace DistributedDB { +class SingleVerRelationalSyncTaskContext : public SingleVerSyncTaskContext { +public: + + explicit SingleVerRelationalSyncTaskContext(); + + DISABLE_COPY_ASSIGN_MOVE(SingleVerRelationalSyncTaskContext); + + void Clear() override; + std::string GetQuerySyncId() const override; + std::string GetDeleteSyncId() const override; + + void SetRelationalSyncStrategy(RelationalSyncStrategy strategy); + SyncStrategy GetSyncStrategy(QuerySyncObject &querySyncObject) const override; +protected: + ~SingleVerRelationalSyncTaskContext() override; + void CopyTargetData(const ISyncTarget *target, const TaskParam &taskParam) override; + + std::string querySyncId_; + std::string deleteSyncId_; + + // for relational syncStrategy + RelationalSyncStrategy relationalSyncStrategy_; +}; +} +#endif // RELATIONAL_STORE +#endif // SINGLE_VER_RELATIONAL_SYNC_TASK_CONTEXT_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp index 7cb09883fc8e5fa0191d9ca3e153df48956edf20..226b72f5ab5f92efc1d251e603330cfa5bfda993 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.cpp @@ -19,6 +19,17 @@ #include "single_ver_sync_engine.h" namespace DistributedDB { +int SingleVerRelationalSyncer::Initialize(ISyncInterface *syncInterface) +{ + int errCode = SingleVerSyncer::Initialize(syncInterface); + if (errCode != E_OK) { + return errCode; + } + auto callback = std::bind(&SingleVerRelationalSyncer::SchemaChangeCallback, this); + return static_cast(syncInterface)-> + RegisterSchemaChangedCallback(callback); +} + int SingleVerRelationalSyncer::Sync(const SyncParma ¶m) { if (param.mode == SYNC_MODE_PUSH_PULL) { @@ -59,8 +70,9 @@ int SingleVerRelationalSyncer::GenerateEachSyncTask(const SyncParma ¶m, uint int errCode = E_OK; for (const QuerySyncObject &table : tablesQuery) { uint32_t subSyncId = GenerateSyncId(); - LOGI("[SingleVerRelationalSyncer] SubSyncId %d create by SyncId %d, tableName = %s", - subSyncId, syncId, table.GetRelationTableName().c_str()); + std::string hashTableName = DBCommon::TransferHashString(table.GetRelationTableName()); + LOGI("[SingleVerRelationalSyncer] SubSyncId %d create by SyncId %d, hashTableName = %s", + subSyncId, syncId, STR_MASK(DBCommon::TransferStringToHex(hashTableName))); subParam.syncQuery = table; subParam.onComplete = std::bind(&SingleVerRelationalSyncer::DoOnSubSyncComplete, this, subSyncId, syncId, param, std::placeholders::_1); @@ -137,17 +149,32 @@ void SingleVerRelationalSyncer::EnableAutoSync(bool enable) { } -int SingleVerRelationalSyncer::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) +void SingleVerRelationalSyncer::LocalDataChanged(int notifyEvent) { - return E_OK; } -void SingleVerRelationalSyncer::LocalDataChanged(int notifyEvent) +void SingleVerRelationalSyncer::SchemaChangeCallback() { + if (syncEngine_ != nullptr) { + syncEngine_->ResetAbilitySync(); + } } -void SingleVerRelationalSyncer::RemoteDataChanged(const std::string &device) +int SingleVerRelationalSyncer::SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, + const std::vector &devices) const { + if (!isQuerySync) { + return E_OK; + } + int errCode = static_cast(syncInterface_)->CheckAndInitQueryCondition(query); + if (errCode != E_OK) { + LOGE("[SingleVerRelationalSyncer] QuerySyncObject check failed"); + return errCode; + } + if (mode == SUBSCRIBE_QUERY) { + return -E_NOT_SUPPORT; + } + return E_OK; } } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.h index 15e4ef814348398e2d277300316edc6abf7bdea9..bf6bd992be9676b10302997ce0afc69b1ab65392 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_relational_syncer.h @@ -22,20 +22,21 @@ public: SingleVerRelationalSyncer() = default; ~SingleVerRelationalSyncer() override = default; + int Initialize(ISyncInterface *syncInterface) override; + // Sync function. use SyncParma to reduce paramter. int Sync(const SyncParma ¶m) override; void EnableAutoSync(bool enable) override; - int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) override; - void LocalDataChanged(int notifyEvent) override; protected: int PrepareSync(const SyncParma ¶m, uint32_t syncId) override; - void RemoteDataChanged(const std::string &device) override; + int SyncConditionCheck(QuerySyncObject &query, int mode, bool isQuerySync, + const std::vector &devices) const override; private: @@ -48,6 +49,8 @@ private: void DoOnSubSyncComplete(const uint32_t subSyncId, const uint32_t syncId, const SyncParma ¶m, const std::map &devicesMap); + void SchemaChangeCallback(); + mutable std::mutex syncMapLock_; std::map> fullSyncIdMap_; std::map>> resMap_; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp index bec6bd4bf73ef830ee50eec1e638024c099b3b91..8681a465488cd7be29dc9b6439081378e1cb5ff0 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_engine.cpp @@ -16,12 +16,27 @@ #include "single_ver_sync_engine.h" #include "db_common.h" #include "single_ver_sync_task_context.h" +#include "single_ver_kv_sync_task_context.h" +#include "single_ver_relational_sync_task_context.h" #include "log_print.h" namespace DistributedDB { ISyncTaskContext *SingleVerSyncEngine::CreateSyncTaskContext() { - auto context = new (std::nothrow) SingleVerSyncTaskContext(); + SingleVerSyncTaskContext *context = nullptr; + switch (syncInterface_->GetInterfaceType()) { + case ISyncInterface::SYNC_SVD: + context = new (std::nothrow) SingleVerKvSyncTaskContext(); + break; +#ifdef RELATIONAL_STORE + case ISyncInterface::SYNC_RELATION: + context = new (std::nothrow) SingleVerRelationalSyncTaskContext(); + break; +#endif + default: + break; + } + if (context == nullptr) { LOGE("[SingleVerSyncEngine][CreateSyncTaskContext] create failed, may be out of memory"); return nullptr; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp index 1de9493fa4fa669b03970af5c9c721923a2d2e55..ede83348c22f3190aa77e4b95055d210c9a8a5b9 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.cpp @@ -729,8 +729,8 @@ int SingleVerSyncStateMachine::HandleDataAckRecv(const Message *inMsg) return errCode; } // when this msg is from response task while request task is running, ignore the errCode - bool ignoreInnerErr = inMsg->GetSessionId() == context_->GetResponseSessionId() - && context_->GetRequestSessionId() != 0; + bool ignoreInnerErr = inMsg->GetSessionId() == context_->GetResponseSessionId() && + context_->GetRequestSessionId() != 0; DataAckRecvErrCodeHandle(errCode, !ignoreInnerErr); HandleDataAckRecvWithSlidingWindow(errCode, inMsg, ignoreInnerErr); return errCode; @@ -840,6 +840,7 @@ int SingleVerSyncStateMachine::GetSyncOperationStatus(int errCode) const { -E_NOT_SUPPORT, SyncOperation::OP_NOT_SUPPORT }, { -E_INTERCEPT_DATA_FAIL, SyncOperation::OP_INTERCEPT_DATA_FAIL }, { -E_MAX_LIMITS, SyncOperation::OP_MAX_LIMITS }, + { -E_DISTRIBUTED_SCHEMA_CHANGED, SyncOperation::OP_SCHEMA_CHANGED }, { -E_NOT_REGISTER, SyncOperation::OP_NOT_SUPPORT }, }; auto iter = statusMap.find(errCode); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.h index 587ec04a2b8c9d69c479e4df27906856cd34ce13..a9aca600a913f55c1b6c9501b038fcf80b32ec89 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_state_machine.h @@ -69,7 +69,7 @@ namespace { } using stateMappingHandler = std::function; -class SingleVerSyncStateMachine final : public SyncStateMachine { +class SingleVerSyncStateMachine : public SyncStateMachine { public: SingleVerSyncStateMachine(); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp index cbc1fbb563433f716f8da2d65d8399378f7163f3..ded9bd059c147922d7eff0c2e0ac5b095090889b 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.cpp @@ -150,7 +150,7 @@ void SingleVerSyncTaskContext::SetContinueToken(ContinueToken token) void SingleVerSyncTaskContext::ReleaseContinueToken() { if (token_ != nullptr) { - static_cast(syncInterface_)->ReleaseContinueToken(token_); + static_cast(syncInterface_)->ReleaseContinueToken(token_); token_ = nullptr; } } @@ -351,20 +351,6 @@ bool SingleVerSyncTaskContext::GetSendPermitCheck() const { return isSendPermitChecked_; } - -void SingleVerSyncTaskContext::SetSyncStrategy(SyncStrategy strategy) -{ - syncStrategy_.permitSync = strategy.permitSync; - syncStrategy_.convertOnSend = strategy.convertOnSend; - syncStrategy_.convertOnReceive = strategy.convertOnReceive; - syncStrategy_.checkOnReceive = strategy.checkOnReceive; -} - -SyncStrategy SingleVerSyncTaskContext::GetSyncStrategy() const -{ - return syncStrategy_; -} - void SingleVerSyncTaskContext::SetIsSchemaSync(bool isSchemaSync) { isSchemaSync_ = isSchemaSync; @@ -449,9 +435,10 @@ std::string SingleVerSyncTaskContext::GetRemoteCompressAlgoStr() const void SingleVerSyncTaskContext::SetDbAbility(DbAbility &remoteDbAbility) { remoteDbAbility_ = remoteDbAbility; - LOGI("[SingleVerSyncTaskContext] set dev=%s compressAlgo=%s, IsSupAllPredicateQuery=%u, IsSupSubscribeQuery=%u", + LOGI("[SingleVerSyncTaskContext] set dev=%s compressAlgo=%s, IsSupAllPredicateQuery=%u, \ + IsSupSubscribeQuery=%u, inKeys=%u", STR_MASK(GetDeviceId()), GetRemoteCompressAlgoStr().c_str(), remoteDbAbility.GetAbilityItem(ALLPREDICATEQUERY), - remoteDbAbility.GetAbilityItem(SUBSCRIBEQUERY)); + remoteDbAbility.GetAbilityItem(SUBSCRIBEQUERY), remoteDbAbility.GetAbilityItem(INKEYS_QUERY)); } CompressAlgorithm SingleVerSyncTaskContext::ChooseCompressAlgo() const @@ -461,7 +448,7 @@ CompressAlgorithm SingleVerSyncTaskContext::ChooseCompressAlgo() const return CompressAlgorithm::NONE; } std::set localAlgorithmSet; - (void)(static_cast(syncInterface_))->GetCompressionAlgo(localAlgorithmSet); + (void)(static_cast(syncInterface_))->GetCompressionAlgo(localAlgorithmSet); std::set algoIntersection; set_intersection(remoteAlgo.begin(), remoteAlgo.end(), localAlgorithmSet.begin(), localAlgorithmSet.end(), inserter(algoIntersection, algoIntersection.begin())); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.h index 85f29c2123aae99e81687629ddc2190f813b471d..5e9afe2b17ec30aec54981249e1944eecedf3d73 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_sync_task_context.h @@ -23,6 +23,7 @@ #include "db_ability.h" #include "query_sync_object.h" +#include "schema.h" #include "single_ver_kvdb_sync_interface.h" #include "single_ver_sync_target.h" #include "subscribe_manager.h" @@ -108,9 +109,7 @@ public: bool GetSendPermitCheck() const; - void SetSyncStrategy(SyncStrategy strategy); - - SyncStrategy GetSyncStrategy() const; + virtual SyncStrategy GetSyncStrategy(QuerySyncObject &querySyncObject) const = 0; void SetIsSchemaSync(bool isChecked); @@ -136,14 +135,19 @@ public: void SaveLastPushTaskExecStatus(int finalStatus) override; void ResetLastPushTaskStatus() override; + + virtual std::string GetQuerySyncId() const = 0; + virtual std::string GetDeleteSyncId() const = 0; protected: ~SingleVerSyncTaskContext() override; void CopyTargetData(const ISyncTarget *target, const TaskParam &taskParam) override; + // For querySync + QuerySyncObject query_; + bool isQuerySync_ = false; private: int GetCorrectedSendWaterMarkForCurrentTask(uint64_t &waterMark) const; -private: constexpr static int64_t REDUNDACE_WATER_MARK = 1 * 1000LL * 1000LL * 10LL; // 1s DECLARE_OBJECT_TAG(SingleVerSyncTaskContext); @@ -156,16 +160,11 @@ private: SecurityOption remoteSecOption_ = {0, 0}; // remote targe can handle secOption data or not. bool isReceivcPermitChecked_ = false; bool isSendPermitChecked_ = false; - SyncStrategy syncStrategy_; bool isSchemaSync_ = false; // is receive waterMark err, peerWaterMark bigger than remote localWaterMark bool isReceiveWaterMarkErr_ = false; - // For querySync - QuerySyncObject query_; - bool isQuerySync_ = false; - // For db ability DbAbility remoteDbAbility_; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.cpp index cbe12a6d8fe5d8902866b4c1d86203d897261ce4..3069f5e90eacbbae05e105099ded7a6406e2bc9c 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.cpp @@ -18,14 +18,34 @@ #include "single_ver_sync_engine.h" namespace DistributedDB { +void SingleVerSyncer::RemoteDataChanged(const std::string &device) +{ + LOGI("[SingleVerSyncer] device online dev %s", STR_MASK(device)); + // while remote db is online again, need to do abilitySync + static_cast(syncEngine_)->SetIsNeedResetAbilitySync(device, true); +} + void SingleVerSyncer::RemoteDeviceOffline(const std::string &device) { LOGI("[SingleVerRelationalSyncer] device offline dev %s", STR_MASK(device)); + std::string userId = syncInterface_->GetDbProperties().GetStringProp(KvDBProperties::USER_ID, ""); + std::string appId = syncInterface_->GetDbProperties().GetStringProp(KvDBProperties::APP_ID, ""); + std::string storeId = syncInterface_->GetDbProperties().GetStringProp(KvDBProperties::STORE_ID, ""); + RuntimeContext::GetInstance()->NotifyDatabaseStatusChange(userId, appId, storeId, device, false); RefObject::IncObjRef(syncEngine_); static_cast(syncEngine_)->OfflineHandleByDevice(device); RefObject::DecObjRef(syncEngine_); } +int SingleVerSyncer::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, + const std::string &tableName) +{ + if (metadata_ == nullptr) { + return -E_NOT_INIT; + } + return metadata_->EraseDeviceWaterMark(deviceId, isNeedHash, tableName); +} + int SingleVerSyncer::SetStaleDataWipePolicy(WipePolicy policy) { std::lock_guard lock(syncerLock_); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.h b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.h index b88b6c5204bfcbfa459f8b45ab75e9936da2fb2a..dab50ddb802225a93b26768ba723635d77e3bff5 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/single_ver_syncer.h @@ -20,11 +20,17 @@ namespace DistributedDB { class SingleVerSyncer : public GenericSyncer { public: + void RemoteDataChanged(const std::string &device) override; + void RemoteDeviceOffline(const std::string &device) override; // Set stale data wipe policy int SetStaleDataWipePolicy(WipePolicy policy) override; + // delete specified device's watermark + int EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, + const std::string &tableName = "") override; + protected: // Create a sync engine, if has memory error, will return nullptr. ISyncEngine *CreateSyncEngine() override; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.cpp index abd479b8708d59b4704877faa6616e8df2a88a04..c0176d53c34ce6230bc0ba4b5a48ee822a86101b 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.cpp @@ -604,8 +604,12 @@ int SyncEngine::ExecSyncTask(ISyncTaskContext *context) context->SetTaskExecStatus(ISyncTaskContext::RUNNING); if (!context->IsTargetQueueEmpty()) { context->MoveToNextTarget(); - int checkErrCode = RunPermissionCheck(context->GetDeviceId(), - GetPermissionCheckFlag(context->IsAutoSync(), context->GetMode())); + int checkErrCode = E_OK; + // rdb dont support PermissionCheck + if (syncInterface_->GetInterfaceType() != ISyncInterface::SYNC_RELATION) { + checkErrCode = RunPermissionCheck(context->GetDeviceId(), + GetPermissionCheckFlag(context->IsAutoSync(), context->GetMode())); + } if (checkErrCode != E_OK) { context->SetOperationStatus(SyncOperation::OP_PERMISSION_CHECK_FAILED); context->SetTaskExecStatus(ISyncTaskContext::FINISHED); @@ -969,4 +973,19 @@ bool SyncEngine::IsEngineActive() const { return isActive_; } + +void SyncEngine::ResetAbilitySync() +{ + std::lock_guard lock(contextMapLock_); + for (auto &enrty : syncTaskContextMap_) { + auto context = enrty.second; + if (context->IsKilled()) { + continue; + } + // IncRef for SyncEngine to make sure context is valid, to avoid a big lock + RefObject::IncObjRef(context); + context->SetIsNeedResetAbilitySync(true); + RefObject::DecObjRef(context); + } +} } // namespace DistributedDB diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.h b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.h index 7456da44c9ce0af3e30ce065ff4036e26f985bcd..ca4d176d6b281931a77765b8a13ec52dfe662d69 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_engine.h @@ -106,6 +106,8 @@ public: bool IsEngineActive() const override; + void ResetAbilitySync() override; + protected: // Create a context virtual ISyncTaskContext *CreateSyncTaskContext() = 0; @@ -116,6 +118,7 @@ protected: void GetQueryAutoSyncParam(const std::string &device, const QuerySyncObject &query, InternalSyncParma &outParam); void GetSubscribeSyncParam(const std::string &device, const QuerySyncObject &query, InternalSyncParma &outParam); + ISyncInterface *syncInterface_; // Used to store all send sync task infos (such as pull sync response, and push sync request) std::map syncTaskContextMap_; std::mutex contextMapLock_; @@ -185,7 +188,6 @@ private: static uint8_t GetPermissionCheckFlag(bool isAutoSync, int syncMode); - ISyncInterface *syncInterface_; ICommunicator *communicator_; DeviceManager *deviceManager_; std::function onRemoteDataChanged_; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.cpp index 70477fee5854b92e52a6a15e48d90b682e88c26c..8bb39a2e9b361aaf082d44bf0de534b2680d1fb8 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.cpp @@ -270,7 +270,6 @@ std::string SyncOperation::GetQueryId() const return query_.GetIdentify(); } - const std::map &SyncOperation::DBStatusTransMap() { static const std::map transMap = { @@ -287,6 +286,7 @@ const std::map &SyncOperation::DBStatusTransMap() { static_cast(OP_NOT_SUPPORT), NOT_SUPPORT }, { static_cast(OP_INTERCEPT_DATA_FAIL), INTERCEPT_DATA_FAIL }, { static_cast(OP_MAX_LIMITS), OVER_MAX_LIMITS }, + { static_cast(OP_SCHEMA_CHANGED), DISTRIBUTED_SCHEMA_CHANGED }, { static_cast(OP_INVALID_ARGS), INVALID_ARGS }, }; return transMap; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.h b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.h index 430f23f77352447eb66e6975e8bb19e1931a1098..46510a772122f193bb7eb956a3431a4ea387750e 100644 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_operation.h @@ -52,6 +52,7 @@ public: OP_NOT_SUPPORT, OP_INTERCEPT_DATA_FAIL, OP_MAX_LIMITS, + OP_SCHEMA_CHANGED, OP_INVALID_ARGS }; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_state_machine.h b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_state_machine.h index cf493e9e5ad100055172fcfb94cf9c3bd65fb412..9560631ba14afb766fc928893ad67a34dec02840 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_state_machine.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_state_machine.h @@ -101,7 +101,7 @@ protected: int SwitchMachineState(uint8_t event); // Do state switch with the event, and do syncstep - void SwitchStateAndStep(uint8_t event); + virtual void SwitchStateAndStep(uint8_t event); // To Exec next sync task in context targetQueue int ExecNextTask(); diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.cpp index 909d78c58abb1b42b27905e8706f7e8cf1611660..5204e8eccd8b5b31e2153384a96303932bb3ba13 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.cpp @@ -44,6 +44,7 @@ SyncTaskContext::SyncTaskContext() communicator_(nullptr), stateMachine_(nullptr), requestSessionId_(0), + lastRequestSessionId_(0), timeHelper_(nullptr), remoteSoftwareVersion_(0), remoteSoftwareVersionId_(0), @@ -555,8 +556,14 @@ void SyncTaskContext::CopyTargetData(const ISyncTarget *target, const TaskParam } requestSessionId_ = Hash::Hash32Func(deviceId_ + std::to_string(syncId_) + std::to_string(TimeHelper::GetSysCurrentTime())); + if (lastRequestSessionId_ == requestSessionId_) { + // Hash32Func max is 0x7fffffff and UINT32_MAX is 0xffffffff + requestSessionId_++; + LOGI("last sessionId is equal to this sessionId!"); + } LOGI("[SyncTaskContext][copyTarget] mode=%d,syncId=%d,isAutoSync=%d,isRetry=%d,dev=%s{private}", mode_, syncId_, isAutoSync_, syncTaskRetryStatus_, deviceId_.c_str()); + lastRequestSessionId_ = requestSessionId_; } else { isAutoSync_ = false; LOGI("[SyncTaskContext][copyTarget] for response data dev %s{private},isRetry=%d", deviceId_.c_str(), diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.h b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.h index 6efd23ad652a88691c7d0c6c841fdf236f77dd57..e7ed88459b3a4d664d145ff965a4561682ad9756 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.h +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/sync_task_context.h @@ -241,6 +241,7 @@ protected: int retryTime_ = 0; int isNeedRetry_ = SyncTaskContext::NO_NEED_RETRY; uint32_t requestSessionId_ = 0; + uint32_t lastRequestSessionId_ = 0; uint32_t sequenceId_ = 1; std::function onSyncTaskAdd_; diff --git a/services/distributeddataservice/libs/distributeddb/syncer/src/syncer_proxy.cpp b/services/distributeddataservice/libs/distributeddb/syncer/src/syncer_proxy.cpp index 3679cd30cec55ca561005be810949cafa1542b9c..a2a9a20b7ceefacc8365dc807cb204910abfd77a 100755 --- a/services/distributeddataservice/libs/distributeddb/syncer/src/syncer_proxy.cpp +++ b/services/distributeddataservice/libs/distributeddb/syncer/src/syncer_proxy.cpp @@ -104,12 +104,14 @@ void SyncerProxy::EnableAutoSync(bool enable) syncer_->EnableAutoSync(enable); } -int SyncerProxy::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash) +int SyncerProxy::EraseDeviceWaterMark(const std::string &deviceId, bool isNeedHash, + const std::string &tableName) { if (syncer_ == nullptr) { - return SyncerFactory::GetSyncer(ISyncInterface::SYNC_SVD)->EraseDeviceWaterMark(deviceId, isNeedHash); + LOGE("[SyncerProxy] Syncer no init, unknown rule to erase waterMark!"); + return -E_NOT_INIT; } - return syncer_->EraseDeviceWaterMark(deviceId, isNeedHash); + return syncer_->EraseDeviceWaterMark(deviceId, isNeedHash, tableName); } void SyncerProxy::LocalDataChanged(int notifyEvent) diff --git a/services/distributeddataservice/libs/distributeddb/test/BUILD.gn b/services/distributeddataservice/libs/distributeddb/test/BUILD.gn index 0a46a901d0de9dd55fbc67ebd04a8f49aefd6ec7..efda2409d0a8070fcc23e21f6e93c61004777a7b 100755 --- a/services/distributeddataservice/libs/distributeddb/test/BUILD.gn +++ b/services/distributeddataservice/libs/distributeddb/test/BUILD.gn @@ -58,6 +58,7 @@ config("module_private_config") { "JSONCPP_USE_BUILDER", "OMIT_FLATBUFFER", "RELATIONAL_STORE", + "SQLITE_DISTRIBUTE_RELATIONAL", ] } @@ -68,6 +69,7 @@ ohos_source_set("src_file") { sources = [ "../common/src/auto_launch.cpp", "../common/src/data_compression.cpp", + "../common/src/data_value.cpp", "../common/src/db_ability.cpp", "../common/src/db_common.cpp", "../common/src/db_constant.cpp", @@ -93,6 +95,7 @@ ohos_source_set("src_file") { "../common/src/relational/relational_schema_object.cpp", "../common/src/runtime_context.cpp", "../common/src/runtime_context_impl.cpp", + "../common/src/schema_constant.cpp", "../common/src/schema_object.cpp", "../common/src/schema_utils.cpp", "../common/src/semaphore_utils.cpp", @@ -124,7 +127,7 @@ ohos_source_set("src_file") { "../interfaces/src/kv_store_nb_delegate_impl.cpp", "../interfaces/src/kv_store_result_set_impl.cpp", "../interfaces/src/kv_store_snapshot_delegate_impl.cpp", - "../interfaces/src/relational/data_value.cpp", + "../interfaces/src/relational/relational_store_changed_data_impl.cpp", "../interfaces/src/relational/relational_store_delegate_impl.cpp", "../interfaces/src/relational/relational_store_manager.cpp", "../interfaces/src/relational/relational_store_sqlite_ext.cpp", @@ -219,7 +222,9 @@ ohos_source_set("src_file") { "../syncer/src/single_ver_data_message_schedule.cpp", "../syncer/src/single_ver_data_packet.cpp", "../syncer/src/single_ver_data_sync.cpp", + "../syncer/src/single_ver_kv_sync_task_context.cpp", "../syncer/src/single_ver_kv_syncer.cpp", + "../syncer/src/single_ver_relational_sync_task_context.cpp", "../syncer/src/single_ver_relational_syncer.cpp", "../syncer/src/single_ver_serialize_manager.cpp", "../syncer/src/single_ver_sync_engine.cpp", @@ -243,6 +248,7 @@ ohos_source_set("src_file") { "unittest/common/interfaces/process_system_api_adapter_impl.cpp", "unittest/common/syncer/generic_virtual_device.cpp", "unittest/common/syncer/kv_virtual_device.cpp", + "unittest/common/syncer/relational_virtual_device.cpp", "unittest/common/syncer/virtual_communicator.cpp", "unittest/common/syncer/virtual_communicator_aggregator.cpp", "unittest/common/syncer/virtual_multi_ver_sync_db_interface.cpp", @@ -621,6 +627,31 @@ distributeddb_unittest("DistributedDBSingleVerP2PSubscribeSyncTest") { sources = [ "unittest/common/syncer/distributeddb_single_ver_p2p_subsribe_sync_test.cpp" ] } +distributeddb_unittest("DistributedDBMockSyncModuleTest") { + sources = [ "unittest/common/syncer/distributeddb_mock_sync_module_test.cpp" ] +} + +distributeddb_unittest("DistributedInterfacesRelationalTest") { + sources = [ + "unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp", + ] +} + +distributeddb_unittest("DistributedDBRelationalSchemaObjectTest") { + sources = [ + "unittest/common/common/distributeddb_relational_schema_object_test.cpp", + ] +} + +distributeddb_unittest("DistributedDBInterfacesRelationalSyncTest") { + sources = [ "unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp" ] +} + +distributeddb_unittest("DistributedDBRelationalGetDataTest") { + sources = + [ "unittest/common/storage/distributeddb_relational_get_data_test.cpp" ] +} + ############################################################################### group("unittest") { testonly = true @@ -655,16 +686,20 @@ group("unittest") { ":DistributedDBInterfacesNBUnpublishTest", ":DistributedDBInterfacesQueryDBTest", ":DistributedDBInterfacesRegisterSyncDBTest", + ":DistributedDBInterfacesRelationalSyncTest", ":DistributedDBInterfacesSchemaDatabaseUpgradeTest", ":DistributedDBInterfacesSpaceManagementTest", ":DistributedDBInterfacesTransactionOptimizationTest", ":DistributedDBInterfacesTransactionSyncDBTest", ":DistributedDBInterfacesTransactionTest", ":DistributedDBJsonPrecheckUnitTest", + ":DistributedDBMockSyncModuleTest", ":DistributedDBMultiVerP2PSyncTest", ":DistributedDBMultiVerVacuumTest", ":DistributedDBNotificationChainTest", ":DistributedDBParcelTest", + ":DistributedDBRelationalGetDataTest", + ":DistributedDBRelationalSchemaObjectTest", ":DistributedDBSchemaObjectTest", ":DistributedDBSchemalTest", ":DistributedDBSingleVerMsgScheduleTest", @@ -688,6 +723,7 @@ group("unittest") { ":DistributedDBStorageTransactionRecordTest", ":DistributedDBSyncerDeviceManagerTest", ":DistributedDBTimeSyncTest", + ":DistributedInterfacesRelationalTest", ":RuntimeContextProcessSystemApiAdapterImplTest", ] } diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp index 7ad339b78cf5392e689f73296576f6603172c4b6..b4a84e5d34214c8da56aa1573ff3c79ee5b8c152 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp @@ -666,7 +666,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch007, TestSize.Level3) * @tc.expected: step1. success. */ RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback( - std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, true)); + std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, true), DBType::DB_KV); /** * @tc.steps: step2. RunCommunicatorLackCallback * @tc.expected: step2. success. @@ -709,7 +709,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch007, TestSize.Level3) g_statusMap.clear(); g_finished = false; } - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr, DBType::DB_KV); delete observer; } @@ -729,7 +729,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch008, TestSize.Level3) * @tc.expected: step1. success. */ RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback( - std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, false)); + std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, false), DBType::DB_KV); /** * @tc.steps: step2. RunCommunicatorLackCallback * @tc.expected: step2. success. @@ -747,7 +747,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch008, TestSize.Level3) std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); EXPECT_TRUE(observer->GetCallCount() == 0); EXPECT_TRUE(g_finished == false); - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr, DBType::DB_KV); delete observer; } @@ -766,7 +766,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch009, TestSize.Level3) * @tc.steps: step1. SetAutoLaunchRequestCallback * @tc.expected: step1. success. */ - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(AutoLaunchCallBackBadParam); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(AutoLaunchCallBackBadParam, DBType::DB_KV); /** * @tc.steps: step2. RunCommunicatorLackCallback * @tc.expected: step2. success. @@ -789,7 +789,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch009, TestSize.Level3) g_statusMap.clear(); g_finished = false; } - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr, DBType::DB_KV); delete observer; } @@ -809,9 +809,9 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch010, TestSize.Level3) * @tc.expected: step1. success. */ RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback( - std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, false)); + std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, false), DBType::DB_KV); - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr, DBType::DB_KV); /** * @tc.steps: step2. RunCommunicatorLackCallback * @tc.expected: step2. success. @@ -828,7 +828,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch010, TestSize.Level3) std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME)); EXPECT_TRUE(observer->GetCallCount() == 0); EXPECT_TRUE(g_finished == false); - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr, DBType::DB_KV); delete observer; } @@ -941,7 +941,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch013, TestSize.Level3) KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; ASSERT_TRUE(observer != nullptr); RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback( - std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, true)); + std::bind(AutoLaunchCallBack, std::placeholders::_1, std::placeholders::_2, observer, true), DBType::DB_KV); /** * @tc.steps: step2. RunOnConnectCallback RunCommunicatorLackCallback @@ -988,7 +988,7 @@ HWTEST_F(DistributedDBAutoLaunchUnitTest, AutoLaunch013, TestSize.Level3) g_statusMap.clear(); g_finished = false; } - RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr); + RuntimeContext::GetInstance()->SetAutoLaunchRequestCallback(nullptr, DBType::DB_KV); delete observer; /** * @tc.steps: step4. param A B disable diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.cpp index 7ff688c6497dd8e9c4049207e87beef13cbee2d1..74c440cf5760a9493eb95b611382a77b7aabae68 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.cpp @@ -14,7 +14,7 @@ */ #include "distributeddb_data_generate_unit_test.h" -#include "types.h" +#include "store_types.h" using namespace DistributedDB; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h index e78ce75ec1017508839ebbe76f5440bb3f3e1bac..3b6f8d8efef990940ada15ff4e02779217e9cb61 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.h @@ -19,7 +19,7 @@ #include #include #include "distributeddb_tools_unit_test.h" -#include "types.h" +#include "store_types.h" namespace DistributedDBUnitTest { // define some variables to init a KvStoreDelegateManager object. diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6a7ac034ad3c1aeb8038e64b50f21d6e655ed0c1 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2022 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 OMIT_JSON +#include +#include + +#include "db_errno.h" +#include "distributeddb_tools_unit_test.h" +#include "log_print.h" +#include "relational_schema_object.h" +#include "schema_utils.h" +#include "schema_constant.h" + +using namespace std; +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { + const std::string NORMAL_SCHEMA = R""({ + "SCHEMA_VERSION": "2.0", + "SCHEMA_TYPE": "RELATIVE", + "TABLES": [{ + "NAME": "FIRST", + "DEFINE": { + "field_name1": { + "COLUMN_ID":1, + "TYPE": "STRING", + "NOT_NULL": true, + "DEFAULT": "abcd" + }, + "field_name2": { + "COLUMN_ID":2, + "TYPE": "MYINT(21)", + "NOT_NULL": false, + "DEFAULT": "222" + }, + "field_name3": { + "COLUMN_ID":3, + "TYPE": "INTGER", + "NOT_NULL": false, + "DEFAULT": "1" + } + }, + "AUTOINCREMENT": true, + "UNIQUE": ["field_name1", ["field_name2", "field_name3"]], + "PRIMARY_KEY": "field_name1", + "INDEX": { + "index_name1": ["field_name1", "field_name2"], + "index_name2": ["field_name3"] + } + }, { + "NAME": "SECOND", + "DEFINE": { + "key": { + "COLUMN_ID":1, + "TYPE": "BLOB", + "NOT_NULL": true + }, + "value": { + "COLUMN_ID":2, + "TYPE": "BLOB", + "NOT_NULL": false + } + }, + "PRIMARY_KEY": "field_name1" + }] + })""; + + const std::string INVALID_SCHEMA = R""({ + "SCHEMA_VERSION": "2.0", + "SCHEMA_TYPE": "RELATIVE", + "TABLES": [{ + "NAME": "FIRST", + "DEFINE": { + "field_name1": { + "COLUMN_ID":1, + "TYPE": "STRING", + "NOT_NULL": true, + "DEFAULT": "abcd" + },"field_name2": { + "COLUMN_ID":2, + "TYPE": "MYINT(21)", + "NOT_NULL": false, + "DEFAULT": "222" + } + }, + "PRIMARY_KEY": "field_name1" + }] + })""; + + const std::string INVALID_JSON_STRING = R""({ + "SCHEMA_VERSION": "2.0", + "SCHEMA_TYPE": "RELATIVE", + "TABLES": [{ + "NAME": "FIRST", + "DEFINE": { + "field_name1": {)""; + + const std::string SCHEMA_VERSION_STR_1 = R"("SCHEMA_VERSION": "1.0",)"; + const std::string SCHEMA_VERSION_STR_2 = R"("SCHEMA_VERSION": "2.0",)"; + const std::string SCHEMA_VERSION_STR_INVALID = R"("SCHEMA_VERSION": "awd3",)"; + const std::string SCHEMA_TYPE_STR_NONE = R"("SCHEMA_TYPE": "NONE",)"; + const std::string SCHEMA_TYPE_STR_JSON = R"("SCHEMA_TYPE": "JSON",)"; + const std::string SCHEMA_TYPE_STR_FLATBUFFER = R"("SCHEMA_TYPE": "FLATBUFFER",)"; + const std::string SCHEMA_TYPE_STR_RELATIVE = R"("SCHEMA_TYPE": "RELATIVE",)"; + const std::string SCHEMA_TYPE_STR_INVALID = R"("SCHEMA_TYPE": "adewaaSAD",)"; + + const std::string SCHEMA_TABLE_STR = R""("TABLES": [{ + "NAME": "FIRST", + "DEFINE": { + "field_name1": { + "COLUMN_ID":1, + "TYPE": "STRING", + "NOT_NULL": true, + "DEFAULT": "abcd" + },"field_name2": { + "COLUMN_ID":2, + "TYPE": "MYINT(21)", + "NOT_NULL": false, + "DEFAULT": "222" + } + }, + "PRIMARY_KEY": "field_name1" + }])""; + + const std::string TABLE_DEFINE_STR = R""({ + "NAME": "FIRST", + "DEFINE": { + "field_name1": { + "COLUMN_ID":1, + "TYPE": "STRING", + "NOT_NULL": true, + "DEFAULT": "abcd" + },"field_name2": { + "COLUMN_ID":2, + "TYPE": "MYINT(21)", + "NOT_NULL": false, + "DEFAULT": "222" + } + }, + "PRIMARY_KEY": "field_name1" + })""; + + const std::string TABLE_DEFINE_STR_NAME = R""("NAME": "FIRST",)""; + const std::string TABLE_DEFINE_STR_NAME_INVALID = R"("NAME": 123,)"; + const std::string TABLE_DEFINE_STR_FIELDS = R""("DEFINE": { + "field_name1": { + "COLUMN_ID":1, + "TYPE": "STRING", + "NOT_NULL": true, + "DEFAULT": "abcd" + },"field_name2": { + "COLUMN_ID":2, + "TYPE": "MYINT(21)", + "NOT_NULL": false, + "DEFAULT": "222" + } + },)""; + const std::string TABLE_DEFINE_STR_FIELDS_EMPTY = R""("DEFINE": {},)""; + const std::string TABLE_DEFINE_STR_FIELDS_NOTYPE = R""("DEFINE": { + "field_name1": { + "COLUMN_ID":1, + "NOT_NULL": true, + "DEFAULT": "abcd" + }},)""; + const std::string TABLE_DEFINE_STR_KEY = R""("PRIMARY_KEY": "field_name1")""; + const std::string TABLE_DEFINE_STR_KEY_INVALID = R""("PRIMARY_KEY": false)""; +} + +class DistributedDBRelationalSchemaObjectTest : public testing::Test { +public: + static void SetUpTestCase(void) {}; + static void TearDownTestCase(void) {}; + void SetUp() override ; + void TearDown() override {}; +}; + +void DistributedDBRelationalSchemaObjectTest::SetUp() +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); +} + +/** + * @tc.name: RelationalSchemaParseTest001 + * @tc.desc: Test relational schema parse from json string + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest001, TestSize.Level1) +{ + const std::string schemaStr = NORMAL_SCHEMA; + RelationalSchemaObject schemaObj; + int errCode = schemaObj.ParseFromSchemaString(schemaStr); + EXPECT_EQ(errCode, E_OK); + + RelationalSchemaObject schemaObj2; + schemaObj2.ParseFromSchemaString(schemaObj.ToSchemaString()); + EXPECT_EQ(errCode, E_OK); +} + +/** + * @tc.name: RelationalSchemaParseTest002 + * @tc.desc: Test relational schema parse from invalid json string + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest002, TestSize.Level1) +{ + RelationalSchemaObject schemaObj; + + std::string schemaStr01(SchemaConstant::SCHEMA_STRING_SIZE_LIMIT + 1, 's'); + int errCode = schemaObj.ParseFromSchemaString(schemaStr01); + EXPECT_EQ(errCode, -E_INVALID_ARGS); + + errCode = schemaObj.ParseFromSchemaString(INVALID_JSON_STRING); + EXPECT_EQ(errCode, -E_JSON_PARSE_FAIL); + + std::string noVersion = "{" + SCHEMA_TYPE_STR_RELATIVE + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(noVersion); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidVersion1 = "{" + SCHEMA_VERSION_STR_1 + SCHEMA_TYPE_STR_RELATIVE + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(invalidVersion1); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidVersion2 = "{" + SCHEMA_VERSION_STR_INVALID + SCHEMA_TYPE_STR_RELATIVE + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(invalidVersion2); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string noType = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(noType); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidType1 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_NONE + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(invalidType1); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidType2 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_JSON + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(invalidType2); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidType3 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_FLATBUFFER + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(invalidType3); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidType4 = "{" + SCHEMA_VERSION_STR_2 + SCHEMA_TYPE_STR_INVALID + SCHEMA_TABLE_STR + "}"; + errCode = schemaObj.ParseFromSchemaString(invalidType4); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string noTable = "{" + SCHEMA_VERSION_STR_2 + + SCHEMA_TYPE_STR_RELATIVE.substr(0, SCHEMA_TYPE_STR_RELATIVE.length() - 1) + "}"; + errCode = schemaObj.ParseFromSchemaString(noTable); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); +} + +namespace { +std::string GenerateFromTableStr(const std::string tableStr) +{ + return R""({ + "SCHEMA_VERSION": "2.0", + "SCHEMA_TYPE": "RELATIVE", + "TABLES": )"" + tableStr + "}"; +} +} + +/** + * @tc.name: RelationalSchemaParseTest003 + * @tc.desc: Test relational schema parse from invalid json string + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaParseTest003, TestSize.Level1) +{ + RelationalSchemaObject schemaObj; + int errCode = E_OK; + + errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr(TABLE_DEFINE_STR)); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidTableStr01 = "{" + TABLE_DEFINE_STR_FIELDS + TABLE_DEFINE_STR_KEY + "}"; + errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr01 + "]")); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidTableStr02 = "{" + TABLE_DEFINE_STR_NAME_INVALID + TABLE_DEFINE_STR_FIELDS + + TABLE_DEFINE_STR_KEY + "}"; + errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr02 + "]")); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidTableStr04 = "{" + TABLE_DEFINE_STR_NAME + TABLE_DEFINE_STR_FIELDS_NOTYPE + + TABLE_DEFINE_STR_KEY + "}"; + errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr04 + "]")); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); + + std::string invalidTableStr05 = "{" + TABLE_DEFINE_STR_NAME + TABLE_DEFINE_STR_FIELDS + + TABLE_DEFINE_STR_KEY_INVALID + "}"; + errCode = schemaObj.ParseFromSchemaString(GenerateFromTableStr("[" + invalidTableStr05 + "]")); + EXPECT_EQ(errCode, -E_SCHEMA_PARSE_FAIL); +} + +/** + * @tc.name: RelationalSchemaCompareTest001 + * @tc.desc: Test relational schema negotiate with same schema string + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaCompareTest001, TestSize.Level1) +{ + RelationalSchemaObject schemaObj; + int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA); + EXPECT_EQ(errCode, E_OK); + + RelationalSyncOpinion opinion = RelationalSchemaObject::MakeLocalSyncOpinion(schemaObj, NORMAL_SCHEMA, + static_cast(SchemaType::RELATIVE)); + EXPECT_EQ(opinion.GetTableOpinion("FIRST").permitSync, true); + EXPECT_EQ(opinion.GetTableOpinion("FIRST").checkOnReceive, false); + EXPECT_EQ(opinion.GetTableOpinion("FIRST").requirePeerConvert, false); +} + +/** + * @tc.name: RelationalTableCompareTest001 + * @tc.desc: Test relational schema negotiate with same schema string + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalTableCompareTest001, TestSize.Level1) +{ + RelationalSchemaObject schemaObj; + int errCode = schemaObj.ParseFromSchemaString(NORMAL_SCHEMA); + EXPECT_EQ(errCode, E_OK); + TableInfo table1 = schemaObj.GetTable("FIRST"); + TableInfo table2 = schemaObj.GetTable("FIRST"); + EXPECT_EQ(table1.CompareWithTable(table2), -E_RELATIONAL_TABLE_EQUAL); + + table2.AddIndexDefine("indexname", {"field_name2", "field_name1"}); + EXPECT_EQ(table1.CompareWithTable(table2), -E_RELATIONAL_TABLE_COMPATIBLE); + + TableInfo table3 = schemaObj.GetTable("SECOND"); + EXPECT_EQ(table1.CompareWithTable(table3), -E_RELATIONAL_TABLE_INCOMPATIBLE); + + TableInfo table4 = schemaObj.GetTable("FIRST"); + table4.AddField(table3.GetFields().at("value")); + EXPECT_EQ(table1.CompareWithTable(table4), -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE); + + TableInfo table5 = schemaObj.GetTable("FIRST"); + table5.AddField(table3.GetFields().at("key")); + EXPECT_EQ(table1.CompareWithTable(table5), -E_RELATIONAL_TABLE_INCOMPATIBLE); +} + +/** + * @tc.name: RelationalSchemaOpinionTest001 + * @tc.desc: Test relational schema sync opinion + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaOpinionTest001, TestSize.Level1) +{ + const uint32_t softWareVersion = 106; + RelationalSyncOpinion opinion; + opinion.AddSyncOpinion("table_1", SyncOpinion {true, false, false}); + opinion.AddSyncOpinion("table_2", SyncOpinion {false, true, false}); + opinion.AddSyncOpinion("table_3", SyncOpinion {false, false, true}); + + uint32_t len = opinion.CalculateParcelLen(softWareVersion); + std::vector buff(len, 0); + Parcel writeParcel(buff.data(), len); + int errCode = opinion.SerializeData(writeParcel, softWareVersion); + EXPECT_EQ(errCode, E_OK); + + Parcel readParcel(buff.data(), len); + RelationalSyncOpinion opinionRecv; + errCode = RelationalSyncOpinion::DeserializeData(readParcel, opinionRecv); + EXPECT_EQ(errCode, E_OK); + + EXPECT_EQ(opinion.GetOpinions().size(), opinionRecv.GetOpinions().size()); + for (const auto &it : opinion.GetOpinions()) { + SyncOpinion tableOpinionRecv = opinionRecv.GetTableOpinion(it.first); + EXPECT_EQ(it.second.permitSync, tableOpinionRecv.permitSync); + EXPECT_EQ(it.second.requirePeerConvert, tableOpinionRecv.requirePeerConvert); + } +} + +/** + * @tc.name: RelationalSchemaNegotiateTest001 + * @tc.desc: Test relational schema negotiate + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, RelationalSchemaNegotiateTest001, TestSize.Level1) +{ + RelationalSyncOpinion localOpinion; + localOpinion.AddSyncOpinion("table_1", SyncOpinion {true, false, false}); + localOpinion.AddSyncOpinion("table_2", SyncOpinion {false, true, false}); + localOpinion.AddSyncOpinion("table_3", SyncOpinion {false, false, true}); + + RelationalSyncOpinion remoteOpinion; + remoteOpinion.AddSyncOpinion("table_2", SyncOpinion {true, false, false}); + remoteOpinion.AddSyncOpinion("table_3", SyncOpinion {false, true, false}); + remoteOpinion.AddSyncOpinion("table_4", SyncOpinion {false, false, true}); + RelationalSyncStrategy strategy = RelationalSchemaObject::ConcludeSyncStrategy(localOpinion, remoteOpinion); + + EXPECT_EQ(strategy.GetStrategies().size(), 2); + EXPECT_EQ(strategy.GetTableStrategy("table_2").permitSync, true); + EXPECT_EQ(strategy.GetTableStrategy("table_3").permitSync, false); +} + +/** + * @tc.name: TableCompareTest001 + * @tc.desc: Test table compare + * @tc.type: FUNC + * @tc.require: AR000GK58I + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest001, TestSize.Level1) +{ + FieldInfo field1; + field1.SetFieldName("a"); + FieldInfo field2; + field2.SetFieldName("b"); + FieldInfo field3; + field3.SetFieldName("c"); + FieldInfo field4; + field4.SetFieldName("d"); + + TableInfo table; + table.AddField(field2); + table.AddField(field3); + + TableInfo inTable1; + inTable1.AddField(field1); + inTable1.AddField(field2); + inTable1.AddField(field3); + EXPECT_EQ(table.CompareWithTable(inTable1), -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE); + + TableInfo inTable2; + inTable2.AddField(field1); + inTable2.AddField(field2); + inTable2.AddField(field4); + EXPECT_EQ(table.CompareWithTable(inTable2), -E_RELATIONAL_TABLE_INCOMPATIBLE); + + TableInfo inTable3; + inTable3.AddField(field3); + inTable3.AddField(field2); + EXPECT_EQ(table.CompareWithTable(inTable3), -E_RELATIONAL_TABLE_EQUAL); +} +#endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp index 5f53b5eeb4aec50f96ba6c2aa14f40634b205c3a..f7520db5a0767d6873732590094c716ca28db1e1 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_schema_object_test.cpp @@ -20,6 +20,7 @@ #include "db_errno.h" #include "distributeddb_tools_unit_test.h" #include "log_print.h" +#include "schema_constant.h" #include "schema_object.h" #include "schema_utils.h" @@ -382,17 +383,17 @@ std::string SchemaSwitchMode(const std::string &oriSchemaStr) { std::string resultSchemaStr = oriSchemaStr; auto iterForStrict = std::search(resultSchemaStr.begin(), resultSchemaStr.end(), - KEYWORD_MODE_STRICT.begin(), KEYWORD_MODE_STRICT.end()); + SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); auto iterForCompatible = std::search(resultSchemaStr.begin(), resultSchemaStr.end(), - KEYWORD_MODE_COMPATIBLE.begin(), KEYWORD_MODE_COMPATIBLE.end()); + SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); if (iterForStrict != resultSchemaStr.end()) { - resultSchemaStr.replace(iterForStrict, iterForStrict + KEYWORD_MODE_STRICT.size(), - KEYWORD_MODE_COMPATIBLE.begin(), KEYWORD_MODE_COMPATIBLE.end()); + resultSchemaStr.replace(iterForStrict, iterForStrict + SchemaConstant::KEYWORD_MODE_STRICT.size(), + SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); return resultSchemaStr; } if (iterForCompatible != resultSchemaStr.end()) { - resultSchemaStr.replace(iterForCompatible, iterForCompatible + KEYWORD_MODE_COMPATIBLE.size(), - KEYWORD_MODE_STRICT.begin(), KEYWORD_MODE_STRICT.end()); + resultSchemaStr.replace(iterForCompatible, iterForCompatible + SchemaConstant::KEYWORD_MODE_COMPATIBLE.size(), + SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); return resultSchemaStr; } return oriSchemaStr; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp index e15f218f8af58bbc950e5e726a48781f7f68e0b3..8a89423c2105065026b1b9278783d212a41789b1 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp @@ -712,6 +712,41 @@ bool KvStoreObserverUnitTest::IsCleared() const return isCleared_; } +RelationalStoreObserverUnitTest::RelationalStoreObserverUnitTest() : callCount_(0) +{ +} + +unsigned long RelationalStoreObserverUnitTest::GetCallCount() const +{ + return callCount_; +} + +void RelationalStoreObserverUnitTest::OnChange(const StoreChangedData& data) +{ + callCount_++; + changeDevice_ = data.GetDataChangeDevice(); + data.GetStoreProperty(storeProperty_); + LOGD("Onchangedata : %s", changeDevice_.c_str()); + LOGD("Onchange() called success!"); +} + +void RelationalStoreObserverUnitTest::ResetToZero() +{ + callCount_ = 0; + changeDevice_.clear(); + storeProperty_ = {}; +} + +const std::string RelationalStoreObserverUnitTest::GetDataChangeDevice() const +{ + return changeDevice_; +} + +DistributedDB::StoreProperty RelationalStoreObserverUnitTest::GetStoreProperty() const +{ + return storeProperty_; +} + DBStatus DistributedDBToolsUnitTest::SyncTest(KvStoreNbDelegate* delegate, const std::vector& devices, SyncMode mode, std::map& statuses, const Query &query) @@ -842,4 +877,65 @@ int DistributedDBToolsUnitTest::BuildMessage(const DataSyncMessageInfo &messageI message->SetExternalObject(packet); return E_OK; } + +sqlite3 *RelationalTestUtils::CreateDataBase(const std::string &dbUri) +{ + sqlite3 *db = nullptr; + if (int r = sqlite3_open_v2(dbUri.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr) != SQLITE_OK) { + LOGE("Open database [%s] failed. %d", dbUri.c_str(), r); + if (db != nullptr) { + (void)sqlite3_close_v2(db); + db = nullptr; + } + } + return db; +} + +int RelationalTestUtils::ExecSql(sqlite3 *db, const std::string &sql) +{ + if (db == nullptr || sql.empty()) { + return -E_INVALID_ARGS; + } + char *errMsg = nullptr; + int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, &errMsg); + if (errCode != SQLITE_OK && errMsg != nullptr) { + LOGE("Execute sql failed. %d err: %s", errCode, errMsg); + } + sqlite3_free(errMsg); + return errCode; +} + +void RelationalTestUtils::CreateDeviceTable(sqlite3 *db, const std::string &table, const std::string &device) +{ + ASSERT_NE(db, nullptr); + std::string deviceTable = DBCommon::GetDistributedTableName(device, table); + TableInfo baseTbl; + ASSERT_EQ(SQLiteUtils::AnalysisSchema(db, table, baseTbl), E_OK); + EXPECT_EQ(SQLiteUtils::CreateSameStuTable(db, baseTbl, deviceTable), E_OK); + EXPECT_EQ(SQLiteUtils::CloneIndexes(db, table, deviceTable), E_OK); +} + +int RelationalTestUtils::CheckSqlResult(sqlite3 *db, const std::string &sql, bool &result) +{ + if (db == nullptr || sql.empty()) { + return -E_INVALID_ARGS; + } + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + goto END; + } + + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + result = true; + errCode = E_OK; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + result = false; + errCode = E_OK; + } +END: + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} } // namespace DistributedDBUnitTest diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h index d6a8e2903252a2705449d10ddbdb9c4f957f2aaf..64e1b7ee21271bc8c3280f1486b0d5b39f644826 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h @@ -36,11 +36,13 @@ #include "log_print.h" #include "message.h" #include "query.h" +#include "store_observer.h" +#include "store_changed_data.h" #include "single_ver_kv_entry.h" #include "sqlite_single_ver_natural_store.h" #include "sqlite_utils.h" #include "sync_types.h" -#include "types.h" +#include "store_types.h" namespace DistributedDBUnitTest { static const int DIR_PERMISSION = 0750; @@ -252,6 +254,32 @@ private: std::list deleted_; }; +class RelationalStoreObserverUnitTest : public DistributedDB::StoreObserver { +public: + RelationalStoreObserverUnitTest(); + ~RelationalStoreObserverUnitTest() {} + + RelationalStoreObserverUnitTest(const RelationalStoreObserverUnitTest&) = delete; + RelationalStoreObserverUnitTest& operator=(const RelationalStoreObserverUnitTest&) = delete; + RelationalStoreObserverUnitTest(RelationalStoreObserverUnitTest&&) = delete; + RelationalStoreObserverUnitTest& operator=(RelationalStoreObserverUnitTest&&) = delete; + + // callback function will be called when the db data is changed. + void OnChange(const DistributedDB::StoreChangedData &data); + + // reset the callCount_ to zero. + void ResetToZero(); + + // get callback results. + unsigned long GetCallCount() const; + const std::string GetDataChangeDevice() const; + DistributedDB::StoreProperty GetStoreProperty() const; +private: + unsigned long callCount_; + std::string changeDevice_; + DistributedDB::StoreProperty storeProperty_; +}; + class KvStoreCorruptInfo { public: KvStoreCorruptInfo() {} @@ -270,6 +298,14 @@ public: private: std::vector databaseInfoVect_; }; + +class RelationalTestUtils { +public: + static sqlite3 *CreateDataBase(const std::string &dbUri); + static int ExecSql(sqlite3 *db, const std::string &sql); + static void CreateDeviceTable(sqlite3 *db, const std::string &table, const std::string &device); + static int CheckSqlResult(sqlite3 *db, const std::string &sql, bool &result); +}; } // namespace DistributedDBUnitTest #endif // DISTRIBUTEDDB_TOOLS_UNIT_TEST_H diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h index 76a33c374199e0f8fd580741a1e0ee03fd574443..1a31ba62bc29aac6445a4a792ddca1b84e7ef712 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/common/process_communicator_test_stub.h @@ -22,7 +22,7 @@ #include #include "iprocess_communicator.h" -#include "types.h" +#include "store_types.h" namespace DistributedDB { class ProcessCommunicatorTestStub : public IProcessCommunicator { diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp index 5956d322b36cafc512a8819391a022e5036a8ba8..1977e5d9979d950635d089ff9b7cb3d96312ca8c 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_operation_test.cpp @@ -1786,4 +1786,221 @@ HWTEST_F(DistributedDBInterfacesDataOperationTest, PrefixAndOther001, TestSize.L EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtrForQuery), OK); EXPECT_TRUE(g_mgr.DeleteKvStore("PrefixAndOther001") == OK); } -#endif \ No newline at end of file + +/** + * @tc.name: InKeys001 + * @tc.desc: InKeys query base function + * @tc.type: FUNC + * @tc.require: AR000EPARK + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeys001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a database And Preset Data + */ + KvStoreNbDelegate::Option option = {true, false, false}; + g_mgr.GetKvStore("InKeys001", option, g_kvNbDelegateCallbackForQuery); + ASSERT_NE(g_kvNbDelegatePtrForQuery, nullptr); + EXPECT_EQ(g_kvDelegateStatusForQuery, OK); + + Key key = {'1'}; + DBStatus status = g_kvNbDelegatePtrForQuery->Put(key, VALUE_1); + ASSERT_EQ(status, OK); + const int dataSize = 10; // 10 data for test + std::set keys; + for (uint8_t i = 0; i < dataSize; i++) { + key.push_back(i); + DBStatus status = g_kvNbDelegatePtrForQuery->Put(key, VALUE_1); + ASSERT_EQ(status, OK); + keys.emplace(key); + key.pop_back(); + } + + /** + * @tc.steps: step2. Call GetEntries With Query, set all keys at Inkeys. + * @tc.expected: step2. Returns KvStoreResultSet, the count is dataSize, + * all data are equals the preset data + */ + KvStoreResultSet *resultSet = nullptr; + g_kvNbDelegatePtrForQuery->GetEntries(Query::Select().InKeys(keys), resultSet); + ASSERT_NE(resultSet, nullptr); + ASSERT_EQ(resultSet->GetCount(), dataSize); + for (int i = 0; i < dataSize; i++) { + resultSet->MoveToPosition(i); + Entry entry; + resultSet->GetEntry(entry); + key.push_back(i); + EXPECT_EQ(key, entry.key); + EXPECT_EQ(entry.value, VALUE_1); + key.pop_back(); + } + g_kvNbDelegatePtrForQuery->CloseResultSet(resultSet); + + /** + * @tc.steps: step3. Call GetEntries With Query, set one other key at Inkeys. + * @tc.expected: step3. Returns KvStoreResultSet, the count is 0, + */ + g_kvNbDelegatePtrForQuery->GetEntries(Query::Select().InKeys({KEY_7}), resultSet); + ASSERT_NE(resultSet, nullptr); + ASSERT_EQ(resultSet->GetCount(), 0); + g_kvNbDelegatePtrForQuery->CloseResultSet(resultSet); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtrForQuery), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("InKeys001"), OK); +} + +/** + * @tc.name: InKeysLimit001 + * @tc.desc: InKeys query limit verification + * @tc.type: FUNC + * @tc.require: AR000EPARK + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysLimit001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a database + */ + KvStoreNbDelegate::Option option = {true, false, false}; + g_mgr.GetKvStore("InKeysLimit001", option, g_kvNbDelegateCallbackForQuery); + ASSERT_NE(g_kvNbDelegatePtrForQuery, nullptr); + EXPECT_EQ(g_kvDelegateStatusForQuery, OK); + + /** + * @tc.steps: step2. Construct a key set, and the key size over MAX_BATCH_SIZE + */ + std::set keys; + for (uint8_t i = 0; i < DBConstant::MAX_BATCH_SIZE + 1; i++) { + Key key = { i }; + keys.emplace(key); + } + + /** + * @tc.steps: step3. Call GetEntries With Query, set keys at Inkeys. + * @tc.expected: step3. Returns OVER_MAX_LIMITS, the resultSet is nullptr, + */ + KvStoreResultSet *resultSet = nullptr; + DBStatus status = g_kvNbDelegatePtrForQuery->GetEntries(Query::Select().InKeys(keys), resultSet); + EXPECT_EQ(status, OVER_MAX_LIMITS); + EXPECT_EQ(resultSet, nullptr); + + /** + * @tc.steps: step4. Call GetEntries With Query, set keys empty. + * @tc.expected: step4. Returns INVALID_ARGS, the resultSet is nullptr, + */ + status = g_kvNbDelegatePtrForQuery->GetEntries(Query::Select().InKeys({}), resultSet); + EXPECT_EQ(status, INVALID_ARGS); + EXPECT_EQ(resultSet, nullptr); + + /** + * @tc.steps: step4. Call GetEntries With Query, set a invalid key. + * @tc.expected: step4. Returns INVALID_ARGS, the resultSet is nullptr, + */ + status = g_kvNbDelegatePtrForQuery->GetEntries(Query::Select().InKeys({{}}), resultSet); + EXPECT_EQ(status, INVALID_ARGS); + EXPECT_EQ(resultSet, nullptr); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtrForQuery), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("InKeysLimit001"), OK); +} + +/** + * @tc.name: InKeysAndOther001 + * @tc.desc: Combination of InKeys query and logical filtering + * @tc.type: FUNC + * @tc.require: AR000EPARK + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a database And Preset Data + */ + KvStoreNbDelegate::Option option = {true, false, false}; + option.schema = SCHEMA_DEFINE2; + g_mgr.GetKvStore("InKeysAndOther001", option, g_kvNbDelegateCallbackForQuery); + ASSERT_NE(g_kvNbDelegatePtrForQuery, nullptr); + EXPECT_EQ(g_kvDelegateStatusForQuery, OK); + + PresetDataForPreifxAndOrderBy001(); + + std::set keys = { KEY_1, KEY_2, KEY_4 }; + std::vector entriesRes; + + /** + * @tc.steps: step2. Call GetEntries With Query, use EqualTo and InKeys + * @tc.expected: step2. Returns OK + */ + Query query1 = Query::Select().EqualTo("$.field_name1", 1).InKeys(keys); + int errCode = g_kvNbDelegatePtrForQuery->GetEntries(query1, entriesRes); + EXPECT_EQ(errCode, OK); + + /** + * @tc.steps: step3. Call GetEntries With Query, use InKeys and EqualTo + * @tc.expected: step3. Returns OK + */ + query1 = Query::Select().InKeys(keys).EqualTo("$.field_name1", 1); + errCode = g_kvNbDelegatePtrForQuery->GetEntries(query1, entriesRes); + EXPECT_EQ(errCode, OK); + + /** + * @tc.steps: step4. Call GetEntries With Query, use EqualTo, InKeys and EqualTo, all valid + * @tc.expected: step4. Returns OK + */ + query1 = Query::Select().EqualTo("$.field_name1", 1).InKeys(keys).And().EqualTo("$.field_name2", 2); + errCode = g_kvNbDelegatePtrForQuery->GetEntries(query1, entriesRes); + EXPECT_EQ(errCode, OK); + + /** + * @tc.steps: step4. Call GetEntries With Query, use EqualTo, InKeys and EqualTo, has invalid + * @tc.expected: step4. Returns NOT_FOUND + */ + query1 = Query::Select().EqualTo("$.field_name1", 1).InKeys(keys).And().EqualTo("$.field_name1", 2); + errCode = g_kvNbDelegatePtrForQuery->GetEntries(query1, entriesRes); + EXPECT_EQ(errCode, NOT_FOUND); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtrForQuery), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("InKeysAndOther001"), OK); +} + +/** + * @tc.name: InKeysAndOther002 + * @tc.desc: Combination of InKeys query and logical filtering + * @tc.type: FUNC + * @tc.require: AR000EPARK + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesDataOperationTest, InKeysAndOther002, TestSize.Level1) +{ + KvStoreNbDelegate::Option option = {true, false, false}; + option.schema = SCHEMA_DEFINE2; + g_mgr.GetKvStore("InKeysAndOther001", option, g_kvNbDelegateCallbackForQuery); + ASSERT_NE(g_kvNbDelegatePtrForQuery, nullptr); + EXPECT_EQ(g_kvDelegateStatusForQuery, OK); + + std::set keys = { KEY_1, KEY_2, KEY_4 }; + std::vector queries = { + Query::Select().PrefixKey({}).InKeys(keys).Or().EqualTo("$.field_name1", 2), + Query::Select().PrefixKey({}).InKeys(keys).And().EqualTo("$.field_name1", 2), + Query::Select().InKeys(keys).Or().EqualTo("$.field_name1", 2), + Query::Select().InKeys(keys).And().EqualTo("$.field_name1", 2), + Query::Select().PrefixKey({}).Or().EqualTo("$.field_name1", 2), + Query::Select().PrefixKey({}).And().EqualTo("$.field_name1", 2), + Query::Select().PrefixKey({}).And().InKeys(keys).EqualTo("$.field_name1", 2), + Query::Select().And().InKeys(keys).EqualTo("$.field_name1", 2), + Query::Select().Or().PrefixKey({}).EqualTo("$.field_name1", 2), + Query::Select().BeginGroup().PrefixKey({}).Or().EqualTo("$.field_name1", 2).EndGroup(), + Query::Select().EqualTo("$.field_name1", 2).Or().InKeys(keys), + Query::Select().EqualTo("$.field_name1", 2).Or().PrefixKey({}), + }; + + for (const auto &query : queries) { + std::vector entriesRes; + int errCode = g_kvNbDelegatePtrForQuery->GetEntries(query, entriesRes); + EXPECT_EQ(errCode, INVALID_QUERY_FORMAT); + } + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtrForQuery), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("InKeysAndOther001"), OK); +} +#endif // OMIT_JSON \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_value_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_value_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..661203e8479b864431796eff04d1f9feb94ed585 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_data_value_test.cpp @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2022 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 "distributeddb_tools_unit_test.h" +#include "data_value.h" + +using namespace testing::ext; +using namespace DistributedDB; + +namespace { +const int ONE_HUNDERED = 100; +const char DEFAULT_CHAR = 'D'; +const std::string DEFAULT_TEXT = "This is a text"; + +void DataValueDefaultNullCheck(DataValue &dataValue) +{ + /** + * @tc.steps: step1. create a dataValue + * @tc.expected: dataValue type is null. + */ + dataValue.ResetValue(); + EXPECT_EQ(dataValue.GetType(), StorageType::STORAGE_TYPE_NULL); +} + +void DataValueBoolCheck(DataValue &dataValue) +{ + /** + * @tc.steps: step1. create a dataValue and set true + * @tc.expected: dataValue type is bool. + */ + bool targetVal = true; + dataValue = targetVal; + EXPECT_EQ(dataValue.GetType(), StorageType::STORAGE_TYPE_BOOL); + /** + * @tc.steps: step2. get a value from dataValue + * @tc.expected: get ok and value is true. + */ + bool val = false; + EXPECT_EQ(dataValue.GetBool(val), E_OK); + EXPECT_EQ(val, targetVal); + /** + * @tc.steps: step3. set false and then get it from dataValue. + * @tc.expected: get ok and value is false. + */ + targetVal = false; + dataValue = targetVal; + EXPECT_EQ(dataValue.GetType(), StorageType::STORAGE_TYPE_BOOL); + EXPECT_EQ(dataValue.GetBool(val), E_OK); + EXPECT_EQ(targetVal, val); +} + +void DataValueDoubleCheck(DataValue &dataValue) +{ + /** + * @tc.steps: step1. create a dataValue and set true + * @tc.expected: dataValue type is double. + */ + double targetDoubleVal = 1.0; + dataValue = targetDoubleVal; + EXPECT_EQ(dataValue.GetType(), StorageType::STORAGE_TYPE_REAL); + /** + * @tc.steps: step2. get a double from dataValue + * @tc.expected: get ok and value is equal to targetDoubleVal. + */ + double val = 0; + EXPECT_EQ(dataValue.GetDouble(val), E_OK); + EXPECT_EQ(val, targetDoubleVal); +} + +void DataValueInt64Check(DataValue &dataValue) +{ + /** + * @tc.steps: step1. create a dataValue and set INTE64_MAX + * @tc.expected: dataValue type is int64. + */ + int64_t targetInt64Val = INT64_MAX; + dataValue = targetInt64Val; + EXPECT_EQ(dataValue.GetType(), StorageType::STORAGE_TYPE_INTEGER); + /** + * @tc.steps: step2. get a int64 from dataValue + * @tc.expected: get ok and value is equal to INTE64_MAX. + */ + int64_t val = INT64_MIN; + EXPECT_EQ(dataValue.GetInt64(val), E_OK); + EXPECT_EQ(val, targetInt64Val); +} + +void DataValueStringCheck(DataValue &dataValue) +{ + /** + * @tc.steps: step1. set a string + * @tc.expected: dataValue type is string. + */ + dataValue.SetText(DEFAULT_TEXT); + EXPECT_EQ(dataValue.GetType(), StorageType::STORAGE_TYPE_TEXT); + /** + * @tc.steps: step2. get a string from dataValue + * @tc.expected: get ok and string is equal to DEFAULT_TEXT. + */ + std::string val; + EXPECT_EQ(dataValue.GetText(val), E_OK); + EXPECT_EQ(val, DEFAULT_TEXT); +} + +void DataValueBlobCheck(DataValue &dataValue) +{ + /** + * @tc.steps: step1. set a blob + * @tc.expected: dataValue type is blob. + */ + Blob targetVal; + std::vector vector(ONE_HUNDERED, DEFAULT_CHAR); + targetVal.WriteBlob(reinterpret_cast(vector.data()), vector.size()); + dataValue.SetBlob(targetVal); + EXPECT_EQ(dataValue.GetType(), StorageType::STORAGE_TYPE_BLOB); + /** + * @tc.steps: step2. get a blob from dataValue + * @tc.expected: get ok and value is equal to DEFAULT_TEXT. + */ + Blob val; + EXPECT_EQ(dataValue.GetBlob(val), E_OK); + for (int i = 0; i < ONE_HUNDERED; i++) { + EXPECT_EQ(targetVal.GetData()[i], val.GetData()[i]); + } +} + +const std::vector g_checkFuncList = { + &DataValueDefaultNullCheck, &DataValueBoolCheck, &DataValueInt64Check, + &DataValueDoubleCheck, &DataValueStringCheck, &DataValueBlobCheck +}; + +class DistributedDBInterfacesDataValueTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBInterfacesDataValueTest::SetUpTestCase(void) +{ +} + +void DistributedDBInterfacesDataValueTest::TearDownTestCase(void) +{ +} + +void DistributedDBInterfacesDataValueTest::SetUp(void) +{ +} + +void DistributedDBInterfacesDataValueTest::TearDown(void) +{ +} + +/** + * @tc.name: DataValueCheck001 + * @tc.desc: To test dataValue work correctly when data is nullptr, bool, string, double, int64, uint8_t*. + * @tc.type: Func + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesDataValueTest, DataValueCheck001, TestSize.Level1) +{ + for (const auto &func : g_checkFuncList) { + DataValue dataValue; + func(dataValue); + } +} + +/** + * @tc.name: DataValueCheck002 + * @tc.desc: To test dataValue work correctly when different type overwrite into dataValue. + * @tc.type: Func + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesDataValueTest, DataValueCheck002, TestSize.Level1) +{ + for (uint32_t lastWriteIndex = 0; lastWriteIndex < g_checkFuncList.size(); lastWriteIndex++) { + DataValue dataValue; + for (uint32_t i = 0; i < g_checkFuncList.size(); i++) { + uint32_t index = (lastWriteIndex + i + 1) % static_cast(g_checkFuncList.size()); + g_checkFuncList[index](dataValue); + } + } +} +} \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp index dd7e39e7cd2c031ca2756e9b94374bc3ae8ffd9d..88935b39e64f8aaf7a5612d785d9a95ff608398e 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp @@ -20,6 +20,7 @@ #include "db_constant.h" #include "distributeddb_tools_unit_test.h" #include "query.h" +#include "schema_constant.h" #include "schema_utils.h" #include "sqlite_import.h" #include "sqlite_local_kvdb_connection.h" @@ -89,7 +90,7 @@ namespace { result += "_Level_"; result += to_string(level); if (fullLength) { - while (result.size() < SCHEMA_FEILD_NAME_LENGTH_MAX) { + while (result.size() < SchemaConstant::SCHEMA_FEILD_NAME_LENGTH_MAX) { result.push_back('_'); } } @@ -214,14 +215,14 @@ namespace { void PrepareCommonInfo(bool fullLength) { int serial = 0; - for (uint32_t level = 1; level <= SCHEMA_FEILD_PATH_DEPTH_MAX; level++) { + for (uint32_t level = 1; level <= SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; level++) { FieldPath path = GenerateFieldPath(level, serial, fullLength); string pathStr = SchemaUtils::FieldPathString(path); g_pathGroup1.push_back(path); g_pathStrGroup1.push_back(pathStr); serial++; } - for (uint32_t level = 1; level <= SCHEMA_FEILD_PATH_DEPTH_MAX; level++) { + for (uint32_t level = 1; level <= SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; level++) { FieldPath path = GenerateFieldPath(level, serial, fullLength); string pathStr = SchemaUtils::FieldPathString(path); g_pathGroup2.push_back(path); @@ -553,8 +554,8 @@ HWTEST_F(DistributedDBInterfacesIndexUnitTest, CreateIndex001, TestSize.Level1) namespace { void PrepareInfoForCreateIndex002() { - for (uint32_t serial = 0; serial < SCHEMA_INDEX_COUNT_MAX; serial++) { - FieldPath path = GenerateFieldPath(SCHEMA_FEILD_PATH_DEPTH_MAX, serial, true); + for (uint32_t serial = 0; serial < SchemaConstant::SCHEMA_INDEX_COUNT_MAX; serial++) { + FieldPath path = GenerateFieldPath(SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX, serial, true); string pathStr = SchemaUtils::FieldPathString(path); g_pathGroup1.push_back(path); g_pathStrGroup1.push_back(pathStr); diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp index 2080a5e4f7f1e50efb03da1a021ecf485e7282e6..fc1e84025c3ffe95477fc8cd30981ed7ba3801b8 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp @@ -1955,6 +1955,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MaxLogCheckPoint001, TestSize.Le EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); EXPECT_EQ(g_mgr.DeleteKvStore("MaxLogCheckPoint001"), OK); } + /** * @tc.name: CreateMemoryDbWithoutPath * @tc.desc: Create memory database without path. @@ -1974,4 +1975,45 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, CreateMemoryDbWithoutPath, TestS ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); EXPECT_TRUE(g_kvDelegateStatus == OK); EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); +} + +/** + * @tc.name: OpenStorePathCheckTest001 + * @tc.desc: Test open store with same label but different path. + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, OpenStorePathCheckTest001, TestSize.Level1) +{ + std::string dir1 = g_testDir + "/dbDir1"; + EXPECT_EQ(OS::MakeDBDirectory(dir1), E_OK); + std::string dir2 = g_testDir + "/dbDir2"; + EXPECT_EQ(OS::MakeDBDirectory(dir2), E_OK); + + KvStoreDelegateManager mgr1(APP_ID, USER_ID); + mgr1.SetKvStoreConfig({dir1}); + + KvStoreNbDelegate *delegate1 = nullptr; + auto callback1 = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, + placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(delegate1)); + + KvStoreNbDelegate::Option option; + mgr1.GetKvStore(STORE_ID_1, option, callback1); + EXPECT_EQ(g_kvDelegateStatus, OK); + ASSERT_NE(delegate1, nullptr); + + KvStoreNbDelegate *delegate2 = nullptr; + auto callback2 = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, + placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(delegate2)); + KvStoreDelegateManager mgr2(APP_ID, USER_ID); + mgr2.SetKvStoreConfig({dir2}); + mgr2.GetKvStore(STORE_ID_1, option, callback2); + EXPECT_EQ(g_kvDelegateStatus, INVALID_ARGS); + ASSERT_EQ(delegate2, nullptr); + + mgr1.CloseKvStore(delegate1); + mgr1.DeleteKvStore(STORE_ID_1); + mgr2.CloseKvStore(delegate2); + mgr2.DeleteKvStore(STORE_ID_1); } \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..052ee8cab995ba9278ca5d5897534d3d7eb92131 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2022 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 "db_common.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "log_print.h" +#include "relational_store_manager.h" +#include "virtual_communicator_aggregator.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"; + const std::string DEVICE_A = "DEVICE_A"; + std::string g_testDir; + std::string g_dbDir; + DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + VirtualCommunicatorAggregator* g_communicatorAggregator = 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 EMPTY_COLUMN_TYPE_CREATE_TABLE_SQL = "CREATE TABLE IF NOT EXISTS student(" \ + "id INTEGER NOT NULL UNIQUE," \ + "name TEXT," \ + "field_1);"; +} + +class DistributedDBRelationalSyncTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void) {}; + void SetUp() override ; + void TearDown() override; +protected: + sqlite3 *db = nullptr; + RelationalStoreDelegate *delegate = nullptr; +}; + +void DistributedDBRelationalSyncTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + + g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(g_communicatorAggregator != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); +} + +void DistributedDBRelationalSyncTest::SetUp() +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + + 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); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", DEVICE_A); + + 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"); + EXPECT_EQ(status, OK); +} + +void DistributedDBRelationalSyncTest::TearDown() +{ + g_mgr.CloseStore(delegate); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +/** + * @tc.name: RelationalSyncTest001 + * @tc.desc: Test with sync interface, table is not a distributed table + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest001, TestSize.Level1) +{ + std::vector devices = {DEVICE_A}; + Query query = Query::Select("sync_datb"); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, DISTRIBUTED_SCHEMA_NOT_FOUND); +} + +/** + * @tc.name: RelationalSyncTest002 + * @tc.desc: Test with sync interface, query is not support + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest002, TestSize.Level1) +{ + std::vector devices = {DEVICE_A}; + Query query = Query::Select("sync_data").Like("value", "abc"); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, NOT_SUPPORT); +} + +/** + * @tc.name: RelationalSyncTest003 + * @tc.desc: Test with sync interface, query is invalid format + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest003, TestSize.Level1) +{ + std::vector devices = {DEVICE_A}; + Query query = Query::Select("sync_data").And().Or().EqualTo("flag", 2); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, INVALID_QUERY_FORMAT); +} + +/** + * @tc.name: RelationalSyncTest004 + * @tc.desc: Test with sync interface, query use invalid field + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest004, TestSize.Level1) +{ + std::vector devices = {DEVICE_A}; + Query query = Query::Select("sync_data").EqualTo("fleg", 2); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, INVALID_QUERY_FIELD); +} + +/** + * @tc.name: RelationalSyncTest005 + * @tc.desc: Test with sync interface, query table has been modified + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest005, TestSize.Level1) +{ + std::string modifySql = "ALTER TABLE sync_data ADD COLUMN add_field INTEGER;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, modifySql), SQLITE_OK); + + std::vector devices = {DEVICE_A}; + Query query = Query::Select("sync_data"); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, DISTRIBUTED_SCHEMA_CHANGED); +} + +/** + * @tc.name: RelationalSyncTest006 + * @tc.desc: Test with sync interface, query is not set table name + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest006, TestSize.Level1) +{ + std::vector devices = {DEVICE_A}; + Query query = Query::Select(); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, NOT_SUPPORT); +} + +/** + * @tc.name: RelationalSyncTest007 + * @tc.desc: Test with sync interface, distributed table has empty column type + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest007, TestSize.Level1) +{ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, EMPTY_COLUMN_TYPE_CREATE_TABLE_SQL), SQLITE_OK); + RelationalTestUtils::CreateDeviceTable(db, "student", DEVICE_A); + + DBStatus status = delegate->CreateDistributedTable("student"); + EXPECT_EQ(status, OK); + + std::vector devices = {DEVICE_A}; + Query query = Query::Select("student"); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, OK); +} + +/** + * @tc.name: RelationalSyncTest008 + * @tc.desc: Test sync with rebuilt table + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBRelationalSyncTest, RelationalSyncTest008, TestSize.Level1) +{ + /** + * @tc.steps:step1. Drop sync_data + * @tc.expected: step1. ok + */ + std::string dropSql = "DROP TABLE IF EXISTS sync_data;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, dropSql), SQLITE_OK); + + /** + * @tc.steps:step2. sync with sync_data + * @tc.expected: step2. return INVALID_QUERY_FORMAT + */ + std::vector devices = {DEVICE_A}; + Query query = Query::Select("sync_data"); + int errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + EXPECT_EQ(errCode, INVALID_QUERY_FORMAT); + + /** + * @tc.steps:step3. recreate sync_data + * @tc.expected: step3. ok + */ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + DBStatus status = delegate->CreateDistributedTable("sync_data"); + EXPECT_EQ(status, OK); + + /** + * @tc.steps:step4. Check trigger + * @tc.expected: step4. trigger exists + */ + bool result = false; + std::string checkSql = "select * from sqlite_master where type = 'trigger' and tbl_name = 'sync_data';"; + EXPECT_EQ(RelationalTestUtils::CheckSqlResult(db, checkSql, result), E_OK); + EXPECT_EQ(result, true); + + /** + * @tc.steps:step5. sync with sync_data + * @tc.expected: step5. ok + */ + errCode = delegate->Sync(devices, SyncMode::SYNC_MODE_PUSH_ONLY, query, + [&devices](const std::map> &devicesMap) { + EXPECT_EQ(devicesMap.size(), devices.size()); + }, true); + + EXPECT_EQ(errCode, OK); +} \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3bee2a165a0cc8583f982e9eeeb754819055d007 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -0,0 +1,610 @@ +/* + * Copyright (c) 2022 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 "db_common.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "log_print.h" +#include "platform_specific.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_testDir; + std::string g_dbDir; + DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + + 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 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);"; +} + +class DistributedDBInterfacesRelationalTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBInterfacesRelationalTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; +} + +void DistributedDBInterfacesRelationalTest::TearDownTestCase(void) +{ +} + +void DistributedDBInterfacesRelationalTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); +} + +void DistributedDBInterfacesRelationalTest::TearDown(void) +{ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); +} + +/** + * @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) +{ + /** + * @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); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A"); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. open relational store, create distributed table, close store + * @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"); + EXPECT_EQ(status, OK); + + // test create same table again + status = delegate->CreateDistributedTable("sync_data"); + EXPECT_EQ(status, OK); + + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + + /** + * @tc.steps:step3. drop sync_data table + * @tc.expected: step3. Return OK. + */ + db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "drop table sync_data;"), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step4. open again, check auxiliary should be delete + * @tc.expected: step4. Return OK. + */ + delegate = nullptr; + status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); +} + +/** + * @tc.name: RelationalStoreTest002 + * @tc.desc: Test open store with invalid path or store ID + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest002, TestSize.Level1) +{ + /** + * @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. Test open store with invalid path or store ID + * @tc.expected: step2. open store failed. + */ + RelationalStoreDelegate *delegate = nullptr; + + // test open store with path not exist + DBStatus status = g_mgr.OpenStore(g_dbDir + "tmp/" + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_NE(status, OK); + ASSERT_EQ(delegate, nullptr); + + // test open store with empty store_id + status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, {}, {}, delegate); + EXPECT_NE(status, OK); + ASSERT_EQ(delegate, nullptr); + + // test open store with path has invalid character + status = g_mgr.OpenStore(g_dbDir + "t&m$p/" + STORE_ID + DB_SUFFIX, {}, {}, delegate); + EXPECT_NE(status, OK); + ASSERT_EQ(delegate, nullptr); + + // test open store with store_id has invalid character + status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, "Relation@al_S$tore_ID", {}, delegate); + EXPECT_NE(status, OK); + ASSERT_EQ(delegate, nullptr); + + // test open store with store_id length over MAX_STORE_ID_LENGTH + status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, + std::string(DBConstant::MAX_STORE_ID_LENGTH + 1, 'a'), {}, delegate); + EXPECT_NE(status, OK); + ASSERT_EQ(delegate, nullptr); +} + +/** + * @tc.name: RelationalStoreTest003 + * @tc.desc: Test open store with journal_mode is not WAL + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. Prepare db file with string is not WAL + * @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=PERSIST;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. Test open store + * @tc.expected: step2. Open store failed. + */ + RelationalStoreDelegate *delegate = nullptr; + + // test open store with journal mode is not WAL + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_NE(status, OK); + 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) +{ + /** + * @tc.steps:step1. Prepare db file with multiple tables + * @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); + 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); + } else { + EXPECT_NE(delegate->CreateDistributedTable("TEST_" + std::to_string(i)), OK); + } + } + + /** + * @tc.steps:step3. Close store + * @tc.expected: step3. Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); +} + +/** + * @tc.name: RelationalStoreTest005 + * @tc.desc: Test create distributed table with invalid table name + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest005, TestSize.Level1) +{ + /** + * @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 store + * @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); + + /** + * @tc.steps:step3. Create distributed table with invald table name + * @tc.expected: step3. Create distributed table failed. + */ + EXPECT_NE(delegate->CreateDistributedTable(DBConstant::SYSTEM_TABLE_PREFIX + "_tmp"), OK); + + /** + * @tc.steps:step4. Close store + * @tc.expected: step4. Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); +} + +/** + * @tc.name: RelationalStoreTest005 + * @tc.desc: Test create distributed table with non primary key schema + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalStoreTest006, TestSize.Level1) +{ + /** + * @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, CREATE_TABLE_SQL_NO_PRIMARY_KEY), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. Open store + * @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); + + /** + * @tc.steps:step3. Create distributed table with invald table name + * @tc.expected: step3. Create distributed table failed. + */ + EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + + /** + * @tc.steps:step4. Close store + * @tc.expected: step4. Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + delegate = nullptr; + + status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); +} + +namespace { +void TableModifyTest(const std::string &modifySql, DBStatus expect) +{ + /** + * @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); + + /** + * @tc.steps:step2. Open store + * @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); + + /** + * @tc.steps:step3. Create distributed table + * @tc.expected: step3. Create distributed table OK. + */ + EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + + /** + * @tc.steps:step4. Upgrade table with modifySql + * @tc.expected: step4. return OK + */ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, modifySql), SQLITE_OK); + + /** + * @tc.steps:step5. Create distributed table again + * @tc.expected: step5. Create distributed table return expect. + */ + EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), expect); + + /** + * @tc.steps:step6. Close store + * @tc.expected: step6 Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} +} + +/** + * @tc.name: RelationalTableModifyTest001 + * @tc.desc: Test modify distributed table with compatible upgrade + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest001, TestSize.Level1) +{ + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER;", OK); +} + +/** + * @tc.name: RelationalTableModifyTest002 + * @tc.desc: Test modify distributed table with incompatible upgrade + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest002, TestSize.Level1) +{ + TableModifyTest("ALTER TABLE sync_data ADD COLUMN add_field INTEGER NOT NULL;", SCHEMA_MISMATCH); +} + +/** + * @tc.name: RelationalTableModifyTest003 + * @tc.desc: Test modify distributed table with incompatible upgrade + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalTableModifyTest003, TestSize.Level1) +{ + TableModifyTest("ALTER TABLE sync_data DROP COLUMN w_timestamp;", SCHEMA_MISMATCH); +} + +/** + * @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) +{ + /** + * @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); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A"); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_B"); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_C"); + + /** + * @tc.steps:step2. Open store + * @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); + + /** + * @tc.steps:step3. Create distributed table + * @tc.expected: step3. Create distributed table OK. + */ + EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + + /** + * @tc.steps:step4. Upgrade table + * @tc.expected: step4. return OK + */ + std::string modifySql = "ALTER TABLE sync_data ADD COLUMN add_field INTEGER;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, modifySql), SQLITE_OK); + std::string indexSql = "CREATE INDEX add_index ON sync_data (add_field);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, indexSql), SQLITE_OK); + std::string deleteIndexSql = "DROP INDEX IF EXISTS key_index"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, deleteIndexSql), SQLITE_OK); + + /** + * @tc.steps:step5. Create distributed table again + * @tc.expected: step5. Create distributed table return expect. + */ + EXPECT_EQ(delegate->CreateDistributedTable("sync_data"), OK); + + /** + * @tc.steps:step6. Close store + * @tc.expected: step6 Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: RelationalRemoveDeviceDataTest001 + * @tc.desc: Test remove device data + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalRemoveDeviceDataTest001, TestSize.Level1) +{ + /** + * @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); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_A"); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_B"); + RelationalTestUtils::CreateDeviceTable(db, "sync_data", "DEVICE_C"); + + /** + * @tc.steps:step2. Open store + * @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); + + /** + * @tc.steps:step3. Remove device data + * @tc.expected: step3. ok + */ + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_A"), OK); + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_B"), OK); + EXPECT_EQ(delegate->RemoveDeviceData("DEVICE_C", "sync_data"), OK); + + /** + * @tc.steps:step4. Close store + * @tc.expected: step4 Return OK. + */ + status = g_mgr.CloseStore(delegate); + EXPECT_EQ(status, OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +} + +/** + * @tc.name: RelationalOpenStorePathCheckTest001 + * @tc.desc: Test open store with same label but different path. + * @tc.type: FUNC + * @tc.require: AR000GK58F + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, RelationalOpenStorePathCheckTest001, TestSize.Level1) +{ + std::string dir1 = g_dbDir + "dbDir1"; + EXPECT_EQ(OS::MakeDBDirectory(dir1), E_OK); + sqlite3 *db1 = RelationalTestUtils::CreateDataBase(dir1 + STORE_ID + DB_SUFFIX); + ASSERT_NE(db1, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db1, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db1, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db1), SQLITE_OK); + + std::string dir2 = g_dbDir + "dbDir2"; + EXPECT_EQ(OS::MakeDBDirectory(dir2), E_OK); + sqlite3 *db2 = RelationalTestUtils::CreateDataBase(dir2 + STORE_ID + DB_SUFFIX); + ASSERT_NE(db2, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db2, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db2, NORMAL_CREATE_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db2), SQLITE_OK); + + DBStatus status = OK; + RelationalStoreDelegate *delegate1 = nullptr; + status = g_mgr.OpenStore(dir1 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate1); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate1, nullptr); + + RelationalStoreDelegate *delegate2 = nullptr; + status = g_mgr.OpenStore(dir2 + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate2); + EXPECT_EQ(status, INVALID_ARGS); + ASSERT_EQ(delegate2, nullptr); + + status = g_mgr.CloseStore(delegate1); + EXPECT_EQ(status, OK); + + status = g_mgr.CloseStore(delegate2); + EXPECT_EQ(status, INVALID_ARGS); +} \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp index 560285b8c4ea4bfedc02e5f5db1d886333a92ec1..0ded0a669fe1f7e81b1791467849509df56a4af3 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_resultset_performance.cpp @@ -19,7 +19,7 @@ #include "kv_store_delegate_manager.h" #include "kv_store_nb_delegate.h" #include "log_print.h" -#include "types.h" +#include "store_types.h" using namespace testing::ext; using namespace DistributedDB; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp index 6ca726e0114aaa1f6f04ab1feb8f1aefa554bcb8..d8e4caf6f71fdefb23d3b9d87145bd916fd6ee92 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_schema_database_upgrade_test.cpp @@ -17,6 +17,7 @@ #include #include "distributeddb_tools_unit_test.h" #include "kv_store_delegate_manager.h" +#include "schema_constant.h" #include "schema_object.h" #include "schema_utils.h" @@ -79,18 +80,18 @@ namespace { std::string SchemaSwitchMode(const std::string &oriSchemaStr) { std::string resStr = oriSchemaStr; - auto iterStrict = std::search(resStr.begin(), resStr.end(), KEYWORD_MODE_STRICT.begin(), - KEYWORD_MODE_STRICT.end()); - auto iterCompatible = std::search(resStr.begin(), resStr.end(), KEYWORD_MODE_COMPATIBLE.begin(), - KEYWORD_MODE_COMPATIBLE.end()); + auto iterStrict = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_STRICT.begin(), + SchemaConstant::KEYWORD_MODE_STRICT.end()); + auto iterCompatible = std::search(resStr.begin(), resStr.end(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), + SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); if (iterStrict != resStr.end()) { - resStr.replace(iterStrict, iterStrict + KEYWORD_MODE_STRICT.size(), KEYWORD_MODE_COMPATIBLE.begin(), - KEYWORD_MODE_COMPATIBLE.end()); + resStr.replace(iterStrict, iterStrict + SchemaConstant::KEYWORD_MODE_STRICT.size(), + SchemaConstant::KEYWORD_MODE_COMPATIBLE.begin(), SchemaConstant::KEYWORD_MODE_COMPATIBLE.end()); return resStr; } if (iterCompatible != resStr.end()) { - resStr.replace(iterCompatible, iterCompatible + KEYWORD_MODE_COMPATIBLE.size(), KEYWORD_MODE_STRICT.begin(), - KEYWORD_MODE_STRICT.end()); + resStr.replace(iterCompatible, iterCompatible + SchemaConstant::KEYWORD_MODE_COMPATIBLE.size(), + SchemaConstant::KEYWORD_MODE_STRICT.begin(), SchemaConstant::KEYWORD_MODE_STRICT.end()); return resStr; } return oriSchemaStr; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h index b3aec5ce646232e7a9839c2a0866d7e70c44c4d7..474e71d518ed1bd6be20eaf57fc55c611c0c2c56 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/interfaces/process_system_api_adapter_impl.h @@ -21,7 +21,7 @@ #include #include "iprocess_system_api_adapter.h" -#include "types.h" +#include "store_types.h" namespace DistributedDB { class ProcessSystemApiAdapterImpl : public IProcessSystemApiAdapter { diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_data_transformer_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_data_transformer_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac0c770b142ba5fdaa462dd88e8e6a6bbe09e816 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_data_transformer_test.cpp @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2022 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 "data_transformer.h" + +using namespace testing::ext; +using namespace DistributedDB; +namespace { +const int ONE_HUNDERED = 100; +const char DEFAULT_CHAR = 'D'; +const std::string DEFAULT_TEXT = "This is a text"; +const std::vector DEFAULT_BLOB(ONE_HUNDERED, DEFAULT_CHAR); +void SetNull(DataValue &dataValue) +{ + dataValue.ResetValue(); +} + +void SetBool(DataValue &dataValue) +{ + dataValue = false; +} + +void SetInt64(DataValue &dataValue) +{ + dataValue = INT64_MAX; +} + +void SetDouble(DataValue &dataValue) +{ + dataValue = 1.0; +} + +void SetText(DataValue &dataValue) +{ + dataValue.SetText(DEFAULT_TEXT); +} + +void SetBlob(DataValue &dataValue) +{ + Blob blob; + blob.WriteBlob(DEFAULT_BLOB.data(), DEFAULT_BLOB.size()); + dataValue.SetBlob(blob); +} + +std::map g_typeMapFunction = { + {StorageType::STORAGE_TYPE_NULL, &SetNull}, + {StorageType::STORAGE_TYPE_BOOL, &SetBool}, + {StorageType::STORAGE_TYPE_INTEGER, &SetInt64}, + {StorageType::STORAGE_TYPE_REAL, &SetDouble}, + {StorageType::STORAGE_TYPE_TEXT, &SetText}, + {StorageType::STORAGE_TYPE_BLOB, &SetBlob} +}; + +void GenerateRowData(const std::vector &fieldInfoList, RowData &rowData) +{ + for (auto &item: fieldInfoList) { + DataValue dataValue; + StorageType type = StorageType::STORAGE_TYPE_NULL; + if (g_typeMapFunction.find(item.GetStorageType()) != g_typeMapFunction.end()) { + type = item.GetStorageType(); + } + g_typeMapFunction[type](dataValue); + rowData.push_back(std::move(dataValue)); + } +} + +void GenerateTableDataWithLog(const std::vector &fieldInfoList, TableDataWithLog &tableDataWithLog) +{ + tableDataWithLog.tableName = DEFAULT_TEXT; + for (int i = 0; i < ONE_HUNDERED; i++) { + RowDataWithLog rowDataWithLog; + GenerateRowData(fieldInfoList, rowDataWithLog.rowData); + LogInfo logInfo; + // choose first element as primary key + logInfo.dataKey = i; + tableDataWithLog.dataList.push_back(std::move(rowDataWithLog)); + } +} + +bool Equal(const LogInfo &origin, const LogInfo &target) +{ + if (origin.dataKey != target.dataKey) { + return false; + } + if (origin.device != target.device) { + return false; + } + if (origin.flag != target.flag) { + return false; + } + if (origin.hashKey != target.hashKey) { + return false; + } + if (origin.originDev != target.originDev) { + return false; + } + if (origin.timestamp != target.timestamp) { + return false; + } + if (origin.wTimeStamp != target.wTimeStamp) { + return false; + } + return true; +} + +bool Equal(const RowDataWithLog &origin, const OptRowDataWithLog &target) +{ + if (!Equal(origin.logInfo, target.logInfo)) { + return false; + } + if (origin.rowData.size() != target.optionalData.size()) { + return false; + } + for (uint32_t i = 0; i < origin.rowData.size(); i++) { + const auto &originData = origin.rowData[i]; + const auto &targetData = target.optionalData[i]; + if (!targetData.has_value()) { + return false; + } + if (originData != targetData.value()) { + LOGD("VALUE NOT EQUAL!"); + return false; + } + } + return true; +} + +bool Equal(TableDataWithLog origin, OptTableDataWithLog target) +{ + if (origin.dataList.size() != target.dataList.size()) { + return false; + } + for (uint32_t i = 0; i < origin.dataList.size(); i++) { + RowDataWithLog originData = origin.dataList[i]; + OptRowDataWithLog targetData = target.dataList[i]; + if (!Equal(originData, targetData)) { + return false; + } + } + return true; +} + +void GenerateDiffFieldInfo(std::vector &sendFieldInfoList, std::vector &receiveFieldInfoList) +{ + const int columnCounts = 6; // 6 columns + const char sendColumn = 'A'; // sendColumn start with 'A' + const char receiveColumn = 'B'; // receiveColumn start with 'B' + // we generate 2 diff schema here (A, B, C, D, E, F) and (B, C, D, E, F, G) + for (uint32_t i = 0; i < columnCounts; i++) { + FieldInfo sendFieldInfo; + sendFieldInfo.SetFieldName(std::string(1, static_cast(sendColumn + i))); + sendFieldInfo.SetStorageType(StorageType::STORAGE_TYPE_INTEGER); + sendFieldInfoList.push_back(sendFieldInfo); + FieldInfo receiveFieldInfo; + receiveFieldInfo.SetFieldName(std::string(1, static_cast(receiveColumn + i))); + receiveFieldInfo.SetStorageType(StorageType::STORAGE_TYPE_INTEGER); + receiveFieldInfoList.push_back(receiveFieldInfo); + } +} +} + +class DistributedDBDataTransformerTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBDataTransformerTest::SetUpTestCase(void) +{ +} + +void DistributedDBDataTransformerTest::TearDownTestCase(void) +{ +} + +void DistributedDBDataTransformerTest::SetUp(void) +{ +} + +void DistributedDBDataTransformerTest::TearDown(void) +{ +} + +/** + * @tc.name: DataTransformerCheck001 + * @tc.desc: To test transformer work correctly when data contains nullptr, bool, string, double, int64, uint8_t*. + * @tc.type: Func + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBDataTransformerTest, DataTransformerCheck001, TestSize.Level1) +{ + /** + * @tc.steps: step1. generate the fieldInfoList which contains nullptr, bool, string, double, int64, uint8_t*. + */ + std::vector fieldInfoList; + int count = 0; + for (const auto &item : g_typeMapFunction) { + FieldInfo fieldInfo; + fieldInfo.SetStorageType(item.first); + fieldInfo.SetFieldName(std::to_string(count++)); + fieldInfoList.push_back(fieldInfo); + } + + /** + * @tc.steps: step2. generate a originData by fieldInfoLiist. + */ + TableDataWithLog originData; + GenerateTableDataWithLog(fieldInfoList, originData); + + /** + * @tc.steps: step3. transform originData to KV data and transform back to relationData. + * @tc.expected: get ok and value has no change + */ + std::vector dataItemList; + EXPECT_EQ(DataTransformer::TransformTableData(originData, fieldInfoList, dataItemList), E_OK); + + OptTableDataWithLog targetData; + EXPECT_EQ(DataTransformer::TransformDataItem(dataItemList, fieldInfoList, fieldInfoList, targetData), E_OK); + + EXPECT_TRUE(Equal(originData, targetData)); +} + +/** + * @tc.name: DataTransformerCheck002 + * @tc.desc: To test transformer work correctly when table is different between send and receive. + * @tc.type: Func + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBDataTransformerTest, DataTransformerCheck002, TestSize.Level1) +{ + /** + * @tc.steps: step1. generate the fieldInfoList which contains nullptr, bool, string, double, int64, uint8_t*. + */ + std::vector sendFieldInfoList; + std::vector receiveFieldInfoList; + GenerateDiffFieldInfo(sendFieldInfoList, receiveFieldInfoList); + + /** + * @tc.steps: step2. generate a originData by fieldInfoList. + */ + TableDataWithLog originData; + GenerateTableDataWithLog(sendFieldInfoList, originData); + + /** + * @tc.steps: step3. get a value from dataValue. + * @tc.expected: get ok and value is true + */ + std::vector dataItemList; + EXPECT_EQ(DataTransformer::TransformTableData(originData, sendFieldInfoList, dataItemList), E_OK); + + OptTableDataWithLog targetData; + EXPECT_EQ(DataTransformer::TransformDataItem(dataItemList, sendFieldInfoList, receiveFieldInfoList, + targetData), E_OK); + + DataValue target; + target = INT64_MAX; + EXPECT_EQ(targetData.dataList.size(), dataItemList.size()); + for (const auto &optDataWithLog : targetData.dataList) { + for (uint32_t i = 0; i < optDataWithLog.optionalData.size(); i++) { + const std::optional &optData = optDataWithLog.optionalData[i]; + if (i == optDataWithLog.optionalData.size() - 1) { + EXPECT_TRUE(!optData.has_value()); + } else { + EXPECT_TRUE(optData.has_value()); + EXPECT_EQ(optData.value(), target); + } + } + } +} \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp index 503e0d5d0db502d8feccc3fbfc647a220f088773..e2b0dfa32d44aa6c5a2a00e4020482b90cc663b6 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_get_data_test.cpp @@ -25,6 +25,7 @@ #include "generic_single_ver_kv_entry.h" #include "kvdb_properties.h" #include "log_print.h" +#include "relational_schema_object.h" #include "relational_store_delegate.h" #include "relational_store_instance.h" #include "relational_store_manager.h" @@ -163,6 +164,39 @@ int GetCount(sqlite3 *db, const string &sql, size_t &count) SQLiteUtils::ResetStatement(stmt, true, errCode); return errCode; } + +int PutBatchData(uint32_t totalCount, uint32_t valueSize) +{ + sqlite3 *db = nullptr; + sqlite3_stmt *stmt = nullptr; + const string sql = "INSERT INTO " + g_tableName + " VALUES(?,?);"; + int errCode = sqlite3_open(g_storePath.c_str(), &db); + if (errCode != SQLITE_OK) { + goto ERROR; + } + errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + goto ERROR; + } + for (uint32_t i = 0; i < totalCount; i++) { + errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, Value(valueSize, 'a'), false); + if (errCode != E_OK) { + break; + } + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + break; + } + errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, false, errCode); + } + +ERROR: + SQLiteUtils::ResetStatement(stmt, true, errCode); + errCode = SQLiteUtils::MapSQLiteErrno(errCode); + sqlite3_close(db); + return errCode; +} } class DistributedDBRelationalGetDataTest : public testing::Test { @@ -193,7 +227,6 @@ void DistributedDBRelationalGetDataTest::TearDown(void) { if (g_delegate != nullptr) { EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK); - EXPECT_EQ(g_mgr.DeleteStore(g_storePath), DBStatus::OK); g_delegate = nullptr; } if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { @@ -281,6 +314,159 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData1, TestSize.Level1) RefObject::DecObjRef(g_store); } +/** + * @tc.name: GetSyncData2 + * @tc.desc: GetSyncData interface. For overlarge data(over 4M), ignore it. + * @tc.type: FUNC + * @tc.require: AR000GK58H + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData2, TestSize.Level1) +{ + ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option {}, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); + + /** + * @tc.steps: step1. Put 10 records.(1M + 2M + 3M + 4M + 5M) * 2. + * @tc.expected: Succeed, return OK. + */ + for (int i = 1; i <= 5; ++i) { + EXPECT_EQ(PutBatchData(1, i * 1024 * 1024), E_OK); // 1024*1024 equals 1M. + } + for (int i = 1; i <= 5; ++i) { + EXPECT_EQ(PutBatchData(1, i * 1024 * 1024), E_OK); // 1024*1024 equals 1M. + } + + /** + * @tc.steps: step2. Get all data. + * @tc.expected: Succeed and the count is 6. + */ + auto store = GetRelationalStore(); + ASSERT_NE(store, nullptr); + ContinueToken token = nullptr; + QueryObject query(Query::Select(g_tableName)); + std::vector entries; + + const size_t EXPECT_COUNT = 6; // expect 6 records. + DataSizeSpecInfo sizeInfo; + sizeInfo.blockSize = 100 * 1024 * 1024; // permit 100M. + EXPECT_EQ(store->GetSyncData(query, SyncTimeRange {}, sizeInfo, token, entries), E_OK); + EXPECT_EQ(entries.size(), EXPECT_COUNT); + SingleVerKvEntry::Release(entries); + RefObject::DecObjRef(g_store); +} + +/** + * @tc.name: GetSyncData3 + * @tc.desc: GetSyncData interface. For deleted data. + * @tc.type: FUNC + * @tc.require: AR000GK58H + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBRelationalGetDataTest, GetSyncData3, TestSize.Level1) +{ + ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option {}, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); + + /** + * @tc.steps: step1. Create distributed table "dataPlus". + * @tc.expected: Succeed, return OK. + */ + const string tableName = g_tableName + "Plus"; + std::string sql = "CREATE TABLE " + tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + ASSERT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(tableName), DBStatus::OK); + + /** + * @tc.steps: step2. Put 5 records with different type into "dataPlus" table. Put 5 records into "data" table. + * @tc.expected: Succeed, return OK. + */ + vector sqls = { + "INSERT INTO " + tableName + " VALUES(NULL, 1);", + "INSERT INTO " + tableName + " VALUES(NULL, 0.01);", + "INSERT INTO " + tableName + " VALUES(NULL, NULL);", + "INSERT INTO " + tableName + " VALUES(NULL, 'This is a text.');", + "INSERT INTO " + tableName + " VALUES(NULL, x'0123456789');", + }; + const size_t RECORD_COUNT = sqls.size(); + for (const auto &sql : sqls) { + ASSERT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + } + + /** + * @tc.steps: step3. Get all data from "dataPlus" table. + * @tc.expected: Succeed and the count is right. + */ + auto store = GetRelationalStore(); + ASSERT_NE(store, nullptr); + ContinueToken token = nullptr; + QueryObject query(Query::Select(tableName)); + std::vector entries; + EXPECT_EQ(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); + EXPECT_EQ(entries.size(), RECORD_COUNT); + + /** + * @tc.steps: step4. Put data into "data" table from deviceA and deviceB + * @tc.expected: Succeed, return OK. + */ + query = QueryObject(Query::Select(g_tableName)); + DeviceID deviceA = "deviceA"; + ASSERT_EQ(E_OK, SQLiteUtils::CreateSameStuTable(db, store->GetSchemaInfo().GetTable(g_tableName), + DBCommon::GetDistributedTableName(deviceA, g_tableName))); + EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(query, entries, deviceA), E_OK); + + DeviceID deviceB = "deviceB"; + auto rEntries = std::vector(entries.rbegin(), entries.rend()); + ASSERT_EQ(E_OK, SQLiteUtils::CreateSameStuTable(db, store->GetSchemaInfo().GetTable(g_tableName), + DBCommon::GetDistributedTableName(deviceB, g_tableName))); + EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(query, rEntries, deviceB), E_OK); + rEntries.clear(); + SingleVerKvEntry::Release(entries); + + /** + * @tc.steps: step5. Delete 2 "dataPlus" data from deviceA. + * @tc.expected: Succeed. + */ + sql = "DELETE FROM " + tableName + " WHERE rowid<=2;"; + ASSERT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + + query = QueryObject(Query::Select(tableName)); + EXPECT_EQ(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); + EXPECT_EQ(entries.size(), RECORD_COUNT); + + query = QueryObject(Query::Select(g_tableName)); + EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(query, entries, deviceA), E_OK); + SingleVerKvEntry::Release(entries); + + /** + * @tc.steps: step6. Check data. + * @tc.expected: 2 data in the from deviceA are deleted and all data from deviceB are not deleted. + */ + sql = "SELECT count(*) FROM " + DBConstant::RELATIONAL_PREFIX + g_tableName + "_log WHERE flag&0x01=0x01;"; + size_t count = 0; + EXPECT_EQ(GetCount(db, sql, count), E_OK); + EXPECT_EQ(count, 2UL); // 2 for test + + sql = "SELECT count(*) FROM " + DBConstant::RELATIONAL_PREFIX + g_tableName + "_" + + DBCommon::TransferStringToHex(DBCommon::TransferHashString(deviceA)) + ";"; + count = 0; + EXPECT_EQ(GetCount(db, sql, count), E_OK); + EXPECT_EQ(count, 3UL); // 0 for test + + sql = "SELECT count(*) FROM " + DBConstant::RELATIONAL_PREFIX + g_tableName + "_" + + DBCommon::TransferStringToHex(DBCommon::TransferHashString(deviceB)) + ";"; + count = 0; + EXPECT_EQ(GetCount(db, sql, count), E_OK); + EXPECT_EQ(count, RECORD_COUNT); + + sqlite3_close(db); + RefObject::DecObjRef(g_store); +} + /** * @tc.name: GetQuerySyncData1 * @tc.desc: GetSyncData interface. @@ -324,6 +510,75 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData1, TestSize.Level1) RefObject::DecObjRef(g_store); } +/** + * @tc.name: GetQuerySyncData2 + * @tc.desc: GetSyncData interface. + * @tc.type: FUNC + * @tc.require: AR000GK58H + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBRelationalGetDataTest, GetQuerySyncData2, TestSize.Level1) +{ + ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option {}, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); + + /** + * @tc.steps: step1. Put 100 records. + * @tc.expected: Succeed, return OK. + */ + const int RECORD_COUNT = 100; // 100 records. + for (int i = 0; i < RECORD_COUNT; ++i) { + EXPECT_EQ(AddOrUpdateRecord(i, i), E_OK); + } + + /** + * @tc.steps: step2. Get record whose key is not equal to 10 and value is not equal to 20, order by key desc. + * @tc.expected: Succeed, Get 98 records. + */ + auto store = GetRelationalStore(); + ASSERT_NE(store, nullptr); + ContinueToken token = nullptr; + + Query query = Query::Select(g_tableName).NotEqualTo("key", 10).And().NotEqualTo("value", 20).OrderBy("key", false); + size_t expectCount = 98; // expect 98 records. + QueryObject queryObj(query); + queryObj.SetSchema(store->GetSchemaInfo()); + + std::vector entries; + EXPECT_EQ(store->GetSyncData(queryObj, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); + EXPECT_EQ(entries.size(), expectCount); + EXPECT_EQ(token, nullptr); + for (auto iter = entries.begin(); iter != entries.end(); ++iter) { + auto nextOne = std::next(iter, 1); + if (nextOne != entries.end()) { + EXPECT_GT((*iter)->GetTimestamp(), (*nextOne)->GetTimestamp()); + } + } + SingleVerKvEntry::Release(entries); + + /** + * @tc.steps: step3. Get record whose key is equal to 10 or value is equal to 20, order by key asc. + * @tc.expected: Succeed, Get 98 records. + */ + query = Query::Select(g_tableName).EqualTo("key", 10).Or().EqualTo("value", 20).OrderBy("key", true); + expectCount = 2; // expect 2 records. + queryObj = QueryObject(query); + queryObj.SetSchema(store->GetSchemaInfo()); + + EXPECT_EQ(store->GetSyncData(queryObj, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); + EXPECT_EQ(entries.size(), expectCount); + EXPECT_EQ(token, nullptr); + for (auto iter = entries.begin(); iter != entries.end(); ++iter) { + auto nextOne = std::next(iter, 1); + if (nextOne != entries.end()) { + EXPECT_LT((*iter)->GetTimestamp(), (*nextOne)->GetTimestamp()); + } + } + SingleVerKvEntry::Release(entries); + RefObject::DecObjRef(g_store); +} + /** * @tc.name: GetIncorrectTypeData1 * @tc.desc: GetSyncData and PutSyncDataWithQuery interface. @@ -390,6 +645,10 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetIncorrectTypeData1, TestSize.Lev */ QueryObject queryPlus(Query::Select(g_tableName)); const DeviceID deviceID = "deviceA"; + ASSERT_EQ(E_OK, SQLiteUtils::CreateSameStuTable(db, store->GetSchemaInfo().GetTable(g_tableName), + DBCommon::GetDistributedTableName(deviceID, g_tableName))); + ASSERT_EQ(E_OK, SQLiteUtils::CloneIndexes(db, g_tableName, + DBCommon::GetDistributedTableName(deviceID, g_tableName))); EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(queryPlus, entries, deviceID), E_OK); SingleVerKvEntry::Release(entries); @@ -416,4 +675,149 @@ HWTEST_F(DistributedDBRelationalGetDataTest, GetIncorrectTypeData1, TestSize.Lev sqlite3_close(db); RefObject::DecObjRef(g_store); } + +/** + * @tc.name: UpdateData1 + * @tc.desc: UpdateData succeed when the table has primary key. + * @tc.type: FUNC + * @tc.require: AR000GK58H + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBRelationalGetDataTest, UpdateData1, TestSize.Level1) +{ + ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option {}, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); + + /** + * @tc.steps: step1. Create distributed table "dataPlus". + * @tc.expected: Succeed, return OK. + */ + const string tableName = g_tableName + "Plus"; + std::string sql = "CREATE TABLE " + tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + ASSERT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(tableName), DBStatus::OK); + + /** + * @tc.steps: step2. Put 5 records with different type into "dataPlus" table. + * @tc.expected: Succeed, return OK. + */ + vector sqls = { + "INSERT INTO " + tableName + " VALUES(NULL, 1);", + "INSERT INTO " + tableName + " VALUES(NULL, 0.01);", + "INSERT INTO " + tableName + " VALUES(NULL, NULL);", + "INSERT INTO " + tableName + " VALUES(NULL, 'This is a text.');", + "INSERT INTO " + tableName + " VALUES(NULL, x'0123456789');", + }; + const size_t RECORD_COUNT = sqls.size(); + for (const auto &sql : sqls) { + ASSERT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + } + + /** + * @tc.steps: step3. Get all data from "dataPlus" table. + * @tc.expected: Succeed and the count is right. + */ + auto store = GetRelationalStore(); + ASSERT_NE(store, nullptr); + ContinueToken token = nullptr; + QueryObject query(Query::Select(tableName)); + std::vector entries; + EXPECT_EQ(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); + EXPECT_EQ(entries.size(), RECORD_COUNT); + + /** + * @tc.steps: step4. Put data into "data" table from deviceA for 10 times. + * @tc.expected: Succeed, return OK. + */ + query = QueryObject(Query::Select(g_tableName)); + const DeviceID deviceID = "deviceA"; + ASSERT_EQ(E_OK, SQLiteUtils::CreateSameStuTable(db, store->GetSchemaInfo().GetTable(g_tableName), + DBCommon::GetDistributedTableName(deviceID, g_tableName))); + for (uint32_t i = 0; i < 10; ++i) { // 10 for test. + EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(query, entries, deviceID), E_OK); + } + SingleVerKvEntry::Release(entries); + + /** + * @tc.steps: step5. Check data. + * @tc.expected: There is 5 data in table. + */ + sql = "SELECT count(*) FROM " + DBConstant::RELATIONAL_PREFIX + g_tableName + "_" + + DBCommon::TransferStringToHex(DBCommon::TransferHashString(deviceID)) + ";"; + size_t count = 0; + EXPECT_EQ(GetCount(db, sql, count), E_OK); + EXPECT_EQ(count, RECORD_COUNT); + + sql = "SELECT count(*) FROM " + DBConstant::RELATIONAL_PREFIX + g_tableName + "_log;"; + count = 0; + EXPECT_EQ(GetCount(db, sql, count), E_OK); + EXPECT_EQ(count, RECORD_COUNT); + + sqlite3_close(db); + RefObject::DecObjRef(g_store); +} + +/** + * @tc.name: UpdateDataWithMulDevData1 + * @tc.desc: UpdateData succeed when there is multiple devices data exists. + * @tc.type: FUNC + * @tc.require: AR000GK58H + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBRelationalGetDataTest, UpdateDataWithMulDevData1, TestSize.Level1) +{ + ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option {}, g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName), DBStatus::OK); + /** + * @tc.steps: step1. Create distributed table "dataPlus". + * @tc.expected: Succeed, return OK. + */ + const string tableName = g_tableName + "Plus"; + std::string sql = "CREATE TABLE " + tableName + "(key INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, value INTEGER);"; + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + ASSERT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(tableName), DBStatus::OK); + /** + * @tc.steps: step2. Put k1v1 into "dataPlus" table. + * @tc.expected: Succeed, return OK. + */ + sql = "INSERT INTO " + tableName + " VALUES(1, 1);"; // k1v1 + ASSERT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); + /** + * @tc.steps: step3. Get k1v1 from "dataPlus" table. + * @tc.expected: Succeed and the count is right. + */ + auto store = GetRelationalStore(); + ASSERT_NE(store, nullptr); + ContinueToken token = nullptr; + QueryObject query(Query::Select(tableName)); + std::vector entries; + EXPECT_EQ(store->GetSyncData(query, SyncTimeRange {}, DataSizeSpecInfo {}, token, entries), E_OK); + /** + * @tc.steps: step4. Put k1v1 into "data" table from deviceA. + * @tc.expected: Succeed, return OK. + */ + query = QueryObject(Query::Select(g_tableName)); + const DeviceID deviceID = "deviceA"; + ASSERT_EQ(E_OK, SQLiteUtils::CreateSameStuTable(db, store->GetSchemaInfo().GetTable(g_tableName), + DBCommon::GetDistributedTableName(deviceID, g_tableName))); + EXPECT_EQ(const_cast(store)->PutSyncDataWithQuery(query, entries, deviceID), E_OK); + SingleVerKvEntry::Release(entries); + /** + * @tc.steps: step4. Put k1v1 into "data" table. + * @tc.expected: Succeed, return OK. + */ + EXPECT_EQ(AddOrUpdateRecord(1, 1), E_OK); // k1v1 + /** + * @tc.steps: step5. Change k1v1 to k1v2 + * @tc.expected: Succeed, return OK. + */ + sql = "UPDATE " + g_tableName + " SET value=2 WHERE key=1;"; // k1v1 + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr), SQLITE_OK); // change k1v1 to k1v2 +} #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp index f8c8df347e07489c5afd03f66cfb1116ea947263..77805452792af6cd27bedefee9bfc16292a5b903 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp @@ -23,7 +23,7 @@ #include "log_print.h" #include "platform_specific.h" #include "sqlite_import.h" -#include "types.h" +#include "store_types.h" using namespace testing::ext; using namespace DistributedDB; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp index 5244086afdfa1fd26397da2f732f7b12c904119a..0de7b73d68f44bcb5cf0ccc11f280bc06b34d1ad 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp @@ -1127,7 +1127,7 @@ HWTEST_F(DistributedDBStorageQuerySyncTest, RelationalQuerySyncTest001, TestSize * @tc.steps:step1. Create a query object with table name is specified * @tc.expected: ok */ - Query query1 = Query::Select("Relatonal_table").EqualTo("field1", "abc"); + Query query1 = Query::Select("Relational_table").EqualTo("field1", "abc"); QuerySyncObject obj1(query1); /** @@ -1158,10 +1158,10 @@ HWTEST_F(DistributedDBStorageQuerySyncTest, RelationalQuerySyncTest001, TestSize */ HWTEST_F(DistributedDBStorageQuerySyncTest, RelationalQuerySyncTest002, TestSize.Level1) { - Query query1 = Query::Select("Relatonal_table1").EqualTo("field1", "abc"); + Query query1 = Query::Select("Relational_table1").EqualTo("field1", "abc"); QuerySyncObject obj1(query1); - Query query2 = Query::Select("Relatonal_table2").EqualTo("field1", "abc"); + Query query2 = Query::Select("Relational_table2").EqualTo("field1", "abc"); QuerySyncObject obj2(query2); /** @@ -1169,4 +1169,65 @@ HWTEST_F(DistributedDBStorageQuerySyncTest, RelationalQuerySyncTest002, TestSize * @tc.expected: identity should be different. */ EXPECT_NE(obj1.GetIdentify(), obj2.GetIdentify()); +} + +/** + * @tc.name: SerializeAndDeserializeForVer1 + * @tc.desc: Test querySyncObject serialization and deserialization. + * @tc.type: FUNC + * @tc.require: AR000GOHO7 + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBStorageQuerySyncTest, SerializeAndDeserializeForVer1, TestSize.Level1) +{ + Query qeury1 = Query::Select("table1").EqualTo("field1", "abc").InKeys({KEY_1, KEY_2, KEY_3}); + QuerySyncObject obj1(qeury1); + + /** + * @tc.steps:step1. Serialize obj1. + * @tc.expected: Serialize successfully. + */ + auto len = obj1.CalculateParcelLen(SOFTWARE_VERSION_CURRENT); + std::vector buffer(len); + Parcel parcel1(buffer.data(), buffer.size()); + obj1.SerializeData(parcel1, SOFTWARE_VERSION_CURRENT); + ASSERT_EQ(parcel1.IsError(), false); + + /** + * @tc.steps:step2. Deserialize obj1. + * @tc.expected: Deserialize successfully. + */ + QuerySyncObject obj2; + Parcel parcel2(buffer.data(), buffer.size()); + ASSERT_EQ(parcel2.IsError(), false); + + /** + * @tc.steps:step3. check object identity + * @tc.expected: identity should be the same. + */ + EXPECT_NE(obj1.GetIdentify(), obj2.GetIdentify()); +} + +/** + * @tc.name: MultiInkeys1 + * @tc.desc: Test the rc when multiple inkeys exists. + * @tc.type: FUNC + * @tc.require: AR000GOHO7 + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBStorageQuerySyncTest, MultiInkeys1, TestSize.Level1) +{ + /** + * @tc.steps:step1. Create an invalid query, with multiple inkeys. + */ + Query query = Query::Select().InKeys({KEY_1, KEY_2}).InKeys({KEY_3}); + + /** + * @tc.steps:step2. Get data. + * @tc.expected: Return INVALID_QUERY_FORMAT. + */ + std::vector entries; + IOption option; + option.dataType = IOption::SYNC_DATA; + EXPECT_EQ(g_schemaConnect->GetEntries(option, query, entries), -E_INVALID_QUERY_FORMAT); } \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp index b74fa08abec0582c0a83077f8ac864863121a8ab..4ee0ecbba178bb7dc948b6c16c392df51a9cd7e9 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp @@ -26,7 +26,7 @@ #include "sqlite_single_ver_natural_store_connection.h" #include "sqlite_single_ver_result_set.h" #include "sqlite_utils.h" -#include "types.h" +#include "store_types.h" using namespace testing::ext; using namespace DistributedDB; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp index d1c463efd1ad1c81412219394051312857f51e7a..b1a4da85c7dbefd5df738ce5aae14cc7d0353635 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_ability_sync_test.cpp @@ -17,7 +17,7 @@ #include "ability_sync.h" #include "distributeddb_tools_unit_test.h" -#include "single_ver_sync_task_context.h" +#include "single_ver_kv_sync_task_context.h" #include "sync_types.h" #include "version.h" #include "virtual_communicator_aggregator.h" @@ -434,7 +434,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, RequestReceiveTest001, TestSize.Level0) */ Message msg1(ABILITY_SYNC_MESSAGE); msg1.SetMessageType(TYPE_REQUEST); - SingleVerSyncTaskContext *context = new (std::nothrow) SingleVerSyncTaskContext(); + SingleVerSyncTaskContext *context = new (std::nothrow) SingleVerKvSyncTaskContext(); ASSERT_TRUE(context != nullptr); EXPECT_EQ(async.RequestRecv(nullptr, context), -E_INVALID_ARGS); EXPECT_EQ(async.RequestRecv(&msg1, nullptr), -E_INVALID_ARGS); @@ -503,7 +503,7 @@ HWTEST_F(DistributedDBAbilitySyncTest, AckReceiveTest001, TestSize.Level0) * @tc.steps: step2. call AckRecv, set inMsg nullptr or set context nullptr * @tc.expected: step2. AckRecv return -E_INVALID_ARGS */ - SingleVerSyncTaskContext *context = new (std::nothrow) SingleVerSyncTaskContext(); + SingleVerSyncTaskContext *context = new (std::nothrow) SingleVerKvSyncTaskContext(); ASSERT_TRUE(context != nullptr); Message msg1(ABILITY_SYNC_MESSAGE); msg1.SetMessageType(TYPE_RESPONSE); diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..328a69ff16e8f7e8c0a20249e9a4607a3b0d084f --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2022 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 "distributeddb_tools_unit_test.h" +#include "message.h" +#include "mock_auto_launch.h" +#include "mock_communicator.h" +#include "mock_single_ver_state_machine.h" +#include "mock_sync_task_context.h" +#include "virtual_single_ver_sync_db_Interface.h" + +using namespace testing::ext; +using namespace testing; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { +void Init(MockSingleVerStateMachine &stateMachine, MockSyncTaskContext &syncTaskContext, + MockCommunicator &communicator, VirtualSingleVerSyncDBInterface &dbSyncInterface) +{ + std::shared_ptr metadata = std::make_shared(); + (void)stateMachine.Initialize(&syncTaskContext, &dbSyncInterface, metadata, &communicator); +} +} + +class DistributedDBMockSyncModuleTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBMockSyncModuleTest::SetUpTestCase(void) +{ +} + +void DistributedDBMockSyncModuleTest::TearDownTestCase(void) +{ +} + +void DistributedDBMockSyncModuleTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); +} + +void DistributedDBMockSyncModuleTest::TearDown(void) +{ +} + +/** + * @tc.name: StateMachineCheck001 + * @tc.desc: Test machine do timeout when has same timerId. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck001, TestSize.Level1) +{ + MockSingleVerStateMachine stateMachine; + MockSyncTaskContext syncTaskContext; + MockCommunicator communicator; + VirtualSingleVerSyncDBInterface dbSyncInterface; + Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); + + TimerId expectId = 0; + TimerId actualId = expectId; + EXPECT_CALL(syncTaskContext, GetTimerId()).WillOnce(Return(expectId)); + EXPECT_CALL(stateMachine, SwitchStateAndStep(_)).WillOnce(Return()); + + stateMachine.CallStepToTimeout(actualId); +} + +/** + * @tc.name: StateMachineCheck002 + * @tc.desc: Test machine do timeout when has diff timerId. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck002, TestSize.Level1) +{ + MockSingleVerStateMachine stateMachine; + MockSyncTaskContext syncTaskContext; + MockCommunicator communicator; + VirtualSingleVerSyncDBInterface dbSyncInterface; + Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); + + TimerId expectId = 0; + TimerId actualId = 1; + EXPECT_CALL(syncTaskContext, GetTimerId()).WillOnce(Return(expectId)); + EXPECT_CALL(stateMachine, SwitchStateAndStep(_)).Times(0); + + stateMachine.CallStepToTimeout(actualId); +} + +/** + * @tc.name: StateMachineCheck003 + * @tc.desc: Test machine exec next task when queue not empty. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, StateMachineCheck003, TestSize.Level1) +{ + MockSingleVerStateMachine stateMachine; + MockSyncTaskContext syncTaskContext; + MockCommunicator communicator; + VirtualSingleVerSyncDBInterface dbSyncInterface; + Init(stateMachine, syncTaskContext, communicator, dbSyncInterface); + + EXPECT_CALL(stateMachine, PrepareNextSyncTask()).WillOnce(Return(E_OK)); + + EXPECT_CALL(syncTaskContext, IsTargetQueueEmpty()).WillRepeatedly(Return(false)); + EXPECT_CALL(syncTaskContext, MoveToNextTarget()).WillRepeatedly(Return()); + EXPECT_CALL(syncTaskContext, IsCurrentSyncTaskCanBeSkipped()) + .WillOnce(Return(true)) + .WillOnce(Return(false)); + // we expect machine dont change context status when queue not empty + EXPECT_CALL(syncTaskContext, SetOperationStatus(_)).WillOnce(Return()); + EXPECT_CALL(syncTaskContext, SetTaskExecStatus(_)).Times(0); + + EXPECT_EQ(stateMachine.CallExecNextTask(), E_OK); +} + +/** + * @tc.name: DataSyncCheck001 + * @tc.desc: Test dataSync recv error ack. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck001, TestSize.Level1) +{ + SingleVerDataSync dataSync; + DistributedDB::Message *message = new(std::nothrow) DistributedDB::Message(); + ASSERT_TRUE(message != nullptr); + message->SetErrorNo(E_FEEDBACK_COMMUNICATOR_NOT_FOUND); + EXPECT_EQ(dataSync.AckPacketIdCheck(message), true); + delete message; +} + +/** + * @tc.name: DataSyncCheck002 + * @tc.desc: Test dataSync recv notify ack. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, DataSyncCheck002, TestSize.Level1) +{ + SingleVerDataSync dataSync; + DistributedDB::Message *message = new(std::nothrow) DistributedDB::Message(); + ASSERT_TRUE(message != nullptr); + message->SetMessageType(TYPE_NOTIFY); + EXPECT_EQ(dataSync.AckPacketIdCheck(message), true); + delete message; +} + +/** + * @tc.name: AutoLaunchCheck001 + * @tc.desc: Test autoLaunch close connection. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBMockSyncModuleTest, AutoLaunchCheck001, TestSize.Level1) +{ + MockAutoLaunch mockAutoLaunch; + /** + * @tc.steps: step1. put AutoLaunchItem in cache to simulate a connection was auto launched + */ + std::string id = "TestAutoLaunch"; + AutoLaunchItem item; + mockAutoLaunch.SetAutoLaunchItem(id, item); + EXPECT_CALL(mockAutoLaunch, TryCloseConnection(_)).WillOnce(Return()); + /** + * @tc.steps: step2. send close singal to simulate a connection was unused in 1 min + * @tc.expected: 10 thread try to close the connection and one thread close success + */ + const int loopCount = 10; + int finishCount = 0; + std::mutex mutex; + std::unique_lock lock(mutex); + std::condition_variable cv; + for (int i = 0; i < loopCount; i++) { + std::thread t = std::thread([&finishCount, &mockAutoLaunch, &id, &mutex, &cv]{ + mockAutoLaunch.CallExtConnectionLifeCycleCallbackTask(id); + finishCount++; + if (finishCount == loopCount) { + std::unique_lock lockInner(mutex); + cv.notify_one(); + } + }); + t.detach(); + } + cv.wait(lock, [&finishCount, &loopCount](){ + return finishCount == loopCount; + }); +} \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index 40584d5faa9b26802189e97ab3e35713683fdf58..4e3cba7e9bf9723c135053eb04e3cdc250fd6b33 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -34,16 +34,44 @@ using namespace DistributedDBUnitTest; namespace { const std::string DEVICE_B = "deviceB"; + const std::string DEVICE_C = "deviceC"; const std::string g_tableName = "TEST_TABLE"; + const int ONE_HUNDERED = 100; + const char DEFAULT_CHAR = 'D'; + const std::string DEFAULT_TEXT = "This is a text"; + const std::vector DEFAULT_BLOB(ONE_HUNDERED, DEFAULT_CHAR); + RelationalStoreManager g_mgr(APP_ID, USER_ID); std::string g_testDir; std::string g_dbDir; + std::string g_id; + std::vector g_storageType = { + StorageType::STORAGE_TYPE_INTEGER, StorageType::STORAGE_TYPE_REAL, + StorageType::STORAGE_TYPE_TEXT, StorageType::STORAGE_TYPE_BLOB + }; DistributedDBToolsUnitTest g_tool; - DBStatus g_kvDelegateStatus = INVALID_ARGS; - RelationalStoreDelegate* g_kvDelegatePtr = nullptr; + RelationalStoreDelegate* g_rdbDelegatePtr = nullptr; VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr; RelationalVirtualDevice *g_deviceB = nullptr; + RelationalVirtualDevice *g_deviceC = nullptr; + std::vector g_fieldInfoList; + RelationalStoreObserverUnitTest *g_observer = nullptr; + std::string GetDeviceTableName(const std::string &tableName) + { + return "naturalbase_rdb_aux_" + + tableName + "_" + DBCommon::TransferStringToHex(DBCommon::TransferHashString(DEVICE_B)); + } + + void OpenStore() + { + if (g_observer == nullptr) { + g_observer = new (std::nothrow) RelationalStoreObserverUnitTest(); + } + RelationalStoreDelegate::Option option = {g_observer}; + g_mgr.OpenStore(g_dbDir, STORE_ID_1, option, g_rdbDelegatePtr); + ASSERT_TRUE(g_rdbDelegatePtr != nullptr); + } int GetDB(sqlite3 *&db) { @@ -59,22 +87,70 @@ namespace { return rc; } - int CreateTable(sqlite3 *db) + std::string GetType(StorageType type) + { + static std::map typeMap = { + {StorageType::STORAGE_TYPE_INTEGER, "INT"}, + {StorageType::STORAGE_TYPE_BOOL, "BOOL"}, + {StorageType::STORAGE_TYPE_REAL, "DOUBLE"}, + {StorageType::STORAGE_TYPE_TEXT, "TEXT"}, + {StorageType::STORAGE_TYPE_BLOB, "BLOB"} + }; + if (typeMap.find(type) == typeMap.end()) { + type = StorageType::STORAGE_TYPE_INTEGER; + } + return typeMap[type]; + } + + int DropTable(sqlite3 *db, const std::string &tableName) { - char *pErrMsg = nullptr; + std::string sql = "DROP TABLE " + tableName + ";"; + return sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + } - const char *sql1 = "CREATE TABLE TEST_TABLE(" \ - "ID INT PRIMARY KEY NOT NULL," \ - "NAME TEXT ," \ - "AGE INT);"; - return sqlite3_exec(db, sql1, nullptr, nullptr, &pErrMsg); + int CreateTable(sqlite3 *db, std::vector &fieldInfoList, const std::string &tableName) + { + std::string sql = "CREATE TABLE " + tableName + "("; + int index = 0; + for (const auto &field : fieldInfoList) { + if (index != 0) { + sql += ","; + } + sql += field.GetFieldName() + " "; + std::string type = GetType(field.GetStorageType()); + sql += type + " "; + if (index == 0) { + sql += "PRIMARY KEY NOT NULL "; + } + index++; + } + sql += ");"; + int rc = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + return rc; } - int PrepareInsert(sqlite3 *db, sqlite3_stmt *&statement) + int PrepareInsert(sqlite3 *db, sqlite3_stmt *&statement, + std::vector fieldInfoList, const std::string &tableName) { - const char *sql = "INSERT OR REPLACE INTO TEST_TABLE (ID,NAME,AGE) " \ - "VALUES (?, ?, ?);"; - return sqlite3_prepare_v2(db, sql, -1, &statement, nullptr); + std::string sql = "INSERT OR REPLACE INTO " + tableName + "("; + int index = 0; + for (const auto &fieldInfo : fieldInfoList) { + if (index != 0) { + sql += ","; + } + sql += fieldInfo.GetFieldName(); + index++; + } + sql += ") VALUES ("; + while (index > 0) { + sql += "?"; + if (index != 1) { + sql += ", "; + } + index--; + } + sql += ");"; + return sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr); } int SimulateCommitData(sqlite3 *db, sqlite3_stmt *&statement) @@ -87,44 +163,131 @@ namespace { return rc; } - void InsertValue(sqlite3 *db, RowData &rowData) + void BindValue(const DataValue &item, sqlite3_stmt *stmt, int col) + { + switch (item.GetType()) { + case StorageType::STORAGE_TYPE_BOOL: { + bool boolData = false; + (void)item.GetBool(boolData); + EXPECT_EQ(sqlite3_bind_int(stmt, col, boolData), SQLITE_OK); + break; + } + + case StorageType::STORAGE_TYPE_INTEGER: { + int64_t intData = 0; + (void)item.GetInt64(intData); + EXPECT_EQ(sqlite3_bind_int64(stmt, col, intData), SQLITE_OK); + break; + } + + case StorageType::STORAGE_TYPE_REAL: { + double doubleData = 0; + (void)item.GetDouble(doubleData); + EXPECT_EQ(sqlite3_bind_double(stmt, col, doubleData), SQLITE_OK); + break; + } + + case StorageType::STORAGE_TYPE_TEXT: { + std::string strData; + (void)item.GetText(strData); + EXPECT_EQ(SQLiteUtils::BindTextToStatement(stmt, col, strData), E_OK); + break; + } + + case StorageType::STORAGE_TYPE_BLOB: { + Blob blob; + (void)item.GetBlob(blob); + std::vector blobData(blob.GetData(), blob.GetData() + blob.GetSize()); + EXPECT_EQ(SQLiteUtils::BindBlobToStatement(stmt, col, blobData, true), E_OK); + break; + } + + case StorageType::STORAGE_TYPE_NULL: { + EXPECT_EQ(SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(stmt, col)), E_OK); + break; + } + + default: + break; + } + } + + void InsertValue(sqlite3 *db, std::map &dataMap, + std::vector &fieldInfoList, const std::string &tableName) { sqlite3_stmt *stmt = nullptr; - EXPECT_EQ(PrepareInsert(db, stmt), SQLITE_OK); - for (int i = 0; i < static_cast(rowData.size()); ++i) { - const auto &item = rowData[i]; + EXPECT_EQ(PrepareInsert(db, stmt, fieldInfoList, tableName), SQLITE_OK); + for (int i = 0; i < static_cast(fieldInfoList.size()); ++i) { + const auto &fieldName = fieldInfoList[i].GetFieldName(); + ASSERT_TRUE(dataMap.find(fieldName) != dataMap.end()); + const auto &item = dataMap[fieldName]; const int index = i + 1; - int errCode; - if (item.GetType() == StorageType::STORAGE_TYPE_INTEGER) { - int64_t val; - (void)item.GetInt64(val); - errCode = SQLiteUtils::BindInt64ToStatement(stmt, index, val); - } else if (item.GetType() == StorageType::STORAGE_TYPE_TEXT) { - std::string val; - (void)item.GetText(val); - errCode = SQLiteUtils::BindTextToStatement(stmt, index, val); - } - EXPECT_EQ(errCode, E_OK); + BindValue(item, stmt, index); } EXPECT_EQ(SimulateCommitData(db, stmt), SQLITE_DONE); sqlite3_finalize(stmt); } - void GenerateValue(RowData &rowData, std::map &dataMap) + void InsertValue(sqlite3 *db, std::map &dataMap) { - int64_t id = 0; - dataMap["ID"] = id; - rowData.push_back(dataMap["ID"]); - std::string val = "test"; - dataMap["NAME"] = val; - rowData.push_back(dataMap["NAME"]); - dataMap["AGE"] = INT64_MAX; - rowData.push_back(dataMap["AGE"]); + InsertValue(db, dataMap, g_fieldInfoList, g_tableName); } - void InsertFieldInfo() + void SetNull(DataValue &dataValue) { - std::vector localFieldInfo; + dataValue.ResetValue(); + } + + void SetBool(DataValue &dataValue) + { + dataValue = false; + } + + void SetInt64(DataValue &dataValue) + { + dataValue = INT64_MAX; + } + + void SetDouble(DataValue &dataValue) + { + dataValue = 1.0; + } + + void SetText(DataValue &dataValue) + { + dataValue.SetText(DEFAULT_TEXT); + } + + void SetBlob(DataValue &dataValue) + { + Blob blob; + blob.WriteBlob(DEFAULT_BLOB.data(), DEFAULT_BLOB.size()); + dataValue.SetBlob(blob); + } + + void GenerateValue(std::map &dataMap, std::vector &fieldInfoList) + { + static std::map typeMapFunction = { + {StorageType::STORAGE_TYPE_NULL, &SetNull}, + {StorageType::STORAGE_TYPE_BOOL, &SetBool}, + {StorageType::STORAGE_TYPE_INTEGER, &SetInt64}, + {StorageType::STORAGE_TYPE_REAL, &SetDouble}, + {StorageType::STORAGE_TYPE_TEXT, &SetText}, + {StorageType::STORAGE_TYPE_BLOB, &SetBlob} + }; + for (auto &fieldInfo : fieldInfoList) { + DataValue dataValue; + if (typeMapFunction.find(fieldInfo.GetStorageType()) == typeMapFunction.end()) { + fieldInfo.SetStorageType(StorageType::STORAGE_TYPE_NULL); + } + typeMapFunction[fieldInfo.GetStorageType()](dataValue); + dataMap[fieldInfo.GetFieldName()] = std::move(dataValue); + } + } + + void InsertFieldInfo(std::vector &fieldInfoList) + { + fieldInfoList.clear(); FieldInfo columnFirst; columnFirst.SetFieldName("ID"); columnFirst.SetStorageType(StorageType::STORAGE_TYPE_INTEGER); @@ -134,22 +297,21 @@ namespace { FieldInfo columnThird; columnThird.SetFieldName("AGE"); columnThird.SetStorageType(StorageType::STORAGE_TYPE_INTEGER); - localFieldInfo.push_back(columnFirst); - localFieldInfo.push_back(columnSecond); - localFieldInfo.push_back(columnThird); - g_deviceB->SetLocalFieldInfo(localFieldInfo); + fieldInfoList.push_back(columnFirst); + fieldInfoList.push_back(columnSecond); + fieldInfoList.push_back(columnThird); } - void BlockSync(SyncMode syncMode, DBStatus exceptStatus) + void BlockSync(const std::string &tableName, SyncMode syncMode, DBStatus exceptStatus, + const std::vector &devices) { - std::vector devices = {DEVICE_B}; - Query query = Query::Select(g_tableName); + Query query = Query::Select(tableName); std::map> statusMap; SyncStatusCallback callBack = [&statusMap]( const std::map> &devicesMap) { statusMap = devicesMap; }; - DBStatus callStatus = g_kvDelegatePtr->Sync(devices, syncMode, query, callBack, true); + DBStatus callStatus = g_rdbDelegatePtr->Sync(devices, syncMode, query, callBack, true); EXPECT_EQ(callStatus, OK); for (const auto &tablesRes : statusMap) { for (const auto &tableStatus : tablesRes.second) { @@ -158,48 +320,236 @@ namespace { } } - void InsertValueToDB(RowData &rowData) + void BlockSync(SyncMode syncMode, DBStatus exceptStatus, const std::vector &devices) + { + BlockSync(g_tableName, syncMode, exceptStatus, devices); + } + + int PrepareSelect(sqlite3 *db, sqlite3_stmt *&statement, const std::string &table) + { + const std::string sql = "SELECT * FROM " + table; + return sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr); + } + + void GetDataValue(sqlite3_stmt *statement, int col, DataValue &dataValue) + { + int type = sqlite3_column_type(statement, col); + switch (type) { + case SQLITE_INTEGER: { + dataValue = static_cast(sqlite3_column_int64(statement, col)); + break; + } + case SQLITE_FLOAT: { + dataValue = sqlite3_column_double(statement, col); + break; + } + case SQLITE_TEXT: { + dataValue.SetText(std::string(reinterpret_cast(sqlite3_column_text(statement, col)))); + break; + } + case SQLITE_BLOB: { + std::vector blobValue; + (void)SQLiteUtils::GetColumnBlobValue(statement, col, blobValue); + Blob blob; + blob.WriteBlob(blobValue.data(), static_cast(blobValue.size())); + dataValue.SetBlob(blob); + break; + } + case SQLITE_NULL: + break; + default: + LOGW("unknown type[%d] column[%d] ignore", type, col); + } + } + + void GetSyncDataStep(std::map &dataMap, sqlite3_stmt *statement, + std::vector fieldInfoList) + { + int columnCount = sqlite3_column_count(statement); + ASSERT_EQ(static_cast(columnCount), fieldInfoList.size()); + for (int col = 0; col < columnCount; ++col) { + DataValue dataValue; + GetDataValue(statement, col, dataValue); + dataMap[fieldInfoList.at(col).GetFieldName()] = std::move(dataValue); + } + } + + void GetSyncData(sqlite3 *db, std::map &dataMap, const std::string &tableName, + std::vector fieldInfoList) + { + sqlite3_stmt *statement = nullptr; + EXPECT_EQ(PrepareSelect(db, statement, GetDeviceTableName(tableName)), SQLITE_OK); + while (true) { + int rc = sqlite3_step(statement); + if (rc != SQLITE_ROW) { + LOGD("GetSyncData Exist by code[%d]", rc); + break; + } + GetSyncDataStep(dataMap, statement, fieldInfoList); + } + sqlite3_finalize(statement); + } + + void InsertValueToDB(std::map &dataMap) { sqlite3 *db = nullptr; EXPECT_EQ(GetDB(db), SQLITE_OK); - InsertValue(db, rowData); + InsertValue(db, dataMap); sqlite3_close(db); } - void PrepareEnvironment(RowData &rowData) + void PrepareBasicTable(const std::string &tableName, std::vector &fieldInfoList, + std::vector remoteDeviceVec) { sqlite3 *db = nullptr; EXPECT_EQ(GetDB(db), SQLITE_OK); - EXPECT_EQ(CreateTable(db), SQLITE_OK); + if (fieldInfoList.empty()) { + InsertFieldInfo(fieldInfoList); + } + for (auto &dev : remoteDeviceVec) { + dev->SetLocalFieldInfo(fieldInfoList); + } + EXPECT_EQ(CreateTable(db, fieldInfoList, tableName), SQLITE_OK); + TableInfo tableInfo; + SQLiteUtils::AnalysisSchema(db, tableName, tableInfo); + for (auto &dev : remoteDeviceVec) { + dev->SetTableInfo(tableInfo); + } - EXPECT_EQ(g_kvDelegatePtr->CreateDistributedTable(g_tableName), OK); + EXPECT_EQ(g_rdbDelegatePtr->CreateDistributedTable(tableName), OK); sqlite3_close(db); + } - InsertFieldInfo(); - std::map dataMap; - GenerateValue(rowData, dataMap); - InsertValueToDB(rowData); + void PrepareEnvironment(std::map &dataMap, std::vector remoteDeviceVec) + { + PrepareBasicTable(g_tableName, g_fieldInfoList, remoteDeviceVec); + GenerateValue(dataMap, g_fieldInfoList); + InsertValueToDB(dataMap); + } - rowData.clear(); + void PrepareVirtualEnvironment(std::map &dataMap, const std::string &tableName, + std::vector &fieldInfoList, std::vector remoteDeviceVec) + { + PrepareBasicTable(tableName, fieldInfoList, remoteDeviceVec); + GenerateValue(dataMap, fieldInfoList); + VirtualRowData virtualRowData; for (const auto &item : dataMap) { - rowData.push_back(item.second); + virtualRowData.objectData.PutDataValue(item.first, item.second); } + virtualRowData.logInfo.timestamp = 1; + g_deviceB->PutData(tableName, {virtualRowData}); } - void CheckVirtualData(RowData &rowData) + void PrepareVirtualEnvironment(std::map &dataMap, std::vector remoteDeviceVec) { - std::vector targetData; - g_deviceB->GetAllSyncData(g_tableName, targetData); + PrepareVirtualEnvironment(dataMap, g_tableName, g_fieldInfoList, remoteDeviceVec); + } - for (auto &item : targetData) { - for (int j = 0; j < static_cast(item.rowData.size()); ++j) { - LOGD("index %d actual_val[%s] except_val[%s]", - j, item.rowData[j].ToString().c_str(), rowData[j].ToString().c_str()); - EXPECT_TRUE(item.rowData[j] == rowData[j]); - } + void CheckData(std::map &targetMap, const std::string &tableName, + std::vector fieldInfoList) + { + std::map dataMap; + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db), SQLITE_OK); + GetSyncData(db, dataMap, tableName, fieldInfoList); + sqlite3_close(db); + + for (const auto &[fieldName, dataValue] : targetMap) { + ASSERT_TRUE(dataMap.find(fieldName) != dataMap.end()); + EXPECT_TRUE(dataMap[fieldName] == dataValue); + } + } + + void CheckData(std::map &targetMap) + { + CheckData(targetMap, g_tableName, g_fieldInfoList); + } + + void CheckVirtualData(const std::string &tableName, std::map &data) + { + std::vector targetData; + g_deviceB->GetAllSyncData(tableName, targetData); + + ASSERT_EQ(targetData.size(), 1u); + for (auto &[field, value] : data) { + DataValue target; + EXPECT_EQ(targetData[0].objectData.GetDataValue(field, target), E_OK); + LOGD("field %s actual_val[%s] except_val[%s]", field.c_str(), target.ToString().c_str(), + value.ToString().c_str()); + EXPECT_TRUE(target == value); + } + } + + void CheckVirtualData(std::map &data) + { + CheckVirtualData(g_tableName, data); + } + + void GetFieldInfo(std::vector &fieldInfoList, std::vector typeList) + { + fieldInfoList.clear(); + for (size_t index = 0; index < typeList.size(); index++) { + const auto &type = typeList[index]; + FieldInfo fieldInfo; + fieldInfo.SetFieldName("field_" + std::to_string(index)); + fieldInfo.SetColumnId(index); + fieldInfo.SetStorageType(type); + fieldInfoList.push_back(fieldInfo); } } + + void InsertValueToDB(std::map &dataMap, + std::vector fieldInfoList, const std::string &tableName) + { + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db), SQLITE_OK); + InsertValue(db, dataMap, fieldInfoList, tableName); + sqlite3_close(db); + } + + void PrepareEnvironment(std::map &dataMap, const std::string &tableName, + std::vector &localFieldInfoList, std::vector &remoteFieldInfoList, + std::vector remoteDeviceVec) + { + sqlite3 *db = nullptr; + EXPECT_EQ(GetDB(db), SQLITE_OK); + + EXPECT_EQ(CreateTable(db, remoteFieldInfoList, tableName), SQLITE_OK); + TableInfo tableInfo; + SQLiteUtils::AnalysisSchema(db, tableName, tableInfo); + for (auto &dev : remoteDeviceVec) { + dev->SetTableInfo(tableInfo); + } + + EXPECT_EQ(DropTable(db, tableName), SQLITE_OK); + EXPECT_EQ(CreateTable(db, localFieldInfoList, tableName), SQLITE_OK); + EXPECT_EQ(g_rdbDelegatePtr->CreateDistributedTable(tableName), OK); + + sqlite3_close(db); + + GenerateValue(dataMap, localFieldInfoList); + InsertValueToDB(dataMap, localFieldInfoList, tableName); + for (auto &dev : remoteDeviceVec) { + dev->SetLocalFieldInfo(remoteFieldInfoList); + } + } + + void PrepareEnvironment(std::map &dataMap, + std::vector &localFieldInfoList, std::vector &remoteFieldInfoList, + std::vector remoteDeviceVec) + { + PrepareEnvironment(dataMap, g_tableName, localFieldInfoList, remoteFieldInfoList, remoteDeviceVec); + } + + void CheckIdentify(RelationalStoreObserverUnitTest *observer) + { + ASSERT_NE(observer, nullptr); + StoreProperty property = observer->GetStoreProperty(); + EXPECT_EQ(property.appId, APP_ID); + EXPECT_EQ(property.storeId, STORE_ID_1); + EXPECT_EQ(property.userId, USER_ID); + } } class DistributedDBRelationalVerP2PSyncTest : public testing::Test { @@ -224,6 +574,8 @@ void DistributedDBRelationalVerP2PSyncTest::SetUpTestCase() g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); ASSERT_TRUE(g_communicatorAggregator != nullptr); RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); + + g_id = g_mgr.GetRelationalStoreIdentifier(USER_ID, APP_ID, STORE_ID_1); } void DistributedDBRelationalVerP2PSyncTest::TearDownTestCase() @@ -241,17 +593,23 @@ void DistributedDBRelationalVerP2PSyncTest::TearDownTestCase() void DistributedDBRelationalVerP2PSyncTest::SetUp(void) { DistributedDBToolsUnitTest::PrintTestCaseInfo(); + g_fieldInfoList.clear(); /** * @tc.setup: create virtual device B, and get a KvStoreNbDelegate as deviceA */ - g_kvDelegateStatus = g_mgr.OpenStore(g_dbDir, "Relational_default_id", {}, g_kvDelegatePtr); - ASSERT_TRUE(g_kvDelegateStatus == OK); - ASSERT_TRUE(g_kvDelegatePtr != nullptr); + sqlite3 *db = nullptr; + ASSERT_EQ(GetDB(db), SQLITE_OK); + sqlite3_close(db); + OpenStore(); g_deviceB = new (std::nothrow) RelationalVirtualDevice(DEVICE_B); ASSERT_TRUE(g_deviceB != nullptr); + g_deviceC = new (std::nothrow) RelationalVirtualDevice(DEVICE_C); + ASSERT_TRUE(g_deviceC != nullptr); auto *syncInterfaceB = new (std::nothrow) VirtualRelationalVerSyncDBInterface(); + auto *syncInterfaceC = new (std::nothrow) VirtualRelationalVerSyncDBInterface(); ASSERT_TRUE(syncInterfaceB != nullptr); ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, syncInterfaceB), E_OK); + ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, syncInterfaceC), E_OK); auto permissionCheckCallback = [] (const std::string &userId, const std::string &appId, const std::string &storeId, const std::string &deviceId, uint8_t flag) -> bool { @@ -265,21 +623,26 @@ void DistributedDBRelationalVerP2PSyncTest::TearDown(void) /** * @tc.teardown: Release device A, B, C */ - if (g_kvDelegatePtr != nullptr) { + if (g_rdbDelegatePtr != nullptr) { LOGD("CloseStore Start"); - ASSERT_EQ(g_mgr.CloseStore(g_kvDelegatePtr), OK); - g_kvDelegatePtr = nullptr; - LOGD("DeleteStore Start"); - DBStatus status = g_mgr.DeleteStore(g_dbDir); - LOGD("delete kv store status %d", status); - ASSERT_TRUE(status == OK); + ASSERT_EQ(g_mgr.CloseStore(g_rdbDelegatePtr), OK); + g_rdbDelegatePtr = nullptr; } if (g_deviceB != nullptr) { delete g_deviceB; g_deviceB = nullptr; } + if (g_deviceC != nullptr) { + delete g_deviceC; + g_deviceC = nullptr; + } + if (g_observer != nullptr) { + delete g_observer; + g_observer = nullptr; + } PermissionCheckCallbackV2 nullCallback; EXPECT_EQ(RuntimeConfig::SetPermissionCheckCallback(nullCallback), OK); + EXPECT_EQ(DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir), OK); LOGD("TearDown FINISH"); } @@ -287,100 +650,484 @@ void DistributedDBRelationalVerP2PSyncTest::TearDown(void) * @tc.name: Normal Sync 001 * @tc.desc: Test normal push sync for add data. * @tc.type: FUNC -* @tc.require: +* @tc.require: AR000GK58N * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync001, TestSize.Level0) { - RowData rowData; - PrepareEnvironment(rowData); - BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK); + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); - CheckVirtualData(rowData); + CheckVirtualData(dataMap); } /** * @tc.name: Normal Sync 002 * @tc.desc: Test normal pull sync for add data. * @tc.type: FUNC -* @tc.require: +* @tc.require: AR000GK58N * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level1) +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync002, TestSize.Level0) { - RowData rowData; - PrepareEnvironment(rowData); + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); - std::vector devices = {DEVICE_B}; Query query = Query::Select(g_tableName); g_deviceB->GenericVirtualDevice::Sync(DistributedDB::SYNC_MODE_PULL_ONLY, query, true); - CheckVirtualData(rowData); + CheckVirtualData(dataMap); } /** * @tc.name: Normal Sync 003 * @tc.desc: Test normal push sync for update data. * @tc.type: FUNC -* @tc.require: +* @tc.require: AR000GK58N * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync003, TestSize.Level1) { - RowData rowData; - PrepareEnvironment(rowData); + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); - BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); - CheckVirtualData(rowData); + CheckVirtualData(dataMap); int64_t val = 0; - std::map dataMap; - rowData.clear(); - GenerateValue(rowData, dataMap); - EXPECT_EQ(rowData[rowData.size() - 1].GetInt64(val), E_OK); - rowData[rowData.size() - 1] = static_cast(1); - InsertValueToDB(rowData); - BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK); - - rowData.clear(); + GenerateValue(dataMap, g_fieldInfoList); dataMap["AGE"] = static_cast(1); - for (const auto &item : dataMap) { - rowData.push_back(item.second); - } - CheckVirtualData(rowData); + InsertValueToDB(dataMap); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); + + CheckVirtualData(dataMap); } /** * @tc.name: Normal Sync 004 * @tc.desc: Test normal push sync for delete data. * @tc.type: FUNC -* @tc.require: +* @tc.require: AR000GK58N * @tc.author: zhangqiquan */ HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync004, TestSize.Level1) { - RowData rowData; - PrepareEnvironment(rowData); + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); - BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); - CheckVirtualData(rowData); + CheckVirtualData(dataMap); sqlite3 *db = nullptr; EXPECT_EQ(GetDB(db), SQLITE_OK); - std::string sql = "DELETE FROM TEST_TABLE WHERE ID = 0"; + std::string sql = "DELETE FROM TEST_TABLE WHERE 1 = 1"; EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); sqlite3_close(db); - BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); - std::vector dataList; + std::vector dataList; EXPECT_EQ(g_deviceB->GetAllSyncData(g_tableName, dataList), E_OK); EXPECT_EQ(static_cast(dataList.size()), 1); for (const auto &item : dataList) { EXPECT_EQ(item.logInfo.flag, DataItem::DELETE_FLAG); } } + +/** +* @tc.name: Normal Sync 005 +* @tc.desc: Test normal push sync for add data. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync005, TestSize.Level0) +{ + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + + Query query = Query::Select(g_tableName); + g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true); + + CheckData(dataMap); +} + +/** +* @tc.name: Normal Sync 006 +* @tc.desc: Test normal pull sync for add data. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, NormalSync006, TestSize.Level1) +{ + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + + BlockSync(SYNC_MODE_PULL_ONLY, OK, {DEVICE_B}); + + CheckData(dataMap); +} + +/** +* @tc.name: AutoLaunchSync 001 +* @tc.desc: Test rdb autoLaunch success when callback return true. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync001, TestSize.Level3) +{ + /** + * @tc.steps: step1. open rdb store, create distribute table and insert data + */ + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + + /** + * @tc.steps: step2. set auto launch callBack + */ + const AutoLaunchRequestCallback callback = [](const std::string &identifier, AutoLaunchParam ¶m) { + if (g_id != identifier) { + return false; + } + param.path = g_dbDir; + param.appId = APP_ID; + param.userId = USER_ID; + param.storeId = STORE_ID_1; + return true; + }; + g_mgr.SetAutoLaunchRequestCallback(callback); + /** + * @tc.steps: step3. close store ensure communicator has closed + */ + g_mgr.CloseStore(g_rdbDelegatePtr); + g_rdbDelegatePtr = nullptr; + /** + * @tc.steps: step4. RunCommunicatorLackCallback to autolaunch store + */ + LabelType labelType(g_id.begin(), g_id.end()); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(1)); + /** + * @tc.steps: step5. Call sync expect sync successful + */ + Query query = Query::Select(g_tableName); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); + /** + * @tc.steps: step6. check sync data ensure sync successful + */ + CheckData(dataMap); + + OpenStore(); + std::this_thread::sleep_for(std::chrono::minutes(1)); +} + +/** +* @tc.name: AutoLaunchSync 002 +* @tc.desc: Test rdb autoLaunch failed when callback return false. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync002, TestSize.Level3) +{ + /** + * @tc.steps: step1. open rdb store, create distribute table and insert data + */ + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + + /** + * @tc.steps: step2. set auto launch callBack + */ + const AutoLaunchRequestCallback callback = [](const std::string &identifier, AutoLaunchParam ¶m) { + return false; + }; + g_mgr.SetAutoLaunchRequestCallback(callback); + /** + * @tc.steps: step2. close store ensure communicator has closed + */ + g_mgr.CloseStore(g_rdbDelegatePtr); + g_rdbDelegatePtr = nullptr; + /** + * @tc.steps: step3. store can't autoLaunch because callback return false + */ + LabelType labelType(g_id.begin(), g_id.end()); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(1)); + /** + * @tc.steps: step4. Call sync expect sync fail + */ + Query query = Query::Select(g_tableName); + SyncOperation::UserCallback callBack = [](const std::map &statusMap) { + for (const auto &entry : statusMap) { + EXPECT_EQ(entry.second, static_cast(SyncOperation::OP_COMM_ABNORMAL)); + } + }; + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, callBack, true), E_OK); + + OpenStore(); + std::this_thread::sleep_for(std::chrono::minutes(1)); +} + +/** +* @tc.name: AutoLaunchSync 003 +* @tc.desc: Test rdb autoLaunch failed when callback is nullptr. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AutoLaunchSync003, TestSize.Level3) +{ + /** + * @tc.steps: step1. open rdb store, create distribute table and insert data + */ + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + + g_mgr.SetAutoLaunchRequestCallback(nullptr); + /** + * @tc.steps: step2. close store ensure communicator has closed + */ + g_mgr.CloseStore(g_rdbDelegatePtr); + g_rdbDelegatePtr = nullptr; + /** + * @tc.steps: step3. store cann't autoLaunch because callback is nullptr + */ + LabelType labelType(g_id.begin(), g_id.end()); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(1)); + /** + * @tc.steps: step4. Call sync expect sync fail + */ + Query query = Query::Select(g_tableName); + SyncOperation::UserCallback callBack = [](const std::map &statusMap) { + for (const auto &entry : statusMap) { + EXPECT_EQ(entry.second, static_cast(SyncOperation::OP_COMM_ABNORMAL)); + } + }; + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, callBack, true), E_OK); + + OpenStore(); + std::this_thread::sleep_for(std::chrono::minutes(1)); +} + +/** +* @tc.name: Ability Sync 001 +* @tc.desc: Test ability sync success when has same schema. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync001, TestSize.Level1) +{ + std::map dataMap; + std::vector localFieldInfo; + GetFieldInfo(localFieldInfo, g_storageType); + + PrepareEnvironment(dataMap, localFieldInfo, localFieldInfo, {g_deviceB}); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); + + CheckVirtualData(dataMap); +} + +/** +* @tc.name: Ability Sync 002 +* @tc.desc: Test ability sync failed when has different schema. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, AbilitySync002, TestSize.Level1) +{ + /** + * @tc.steps: step1. set local schema is (BOOL, INTEGER, REAL, TEXT, BLOB, INTEGER) + */ + std::map dataMap; + std::vector localFieldInfo; + std::vector localStorageType = g_storageType; + localStorageType.push_back(StorageType::STORAGE_TYPE_INTEGER); + GetFieldInfo(localFieldInfo, localStorageType); + + /** + * @tc.steps: step2. set remote schema is (BOOL, INTEGER, REAL, TEXT, BLOB, TEXT) + */ + std::vector remoteFieldInfo; + std::vector remoteStorageType = g_storageType; + remoteStorageType.push_back(StorageType::STORAGE_TYPE_TEXT); + GetFieldInfo(remoteFieldInfo, remoteStorageType); + + /** + * @tc.steps: step3. call sync + * @tc.expected: sync fail when abilitySync + */ + PrepareEnvironment(dataMap, localFieldInfo, remoteFieldInfo, {g_deviceB}); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, SCHEMA_MISMATCH, {DEVICE_B}); +} + +/** +* @tc.name: WaterMark 001 +* @tc.desc: Test sync success after erase waterMark. +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, WaterMark001, TestSize.Level1) +{ + std::map dataMap; + PrepareEnvironment(dataMap, {g_deviceB}); + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); + + CheckVirtualData(dataMap); + + EXPECT_EQ(g_rdbDelegatePtr->RemoveDeviceData(g_deviceB->GetDeviceId(), g_tableName), OK); + g_deviceB->EraseSyncData(g_tableName); + + BlockSync(SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); + + CheckVirtualData(dataMap); +} + +/* +* @tc.name: pressure sync 001 +* @tc.desc: Test rdb sync different table at same time +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhangqiquan +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, PressureSync001, TestSize.Level1) +{ + /** + * @tc.steps: step1. create table A and device A push data to device B + * @tc.expected: step1. all is ok + */ + std::map tableADataMap; + std::vector tableAFieldInfo; + std::vector localStorageType = g_storageType; + localStorageType.push_back(StorageType::STORAGE_TYPE_INTEGER); + GetFieldInfo(tableAFieldInfo, localStorageType); + const std::string tableNameA = "TABLE_A"; + PrepareEnvironment(tableADataMap, tableNameA, tableAFieldInfo, tableAFieldInfo, {g_deviceB}); + + /** + * @tc.steps: step2. create table B and device B push data to device A + * @tc.expected: step2. all is ok + */ + std::map tableBDataMap; + std::vector tableBFieldInfo; + localStorageType = g_storageType; + localStorageType.push_back(StorageType::STORAGE_TYPE_REAL); + GetFieldInfo(tableBFieldInfo, localStorageType); + const std::string tableNameB = "TABLE_B"; + PrepareVirtualEnvironment(tableBDataMap, tableNameB, tableBFieldInfo, {g_deviceB}); + + std::condition_variable cv; + bool subFinish = false; + std::thread subThread = std::thread([&subFinish, &cv, &tableNameA, &tableADataMap]() { + BlockSync(tableNameA, SyncMode::SYNC_MODE_PUSH_ONLY, OK, {DEVICE_B}); + + CheckVirtualData(tableNameA, tableADataMap); + subFinish = true; + cv.notify_all(); + }); + subThread.detach(); + + Query query = Query::Select(tableNameB); + g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true); + CheckData(tableBDataMap, tableNameB, tableBFieldInfo); + + std::mutex mutex; + std::unique_lock lock(mutex); + cv.wait(lock, [&subFinish] { return subFinish; }); +} + +/* +* @tc.name: relation observer 001 +* @tc.desc: Test relation observer while normal pull sync +* @tc.type: FUNC +* @tc.require: +* @tc.author: zhuwentao +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, Observer001, TestSize.Level0) +{ + /** + * @tc.steps: step1. device A create table and device B insert data and device C don't insert data + * @tc.expected: step1. create and insert ok + */ + g_observer->ResetToZero(); + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB, g_deviceC}); + /** + * @tc.steps: step2. device A pull sync mode + * @tc.expected: step2. sync ok + */ + BlockSync(SyncMode::SYNC_MODE_PULL_ONLY, OK, {DEVICE_B, DEVICE_C}); + /** + * @tc.steps: step3. device A check observer + * @tc.expected: step2. data change device is deviceB + */ + EXPECT_EQ(g_observer->GetCallCount(), 1u); + EXPECT_EQ(g_observer->GetDataChangeDevice(), DEVICE_B); + CheckIdentify(g_observer); +} + +/** +* @tc.name: relation observer 002 +* @tc.desc: Test rdb observer ok in autolauchCallback scene +* @tc.type: FUNC +* @tc.require: AR000GK58N +* @tc.author: zhuwentao +*/ +HWTEST_F(DistributedDBRelationalVerP2PSyncTest, observer002, TestSize.Level3) +{ + /** + * @tc.steps: step1. open rdb store, create distribute table and insert data + */ + g_observer->ResetToZero(); + std::map dataMap; + PrepareVirtualEnvironment(dataMap, {g_deviceB}); + + /** + * @tc.steps: step2. set auto launch callBack + */ + RelationalStoreObserverUnitTest *observer = new (std::nothrow) RelationalStoreObserverUnitTest(); + const AutoLaunchRequestCallback callback = [observer](const std::string &identifier, AutoLaunchParam ¶m){ + if (g_id != identifier) { + return false; + } + param.path = g_dbDir; + param.appId = APP_ID; + param.userId = USER_ID; + param.storeId = STORE_ID_1; + param.option.storeObserver = observer; + return true; + }; + g_mgr.SetAutoLaunchRequestCallback(callback); + /** + * @tc.steps: step3. close store ensure communicator has closed + */ + g_mgr.CloseStore(g_rdbDelegatePtr); + g_rdbDelegatePtr = nullptr; + /** + * @tc.steps: step4. RunCommunicatorLackCallback to autolaunch store + */ + LabelType labelType(g_id.begin(), g_id.end()); + g_communicatorAggregator->RunCommunicatorLackCallback(labelType); + std::this_thread::sleep_for(std::chrono::seconds(1)); + /** + * @tc.steps: step5. Call sync expect sync successful and device A check observer + */ + Query query = Query::Select(g_tableName); + EXPECT_EQ(g_deviceB->GenericVirtualDevice::Sync(SYNC_MODE_PUSH_ONLY, query, true), E_OK); + EXPECT_EQ(observer->GetCallCount(), 1u); + EXPECT_EQ(observer->GetDataChangeDevice(), DEVICE_B); + CheckIdentify(observer); + std::this_thread::sleep_for(std::chrono::minutes(1)); + delete observer; +} #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_msg_schedule_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_msg_schedule_test.cpp index c5c0afa8d159d2cc4b5c268b4cfa449bb3ce3995..fabb61c5fda06a98b091df92c7dd5bad9c48fcde 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_msg_schedule_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_msg_schedule_test.cpp @@ -18,6 +18,7 @@ #include "distributeddb_tools_unit_test.h" #include "single_ver_data_message_schedule.h" #include "single_ver_data_packet.h" +#include "single_ver_kv_sync_task_context.h" using namespace testing::ext; using namespace DistributedDB; @@ -65,7 +66,7 @@ HWTEST_F(DistributedDBSingleVerMsgScheduleTest, MsgSchedule001, TestSize.Level0) * @tc.expected: put msg ok */ SingleVerDataMessageSchedule msgSchedule; - auto *context = new SingleVerSyncTaskContext(); + auto *context = new SingleVerKvSyncTaskContext(); context->SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); DataSyncMessageInfo info; info.sessionId_ = 10; @@ -115,7 +116,7 @@ HWTEST_F(DistributedDBSingleVerMsgScheduleTest, MsgSchedule002, TestSize.Level0) * @tc.expected: put msg ok */ SingleVerDataMessageSchedule msgSchedule; - auto *context = new SingleVerSyncTaskContext(); + auto *context = new SingleVerKvSyncTaskContext(); context->SetRemoteSoftwareVersion(SOFTWARE_VERSION_RELEASE_2_0); DataSyncMessageInfo info; bool isNeedHandle = true; @@ -158,7 +159,7 @@ HWTEST_F(DistributedDBSingleVerMsgScheduleTest, MsgSchedule003, TestSize.Level0) * @tc.expected: handle ok */ SingleVerDataMessageSchedule msgSchedule; - auto *context = new SingleVerSyncTaskContext(); + auto *context = new SingleVerKvSyncTaskContext(); context->SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); DataSyncMessageInfo info; bool isNeedHandle = true; @@ -225,7 +226,7 @@ HWTEST_F(DistributedDBSingleVerMsgScheduleTest, MsgSchedule004, TestSize.Level0) * @tc.expected: put msg ok */ SingleVerDataMessageSchedule msgSchedule; - auto *context = new SingleVerSyncTaskContext(); + auto *context = new SingleVerKvSyncTaskContext(); context->SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); DataSyncMessageInfo info; info.sessionId_ = 10; @@ -284,7 +285,7 @@ HWTEST_F(DistributedDBSingleVerMsgScheduleTest, MsgSchedule005, TestSize.Level0) * @tc.expected: put msg ok */ SingleVerDataMessageSchedule msgSchedule; - auto *context = new SingleVerSyncTaskContext(); + auto *context = new SingleVerKvSyncTaskContext(); context->SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); DataSyncMessageInfo info; info.sessionId_ = 10; @@ -341,7 +342,7 @@ HWTEST_F(DistributedDBSingleVerMsgScheduleTest, MsgSchedule006, TestSize.Level0) * @tc.expected: put msg ok */ SingleVerDataMessageSchedule msgSchedule; - auto *context = new SingleVerSyncTaskContext(); + auto *context = new SingleVerKvSyncTaskContext(); context->SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); DataSyncMessageInfo info; info.sessionId_ = 10; @@ -407,7 +408,7 @@ HWTEST_F(DistributedDBSingleVerMsgScheduleTest, MsgSchedule007, TestSize.Level0) * @tc.expected: put msg ok and get msg seq1_packet4, seq2_packet5 */ SingleVerDataMessageSchedule msgSchedule; - auto *context = new SingleVerSyncTaskContext(); + auto *context = new SingleVerKvSyncTaskContext(); context->SetRemoteSoftwareVersion(SOFTWARE_VERSION_CURRENT); DataSyncMessageInfo info; info.sessionId_ = 10; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp index e9c5bc4afaadb2fd78d42a72b200442f812f6260..9939f468dc4bb9142cf844041a4e6caf19853ad7 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp @@ -463,6 +463,77 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync004, TestSize.Level1) } } +/** + * @tc.name: NormalSync005 + * @tc.desc: Test normal push sync for inkeys query. + * @tc.type: FUNC + * @tc.require: AR000GOHO7 + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, NormalSync005, TestSize.Level1) +{ + InitNormalDb(); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + + /** + * @tc.steps: step1. deviceA put K1-K5 + */ + ASSERT_EQ(g_kvDelegatePtr->PutBatch( + {{KEY_1, VALUE_1}, {KEY_2, VALUE_2}, {KEY_3, VALUE_3}, {KEY_4, VALUE_4}, {KEY_5, VALUE_5}}), OK); + + /** + * @tc.steps: step2. deviceA sync K2,K4 and wait + * @tc.expected: step2. sync should return OK. + */ + Query query = Query::Select().InKeys({KEY_2, KEY_4}); + std::map result; + ASSERT_EQ(g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result, query), OK); + + /** + * @tc.expected: step3. onComplete should be called. + */ + ASSERT_EQ(result.size(), devices.size()); + for (const auto &pair : result) { + LOGD("dev %s, status %d", pair.first.c_str(), pair.second); + EXPECT_EQ(pair.second, OK); + } + + /** + * @tc.steps: step4. deviceB have K2K4 and have no K1K3K5. + * @tc.expected: step4. sync should return OK. + */ + VirtualDataItem item; + EXPECT_EQ(g_deviceB->GetData(KEY_2, item), E_OK); + EXPECT_EQ(item.value, VALUE_2); + EXPECT_EQ(g_deviceB->GetData(KEY_4, item), E_OK); + EXPECT_EQ(item.value, VALUE_4); + EXPECT_EQ(g_deviceB->GetData(KEY_1, item), -E_NOT_FOUND); + EXPECT_EQ(g_deviceB->GetData(KEY_3, item), -E_NOT_FOUND); + EXPECT_EQ(g_deviceB->GetData(KEY_5, item), -E_NOT_FOUND); + + /** + * @tc.steps: step5. deviceA sync with invalid inkeys query + * @tc.expected: step5. sync failed and the rc is right. + */ + query = Query::Select().InKeys({}); + result.clear(); + ASSERT_EQ(g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result, query), INVALID_ARGS); + + std::set keys; + for (uint8_t i = 0; i < DBConstant::MAX_BATCH_SIZE + 1; i++) { + Key key = { i }; + keys.emplace(key); + } + query = Query::Select().InKeys(keys); + result.clear(); + ASSERT_EQ(g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result, query), OVER_MAX_LIMITS); + + query = Query::Select().InKeys({{}}); + result.clear(); + ASSERT_EQ(g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PUSH_ONLY, result, query), INVALID_ARGS); +} + HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, QueryRequestPacketTest001, TestSize.Level1) { /** diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subsribe_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subsribe_sync_test.cpp index cd127f1ebe43c98f1a065286d4294cf25729dff6..0d7037fbcc28f9ec0c7bca20582a071faef20be6 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subsribe_sync_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_subsribe_sync_test.cpp @@ -79,6 +79,18 @@ namespace { "\"field_name8\":100," "\"field_name9\":100," "\"field_name10\":100}"; + + const std::string SCHEMA_VALUE2 = + "{\"field_name1\":false," + "\"field_name2\":true," + "\"field_name3\":100," + "\"field_name4\":200," + "\"field_name5\":3.14," + "\"field_name6\":\"3.1415\"," + "\"field_name7\":100," + "\"field_name8\":100," + "\"field_name9\":100," + "\"field_name10\":100}"; } class DistributedDBSingleVerP2PSubscribeSyncTest : public testing::Test { @@ -166,7 +178,6 @@ void InitSubSchemaDb() ASSERT_TRUE(g_schemaKvDelegatePtr != nullptr); } - void CheckUnFinishedMap(uint32_t sizeA, uint32_t sizeB, std::vector &deviceAQueies, std::vector &deviceBQueies, SubscribeManager &subManager) { @@ -725,4 +736,146 @@ HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync002, TestSize. LOGI("============step 4============"); Query query3 = Query::Select().EqualTo("$.field_name1", 1).OrderBy("$.field_name7"); EXPECT_TRUE(g_schemaKvDelegatePtr->SubscribeRemoteQuery(devices, nullptr, query3, true) == NOT_SUPPORT); +} + +/** + * @tc.name: subscribeSync003 + * @tc.desc: test subscribe sync with inkeys query + * @tc.type: FUNC + * @tc.require: AR000GOHO7 + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync003, TestSize.Level1) +{ + /** + * @tc.steps: step1. InitSchemaDb + */ + LOGI("============step 1============"); + InitSubSchemaDb(); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + + /** + * @tc.steps: step2. deviceB subscribe inkeys(k2k4) query to deviceA + */ + LOGI("============step 2============"); + Query query = Query::Select().InKeys({KEY_2, KEY_4}); + g_deviceB->Subscribe(QuerySyncObject(query), true, 1); + + /** + * @tc.steps: step3. deviceA put k1-k5 and wait + */ + LOGI("============step 3============"); + EXPECT_EQ(OK, g_schemaKvDelegatePtr->PutBatch({ + {KEY_1, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + {KEY_2, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + {KEY_3, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + {KEY_4, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + {KEY_5, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + })); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + /** + * @tc.steps: step4. deviceB has k2k4, has no k1k3k5 + */ + LOGI("============step 4============"); + VirtualDataItem item; + EXPECT_EQ(g_deviceB->GetData(KEY_2, item), E_OK); + EXPECT_EQ(item.value, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())); + EXPECT_EQ(g_deviceB->GetData(KEY_4, item), E_OK); + EXPECT_EQ(item.value, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())); + EXPECT_EQ(g_deviceB->GetData(KEY_1, item), -E_NOT_FOUND); + EXPECT_EQ(g_deviceB->GetData(KEY_3, item), -E_NOT_FOUND); + EXPECT_EQ(g_deviceB->GetData(KEY_5, item), -E_NOT_FOUND); +} + +/** + * @tc.name: subscribeSync004 + * @tc.desc: test subscribe sync with inkeys query + * @tc.type: FUNC + * @tc.require: AR000GOHO7 + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync004, TestSize.Level1) +{ + /** + * @tc.steps: step1. InitSchemaDb + */ + LOGI("============step 1============"); + InitSubSchemaDb(); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + + /** + * @tc.steps: step2. deviceB subscribe inkeys(k3k5) and equal to query to deviceA + */ + LOGI("============step 2============"); + Query query = Query::Select().InKeys({KEY_3, KEY_5}).EqualTo("$.field_name3", 100); // 100 for test. + g_deviceB->Subscribe(QuerySyncObject(query), true, 2); + + /** + * @tc.steps: step3. deviceA put k1v2,k3v2,k5v1 and wait + */ + LOGI("============step 3============"); + EXPECT_EQ(OK, g_schemaKvDelegatePtr->PutBatch({ + {KEY_1, Value(SCHEMA_VALUE2.begin(), SCHEMA_VALUE2.end())}, + {KEY_3, Value(SCHEMA_VALUE2.begin(), SCHEMA_VALUE2.end())}, + {KEY_5, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + })); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + /** + * @tc.steps: step4. deviceB has k3, has no k1k5 + */ + LOGI("============step 4============"); + VirtualDataItem item; + EXPECT_EQ(g_deviceB->GetData(KEY_3, item), E_OK); + EXPECT_EQ(item.value, Value(SCHEMA_VALUE2.begin(), SCHEMA_VALUE2.end())); + EXPECT_EQ(g_deviceB->GetData(KEY_1, item), -E_NOT_FOUND); + EXPECT_EQ(g_deviceB->GetData(KEY_5, item), -E_NOT_FOUND); +} + +/** + * @tc.name: subscribeSync005 + * @tc.desc: test subscribe sync with inkeys query + * @tc.type: FUNC + * @tc.require: AR000GOHO7 + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBSingleVerP2PSubscribeSyncTest, subscribeSync005, TestSize.Level1) +{ + /** + * @tc.steps: step1. InitSchemaDb + */ + LOGI("============step 1============"); + InitSubSchemaDb(); + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + + /** + * @tc.steps: step2. deviceB subscribe inkeys(k1, key6) and prefix key "k" query to deviceA + */ + LOGI("============step 2============"); + Key key6 { 'k', '6' }; + Query query = Query::Select().InKeys({KEY_1, key6}).PrefixKey({ 'k' }); + g_deviceB->Subscribe(QuerySyncObject(query), true, 3); + + /** + * @tc.steps: step3. deviceA put k1,key6 and wait + */ + LOGI("============step 3============"); + EXPECT_EQ(OK, g_schemaKvDelegatePtr->PutBatch({ + {key6, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + {KEY_1, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())}, + })); + std::this_thread::sleep_for(std::chrono::milliseconds(500)); + + /** + * @tc.steps: step4. deviceB has key6, has no k1 + */ + LOGI("============step 4============"); + VirtualDataItem item; + EXPECT_EQ(g_deviceB->GetData(key6, item), E_OK); + EXPECT_EQ(item.value, Value(SCHEMA_VALUE1.begin(), SCHEMA_VALUE1.end())); + EXPECT_EQ(g_deviceB->GetData(KEY_1, item), -E_NOT_FOUND); } \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp index 5ae7a97af6c1e9041c6b662ec7620ccf28288c1c..bcc74326c5fe4a54c4bac2bc8434491d9fe3ad8b 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_test.cpp @@ -2222,3 +2222,69 @@ HWTEST_F(DistributedDBSingleVerP2PSyncTest, SametimeSync001, TestSize.Level3) g_kvDelegatePtr->Get(key, actualValue); EXPECT_EQ(actualValue, value); } + +/** + * @tc.name: DatabaseOnlineCallback001 + * @tc.desc: check database status notify online callback + * @tc.type: FUNC + * @tc.require: AR000CQS3S SR000CQE0B + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBSingleVerP2PSyncTest, DatabaseOnlineCallback001, TestSize.Level1) +{ + /** + * @tc.steps: step1. SetStoreStatusNotifier + * @tc.expected: step1. SetStoreStatusNotifier ok + */ + std::string targetDev = "DEVICE_X"; + bool isCheckOk = false; + auto databaseStatusNotifyCallback = [targetDev, &isCheckOk] (std::string userId, + std::string appId, std::string storeId, const std::string deviceId, bool onlineStatus) -> void { + if (userId == USER_ID && appId == APP_ID && storeId == STORE_ID && deviceId == targetDev && + onlineStatus == true) { + isCheckOk = true; + }}; + g_mgr.SetStoreStatusNotifier(databaseStatusNotifyCallback); + /** + * @tc.steps: step2. trigger device online + * @tc.expected: step2. check callback ok + */ + g_communicatorAggregator->OnlineDevice(targetDev); + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME / 20)); + EXPECT_EQ(isCheckOk, true); + StoreStatusNotifier nullCallback; + g_mgr.SetStoreStatusNotifier(nullCallback); +} + +/** + * @tc.name: DatabaseOfflineCallback001 + * @tc.desc: check database status notify online callback + * @tc.type: FUNC + * @tc.require: AR000CQS3S SR000CQE0B + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBSingleVerP2PSyncTest, DatabaseOfflineCallback001, TestSize.Level1) +{ + /** + * @tc.steps: step1. SetStoreStatusNotifier + * @tc.expected: step1. SetStoreStatusNotifier ok + */ + std::string targetDev = "DEVICE_X"; + bool isCheckOk = false; + auto databaseStatusNotifyCallback = [targetDev, &isCheckOk] (std::string userId, + std::string appId, std::string storeId, const std::string deviceId, bool onlineStatus) -> void { + if (userId == USER_ID && appId == APP_ID && storeId == STORE_ID && deviceId == targetDev && + onlineStatus == false) { + isCheckOk = true; + }}; + g_mgr.SetStoreStatusNotifier(databaseStatusNotifyCallback); + /** + * @tc.steps: step2. trigger device offline + * @tc.expected: step2. check callback ok + */ + g_communicatorAggregator->OfflineDevice(targetDev); + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_TIME / 20)); + EXPECT_EQ(isCheckOk, true); + StoreStatusNotifier nullCallback; + g_mgr.SetStoreStatusNotifier(nullCallback); +} diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp index f002c34f572a333c189ebe7f10cfaf5282250d9d..0ab564c2bf6f2827d07d5330b37604ab10c7d164 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/distributeddb_time_sync_test.cpp @@ -19,6 +19,7 @@ #include "distributeddb_tools_unit_test.h" #include "isyncer.h" #include "single_ver_sync_state_machine.h" +#include "single_ver_kv_sync_task_context.h" #include "sync_types.h" #include "virtual_single_ver_sync_db_Interface.h" #include "virtual_time_sync_communicator.h" @@ -88,7 +89,7 @@ void DistributedDBTimeSyncTest::SetUp(void) g_timeSyncB = new (std::nothrow) TimeSync(); ASSERT_TRUE(g_timeSyncB != nullptr); - g_syncTaskContext = new (std::nothrow) SingleVerSyncTaskContext(); + g_syncTaskContext = new (std::nothrow) SingleVerKvSyncTaskContext(); ASSERT_TRUE(g_syncTaskContext != nullptr); } diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp index 012e141415abda149c6696bac1a02b1a2c592473..338152b18ec2e23c039f8480b31030e20a27d207 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.cpp @@ -15,7 +15,8 @@ #include "generic_virtual_device.h" #include "multi_ver_sync_task_context.h" -#include "single_ver_sync_task_context.h" +#include "single_ver_kv_sync_task_context.h" +#include "single_ver_relational_sync_task_context.h" namespace DistributedDB { GenericVirtualDevice::GenericVirtualDevice(std::string deviceId) @@ -86,11 +87,11 @@ int GenericVirtualDevice::Initialize(VirtualCommunicatorAggregator *comAggregato return -E_NOT_SUPPORT; } if (storage_->GetInterfaceType() == IKvDBSyncInterface::SYNC_SVD) { - context_ = new (std::nothrow) SingleVerSyncTaskContext; + context_ = new (std::nothrow) SingleVerKvSyncTaskContext; subManager_ = std::make_shared(); static_cast(context_)->SetSubscribeManager(subManager_); } else if (storage_->GetInterfaceType() == IKvDBSyncInterface::SYNC_RELATION) { - context_ = new (std::nothrow) SingleVerSyncTaskContext; + context_ = new (std::nothrow) SingleVerRelationalSyncTaskContext; } else { context_ = new (std::nothrow) MultiVerSyncTaskContext; } @@ -212,7 +213,13 @@ int GenericVirtualDevice::Sync(SyncMode mode, bool wait) int GenericVirtualDevice::Sync(SyncMode mode, const Query &query, bool wait) { - auto operation = new (std::nothrow) SyncOperation(1, {remoteDeviceId_}, mode, nullptr, wait); + return Sync(mode, query, nullptr, wait); +} + +int GenericVirtualDevice::Sync(SyncMode mode, const Query &query, + const SyncOperation::UserCallback &callBack, bool wait) +{ + auto operation = new (std::nothrow) SyncOperation(1, {remoteDeviceId_}, mode, callBack, wait); if (operation == nullptr) { return -E_OUT_OF_MEMORY; } diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h index 388a85152e196f0e34959387268dcc8e5861523d..25525870f3aecc27b3bf24a333de0ebb2eff6c67 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/generic_virtual_device.h @@ -21,11 +21,10 @@ #include "meta_data.h" #include "subscribe_manager.h" #include "sync_task_context.h" -#include "types.h" +#include "store_types.h" #include "virtual_communicator_aggregator.h" namespace DistributedDB { - class GenericVirtualDevice { public: explicit GenericVirtualDevice(std::string deviceId); @@ -42,6 +41,7 @@ public: TimeOffset GetLocalTimeOffset() const; virtual int Sync(SyncMode mode, bool wait); virtual int Sync(SyncMode mode, const Query &query, bool wait); + virtual int Sync(SyncMode mode, const Query &query, const SyncOperation::UserCallback &callBack, bool wait); protected: ICommunicator *communicateHandle_; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_auto_launch.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_auto_launch.h new file mode 100644 index 0000000000000000000000000000000000000000..f9f0d7a83f515694302a1e5114380b06df3fe476 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_auto_launch.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 MOCK_AUTO_LAUNCH_H +#define MOCK_AUTO_LAUNCH_H + +#include +#include "auto_launch.h" + +namespace DistributedDB { +class MockAutoLaunch : public AutoLaunch { +public: + + void SetAutoLaunchItem(const std::string &identify, AutoLaunchItem &item) + { + std::lock_guard autoLock(extLock_); + extItemMap_[identify] = item; + } + + void CallExtConnectionLifeCycleCallbackTask(const std::string &identifier) + { + AutoLaunch::ExtConnectionLifeCycleCallbackTask(identifier); + } + + MOCK_METHOD1(TryCloseConnection, void(AutoLaunchItem &)); +}; +} // namespace DistributedDB +#endif // #define MOCK_AUTO_LAUNCH_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h new file mode 100644 index 0000000000000000000000000000000000000000..1220a9d4445025513fe7310ae4cacf49c6f2b8a2 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_single_ver_state_machine.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 MOCK_SINGLE_VER_STATE_MACHINE_H +#define MOCK_SINGLE_VER_STATE_MACHINE_H + +#include +#include "single_ver_sync_state_machine.h" + +namespace DistributedDB { +class MockSingleVerStateMachine : public SingleVerSyncStateMachine { +public: + void CallStepToTimeout(TimerId timerId) + { + SingleVerSyncStateMachine::StepToTimeout(timerId); + } + + int CallExecNextTask() + { + return SyncStateMachine::ExecNextTask(); + } + + MOCK_METHOD1(SwitchStateAndStep, void(uint8_t)); + + MOCK_METHOD0(PrepareNextSyncTask, int(void)); +}; +} // namespace DistributedDB +#endif // #define MOCK_SINGLE_VER_STATE_MACHINE_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h new file mode 100644 index 0000000000000000000000000000000000000000..2c32b1b88d7963d18415cb0f56336ee35e1e6d69 --- /dev/null +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/mock_sync_task_context.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2022 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 MOCK_SYNC_TASK_CONTEXT_H +#define MOCK_SYNC_TASK_CONTEXT_H + +#include +#include "single_ver_kv_sync_task_context.h" + +namespace DistributedDB { +class MockSyncTaskContext : public SingleVerKvSyncTaskContext { +public: + MOCK_CONST_METHOD0(GetTimerId, TimerId(void)); + + MOCK_CONST_METHOD0(IsTargetQueueEmpty, bool(void)); + + MOCK_METHOD0(MoveToNextTarget, void(void)); + + MOCK_CONST_METHOD0(IsCurrentSyncTaskCanBeSkipped, bool(void)); + + MOCK_METHOD1(SetOperationStatus, void(int)); + + MOCK_METHOD1(SetTaskExecStatus, void(int)); + + MOCK_METHOD0(Clear, void(void)); +}; +} // namespace DistributedDB +#endif // #define MOCK_SINGLE_VER_STATE_MACHINE_H \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.cpp index 16272ff4ef8a1105a68b11505b2d59e083da9447..c4a55e158fd72bda839b1f5ad983ba43cacc0a7c 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.cpp @@ -24,16 +24,22 @@ RelationalVirtualDevice::~RelationalVirtualDevice() { } -int RelationalVirtualDevice::PutData(const std::string &tableName, const std::vector &dataList) +int RelationalVirtualDevice::PutData(const std::string &tableName, const std::vector &dataList) { return static_cast(storage_)->PutLocalData(dataList, tableName); } -int RelationalVirtualDevice::GetAllSyncData(const std::string &tableName, std::vector &data) +int RelationalVirtualDevice::GetAllSyncData(const std::string &tableName, std::vector &data) { return static_cast(storage_)->GetAllSyncData(tableName, data); } +int RelationalVirtualDevice::GetSyncData(const std::string &tableName, + const std::string &hashKey, VirtualRowData &data) +{ + return static_cast(storage_)->GetVirtualSyncData(tableName, hashKey, data); +} + void RelationalVirtualDevice::SetLocalFieldInfo(const std::vector &localFieldInfo) { static_cast(storage_)->SetLocalFieldInfo(localFieldInfo); @@ -43,5 +49,15 @@ int RelationalVirtualDevice::Sync(SyncMode mode, bool wait) { return -E_NOT_SUPPORT; } + +void RelationalVirtualDevice::EraseSyncData(const std::string &tableName) +{ + static_cast(storage_)->EraseSyncData(tableName); +} + +void RelationalVirtualDevice::SetTableInfo(const TableInfo &tableInfo) +{ + static_cast(storage_)->SetTableInfo(tableInfo); +} } // DistributedDB #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.h index 32f974bcd8f8f028ef1da6909a8502c1435c73fb..e4e1baf74590c18b3876d9ac740ea94f3fff0b32 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/relational_virtual_device.h @@ -16,9 +16,10 @@ #define RELATIONAL_VIRTUAL_DEVICE_H #ifdef RELATIONAL_STORE +#include "data_transformer.h" #include "generic_virtual_device.h" #include "relational_schema_object.h" -#include "data_transformer.h" +#include "virtual_relational_ver_sync_db_interface.h" namespace DistributedDB { class RelationalVirtualDevice final : public GenericVirtualDevice { @@ -26,10 +27,13 @@ public: explicit RelationalVirtualDevice(const std::string &deviceId); ~RelationalVirtualDevice() override; - int PutData(const std::string &tableName, const std::vector &dataList); - int GetAllSyncData(const std::string &tableName, std::vector &data); + int PutData(const std::string &tableName, const std::vector &dataList); + int GetAllSyncData(const std::string &tableName, std::vector &data); + int GetSyncData(const std::string &tableName, const std::string &hashKey, VirtualRowData &data); void SetLocalFieldInfo(const std::vector &localFieldInfo); + void SetTableInfo(const TableInfo &tableInfo); int Sync(SyncMode mode, bool wait) override; + void EraseSyncData(const std::string &tableName); }; } #endif diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp index 1f12f5b3c17060c937af5b185f6d08bbb67b7671..afae09798630d3a47cab30e5b19a044a4e78124a 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_communicator.cpp @@ -71,7 +71,7 @@ int VirtualCommunicator::SendMessage(const std::string &dstTarget, const Message int VirtualCommunicator::GetRemoteCommunicatorVersion(const std::string &deviceId, uint16_t &version) const { - version = 1; + version = UINT16_MAX; return E_OK; } diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp index abad85f7abfc2cd5b2998650ac3c723b7cf9ecd9..803e4f59c67b86dcba3628298ba8985e183f9c98 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ #ifdef RELATIONAL_STORE +#include "db_common.h" #include "virtual_relational_ver_sync_db_interface.h" #include "generic_single_ver_kv_entry.h" #include "virtual_single_ver_sync_db_Interface.h" @@ -50,6 +51,13 @@ namespace { LOGD("[GetEntriesFromItems] size:%d", dataItems.size()); return errCode; } + + std::string GetStr(const std::vector &vec) + { + std::string str; + DBCommon::VectorToString(vec, str); + return str; + } } int VirtualRelationalVerSyncDBInterface::PutSyncDataWithQuery(const QueryObject &object, @@ -78,37 +86,30 @@ int VirtualRelationalVerSyncDBInterface::PutSyncDataWithQuery(const QueryObject if (errCode != E_OK) { return errCode; } - std::vector dataList; - std::set hashKeySet; for (const auto &optRowDataWithLog : optTableDataWithLog.dataList) { - RowDataWithLog rowDataWithLog; - rowDataWithLog.logInfo = optRowDataWithLog.logInfo; + VirtualRowData virtualRowData; + virtualRowData.logInfo = optRowDataWithLog.logInfo; + int index = 0; for (const auto &optItem : optRowDataWithLog.optionalData) { - if (!optItem.has_value()) { - continue; + DataValue dataValue; + if (optItem.has_value()) { + dataValue = std::move(optItem.value()); } - rowDataWithLog.rowData.push_back(optItem.value()); LOGD("type:%d", optItem.value().GetType()); + virtualRowData.objectData.PutDataValue(localFieldInfo_[index].GetFieldName(), dataValue); + index++; } - hashKeySet.insert(rowDataWithLog.logInfo.hashKey); - dataList.push_back(rowDataWithLog); + syncData_[object.GetTableName()][GetStr(virtualRowData.logInfo.hashKey)] = virtualRowData; } LOGD("tableName %s", optTableDataWithLog.tableName.c_str()); - for (const auto &item : syncData_[optTableDataWithLog.tableName]) { - if (hashKeySet.find(item.logInfo.hashKey) == hashKeySet.end()) { - dataList.push_back(item); - } - } - syncData_[optTableDataWithLog.tableName] = dataList; - return errCode; } -int VirtualRelationalVerSyncDBInterface::PutLocalData(const std::vector &dataList, +int VirtualRelationalVerSyncDBInterface::PutLocalData(const std::vector &dataList, const std::string &tableName) { for (const auto &item : dataList) { - localData_[tableName].push_back(item); + localData_[tableName][GetStr(item.logInfo.hashKey)] = item; } return E_OK; } @@ -123,11 +124,22 @@ int VirtualRelationalVerSyncDBInterface::GetSyncData(QueryObject &query, } std::vector dataItemList; TableDataWithLog tableDataWithLog = {query.GetTableName(), {}}; - for (const auto &data : localData_[query.GetTableName()]) { - if (data.logInfo.timestamp >= timeRange.beginTime && data.logInfo.timestamp < timeRange.endTime) { - tableDataWithLog.dataList.push_back(data); + for (const auto &[hashKey, virtualData] : localData_[query.GetTableName()]) { + if (virtualData.logInfo.timestamp < timeRange.beginTime || + virtualData.logInfo.timestamp >= timeRange.endTime) { + LOGD("ignore hashkey %s", hashKey.c_str()); + continue; + } + RowDataWithLog rowData; + for (const auto &field : localFieldInfo_) { + DataValue dataValue; + (void)virtualData.objectData.GetDataValue(field.GetFieldName(), dataValue); + rowData.rowData.push_back(std::move(dataValue)); } + rowData.logInfo = virtualData.logInfo; + tableDataWithLog.dataList.push_back(rowData); } + int errCode = DataTransformer::TransformTableData(tableDataWithLog, localFieldInfo_, dataItemList); if (errCode != E_OK) { return errCode; @@ -184,11 +196,6 @@ int VirtualRelationalVerSyncDBInterface::LocalDataChanged(int notifyEvent, std:: return E_OK; } -int VirtualRelationalVerSyncDBInterface::SchemaChanged(int notifyEvent) -{ - return E_OK; -} - int VirtualRelationalVerSyncDBInterface::GetInterfaceType() const { return SYNC_RELATION; @@ -210,9 +217,9 @@ std::vector VirtualRelationalVerSyncDBInterface::GetIdentifier() const void VirtualRelationalVerSyncDBInterface::GetMaxTimeStamp(TimeStamp &stamp) const { for (const auto &item : syncData_) { - for (const auto &rowDataWithLog : item.second) { - if (stamp < rowDataWithLog.logInfo.timestamp) { - stamp = rowDataWithLog.logInfo.timestamp; + for (const auto &entry : item.second) { + if (stamp < entry.second.logInfo.timestamp) { + stamp = entry.second.logInfo.timestamp; } } } @@ -273,6 +280,7 @@ const KvDBProperties &VirtualRelationalVerSyncDBInterface::GetDbProperties() con void VirtualRelationalVerSyncDBInterface::SetLocalFieldInfo(const std::vector &localFieldInfo) { + localFieldInfo_.clear(); // sort by dict std::map infoMap; for (const auto &item : localFieldInfo) { @@ -284,13 +292,52 @@ void VirtualRelationalVerSyncDBInterface::SetLocalFieldInfo(const std::vector &data) + std::vector &data) +{ + if (syncData_.find(tableName) == syncData_.end()) { + return -E_NOT_FOUND; + } + for (const auto &entry : syncData_[tableName]) { + data.push_back(entry.second); + } + return E_OK; +} + +int VirtualRelationalVerSyncDBInterface::GetVirtualSyncData(const std::string &tableName, + const std::string &hashKey, VirtualRowData &data) { if (syncData_.find(tableName) == syncData_.end()) { return -E_NOT_FOUND; } - data = syncData_[tableName]; + if (syncData_.find(hashKey) == syncData_.end()) { + return -E_NOT_FOUND; + } + data = syncData_[tableName][hashKey]; return E_OK; } + +void VirtualRelationalVerSyncDBInterface::EraseSyncData(const std::string &tableName) +{ + if (syncData_.find(tableName) == syncData_.end()) { + return; + } + syncData_.erase(tableName); +} + +int VirtualRelationalVerSyncDBInterface::CreateDistributedDeviceTable(const std::string &device, + const RelationalSyncStrategy &syncStrategy) +{ + return E_OK; +} + +int VirtualRelationalVerSyncDBInterface::RegisterSchemaChangedCallback(const std::function &onSchemaChanged) +{ + return E_OK; +} + +void VirtualRelationalVerSyncDBInterface::SetTableInfo(const TableInfo &tableInfo) +{ + schemaObj_.AddRelationalTable(tableInfo); +} } #endif \ No newline at end of file diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h index a95fd5c8370ded650cc8276c2b20881fe32984f8..96f66e652c4b6cbde248ee57d0be09999cd306e7 100644 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h @@ -22,6 +22,11 @@ #include "relational_schema_object.h" namespace DistributedDB { +struct VirtualRowData { + LogInfo logInfo; + ObjectData objectData; +}; + class VirtualRelationalVerSyncDBInterface : public RelationalDBSyncInterface { public: VirtualRelationalVerSyncDBInterface() = default; @@ -30,7 +35,7 @@ public: int PutSyncDataWithQuery(const QueryObject &query, const std::vector &entries, const std::string &deviceName) override; - int PutLocalData(const std::vector &dataList, const std::string &tableName); + int PutLocalData(const std::vector &dataList, const std::string &tableName); RelationalSchemaObject GetSchemaInfo() const override; @@ -44,8 +49,6 @@ public: int LocalDataChanged(int notifyEvent, std::vector &queryObj) override; - int SchemaChanged(int notifyEvent) override; - int GetSyncData(QueryObject &query, const SyncTimeRange &timeRange, const DataSizeSpecInfo &dataSizeInfo, ContinueToken &continueStmtToken, std::vector &entries) const override; @@ -74,7 +77,9 @@ public: void SetLocalFieldInfo(const std::vector &localFieldInfo); - int GetAllSyncData(const std::string &tableName, std::vector &data); + int GetAllSyncData(const std::string &tableName, std::vector &data); + + int GetVirtualSyncData(const std::string &tableName, const std::string &hashKey, VirtualRowData &data); int InterceptData(std::vector &entries, const std::string &sourceID, const std::string &targetID) const override @@ -87,11 +92,19 @@ public: return E_OK; } + int CreateDistributedDeviceTable(const std::string &device, const RelationalSyncStrategy &syncStrategy) override; + + int RegisterSchemaChangedCallback(const std::function &onSchemaChanged) override; + + void EraseSyncData(const std::string &tableName); + + void SetTableInfo(const TableInfo &tableInfo); + private: mutable std::map, std::vector> metadata_; - std::map> syncData_; - mutable std::map> localData_; + std::map> syncData_; + mutable std::map> localData_; std::string schema_; RelationalSchemaObject schemaObj_; std::vector localFieldInfo_; diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp index b3efdebe0a2374c55aabb1ed95f2b2e7c4d32b3e..810ede8db5fb268030c77a09e34f9998960f3f37 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp @@ -18,6 +18,7 @@ #include #include +#include "db_common.h" #include "db_errno.h" #include "generic_single_ver_kv_entry.h" #include "intercepted_data_impl.h" diff --git a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h index 6120cef499791832dd7bd173d6e1ce258898e13e..fb80c8cd3e041837f455660174910db1e8371acd 100755 --- a/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h +++ b/services/distributeddataservice/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h @@ -21,7 +21,7 @@ #include "single_ver_kvdb_sync_interface.h" #include "query_object.h" -#include "types.h" +#include "store_types.h" namespace DistributedDB { struct VirtualDataItem { diff --git a/services/distributeddataservice/test/common/distributeddb/include/delegate_callback.h b/services/distributeddataservice/test/common/distributeddb/include/delegate_callback.h index ecb1497db4e3b21175f243db894be0b8cf8a3983..a6a045fc999bad3d715b81b24d60b6ba1b78dec3 100644 --- a/services/distributeddataservice/test/common/distributeddb/include/delegate_callback.h +++ b/services/distributeddataservice/test/common/distributeddb/include/delegate_callback.h @@ -15,7 +15,6 @@ #ifndef DELEGATE_CALLBACK_H #define DELEGATE_CALLBACK_H #include "kv_store_snapshot_delegate.h" -#include "types.h" #include "types_export.h" // DelegateCallback conclude the Callback implements of function< void(DBStatus, KvStoreSnapshotDelegate*)> diff --git a/services/distributeddataservice/test/common/distributeddb/include/delegate_kv_mgr_callback.h b/services/distributeddataservice/test/common/distributeddb/include/delegate_kv_mgr_callback.h index 00d58a11c9ca1a99532d16d2c9e2c8c1b6aa744e..35b087093736b122859ea93414c9e3ca74cc3336 100644 --- a/services/distributeddataservice/test/common/distributeddb/include/delegate_kv_mgr_callback.h +++ b/services/distributeddataservice/test/common/distributeddb/include/delegate_kv_mgr_callback.h @@ -16,7 +16,6 @@ #define DELEGATE_KV_MGR_CALLBACK_H #include "kv_store_delegate.h" -#include "types.h" // DelegateKvMgrCallback conclude the Callback implements of function< void(DBStatus, KvStoreDelegate*)> class DelegateKvMgrCallback { diff --git a/services/distributeddataservice/test/common/distributeddb/include/distributed_rdb_tools.h b/services/distributeddataservice/test/common/distributeddb/include/distributed_rdb_tools.h index c891afa0b8f944d43e64b79428770f53b345a793..45b007bd6118bc933d2ec58e2120822e66ac15a6 100644 --- a/services/distributeddataservice/test/common/distributeddb/include/distributed_rdb_tools.h +++ b/services/distributeddataservice/test/common/distributeddb/include/distributed_rdb_tools.h @@ -19,7 +19,6 @@ #include "relational_store_delegate.h" #include "relational_store_manager.h" -#include "types.h" #include "distributed_test_sysinfo.h" #include "distributeddb_data_generator.h" #include "log_print.h" diff --git a/services/distributeddataservice/test/common/distributeddb/include/distributed_test_tools.h b/services/distributeddataservice/test/common/distributeddb/include/distributed_test_tools.h index 318b8b00a01fc8ce8721618544cfa6f49f32b00e..6e1e512d949dca0996bdd9650df6564e623e9e30 100755 --- a/services/distributeddataservice/test/common/distributeddb/include/distributed_test_tools.h +++ b/services/distributeddataservice/test/common/distributeddb/include/distributed_test_tools.h @@ -20,7 +20,6 @@ #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" #include "kv_store_observer_impl.h" -#include "types.h" #include "distributed_test_sysinfo.h" #include "distributeddb_data_generator.h" #include "log_print.h" diff --git a/services/distributeddataservice/test/common/distributeddb/include/distributeddb_constant.h b/services/distributeddataservice/test/common/distributeddb/include/distributeddb_constant.h index c92c2d1ca37eeef90f106b8e79719c0256822d35..4f50a04dc4d9c93c91694e9bc87e96a682d5114a 100644 --- a/services/distributeddataservice/test/common/distributeddb/include/distributeddb_constant.h +++ b/services/distributeddataservice/test/common/distributeddb/include/distributeddb_constant.h @@ -17,7 +17,7 @@ #define DISTRIBUTEDDB_CONSTANT_DEFINE_H #include -#include "types.h" +#include "store_types.h" namespace DistributedDBDataGenerator { const int TEST_ID_1 = 1; diff --git a/services/distributeddataservice/test/common/distributeddb/include/distributeddb_data_generator.h b/services/distributeddataservice/test/common/distributeddb/include/distributeddb_data_generator.h index a6836dfd955b4ca17aaf26f0b49fc88e39660115..4603d80bbbe3e7dbda3cb15b3c141292c7cd5819 100755 --- a/services/distributeddataservice/test/common/distributeddb/include/distributeddb_data_generator.h +++ b/services/distributeddataservice/test/common/distributeddb/include/distributeddb_data_generator.h @@ -18,7 +18,6 @@ #include #include #include -#include "types.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" #include "distributed_test_sysinfo.h" diff --git a/services/distributeddataservice/test/common/distributeddb/include/distributeddb_schema_test_tools.h b/services/distributeddataservice/test/common/distributeddb/include/distributeddb_schema_test_tools.h index d1f9fddd93b34162358f6d52eeb96941399cea90..696dfbefea88109f232b013b8abef30b13fccdc0 100755 --- a/services/distributeddataservice/test/common/distributeddb/include/distributeddb_schema_test_tools.h +++ b/services/distributeddataservice/test/common/distributeddb/include/distributeddb_schema_test_tools.h @@ -20,7 +20,6 @@ #endif #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" #include "distributeddb_data_generator.h" #include "distributeddb_nb_test_tools.h" const static int RECORDNUM = 257; diff --git a/services/distributeddataservice/test/common/distributeddb/include/kv_store_observer_impl.h b/services/distributeddataservice/test/common/distributeddb/include/kv_store_observer_impl.h index c70c804df67aa244233c10aa91963933355c8611..a41697669bf10f5fccae02849ef9588bfdd1aef9 100644 --- a/services/distributeddataservice/test/common/distributeddb/include/kv_store_observer_impl.h +++ b/services/distributeddataservice/test/common/distributeddb/include/kv_store_observer_impl.h @@ -21,7 +21,6 @@ #include "distributeddb_data_generator.h" #include "kv_store_changed_data.h" #include "kv_store_observer.h" -#include "types.h" enum ListType { INSERT_LIST = 0, diff --git a/services/distributeddataservice/test/common/distributeddb/include/kv_store_snapshot_callback.h b/services/distributeddataservice/test/common/distributeddb/include/kv_store_snapshot_callback.h index 8c3da202208ec729fdc494a92a78b143831dd6fc..988151946d1469b4dc6d2adfa182480f106094a2 100644 --- a/services/distributeddataservice/test/common/distributeddb/include/kv_store_snapshot_callback.h +++ b/services/distributeddataservice/test/common/distributeddb/include/kv_store_snapshot_callback.h @@ -15,8 +15,8 @@ #ifndef KV_STORE_SNAPSHOT_CALLBACK_H #define KV_STORE_SNAPSHOT_CALLBACK_H +#include "store_types.h" #include "types_export.h" -#include "types.h" class KvStoreSnapshotCallback { public: diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/include/distributed_crud_transaction_tools.h b/services/distributeddataservice/test/moduletest/common/distributeddb/include/distributed_crud_transaction_tools.h index 4e74a0c20328ef7796b887f34dd412ba89914bc0..1363b2780c3bf4b25fde56c21de852c7b9d890ac 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/include/distributed_crud_transaction_tools.h +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/include/distributed_crud_transaction_tools.h @@ -17,7 +17,6 @@ #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" enum class CrudMode { PUT_BATCH = 0, diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/include/process_communicator_test_stub.h b/services/distributeddataservice/test/moduletest/common/distributeddb/include/process_communicator_test_stub.h index 64975bc1d9c955bca66d23242cd3fc31a60869fb..c2a877e3b47cb5c520f8ae1b4a882ddeb65c52de 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/include/process_communicator_test_stub.h +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/include/process_communicator_test_stub.h @@ -22,7 +22,6 @@ #include #include "iprocess_communicator.h" -#include "types.h" namespace DistributedDB { class ProcessCommunicatorTestStub : public IProcessCommunicator { diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributed_crud_transaction_tools.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributed_crud_transaction_tools.cpp index 6fb0ff98f00207a986046374204167be8acb5ab1..a9fa618047bb1c9576600ffab832fea4f924213d 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributed_crud_transaction_tools.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributed_crud_transaction_tools.cpp @@ -28,7 +28,6 @@ #include "distributeddb_data_generator.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace chrono; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_backup_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_backup_test.cpp index 556719b6f760292812478d1d7b66150284b99b60..a92b7d9feaa24c30decaabf1eb65106023b51b04 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_backup_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_backup_test.cpp @@ -26,7 +26,6 @@ #include "distributeddb_nb_test_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" #include "process_communicator_test_stub.h" using namespace std; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_batch_crud_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_batch_crud_test.cpp index 0df39c228a3c7ba286732719caaf33b06a16075b..8784a7a8d488b010d6ce25ed6badef94d2f4489d 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_batch_crud_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_batch_crud_test.cpp @@ -22,7 +22,6 @@ #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" #include "kv_store_snapshot_callback.h" -#include "types.h" using namespace std; using namespace testing; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_concurrency_crud_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_concurrency_crud_test.cpp index bd85549d34a797f2689c02381ad83648433e76bb..62612011c9225d085522c0b3bf95ae4917b94820 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_concurrency_crud_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_concurrency_crud_test.cpp @@ -25,7 +25,6 @@ #include "distributed_test_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace testing; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_create_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_create_test.cpp index abf69a1658adfd33b48dec6004b95e48c488dbcc..c2ef56631733b89bd7b4dc8f141a7ece4a85d60a 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_create_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_create_test.cpp @@ -25,7 +25,6 @@ #include "distributed_test_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" #include "distributed_test_sysinfo.h" using namespace std; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_crud_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_crud_test.cpp index e70a6ba18f03e96dca2c85e4eaf75b32076d72a3..dd0441762e0d37db9ce8657ec4ad87c36f1e6d70 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_crud_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_crud_test.cpp @@ -23,7 +23,6 @@ #include "distributed_test_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace chrono; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_snap_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_snap_test.cpp index 3b3540ee4833eee8e66894aef025be2fe2dcf1f7..4f8efebec1d5bbf5f984e396c0406fd204b7cdfc 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_snap_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_snap_test.cpp @@ -25,7 +25,6 @@ #include "distributed_test_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace chrono; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_test.cpp index 5e5c9e3394e6560a3eae5482fe2719074e9c756c..14ff6fde83eacd75e63ee4799d4c0892700845f1 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_observer_test.cpp @@ -25,7 +25,6 @@ #include "distributed_test_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace chrono; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_realdel_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_realdel_test.cpp index 130703c0302653a7e22e52729b520ff1355af38e..837cbaab05435b24889b9eccb09c22e38cea26e6 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_realdel_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_realdel_test.cpp @@ -25,7 +25,6 @@ #include "distributeddb_nb_test_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace chrono; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_perf_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_perf_test.cpp index 883e1172a7e55b668f254452b399b0d533298b7f..257ee5f97c41afdd569746c4d691145d6490a230 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_perf_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_perf_test.cpp @@ -19,7 +19,6 @@ #include "distributed_crud_transaction_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace testing; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_test.cpp index f7b05c08e7a06f3872daf86a9f115f9b0570085b..4a4bc76805bb51ab8490e9e8008f1f8eb2cdd1c9 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_kv_transaction_test.cpp @@ -27,7 +27,6 @@ #include "distributed_crud_transaction_tools.h" #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" -#include "types.h" using namespace std; using namespace testing; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_autolaunch_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_autolaunch_test.cpp index 180ecf126036799b1a12be8ac0a119e6a1d7d1b9..7b5901e5fc853d74956f51c26a18eabb1d032164 100644 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_autolaunch_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_autolaunch_test.cpp @@ -25,7 +25,6 @@ #include "kv_store_delegate_manager.h" #include "kv_store_nb_delegate.h" #include "process_communicator_test_stub.h" -#include "types.h" using namespace std; using namespace chrono; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_backup_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_backup_test.cpp index 079d394dd96ebd657be04fe659d01340cedc01ad..b52d2c8a73097e7f549e7aabf5a653508d798b36 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_backup_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_backup_test.cpp @@ -24,7 +24,6 @@ #include #include -#include "types.h" #include "kv_store_nb_delegate.h" #include "kv_store_delegate_manager.h" #include "distributeddb_nb_test_tools.h" diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_create_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_create_test.cpp index 1e196a6b8998e1654b972b844e83d8fba2f383a4..24520b4684a7e351334f6cfb4c262d3dca16ee53 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_create_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_create_test.cpp @@ -24,7 +24,6 @@ #include "distributeddb_data_generator.h" #include "distributeddb_nb_test_tools.h" #include "kv_store_delegate_manager.h" -#include "types.h" #include "distributed_test_tools.h" using namespace std; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_power_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_power_test.cpp index e2e6a98b87fa3688c4a1bf4b754c835433102243..2ac6c892929f2744751b38ae830c74509c8c041f 100644 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_power_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_power_test.cpp @@ -25,7 +25,6 @@ #include "kv_store_delegate.h" #include "kv_store_delegate_manager.h" #include "kv_store_nb_delegate.h" -#include "types.h" using namespace std; using namespace chrono; diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_test.cpp index 1358546ae44ec4d00e380cd8da74c7a3e32f15e3..7d06a2ddabc3e43744e3fbdc329799f659f1dba2 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_crud_test.cpp @@ -20,7 +20,6 @@ #include #include -#include "types.h" #include "kv_store_delegate.h" #include "kv_store_nb_delegate.h" #include "kv_store_delegate_manager.h" diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_cursor_testcase.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_cursor_testcase.cpp index 76c4b3a9f68239447e8aacae7e912a4e9a723ea6..54773729e71b0d09cbc157811637552c03d49822 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_cursor_testcase.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_cursor_testcase.cpp @@ -23,7 +23,6 @@ #include #include #include -#include "types.h" #include "types_export.h" #include "kv_store_delegate.h" #include "kv_store_nb_delegate.h" diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_enable_sync_by_closed_db_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_enable_sync_by_closed_db_test.cpp index 7d8a6fedc954c34342e99a81c7733182bed7ebc2..faa90ee44119d6e839588fab49ea30185ee9bfbb 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_enable_sync_by_closed_db_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_enable_sync_by_closed_db_test.cpp @@ -16,7 +16,6 @@ #include #include -#include "types.h" #include "kv_store_delegate.h" #include "kv_store_nb_delegate.h" #include "kv_store_delegate_manager.h" diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_observer_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_observer_test.cpp index 1ebe76ee481bbe07b9fd69ad79b49e197cb46f79..dda8c588bf66a1859e84c64d64cb0645ad9c9bce 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_observer_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_observer_test.cpp @@ -21,7 +21,6 @@ #include #include -#include "types.h" #include "kv_store_delegate.h" #include "kv_store_nb_delegate.h" #include "distributeddb_nb_test_tools.h" diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_expand_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_expand_test.cpp index 9b80b7ba0364ba9adafd6ff6263e025487e2b0f4..8c39c277b2502ac407519706cbda5fb80ed85923 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_expand_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_expand_test.cpp @@ -18,7 +18,6 @@ #include #include -#include "types.h" #include "kv_store_delegate.h" #include "kv_store_nb_delegate.h" #include "kv_store_delegate_manager.h" diff --git a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_test.cpp b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_test.cpp index 8289b81bdaafd949dbfe5665c8a83f5e7fe959a4..e1e45929f45dadac4d0f210ab1355382d6939c62 100755 --- a/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_test.cpp +++ b/services/distributeddataservice/test/moduletest/common/distributeddb/src/distributeddb_nb_predicate_query_test.cpp @@ -19,7 +19,6 @@ #include #include -#include "types.h" #include "kv_store_delegate.h" #include "kv_store_nb_delegate.h" #include "kv_store_delegate_manager.h"