diff --git a/data_object/interfaces/innerkits/BUILD.gn b/data_object/interfaces/innerkits/BUILD.gn index 0702c9c0a010ddfa4ec81469c168133abdb832b3..de25122497fb044b58cff026dc609d2fc97c97e3 100644 --- a/data_object/interfaces/innerkits/BUILD.gn +++ b/data_object/interfaces/innerkits/BUILD.gn @@ -71,6 +71,12 @@ object_external_deps_config = [ "samgr:samgr_proxy", ] ohos_shared_library("distributeddataobject_impl") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } part_name = "data_object" sources = object_source_config @@ -84,6 +90,13 @@ ohos_shared_library("distributeddataobject_impl") { } ohos_static_library("distributeddataobject_static") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + blocklist = "./cfi_blocklist.txt" + } part_name = "data_object" sources = object_source_config diff --git a/data_object/interfaces/innerkits/cfi_blocklist.txt b/data_object/interfaces/innerkits/cfi_blocklist.txt new file mode 100644 index 0000000000000000000000000000000000000000..ca77a3bf4488ab610501aa3e1dc83829bba6ed0c --- /dev/null +++ b/data_object/interfaces/innerkits/cfi_blocklist.txt @@ -0,0 +1,17 @@ +# Copyright (C) 2022-2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +[cfi] +type:OHOS::ObjectStore::AppDeviceStatusChangeListener* +type:OHOS::ObjectStore::AppDataChangeListener* +type:OHOS::ObjectStore::StatusWatcher* \ No newline at end of file diff --git a/data_object/interfaces/jskits/BUILD.gn b/data_object/interfaces/jskits/BUILD.gn index 623f885b0410aa89cf8d3ce19389c8404f00de62..4c8a68909885a1dd0f1973955638ea00fc3a16e0 100644 --- a/data_object/interfaces/jskits/BUILD.gn +++ b/data_object/interfaces/jskits/BUILD.gn @@ -73,6 +73,12 @@ gen_js_obj("distributed_data_object_abc") { } ohos_shared_library("distributeddataobject") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } part_name = "data_object" sources = [ "../../frameworks/jskitsimpl/src/adaptor/js_distributedobject.cpp", diff --git a/data_share/frameworks/js/napi/dataShare/BUILD.gn b/data_share/frameworks/js/napi/dataShare/BUILD.gn index 14e12a8c86cb0ee84a18bb2d45651d792db5f33e..6f0d5e2ced60333d60d8a2ebdf7413a2d85c86f9 100644 --- a/data_share/frameworks/js/napi/dataShare/BUILD.gn +++ b/data_share/frameworks/js/napi/dataShare/BUILD.gn @@ -15,6 +15,12 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/data_share/datashare.gni") ohos_shared_library("datashare") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "${datashare_napi_path}/dataShare/include", "${datashare_common_napi_path}/include", @@ -60,6 +66,12 @@ ohos_shared_library("datashare") { } ohos_shared_library("datasharepredicates") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "${datashare_common_napi_path}/include", "${datashare_common_native_path}/include", diff --git a/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn b/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn index 63b00f2b0fd5b02b98d461e9f96aa4e06aecfbc0..626766d977ef2dcf494467dac122b8b9701c9ef5 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn +++ b/data_share/frameworks/js/napi/datashare_ext_ability/BUILD.gn @@ -35,6 +35,12 @@ gen_js_obj("datashare_ext_ability_abc") { } ohos_shared_library("datashareextensionability_napi") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } sources = [ "datashare_ext_ability_module.cpp" ] deps = [ diff --git a/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn b/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn index 1eebe2a23f31254cb76809866258809725fa1771..98b047c6f60d06770958930210980213b86be01a 100644 --- a/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn +++ b/data_share/frameworks/js/napi/datashare_ext_ability_context/BUILD.gn @@ -36,6 +36,12 @@ gen_js_obj("datashare_ext_ability_context_abc") { } ohos_shared_library("datashareextensionabilitycontext_napi") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } sources = [ "datashare_ext_ability_context_module.cpp" ] deps = [ diff --git a/data_share/frameworks/native/common/include/callbacks_manager.h b/data_share/frameworks/native/common/include/callbacks_manager.h index 4152f78d2e6007ea9e720517f109bfbfe1e055bd..7eae5e931c6d20e76005277426d3a55bc9594801 100644 --- a/data_share/frameworks/native/common/include/callbacks_manager.h +++ b/data_share/frameworks/native/common/include/callbacks_manager.h @@ -122,9 +122,7 @@ void CallbacksManager::RecoverObservers(std::function lck(mutex_); for (auto &it : callbacks_) { - if (GetEnabledSubscriberSize(it.first) > 0) { - keys.emplace_back(it.first); - } + keys.emplace_back(it.first); } } recoverObservers(keys); diff --git a/data_share/frameworks/native/common/src/datashare_result_set.cpp b/data_share/frameworks/native/common/src/datashare_result_set.cpp index c52b349d15a9fe01df05feb5e1b25accbde7b6e8..f4d425ef6b7dbd27e4a1777c4dfa42dc90adb237 100644 --- a/data_share/frameworks/native/common/src/datashare_result_set.cpp +++ b/data_share/frameworks/native/common/src/datashare_result_set.cpp @@ -18,6 +18,7 @@ #include #include "adaptor.h" +#include "datashare_block_writer_impl.h" #include "datashare_errno.h" #include "datashare_log.h" #include "parcel.h" diff --git a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp index 7acb6999b07c2264b36345e696127cd6288c756b..200428da066932b0e647b58b2fc198d82349217b 100644 --- a/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp +++ b/data_share/frameworks/native/consumer/controller/service/src/general_controller_service_impl.cpp @@ -23,7 +23,7 @@ namespace DataShare { constexpr int INVALID_VALUE = -1; int GeneralControllerServiceImpl::Insert(const Uri &uri, const DataShareValuesBucket &value) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return INVALID_VALUE; @@ -34,7 +34,7 @@ int GeneralControllerServiceImpl::Insert(const Uri &uri, const DataShareValuesBu int GeneralControllerServiceImpl::Update(const Uri &uri, const DataSharePredicates &predicates, const DataShareValuesBucket &value) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return INVALID_VALUE; @@ -44,7 +44,7 @@ int GeneralControllerServiceImpl::Update(const Uri &uri, const DataSharePredicat int GeneralControllerServiceImpl::Delete(const Uri &uri, const DataSharePredicates &predicates) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return INVALID_VALUE; @@ -55,7 +55,7 @@ int GeneralControllerServiceImpl::Delete(const Uri &uri, const DataSharePredicat std::shared_ptr GeneralControllerServiceImpl::Query(const Uri &uri, const DataSharePredicates &predicates, std::vector &columns, DatashareBusinessError &businessError) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return nullptr; @@ -93,7 +93,7 @@ void GeneralControllerServiceImpl::UnregisterObserver(const Uri &uri, void GeneralControllerServiceImpl::NotifyChange(const Uri &uri) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return; diff --git a/data_share/frameworks/native/consumer/controller/service/src/persistent_data_controller.cpp b/data_share/frameworks/native/consumer/controller/service/src/persistent_data_controller.cpp index 9e1b5e50e6cf011e736388ac644278894ccd6c60..f726abc8861fdeb3af692f187ade1ae8b1a32a9b 100644 --- a/data_share/frameworks/native/consumer/controller/service/src/persistent_data_controller.cpp +++ b/data_share/frameworks/native/consumer/controller/service/src/persistent_data_controller.cpp @@ -22,7 +22,7 @@ namespace DataShare { constexpr int INVALID_VALUE = -1; int PersistentDataController::AddQueryTemplate(const std::string &uri, int64_t subscriberId, Template &tpl) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return INVALID_VALUE; @@ -32,7 +32,7 @@ int PersistentDataController::AddQueryTemplate(const std::string &uri, int64_t s int PersistentDataController::DelQueryTemplate(const std::string &uri, int64_t subscriberId) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return INVALID_VALUE; @@ -44,7 +44,7 @@ std::vector PersistentDataController::SubscribeRdbData(void *su const std::vector &uris, const TemplateId &templateId, std::function callback) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); @@ -55,7 +55,7 @@ std::vector PersistentDataController::SubscribeRdbData(void *su std::vector PersistentDataController::UnSubscribeRdbData(void *subscriber, const std::vector &uris, const TemplateId &templateId) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); @@ -70,7 +70,7 @@ std::vector PersistentDataController::UnSubscribeRdbData(void * std::vector PersistentDataController::EnableSubscribeRdbData(void *subscriber, const std::vector &uris, const TemplateId &templateId) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); @@ -81,7 +81,7 @@ std::vector PersistentDataController::EnableSubscribeRdbData(vo std::vector PersistentDataController::DisableSubscribeRdbData(void *subscriber, const std::vector &uris, const TemplateId &templateId) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); diff --git a/data_share/frameworks/native/consumer/controller/service/src/published_data_controller.cpp b/data_share/frameworks/native/consumer/controller/service/src/published_data_controller.cpp index 6bc8893a84d6e0e22389c5576cf0d1aaea04e38c..04fdbefb180a539f2a81b96248a88880b2a52620 100644 --- a/data_share/frameworks/native/consumer/controller/service/src/published_data_controller.cpp +++ b/data_share/frameworks/native/consumer/controller/service/src/published_data_controller.cpp @@ -22,7 +22,7 @@ namespace OHOS { namespace DataShare { std::vector PublishedDataController::Publish(const Data &data, const std::string &bundleName) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); @@ -32,7 +32,7 @@ std::vector PublishedDataController::Publish(const Data &data, Data PublishedDataController::GetPublishedData(const std::string &bundleName, int &resultCode) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return Data(); @@ -44,7 +44,7 @@ std::vector PublishedDataController::SubscribePublishedData(voi const std::vector &uris, int64_t subscriberId, const std::function &callback) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); @@ -55,7 +55,7 @@ std::vector PublishedDataController::SubscribePublishedData(voi std::vector PublishedDataController::UnSubscribePublishedData(void *subscriber, const std::vector &uris, int64_t subscriberId) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); @@ -69,7 +69,7 @@ std::vector PublishedDataController::UnSubscribePublishedData(v std::vector PublishedDataController::EnableSubscribePublishedData(void *subscriber, const std::vector &uris, int64_t subscriberId) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); @@ -80,7 +80,7 @@ std::vector PublishedDataController::EnableSubscribePublishedDa std::vector PublishedDataController::DisableSubscribePublishedData(void *subscriber, const std::vector &uris, int64_t subscriberId) { - auto proxy = DataShareManagerImpl::GetInstance().GetServiceProxy(); + auto proxy = DataShareManagerImpl::GetServiceProxy(); if (proxy == nullptr) { LOG_ERROR("proxy is nullptr"); return std::vector(); diff --git a/data_share/frameworks/native/consumer/src/datashare_helper.cpp b/data_share/frameworks/native/consumer/src/datashare_helper.cpp index 9945a711825e30d59d1b985369add40f239b7357..207c58b5a927b4e0a10280e7d90122f89b64bcc4 100644 --- a/data_share/frameworks/native/consumer/src/datashare_helper.cpp +++ b/data_share/frameworks/native/consumer/src/datashare_helper.cpp @@ -108,8 +108,13 @@ std::shared_ptr DataShareHelper::Creator(const string &strUri, std::shared_ptr DataShareHelper::CreateServiceHelper(const std::string &bundleName) { - DataShareManagerImpl::GetInstance().SetBundleName(bundleName); - if (DataShareManagerImpl::GetInstance().GetServiceProxy() == nullptr) { + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("manager_ is nullptr"); + return nullptr; + } + manager->SetBundleName(bundleName); + if (DataShareManagerImpl::GetServiceProxy() == nullptr) { LOG_ERROR("service proxy is nullptr."); return nullptr; } diff --git a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h index 564397dd8de914ac8cc0541221c5b8107f86fc11..929f6b6db3d42b31ae8702726fab980bd61221d0 100644 --- a/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h +++ b/data_share/frameworks/native/provider/include/js_datashare_ext_ability.h @@ -281,13 +281,15 @@ public: callbackResultStringArr_ = value; } - void GetResult(std::shared_ptr &value) + void GetResultSet(std::shared_ptr &value) { + std::lock_guard lock(resultSetLock_); value = callbackResultObject_; } - void SetResult(const std::shared_ptr value) + void SetResultSet(const std::shared_ptr value) { + std::lock_guard lock(resultSetLock_); callbackResultObject_ = value; } @@ -329,6 +331,7 @@ private: int callbackResultNumber_ = -1; std::string callbackResultString_ = ""; std::vector callbackResultStringArr_ = {}; + std::mutex resultSetLock_; std::shared_ptr callbackResultObject_ = nullptr; DatashareBusinessError businessError_; }; diff --git a/data_share/frameworks/native/provider/src/datashare_stub.cpp b/data_share/frameworks/native/provider/src/datashare_stub.cpp index 120c84873792cfc4be68e05f8b3a807d0764226e..15bcd20ee0de7ae183bce5cb16eba89959aeeb3d 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub.cpp @@ -112,7 +112,7 @@ ErrCode DataShareStub::CmdOpenFile(MessageParcel &data, MessageParcel &reply) } int fd = OpenFile(uri, mode); if (fd < 0) { - LOG_ERROR("OpenFile fail, fd is %{pubilc}d", fd); + LOG_ERROR("OpenFile fail, fd is %{public}d", fd); return ERR_INVALID_VALUE; } if (!reply.WriteFileDescriptor(fd)) { diff --git a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp index 811ce0ba12f94c336e86aa7c1d88844759ca2e91..81fb230496ec9e01aeb454b4d3ae952e6d74fa1b 100644 --- a/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp +++ b/data_share/frameworks/native/provider/src/datashare_stub_impl.cpp @@ -231,7 +231,7 @@ std::shared_ptr DataShareStubImpl::Query(const Uri &uri, return false; } extension->SetCallingInfo(info); - extension->GetResult(resultSet); + extension->GetResultSet(resultSet); extension->GetBusinessError(businessError); return (resultSet != nullptr); }; diff --git a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp index c24a492b212dd52a87fd77e41a4b9b9490b32511..bf2eae50f8cf0a0b085f905700935595dd7f12eb 100644 --- a/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp +++ b/data_share/frameworks/native/provider/src/datashare_uv_queue.cpp @@ -19,7 +19,7 @@ namespace OHOS { namespace DataShare { -constexpr int WAIT_TIME = 3; +constexpr int WAIT_TIME = 60; constexpr int SLEEP_TIME = 1; constexpr int TRY_TIMES = 2000; DataShareUvQueue::DataShareUvQueue(napi_env env) @@ -35,16 +35,18 @@ void DataShareUvQueue::LambdaForWork(uv_work_t *work, int uvstatus) return; } auto *entry = static_cast(work->data); - std::unique_lock lock(entry->mutex); - if (entry->func) { - entry->func(); - } - entry->done = true; - if (entry->purge) { - DataShareUvQueue::Purge(work); - } else { - entry->condition.notify_all(); + { + std::unique_lock lock(entry->mutex); + if (entry->func) { + entry->func(); + } + entry->done = true; + if (!entry->purge) { + entry->condition.notify_all(); + return; + } } + DataShareUvQueue::Purge(work); } void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) @@ -55,11 +57,9 @@ void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) return; } work->data = new UvEntry {env_, std::move(func), false, false, {}, {}, std::move(retFunc)}; - auto status = uv_queue_work( - loop_, work, [](uv_work_t *work) {}, LambdaForWork); - if (status != napi_ok) { - LOG_ERROR("queue work failed"); - DataShareUvQueue::Purge(work); + if (work->data == nullptr) { + delete work; + LOG_ERROR("invalid uvEntry."); return; } @@ -71,10 +71,16 @@ void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) return; } std::unique_lock lock(uvEntry->mutex); + auto status = uv_queue_work( + loop_, work, [](uv_work_t *work) {}, LambdaForWork); + if (status != napi_ok) { + LOG_ERROR("queue work failed"); + DataShareUvQueue::Purge(work); + return; + } if (uvEntry->condition.wait_for(lock, std::chrono::seconds(WAIT_TIME), [uvEntry] { return uvEntry->done; })) { LOG_INFO("function ended successfully"); } - CheckFuncAndExec(uvEntry->retFunc); if (!uvEntry->done && !uv_cancel((uv_req_t*)&work)) { LOG_ERROR("uv_cancel failed."); uvEntry->purge = true; @@ -82,6 +88,7 @@ void DataShareUvQueue::SyncCall(NapiVoidFunc func, NapiBoolFunc retFunc) } } + CheckFuncAndExec(uvEntry->retFunc); if (!noNeedPurge) { DataShareUvQueue::Purge(work); } diff --git a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp index 462eb5cefbf4be95ffea83a5391cbf72b40cb7a0..cb31e876d7d72e44cf51e376fd3e34ee5e3f3f2c 100644 --- a/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp +++ b/data_share/frameworks/native/provider/src/js_datashare_ext_ability.cpp @@ -105,7 +105,7 @@ void JsDataShareExtAbility::Init(const std::shared_ptr &reco napi_set_named_property(env, obj, "context", contextObj); napi_wrap(env, contextObj, new std::weak_ptr(context), [](napi_env, void *data, void *) { - LOG_DEBUG("Finalizer for weak_ptr datashare extension ability context is called"); + LOG_INFO("Finalizer for weak_ptr datashare extension ability context is called"); delete static_cast*>(data); }, nullptr, nullptr); } @@ -162,13 +162,13 @@ void JsDataShareExtAbility::CheckAndSetAsyncResult(napi_env env) } else { std::shared_ptr value = proxy->Create(); std::shared_ptr resultSet = std::make_shared(value); - SetResult(resultSet); + SetResultSet(resultSet); } } else { callbackResultNumber_ = -1; callbackResultString_ = ""; callbackResultStringArr_ = {}; - callbackResultObject_ = nullptr; + SetResultSet(nullptr); } } @@ -199,7 +199,7 @@ napi_value JsDataShareExtAbility::AsyncCallback(napi_env env, napi_callback_info LOG_INFO("Error in callback"); UnWrapBusinessError(env, argv[0], businessError); } - JsDataShareExtAbility* instance = static_cast(data); + JsDataShareExtAbility* instance = reinterpret_cast(data); if (instance != nullptr) { instance->SetBlockWaiting(true); instance->SetBusinessError(businessError); @@ -321,7 +321,7 @@ napi_value JsDataShareExtAbility::CallObjectMethod(const char* name, napi_value callbackResultNumber_ = -1; callbackResultString_ = ""; callbackResultStringArr_ = {}; - callbackResultObject_ = nullptr; + SetResultSet(nullptr); napi_create_function(env, ASYNC_CALLBACK_NAME, CALLBACK_LENGTH, JsDataShareExtAbility::AsyncCallback, this, &args[argc]); } else { diff --git a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h index 8848383c9895f288bed8f379734e810d88783d6c..ee2af8572b380dea51184a5ad39242a82e2db4b2 100644 --- a/data_share/frameworks/native/proxy/include/data_share_manager_impl.h +++ b/data_share/frameworks/native/proxy/include/data_share_manager_impl.h @@ -32,11 +32,9 @@ namespace DataShare { class DataShareKvServiceProxy; class DataShareManagerImpl { public: - static DataShareManagerImpl& GetInstance(); + static DataShareManagerImpl* GetInstance(); - virtual ~DataShareManagerImpl(); - - std::shared_ptr GetServiceProxy(); + static std::shared_ptr GetServiceProxy(); void OnRemoteDied(); @@ -63,6 +61,10 @@ public: private: DataShareManagerImpl(); + virtual ~DataShareManagerImpl(); + + std::shared_ptr GetProxy(); + void LinkToDeath(const sptr remote); sptr GetDataShareServiceProxy(); @@ -72,13 +74,12 @@ private: void RegisterClientDeathObserver(); static std::shared_ptr GetDistributedDataManager(); - + static std::mutex pmutex_; + static DataShareManagerImpl* manager_; std::mutex mutex_; std::shared_ptr dataMgrService_; std::shared_ptr dataShareService_; std::string bundleName_; - static constexpr int GET_SA_RETRY_TIMES = 3; - static constexpr int RETRY_INTERVAL = 1; static constexpr int WAIT_TIME = 2; static constexpr int MAX_THREADS = 2; static constexpr int MIN_THREADS = 0; diff --git a/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp b/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp index f1ac1d5b5ab09d354f68d9ee8ab427b5eef88609..13f4dc4f7112a9ebad2c7962520f087f856efeaf 100644 --- a/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp +++ b/data_share/frameworks/native/proxy/src/ams_mgr_proxy.cpp @@ -66,10 +66,10 @@ int AmsMgrProxy::Connect( want.SetUri(uri); std::lock_guard lock(mutex_); if (ConnectSA()) { - LOG_INFO("connect datashareextability start"); + LOG_INFO("connect datashareextability start, uri = %{public}s.", uri.c_str()); int ret = proxy_->ConnectAbilityCommon(want, connect, callerToken, AppExecFwk::ExtensionAbilityType::DATASHARE); if (ret != ERR_OK) { - LOG_ERROR("connect ability failed, ret = %{public}d", ret); + LOG_ERROR("connect ability failed, uri = %{public}s, ret = %{public}d", uri.c_str(), ret); } return ret; } diff --git a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp index 7677f689ae51c82b372940a432a791954b190e64..9f533010192ffa4cd915c5ddcd0852e3d47ee128 100644 --- a/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp +++ b/data_share/frameworks/native/proxy/src/data_share_manager_impl.cpp @@ -28,33 +28,41 @@ namespace OHOS { namespace DataShare { -DataShareManagerImpl& DataShareManagerImpl::GetInstance() + +std::mutex DataShareManagerImpl::pmutex_; +DataShareManagerImpl* DataShareManagerImpl::manager_ = nullptr; + +DataShareManagerImpl* DataShareManagerImpl::GetInstance() { - static DataShareManagerImpl manager; - return manager; + if (manager_ != nullptr) { + return manager_; + } + std::lock_guard lock(pmutex_); + if (manager_ != nullptr) { + return manager_; + } + manager_ = new DataShareManagerImpl(); + if (manager_ == nullptr) { + LOG_ERROR("DataShareManagerImpl: GetInstance failed"); + } + return manager_; } + std::shared_ptr DataShareManagerImpl::GetDistributedDataManager() { - int retry = 0; - while (++retry <= GET_SA_RETRY_TIMES) { - auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); - if (manager == nullptr) { - LOG_ERROR("get system ability manager failed"); - return nullptr; - } - LOG_INFO("get distributed data manager %{public}d", retry); - auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); - if (remoteObject == nullptr) { - std::this_thread::sleep_for(std::chrono::seconds(RETRY_INTERVAL)); - continue; - } - LOG_INFO("get distributed data manager success"); - return std::make_shared(remoteObject); + auto manager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (manager == nullptr) { + LOG_ERROR("get system ability manager failed"); + return nullptr; } - - LOG_ERROR("get distributed data manager failed"); - return nullptr; + auto remoteObject = manager->CheckSystemAbility(DISTRIBUTED_KV_DATA_SERVICE_ABILITY_ID); + if (remoteObject == nullptr) { + LOG_ERROR("get distributed data manager failed"); + return nullptr; + } + LOG_INFO("get distributed data manager success"); + return std::make_shared(remoteObject); } void DataShareManagerImpl::LinkToDeath(const sptr remote) @@ -121,7 +129,7 @@ DataShareManagerImpl::~DataShareManagerImpl() LOG_INFO("destroy"); } -std::shared_ptr DataShareManagerImpl::GetServiceProxy() +std::shared_ptr DataShareManagerImpl::GetProxy() { if (dataShareService_ != nullptr) { return dataShareService_; @@ -143,6 +151,16 @@ std::shared_ptr DataShareManagerImpl::GetServiceProxy() return dataShareService_; } +std::shared_ptr DataShareManagerImpl::GetServiceProxy() +{ + auto manager = DataShareManagerImpl::GetInstance(); + if (manager == nullptr) { + LOG_ERROR("manager_ is nullptr"); + return nullptr; + } + return manager->GetProxy(); +} + void DataShareManagerImpl::ResetServiceHandle() { LOG_INFO("enter"); diff --git a/data_share/interfaces/inner_api/BUILD.gn b/data_share/interfaces/inner_api/BUILD.gn index 622a54e2c603d9a758c6980e3036559694a4a000..777821d57e67bc8705469e4d124038f75a77d513 100644 --- a/data_share/interfaces/inner_api/BUILD.gn +++ b/data_share/interfaces/inner_api/BUILD.gn @@ -87,6 +87,12 @@ datashare_consumer_external_deps = [ ] ohos_shared_library("datashare_consumer") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "${kvstore_base_path}/frameworks/common", "${kvstore_base_path}/interfaces/innerkits/distributeddata/include", @@ -96,7 +102,10 @@ ohos_shared_library("datashare_consumer") { configs = [ ":ability_config" ] public_configs = [ ":datashare_public_config" ] version_script = "consumer/libdatashare_consumer.map" - innerapi_tags = [ "platformsdk" ] + innerapi_tags = [ + "platformsdk", + "sasdk", + ] deps = [ "${datashare_innerapi_path}/common:datashare_common" ] external_deps = datashare_consumer_external_deps @@ -147,6 +156,12 @@ ohos_shared_library("datashare_provider") { } ohos_shared_library("datashare_ext_ability_module") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "${datashare_native_provider_path}/include" ] sources = [ "${datashare_native_provider_path}/src/datashare_ext_ability_module_loader.cpp" ] @@ -172,6 +187,12 @@ ohos_shared_library("datashare_ext_ability_module") { } ohos_static_library("datashare_consumer_static") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "${kvstore_base_path}/frameworks/common", "${kvstore_base_path}/interfaces/innerkits/distributeddata/include", diff --git a/data_share/interfaces/inner_api/common/BUILD.gn b/data_share/interfaces/inner_api/common/BUILD.gn index 52cb4316f2119fa4879833ef05a83cfa3178e580..e72fd80bcd647e8cf018ba05d64d80bd7b12ed5e 100644 --- a/data_share/interfaces/inner_api/common/BUILD.gn +++ b/data_share/interfaces/inner_api/common/BUILD.gn @@ -72,6 +72,12 @@ datashare_common_external_deps = [ ] ohos_shared_library("datashare_common") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = datashare_common_include_dirs sources = datashare_common_sources @@ -83,7 +89,10 @@ ohos_shared_library("datashare_common") { configs = [ ":ability_config" ] public_configs = [ ":datashare_public_config" ] version_script = "libdatashare_common.map" - innerapi_tags = [ "platformsdk" ] + innerapi_tags = [ + "platformsdk", + "sasdk", + ] external_deps = datashare_common_external_deps @@ -92,6 +101,12 @@ ohos_shared_library("datashare_common") { } ohos_static_library("datashare_common_static") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = datashare_common_include_dirs sources = datashare_common_sources diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_abs_result_set.h b/data_share/interfaces/inner_api/consumer/include/datashare_abs_result_set.h new file mode 100644 index 0000000000000000000000000000000000000000..755f294a5492c5e63e8a300e914a601c481a37e4 --- /dev/null +++ b/data_share/interfaces/inner_api/consumer/include/datashare_abs_result_set.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 DATASHARE_ABS_RESULT_SET_H +#define DATASHARE_ABS_RESULT_SET_H + +#include +#include +#include "basic/result_set.h" + +namespace OHOS { +namespace DataShare { +class DataShareAbsResultSet : public ResultSet { +public: + DataShareAbsResultSet(); + virtual ~DataShareAbsResultSet(); + virtual int GetRowCount(int &count) override; + virtual int GetAllColumnNames(std::vector &columnNames) override; + virtual int GetBlob(int columnIndex, std::vector &blob) override; + virtual int GetString(int columnIndex, std::string &value) override; + virtual int GetInt(int columnIndex, int &value) override; + virtual int GetLong(int columnIndex, int64_t &value) override; + virtual int GetDouble(int columnIndex, double &value) override; + virtual int IsColumnNull(int columnIndex, bool &isNull) override; + virtual int GoToRow(int position) override; + virtual int GetDataType(int columnIndex, DataType &dataType) override; + int GetRowIndex(int &position) const override; + int GoTo(int offset) override; + int GoToFirstRow() override; + int GoToLastRow() override; + int GoToNextRow() override; + int GoToPreviousRow() override; + int IsAtFirstRow(bool &result) const override; + int IsAtLastRow(bool &result) override; + int IsStarted(bool &result) const override; + int IsEnded(bool &result) override; + int GetColumnCount(int &count) override; + int GetColumnIndex(const std::string &columnName, int &columnIndex) override; + int GetColumnName(int columnIndex, std::string &columnName) override; + bool IsClosed() const override; + int Close() override; + +protected: + // The default position of the result set + static const int INIT_POS = -1; + // Current row position + int rowPos_; + int count_; + // Indicates whether the result set is closed + bool isClosed_; + std::map indexCache_; +}; +} // namespace DataShare +} // namespace OHOS + +#endif diff --git a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h index 860d15c38856a913f028d93a1adc7ff84e415fa0..29983c73f577e161e254f534ba9d747e358723d9 100644 --- a/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h +++ b/data_share/interfaces/inner_api/consumer/include/datashare_result_set.h @@ -22,15 +22,14 @@ #include #include "datashare_abs_result_set.h" -#include "datashare_block_writer_impl.h" +#include "datashare_errno.h" #include "datashare_shared_result_set.h" #include "message_parcel.h" -#include "parcel.h" #include "result_set_bridge.h" -#include "shared_block.h" namespace OHOS { namespace DataShare { +class DataShareBlockWriterImpl; /** * This module provides data resultsets. diff --git a/datamgr_service/test/fuzztest/autolaunch_fuzzer/corpus/init b/data_share/interfaces/inner_api/consumer/include/datashare_shared_result_set.h similarity index 43% rename from datamgr_service/test/fuzztest/autolaunch_fuzzer/corpus/init rename to data_share/interfaces/inner_api/consumer/include/datashare_shared_result_set.h index 8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5..2b5aaafd342c955e10810ef5dc902dcc1fa06290 100644 --- a/datamgr_service/test/fuzztest/autolaunch_fuzzer/corpus/init +++ b/data_share/interfaces/inner_api/consumer/include/datashare_shared_result_set.h @@ -13,4 +13,34 @@ * limitations under the License. */ -FUZZ \ No newline at end of file +#ifndef DATASHARE_SHARED_RESULT_SET_H +#define DATASHARE_SHARED_RESULT_SET_H + +#include + +namespace OHOS { +namespace AppDataFwk { +class SharedBlock; +} +namespace DataShare { +class DataShareSharedResultSet { +public: + DataShareSharedResultSet() {} + ~DataShareSharedResultSet() {} + /** + * Obtains a block from the {@link SharedResultSet} + */ + virtual AppDataFwk::SharedBlock *GetBlock() const = 0; + /** + * Adds the data of a {@code SharedResultSet} to a {@link SharedBlock} + */ + virtual void FillBlock(int startRowIndex, AppDataFwk::SharedBlock *block) = 0; + /** + * Called when the position of the result set changes + */ + virtual bool OnGo(int oldRowIndex, int newRowIndex, int *cachedIndex) = 0; +}; +} // namespace DataShare +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/pages/index.ets b/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/pages/index.ets index c50c4db9d4965395e0e92cf642342c2c201342b9..ca8c8d99c2b59f1ade440b2300b14bb7ee1432f3 100644 --- a/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/pages/index.ets +++ b/data_share/test/native/resource/datashare_ext_bundle/entry/src/main/ets/pages/index.ets @@ -22,320 +22,14 @@ struct Index { @State message: string = "Main thread message filed" build() { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text('DataShare Extension Ability Test') - .fontSize(25) - .fontWeight(FontWeight.Bold) - - Text(`${this.message}`) - .fontSize(30) - .height('15%') - .width('100%') - .textAlign(TextAlign.Center) - - Row() { - Button() { - Text('Connect') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> Connect onclick enter') - this.message = 'Connect onclick' - await globalThis.connectDataShareExtAbility() - console.info('[ttt] [DataShareTest] <> Connect onclick leave') - }) - - Button() { - Text('Disconnect') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> Disconnect onclick enter') - this.message = 'Disconnect onclick' - await globalThis.disconnectDataShareExtAbility() - console.info('[ttt] [DataShareTest] <> Disconnect onclick leave') - }) - } - - Row() { - Button() { - Text('On') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('25%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> On onclick enter') - this.message = '~ On onclick' - try { - await globalThis.on(); - } catch (err) { - console.error('[ttt] [DataAbilityTest] Observer on catch(err)====>:' + err); - } - console.info('[ttt] [DataShareTest] <> On onclick leave') - }) - - Button() { - Text('Off') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('25%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> Off onclick enter') - this.message = '~ Off onclick' - try { - await globalThis.off(); - } catch (err) { - console.error('[ttt] [DataAbilityTest] Observer Off catch(err)====>:' + err); - } - console.info('[ttt] [DataShareTest] <> Off onclick leave') - }) - - Button() { - Text('OpenFile') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('40%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> OpenFile onclick enter') - this.message = 'OpenFile onclick' - let ret = await globalThis.openFile() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> OpenFile onclick leave') - }) - } - - Row() { - Button() { - Text('Query') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> Query onclick enter') - this.message = 'Query onclick' - let ret = await globalThis.query() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> Query onclick leave') - }) - - Button() { - Text('Insert') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> Insert onclick enter') - this.message = 'Insert onclick' - let ret = await globalThis.insert() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> Insert onclick leave') - }) - } - - Row() { - Button() { - Text('Update') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> Update onclick enter') - this.message = 'Update onclick' - let ret = await globalThis.update() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> Update onclick leave') - }) - - Button() { - Text('Delete') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> Delete onclick enter') - this.message = 'Delete onclick' - let ret = await globalThis.delete() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> Delete onclick leave') - }) - } - - Row() { - Button() { - Text('BatchInsert') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> BatchInsert onclick enter') - this.message = 'BatchInsert onclick' - let ret = await globalThis.batchInsert() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> BatchInsert onclick leave') - }) - - Button() { - Text('NotifyChange') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> NotifyChange onclick enter') - this.message = 'NotifyChange onclick' - await globalThis.notifyChange() - console.info('[ttt] [DataShareTest] <> NotifyChange onclick leave') - }) - } - - Row() { - Button() { - Text('GetType') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> GetType onclick enter') - this.message = 'GetType onclick' - let ret = await globalThis.getType() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> GetType onclick leave') - }) - - Button() { - Text('GetFileTypes') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> GetFileTypes onclick enter') - this.message = 'GetFileTypes onclick' - let ret = await globalThis.getFileTypes() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> GetFileTypes onclick leave') - }) - } - - Row() { - Button() { - Text('NormalizeUri') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> NormalizeUri onclick enter') - this.message = 'NormalizeUri onclick' - let ret = await globalThis.normalizeUri() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> NormalizeUri onclick leave') - }) - - Button() { - Text('DenormalizeUri') - .fontSize(25) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 20 - }) - .width('45%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> DenormalizeUri onclick enter') - this.message = 'DenormalizeUri onclick' - let ret = await globalThis.denormalizeUri() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [DataShareTest] <> DenormalizeUri onclick leave') - }) + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) } + .width('100%') } - .width('100%') .height('100%') } } \ No newline at end of file diff --git a/data_share/test/native/resource/datashareproxy_bundle/proxydatas_with_permission/entry/src/main/ets/pages/index.ets b/data_share/test/native/resource/datashareproxy_bundle/proxydatas_with_permission/entry/src/main/ets/pages/index.ets index b76fce0dcf8e81d0c0b652072674a211aea61055..ab5a19fbbdc65b45aa9e44192ccd39e8301049e2 100644 --- a/data_share/test/native/resource/datashareproxy_bundle/proxydatas_with_permission/entry/src/main/ets/pages/index.ets +++ b/data_share/test/native/resource/datashareproxy_bundle/proxydatas_with_permission/entry/src/main/ets/pages/index.ets @@ -22,77 +22,14 @@ struct Index { @State message: string = "datashareproxyTest Main thread message filed" build() { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text('datashareproxyTest Ability Test') - .fontSize(25) - .fontWeight(FontWeight.Bold) - - Text(`${this.message}`) - .fontSize(35) - .height('20%') - .width('100%') - .textAlign(TextAlign.Center) - - Row() { - Button() { - Text('Connect') - .fontSize(20) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 25 - }) - .width('40%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [datashareproxyTest] <> Connect onclick enter') - this.message = 'Connect onclick' - await globalThis.connectDataShareExtAbility() - console.info('[ttt] [datashareproxyTest] <> Connect onclick leave') - }) - - Button() { - Text('Disconnect') - .fontSize(20) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 25 - }) - .width('40%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [datashareproxyTest] <> Disconnect onclick enter') - this.message = 'Disconnect onclick' - await globalThis.disconnectDataShareExtAbility() - console.info('[ttt] [datashareproxyTest] <> Disconnect onclick leave') - }) - } - - Row() { - Button() { - Text('Insert') - .fontSize(20) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 25 - }) - .width('40%') - .height('8%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [datashareproxyTest] <> Insert onclick enter') - this.message = 'Insert onclick' - let ret = await globalThis.insert() - this.message += "\n\n Test Result: " + ret; - console.info('[ttt] [datashareproxyTest] <> Insert onclick leave') - }) + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) } + .width('100%') } - .width('100%') .height('100%') } } \ No newline at end of file diff --git a/data_share/test/native/resource/errorcode_ext_bundle/entry/src/main/ets/pages/index.ets b/data_share/test/native/resource/errorcode_ext_bundle/entry/src/main/ets/pages/index.ets index 24c9fb21cc01429847d3b3f45a928b3f852ce165..89bbe5e86d35609f04e3dcf3cebfbb363eeed938 100644 --- a/data_share/test/native/resource/errorcode_ext_bundle/entry/src/main/ets/pages/index.ets +++ b/data_share/test/native/resource/errorcode_ext_bundle/entry/src/main/ets/pages/index.ets @@ -22,38 +22,14 @@ struct Index { @State message: string = "Main thread message filed errorcode test" build() { - Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { - Text('DataShare Extension Ability ErrorCode Test') - .fontSize(25) - .fontWeight(FontWeight.Bold) - - Text(`${this.message}`) - .fontSize(25) - .height('20%') - .width('100%') - .textAlign(TextAlign.Center) - - Row() { - Button() { - Text('Connect') - .fontSize(30) - .fontWeight(FontWeight.Bold) - }.type(ButtonType.Capsule) - .margin({ - top: 25 - }) - .width('50%') - .height('10%') - .backgroundColor('#0ddffb') - .onClick(async () => { - console.info('[ttt] [DataShareTest] <> ErrorCode Connect onclick enter') - this.message = 'Connect onclick' - await globalThis.connectDataShareExtAbility() - console.info('[ttt] [DataShareTest] <> ErrorCode Connect onclick leave') - }) + Row() { + Column() { + Text(this.message) + .fontSize(50) + .fontWeight(FontWeight.Bold) } + .width('100%') } - .width('100%') .height('100%') } } \ No newline at end of file diff --git a/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp b/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp index e76367b0360a25d64de9d1efeba3a92d2e179f81..b4eece50c14b7aface95ba362f517f5773575313 100644 --- a/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp +++ b/data_share/test/native/unittest/datashareproxy_test/proxydatas_with_permission_test.cpp @@ -247,6 +247,7 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_Publish_Test_002, TestSize.Level0) HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Level0) { + LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::Start"); auto helper = dataShareHelper; PredicateTemplateNode node("p1", "select name0 as name from TBL00"); std::vector nodes; @@ -270,10 +271,7 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Le for (auto const &operationResult : results1) { EXPECT_EQ(operationResult.errCode_, 0); } - std::vector results2 = helper->DisableRdbSubs(uris, tplId); - for (auto const &operationResult : results2) { - EXPECT_EQ(operationResult.errCode_, 0); - } + std::vector results3 = helper->EnableRdbSubs(uris, tplId); for (auto const &operationResult : results3) { EXPECT_EQ(operationResult.errCode_, 0); @@ -295,6 +293,7 @@ HWTEST_F(ProxyDatasTest, ProxyDatasTest_CombinationRdbData_Test_001, TestSize.Le int retVal2 = helper->Insert(uri, valuesBucket2); EXPECT_EQ((retVal2 > 0), true); EXPECT_EQ(g_callbackTimes, 2); + LOG_INFO("ProxyDatasTest_CombinationRdbData_Test_001::End"); } HWTEST_F(ProxyDatasTest, ProxyDatasTest_SubscribePublishedData_Test_001, TestSize.Level0) diff --git a/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp b/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp index d569b7e35ec68748ee289d6e462557f4fe200c5d..7cb1c84e486cbab81f5364675db9170b0bb6325c 100644 --- a/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp +++ b/data_share/test/native/unittest/mediadatashare_test/src/abnormal_branch_test.cpp @@ -29,6 +29,7 @@ #include "message_parcel.h" #include "ikvstore_data_service.h" #include "shared_block.h" +#include "datashare_block_writer_impl.h" #include "datashare_connection.h" namespace OHOS { diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp index 7c6d028262f0a43fd310e207bd3adbca97bc645f..39105588ce789f9fc79a18256b6fd3bbfd8e0e3a 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.cpp @@ -49,6 +49,12 @@ bool AccountDelegateDefaultImpl::QueryUsers(std::vector &users) return true; } +bool AccountDelegateDefaultImpl::IsVerified(int userId) +{ + ZLOGD("no account part."); + return true; +} + void AccountDelegateDefaultImpl::SubscribeAccountEvent() { ZLOGD("no account part."); diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h index 33ee5fda57579955bee2f00f007520c814873ce6..6b1209c48161e6e1854f896a78a84a7079bbc66d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_default_impl.h @@ -25,6 +25,7 @@ public: std::string GetCurrentAccountId() const override; int32_t GetUserByToken(uint32_t tokenId) const override; bool QueryUsers(std::vector &users) override; + bool IsVerified(int userId) override; void SubscribeAccountEvent() override; void UnsubscribeAccountEvent() override; void BindExecutor(std::shared_ptr executors) override; diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.cpp index 875a2ca3dd7af2943c3b408e66aabacbfc59d6c3..3a25ea0924aa05c453a7e7ee66e8e6ec5f1e28ab 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_impl.cpp @@ -40,6 +40,9 @@ void EventSubscriber::OnReceiveEvent(const CommonEventData &event) } else if (action == CommonEventSupport::COMMON_EVENT_USER_SWITCHED) { accountEventInfo.status = AccountStatus::DEVICE_ACCOUNT_SWITCHED; accountEventInfo.userId = std::to_string(event.GetCode()); + } else if (action == CommonEventSupport::COMMON_EVENT_USER_UNLOCKED) { + accountEventInfo.status = AccountStatus::DEVICE_ACCOUNT_UNLOCKED; + accountEventInfo.userId = std::to_string(event.GetCode()); } else { return; } diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp index 5dd42f3fdf063d2eeac6ee443eee7cc0fc05c458..a2553920c3204db119e0bb421c8c28727e53f3a6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.cpp @@ -77,21 +77,51 @@ bool AccountDelegateNormalImpl::QueryUsers(std::vector &users) return AccountSA::OsAccountManager::QueryActiveOsAccountIds(users) == 0; } +bool AccountDelegateNormalImpl::IsVerified(int userId) +{ + auto [success, res] = userStatus_.Find(userId); + if (success && res) { + return true; + } + auto status = AccountSA::OsAccountManager::IsOsAccountVerified(userId, res); + if (status == 0) { + userStatus_.InsertOrAssign(userId, res); + } + return status == 0 && res; +} + void AccountDelegateNormalImpl::SubscribeAccountEvent() { ZLOGI("Subscribe account event listener start."); MatchingSkills matchingSkills; matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_REMOVED); matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_SWITCHED); + matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_USER_UNLOCKED); CommonEventSubscribeInfo info(matchingSkills); eventSubscriber_ = std::make_shared(info); - eventSubscriber_->SetEventCallback([&](AccountEventInfo &account) { + eventSubscriber_->SetEventCallback([this](AccountEventInfo& account) { + UpdateUserStatus(account); account.harmonyAccountId = GetCurrentAccountId(); NotifyAccountChanged(account); }); executors_->Execute(GetTask(0)); } +void AccountDelegateNormalImpl::UpdateUserStatus(const AccountEventInfo& account) +{ + uint32_t status = static_cast(account.status); + switch (status) { + case static_cast(AccountStatus::DEVICE_ACCOUNT_DELETE): + userStatus_.Erase(atoi(account.userId.c_str())); + break; + case static_cast(AccountStatus::DEVICE_ACCOUNT_UNLOCKED): + userStatus_.InsertOrAssign(atoi(account.userId.c_str()), true); + break; + default: + break; + } +} + ExecutorPool::Task AccountDelegateNormalImpl::GetTask(uint32_t retry) { return [this, retry] { diff --git a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h index 86bdf15c95946ac4ceeee843bd16e8907774e173..8a611614843439bc9a939f439556bd0ef1b17c3b 100644 --- a/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h +++ b/datamgr_service/services/distributeddataservice/adapter/account/src/account_delegate_normal_impl.h @@ -30,6 +30,7 @@ public: std::string GetCurrentAccountId() const override; int32_t GetUserByToken(uint32_t tokenId) const override; bool QueryUsers(std::vector &users) override; + bool IsVerified(int userId) override; void SubscribeAccountEvent() override; void UnsubscribeAccountEvent() override; void BindExecutor(std::shared_ptr executors) override; @@ -38,10 +39,12 @@ private: ~AccountDelegateNormalImpl(); std::string Sha256AccountId(const std::string &plainText) const; ExecutorPool::Task GetTask(uint32_t retry); + void UpdateUserStatus(const AccountEventInfo& account); static constexpr int MAX_RETRY_TIME = 300; static constexpr int RETRY_WAIT_TIME_S = 1; std::shared_ptr eventSubscriber_ {}; std::shared_ptr executors_; + ConcurrentMap userStatus_ {}; }; } // namespace DistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp index 850a052ca20801ec5ddc8d1b5ae1e6121149e44d..25a81d6b8a16ebd87a3c1ceff938983cbeaad2d5 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/communicator_context.cpp @@ -16,7 +16,7 @@ #include "communicator_context.h" namespace OHOS::DistributedData { -CommunicatorContext &CommunicatorContext::getInstance() +CommunicatorContext &CommunicatorContext::GetInstance() { static CommunicatorContext context; return context; diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp index 27f7f185528ec28c69de22240845a915be0c5aa1..fe308e82c368c4a9f9de5c33f7a25eb64bf07c79 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/process_communicator_impl.cpp @@ -124,11 +124,14 @@ DBStatus ProcessCommunicatorImpl::SendData(const DeviceInfos &dstDevInfo, const DeviceId destination; destination.deviceId = dstDevInfo.identifier; Status errCode = CommunicationProvider::GetInstance().SendData(pi, destination, dataInfo, totalLength); + if (errCode == Status::RATE_LIMIT) { + ZLOGE("commProvider_ opening session, status:%{public}d.", static_cast(errCode)); + return DBStatus::RATE_LIMIT; + } if (errCode != Status::SUCCESS) { ZLOGE("commProvider_ SendData Fail."); return DBStatus::DB_ERROR; } - return DBStatus::OK; } diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h index 6d7486b1958f659ce33eab9c980d9d96a1ae769d..4c41f5d91ab08f97be0d8117363cb5bd16cf6add 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter.h @@ -78,21 +78,28 @@ public: const AppDistributedKv::DeviceChangeType &type) const override; }; private: + using Time = std::chrono::steady_clock::time_point; + using Duration = std::chrono::steady_clock::duration; + using Task = ExecutorPool::Task; std::shared_ptr> GetSemaphore(int32_t connId); std::string DelConnect(int32_t connId); void DelSessionStatus(int32_t connId); void AfterStrategyUpdate(const std::string &deviceId); + Task GetCloseSessionTask(); static constexpr uint32_t WAIT_MAX_TIME = 19; + static constexpr Time INVALID_NEXT = std::chrono::steady_clock::time_point::max(); static std::shared_ptr instance_; ConcurrentMap dataChangeListeners_{}; - std::mutex connMutex_{}; - std::map> connects_ {}; + ConcurrentMap> connects_{}; bool flag_ = true; // only for br flag ISessionListener sessionListener_{}; std::mutex statusMutex_{}; std::map>> sessionsStatus_; std::function onBroadcast_; static SofBusDeviceChangeListenerImpl listener_; + std::mutex taskMutex_; + ExecutorPool::TaskId taskId_ = ExecutorPool::INVALID_TASK_ID; + Time next_ = INVALID_NEXT; }; } // namespace AppDistributedKv } // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp index 5f27529d0fa301fc756ddaa371f57932f78560f6..6a0830fabfad1b2a9b23e19dda33383620f9479d 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_adapter_standard.cpp @@ -15,6 +15,7 @@ #include #include +#include "communicator_context.h" #include "device_manager_adapter.h" #include "dfx_types.h" #include "kvstore_utils.h" @@ -32,6 +33,7 @@ namespace OHOS { namespace AppDistributedKv { +using Context = DistributedData::CommunicatorContext; enum SoftBusAdapterErrorCode : int32_t { SESSION_ID_INVALID = 2, MY_SESSION_NAME_INVALID, @@ -43,7 +45,7 @@ enum SoftBusAdapterErrorCode : int32_t { constexpr int32_t SESSION_NAME_SIZE_MAX = 65; constexpr int32_t DEVICE_ID_SIZE_MAX = 65; constexpr uint32_t DEFAULT_MTU_SIZE = 4096u; -constexpr uint32_t DEFAULT_TIMEOUT = 8 * 1000; +constexpr uint32_t DEFAULT_TIMEOUT = 15 * 1000; using namespace std; using namespace OHOS::DistributedDataDfx; using namespace OHOS::DistributedKv; @@ -126,7 +128,7 @@ SoftBusAdapter::~SoftBusAdapter() if (onBroadcast_) { UnregNodeDeviceStateCb(&g_callback); } - connects_.clear(); + connects_.Clear(); } std::shared_ptr SoftBusAdapter::GetInstance() @@ -167,33 +169,85 @@ Status SoftBusAdapter::SendData(const PipeInfo &pipeInfo, const DeviceId &device uint32_t totalLength, const MessageInfo &info) { std::shared_ptr conn; - { - lock_guard lock(connMutex_); - std::string key = pipeInfo.pipeId + deviceId.deviceId; - if (connects_.find(key) == connects_.end()) { - connects_.emplace(key, std::make_shared(pipeInfo, deviceId, [this](int32_t connId) { + connects_.Compute(deviceId.deviceId, + [this, &pipeInfo, &deviceId, &conn](const auto &key, std::shared_ptr &connect) -> bool { + if (connect != nullptr) { + conn = connect; + return true; + } + connect = std::make_shared(pipeInfo, deviceId, [this](int32_t connId) { return GetSessionStatus(connId); - })); - } - conn = connects_[key]; + }); + conn = connect; + return true; + }); + if (conn == nullptr) { + return Status::ERROR; } - - if (conn != nullptr) { - return conn->Send(dataInfo, totalLength); + auto status = conn->Send(dataInfo, totalLength); + if ((status != Status::NETWORK_ERROR) && (status != Status::RATE_LIMIT)) { + Time now = std::chrono::steady_clock::now(); + auto expireTime = conn->GetExpireTime(); + lock_guard lock(taskMutex_); + if (taskId_ != ExecutorPool::INVALID_TASK_ID && expireTime < next_) { + taskId_ = Context::GetInstance().GetThreadPool()->Reset(taskId_, expireTime - now); + next_ = expireTime; + if (taskId_ == ExecutorPool::INVALID_TASK_ID) { + return status; + } + } + if (taskId_ == ExecutorPool::INVALID_TASK_ID) { + taskId_ = Context::GetInstance().GetThreadPool()->Schedule(expireTime - now, GetCloseSessionTask()); + next_ = expireTime; + } } + return status; +} + +SoftBusAdapter::Task SoftBusAdapter::GetCloseSessionTask() +{ + return [this]() mutable { + Time now = std::chrono::steady_clock::now(); + std::vector> connToClose; + connects_.EraseIf([&now, &connToClose](const auto &key, const auto &conn) -> bool { + if (conn == nullptr) { + return true; + } + auto expireTime = conn->GetExpireTime(); + if (expireTime <= now) { + ZLOGD("[timeout] close session connId:%{public}d", conn->GetConnId()); + connToClose.emplace_back(conn); + return true; + } + return false; + }); - return Status::ERROR; + Time next = INVALID_NEXT; + lock_guard lg(taskMutex_); + connects_.ForEach([&next](const auto &key, const auto &conn) -> bool { + if (conn == nullptr) { + return false; + } + auto expireTime = conn->GetExpireTime(); + if (expireTime < next) { + next = expireTime; + } + return false; + }); + if (next == INVALID_NEXT) { + taskId_ = ExecutorPool::INVALID_TASK_ID; + return; + } + taskId_ = Context::GetInstance().GetThreadPool()->Schedule( + next > now ? next - now : ExecutorPool::INVALID_DELAY, GetCloseSessionTask()); + next_ = next; + }; } std::shared_ptr SoftBusAdapter::GetConnect(const std::string &deviceId) { - lock_guard lock(connMutex_); - for (const auto& conn : connects_) { - if (*conn.second == deviceId) { - return conn.second; - } - } - return nullptr; + auto [status, vlaue] = connects_.Find(deviceId); + return vlaue; } uint32_t SoftBusAdapter::GetMtuSize(const DeviceId &deviceId) @@ -216,17 +270,15 @@ uint32_t SoftBusAdapter::GetTimeout(const DeviceId &deviceId) std::string SoftBusAdapter::DelConnect(int32_t connId) { - lock_guard lock(connMutex_); std::string name; - for (auto iter = connects_.begin(); iter != connects_.end();) { - if (*iter->second == connId) { - name += iter->first; + connects_.EraseIf([connId, &name](const auto &key, const auto &value) -> bool { + if (value != nullptr && *value == connId) { + name += key; name += " "; - connects_.erase(iter++); - } else { - iter++; + return true; } - } + return false; + }); return name; } @@ -250,6 +302,15 @@ void SoftBusAdapter::OnSessionOpen(int32_t connId, int32_t status) { auto semaphore = GetSemaphore(connId); semaphore->SetValue(status); + if (status != SOFTBUS_OK) { + return; + } + connects_.ForEach([connId](const auto &key, const auto &value) -> bool { + if (value != nullptr && *value == connId) { + value->UpdateExpireTime(); + } + return false; + }); } std::string SoftBusAdapter::OnSessionClose(int32_t connId) diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp index 29e40681292ac8e8557fd4c5ba2c580cae88907c..6a6d5bee5aa6316aa2a9f5080efbb32ec49bfcd2 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.cpp @@ -66,7 +66,24 @@ uint32_t SoftBusClient::GetMtuSize() const uint32_t SoftBusClient::GetTimeout() const { - return (routeType_ == RouteType::BT_BR || routeType_ == RouteType::BT_BLE) ? BR_TIMEOUT : WIFI_TIMEOUT; + uint32_t timeout = DEFAULT_TIMEOUT; + switch (routeType_) { + case RouteType::WIFI_STA: + timeout = WIFI_TIMEOUT; + break; + case RouteType::WIFI_P2P: + timeout = WIFI_TIMEOUT; + break; + case RouteType::BT_BR: + timeout = BR_TIMEOUT; + break; + case RouteType::BT_BLE: + timeout = BR_TIMEOUT; + break; + default: + break; + } + return timeout; } Status SoftBusClient::Send(const DataInfo &dataInfo, uint32_t totalLength) @@ -76,7 +93,7 @@ Status SoftBusClient::Send(const DataInfo &dataInfo, uint32_t totalLength) if (result != Status::SUCCESS) { return result; } - + expireTime_ = std::chrono::steady_clock::now() + GetDelayTime(totalLength); ZLOGD("send data connId:%{public}d, data size:%{public}u, total length:%{public}u.", connId_, dataInfo.length, totalLength); int32_t ret = SendBytes(connId_, dataInfo.data, dataInfo.length); @@ -84,10 +101,6 @@ Status SoftBusClient::Send(const DataInfo &dataInfo, uint32_t totalLength) ZLOGE("send data to connId%{public}d failed, ret:%{public}d.", connId_, ret); return Status::ERROR; } - - if (routeType_ == RouteType::WIFI_P2P) { - UpdateP2pFinishTime(connId_, dataInfo.length); - } return Status::SUCCESS; } @@ -102,10 +115,8 @@ Status SoftBusClient::OpenConnect(uint32_t totalLength) } return result; } - - auto result = CreateChannel(totalLength); - if (result != Status::SUCCESS) { - return result; + if (routeType_ == RouteType::INVALID_ROUTE_TYPE) { + return CreateChannel(totalLength); } status_ = ConnectStatus::CONNECT_OK; return Status::SUCCESS; @@ -133,7 +144,7 @@ Status SoftBusClient::SwitchChannel(uint32_t totalLength) ZLOGD("switch %{public}s,session:%{public}s,connId:%{public}d,routeType:%{public}d to wifi or p2p.", KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), connId_, routeType_); RestoreDefaultValue(); - return Open(GetSessionAttribute(true)); + return OpenSessionByAsync(GetSessionAttribute(true)); } if (routeType_ == RouteType::WIFI_P2P) { @@ -143,15 +154,8 @@ Status SoftBusClient::SwitchChannel(uint32_t totalLength) ZLOGD("switch %{public}s,session:%{public}s,connId:%{public}d,routeType:%{public}d to ble or br.", KvStoreUtils::ToBeAnonymous(device_.deviceId).c_str(), pipe_.pipeId.c_str(), connId_, routeType_); - { - std::lock_guard lock(taskMutex_); - if (closeP2pTaskId_ == ExecutorPool::INVALID_TASK_ID) { - closeP2pTaskId_ = Context::getInstance(). - GetThreadPool()->Execute(std::bind(&SoftBusClient::CloseP2pSessions, this)); - } - } RestoreDefaultValue(); - return Open(GetSessionAttribute(false)); + return OpenSessionByAsync(GetSessionAttribute(false)); } return Status::NETWORK_ERROR; @@ -162,15 +166,30 @@ Status SoftBusClient::CreateChannel(uint32_t totalLength) if (strategy_ == Strategy::BUTT) { return Status::NETWORK_ERROR; } - if (strategy_ == Strategy::ON_LINE_SELECT_CHANNEL) { - return Open(GetSessionAttribute(true)); + return OpenSessionByAsync(GetSessionAttribute(true)); } - if (totalLength < P2P_SIZE_THRESHOLD) { - return Open(GetSessionAttribute(false)); + return OpenSessionByAsync(GetSessionAttribute(false)); + } + return OpenSessionByAsync(GetSessionAttribute(true)); +} + +Status SoftBusClient::OpenSessionByAsync(SessionAttribute attr) +{ + auto openSessionTask = [attr, client = shared_from_this()]() { + if (client == nullptr) { + ZLOGE("OpenSessionByAsync client is nullptr."); + return; + } + (void)client->Open(attr); + client->sessionFlag_.store(false); + }; + if (sessionFlag_.exchange(true)) { + return Status::RATE_LIMIT; } - return Open(GetSessionAttribute(true)); + Context::GetInstance().GetThreadPool()->Execute(openSessionTask); + return Status::RATE_LIMIT; } Status SoftBusClient::Open(SessionAttribute attr) @@ -245,43 +264,31 @@ void SoftBusClient::AfterStrategyUpdate(Strategy strategy) } } -void SoftBusClient::CloseP2pSessions() +SoftBusClient::Time SoftBusClient::GetExpireTime() const { - Time now = std::chrono::steady_clock::now(); - Time nextClose = std::chrono::steady_clock::time_point::max(); - p2pFinishTime_.EraseIf([&now, &nextClose](const int32_t &connId, Time &finishTime) -> bool { - if (finishTime + P2P_CLOSE_DELAY <= now) { - ZLOGD("close timeout p2p connId:%{public}d", connId); - CloseSession(connId); - return true; - } + return expireTime_; +} - if (finishTime + P2P_CLOSE_DELAY < nextClose) { - nextClose = finishTime + P2P_CLOSE_DELAY; - } - return false; - }); - - std::lock_guard lock(taskMutex_); - if (!p2pFinishTime_.Empty()) { - closeP2pTaskId_ = Context::getInstance().GetThreadPool()->Schedule(nextClose - now, - std::bind(&SoftBusClient::CloseP2pSessions, this)); - } else { - closeP2pTaskId_ = ExecutorPool::INVALID_TASK_ID; - } +int32_t SoftBusClient::GetConnId() const +{ + return connId_; } -void SoftBusClient::UpdateP2pFinishTime(int32_t connId, uint32_t dataLength) +int32_t SoftBusClient::GetRoutType() const { - Time now = std::chrono::steady_clock::now(); - auto delay = std::chrono::microseconds(dataLength / P2P_TRANSFER_PER_MICROSECOND); - p2pFinishTime_.Compute(connId, [&now, &delay](const auto &id, auto &finishTime) -> bool { - if (finishTime < now) { - finishTime = now + delay; - } else { - finishTime += delay; - } - return true; - }); + return routeType_; +} + +void SoftBusClient::UpdateExpireTime() +{ + expireTime_ = std::chrono::steady_clock::now() + GetDelayTime(0); +} + +SoftBusClient::Duration SoftBusClient::GetDelayTime(uint32_t dataLength) +{ + if (routeType_ == RouteType::WIFI_P2P) { + return P2P_CLOSE_DELAY + std::chrono::microseconds(dataLength >> P2P_TRANSFER_PER_MICROSECOND); + } + return SESSION_CLOSE_DELAY; } } \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h index ff5992f534be253ae4d88bedddf0811799dc9aeb..16ff089380aaa80cc5826e4f50cd08c92c24eba6 100644 --- a/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h +++ b/datamgr_service/services/distributeddataservice/adapter/communicator/src/softbus_client.h @@ -16,6 +16,7 @@ #ifndef DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_SOFTBUS_CLIENT_H #define DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_SOFTBUS_CLIENT_H +#include #include #include @@ -25,18 +26,25 @@ #include "session.h" #include "softbus_bus_center.h" namespace OHOS::AppDistributedKv { -class SoftBusClient { +class SoftBusClient : public std::enable_shared_from_this { public: SoftBusClient(const PipeInfo &pipeInfo, const DeviceId &deviceId, const std::function &getConnStatus); ~SoftBusClient(); using Strategy = CommunicationStrategy::Strategy; + using Time = std::chrono::steady_clock::time_point; + using Duration = std::chrono::steady_clock::duration; + static constexpr Duration P2P_CLOSE_DELAY = std::chrono::seconds(3); Status Send(const DataInfo &dataInfo, uint32_t totalLength); bool operator==(int32_t connId) const; bool operator==(const std::string &deviceId) const; uint32_t GetMtuSize() const; uint32_t GetTimeout() const; + Time GetExpireTime() const; + int32_t GetConnId() const; + int32_t GetRoutType() const; + void UpdateExpireTime(); void AfterStrategyUpdate(Strategy strategy); private: enum class ConnectStatus : int32_t { @@ -44,40 +52,38 @@ private: DISCONNECT, }; - using Time = std::chrono::steady_clock::time_point; Status OpenConnect(uint32_t totalLength); Status SwitchChannel(uint32_t totalLength); Status CreateChannel(uint32_t totalLength); Status Open(SessionAttribute attr); + Status OpenSessionByAsync(SessionAttribute attr); SessionAttribute GetSessionAttribute(bool isP2p); void RestoreDefaultValue(); void UpdateMtuSize(); - void CloseP2pSessions(); - void UpdateP2pFinishTime(int32_t connId, uint32_t dataLength); + Duration GetDelayTime(uint32_t dataLength); static constexpr int32_t INVALID_CONNECT_ID = -1; static constexpr uint32_t WIFI_TIMEOUT = 8 * 1000; static constexpr uint32_t BR_TIMEOUT = 15 * 1000; + static constexpr uint32_t DEFAULT_TIMEOUT = 15 * 1000; static constexpr uint32_t WAIT_MAX_TIME = 10; static constexpr uint32_t DEFAULT_MTU_SIZE = 4096u; static constexpr uint32_t P2P_SIZE_THRESHOLD = 0x10000u; // 64KB - static constexpr uint32_t P2P_TRANSFER_PER_MICROSECOND = 10; // 10 bytes per microsecond + static constexpr uint32_t P2P_TRANSFER_PER_MICROSECOND = 3; // 2^3 bytes per microsecond static constexpr float SWITCH_DELAY_FACTOR = 0.6f; - static constexpr std::chrono::steady_clock::duration P2P_CLOSE_DELAY = std::chrono::seconds(3); + static constexpr Duration SESSION_CLOSE_DELAY = std::chrono::seconds(60); + std::atomic_bool sessionFlag_ = false; int32_t connId_ = INVALID_CONNECT_ID; int32_t routeType_ = RouteType::INVALID_ROUTE_TYPE; Strategy strategy_ = Strategy::DEFAULT; ConnectStatus status_ = ConnectStatus::DISCONNECT; std::mutex mutex_; - std::mutex taskMutex_; PipeInfo pipe_; DeviceId device_; uint32_t mtu_; - ConcurrentMap p2pFinishTime_; - ExecutorPool::TaskId closeP2pTaskId_ = ExecutorPool::INVALID_TASK_ID; std::function getConnStatus_; + Time expireTime_ = std::chrono::steady_clock::now(); }; } - #endif // DISTRIBUTEDDATAMGR_DATAMGR_SERVICE_SOFTBUS_CLIENT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/adapter/include/account/account_delegate.h b/datamgr_service/services/distributeddataservice/adapter/include/account/account_delegate.h index 79cdb36d464a8412597edb194d34633183d99c94..925d7cfc89856081f53a2dd1f960da1ab57a2c69 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/account/account_delegate.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/account/account_delegate.h @@ -30,6 +30,7 @@ enum class AccountStatus { HARMONY_ACCOUNT_DELETE, // the openHarmony account is deleted DEVICE_ACCOUNT_DELETE, // the device account is deleted DEVICE_ACCOUNT_SWITCHED, // the device account is switched + DEVICE_ACCOUNT_UNLOCKED, // the device account is unlocked }; struct AccountEventInfo { @@ -62,6 +63,7 @@ public: API_EXPORT virtual void SubscribeAccountEvent() = 0; API_EXPORT virtual void UnsubscribeAccountEvent() = 0; API_EXPORT virtual bool QueryUsers(std::vector &users) = 0; + API_EXPORT virtual bool IsVerified(int userId) = 0; API_EXPORT virtual bool RegisterHashFunc(HashFunc hash) = 0; API_EXPORT virtual void BindExecutor(std::shared_ptr executors) = 0; API_EXPORT static AccountDelegate *GetInstance(); diff --git a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h index bcf7ea854724ac701d392160fd85b5e8d43a7e8c..604dfe3245ca2a0d9915581ec50eb06c2451c8bf 100644 --- a/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h +++ b/datamgr_service/services/distributeddataservice/adapter/include/communicator/communicator_context.h @@ -22,7 +22,7 @@ namespace OHOS::DistributedData { class API_EXPORT CommunicatorContext { public: - API_EXPORT static CommunicatorContext &getInstance(); + API_EXPORT static CommunicatorContext &GetInstance(); API_EXPORT void SetThreadPool(std::shared_ptr executors); std::shared_ptr GetThreadPool(); diff --git a/datamgr_service/services/distributeddataservice/app/BUILD.gn b/datamgr_service/services/distributeddataservice/app/BUILD.gn index bd35fa6a2e71e9e6effca6fd97aec35456c81a63..019ff5dc04aff2b553267e8c29a72a7f6453df65 100644 --- a/datamgr_service/services/distributeddataservice/app/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/BUILD.gn @@ -55,7 +55,7 @@ config("module_private_config") { "${distributedfilejs_path}/interfaces/kits/js/src/mod_securitylabel", "../adapter/include/account", "../adapter/include/permission", - "../adapter/include/uninstaller", + "../adapter/include/installer", "../adapter/include/broadcaster", "../adapter/include/utils", "../adapter/include/dfx", @@ -101,12 +101,12 @@ ohos_shared_library("distributeddataservice") { configs = [ ":module_private_config" ] deps = [ + "${data_service_path}/app/src/installer:distributeddata_installer_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter:distributeddata_adapter", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/broadcaster:distributeddata_broadcaster_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/utils:distributeddata_utils_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/checker:distributeddata_checker_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/flowctrl_manager:distributeddata_flowctrl_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/uninstaller:distributeddata_uninstaller_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", ] diff --git a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt index a9e27a44e98cea63a21e74e4c53862a1dddee015..251306eb2dde21440452412fb86bb72bdbbf69c1 100644 --- a/datamgr_service/services/distributeddataservice/app/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/app/CMakeLists.txt @@ -13,7 +13,7 @@ set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../kv_store") add_definitions(-DPROCESS_LABEL="mytest") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/flowctrl_manager appSrc) -aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/uninstaller appSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/installer appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/security appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/session_manager appSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/checker appSrc) @@ -21,7 +21,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/backup_rule appSrc) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/flowctrl_manager) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/uninstaller) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/installer) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/security) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/session_manager) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src/checker) diff --git a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg index e8632b4cfd88dd3cc70043c076fd56861b019a43..b980a16e769dda97fa7ffd677b71476614573971 100644 --- a/datamgr_service/services/distributeddataservice/app/distributed_data.cfg +++ b/datamgr_service/services/distributeddataservice/app/distributed_data.cfg @@ -34,7 +34,8 @@ "ohos.permission.MANAGE_LOCAL_ACCOUNTS", "ohos.permission.ACCESS_SERVICE_DM", "ohos.permission.PROXY_AUTHORIZATION_URI", - "ohos.permission.CLOUDFILE_SYNC" + "ohos.permission.CLOUDFILE_SYNC", + "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT" ] } ] diff --git a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp index 4ac875dfc36a66be1ef92d094b588c8382135f2b..1cf564f7857552e3c0b235f3329b0726ee5072ae 100644 --- a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.cpp @@ -69,6 +69,14 @@ int32_t FeatureStubImpl::OnAppUpdate(const std::string &bundleName, int32_t user return featureImpl_->OnAppUpdate(bundleName, user, index); } +int32_t FeatureStubImpl::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) +{ + if (featureImpl_ == nullptr) { + return -1; + } + return featureImpl_->OnAppInstall(bundleName, user, index); +} + int32_t FeatureStubImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) { if (featureImpl_ == nullptr) { diff --git a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h index b9714b95c2dabf7062fb06d03b990cbf03e25f11..1a265830289cb88476148c10ba0a47ef804cb0a7 100644 --- a/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/feature_stub_impl.h @@ -34,6 +34,7 @@ public: int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); + int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); int32_t ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m); int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account); int32_t Online(const std::string &device); diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn b/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn similarity index 95% rename from datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn rename to datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn index 87cf3b89482b9b087860fe31f11732974c68e575..cbdb7193d45a0c36c971cac1ef07b6a9e05e04c3 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/src/installer/BUILD.gn @@ -14,10 +14,10 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/datamgr_service/datamgr_service.gni") -ohos_static_library("distributeddata_uninstaller_static") { +ohos_static_library("distributeddata_installer_static") { sources = [ - "uninstaller.cpp", - "uninstaller_impl.cpp", + "installer.cpp", + "installer_impl.cpp", ] include_dirs = [ diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller.cpp b/datamgr_service/services/distributeddataservice/app/src/installer/installer.cpp similarity index 81% rename from datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller.cpp rename to datamgr_service/services/distributeddataservice/app/src/installer/installer.cpp index 905004bb030d4c988dd4b437c3be2131638991e2..d3eccd6b5d0ea3a9106709b17ca367ad45b617cb 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer.cpp @@ -13,13 +13,13 @@ * limitations under the License. */ -#include "uninstaller.h" -#include "uninstaller_impl.h" +#include "installer.h" +#include "installer_impl.h" namespace OHOS::DistributedKv { -Uninstaller &Uninstaller::GetInstance() +Installer &Installer::GetInstance() { - static UninstallerImpl uninstaller; - return uninstaller; + static InstallerImpl Installer; + return Installer; } } // namespace OHOS::DistributedKv diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller.h b/datamgr_service/services/distributeddataservice/app/src/installer/installer.h similarity index 80% rename from datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller.h rename to datamgr_service/services/distributeddataservice/app/src/installer/installer.h index 6047830725884cf776e10a12f3e63185aeb16f71..1a7ebb6e9271b2a3e903d19b3ee02fe30dbf5ca7 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller.h +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_UNINSTALLER_H -#define DISTRIBUTEDDATAMGR_UNINSTALLER_H +#ifndef DISTRIBUTEDDATAMGR_INSTALLER_H +#define DISTRIBUTEDDATAMGR_INSTALLER_H #include #include @@ -24,13 +24,13 @@ namespace OHOS::DistributedKv { class KvStoreDataService; enum Status : int32_t; -class Uninstaller { +class Installer { public: KVSTORE_API virtual Status Init(KvStoreDataService *kvStoreDataService, std::shared_ptr executors) = 0; KVSTORE_API virtual void UnsubscribeEvent() = 0; - KVSTORE_API virtual ~Uninstaller() {} - KVSTORE_API static Uninstaller &GetInstance(); + KVSTORE_API virtual ~Installer() {} + KVSTORE_API static Installer &GetInstance(); }; } // namespace OHOS::DistributedKv -#endif // DISTRIBUTEDDATAMGR_UNINSTALLER_H +#endif // DISTRIBUTEDDATAMGR_INSTALLER_H diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp similarity index 77% rename from datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp rename to datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp index c6f05c8c880cb2c12f053a15efb39b5170009111..9a623baafe8acedec40107a4c3bbd0e11fcea917 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.cpp @@ -13,9 +13,9 @@ * limitations under the License. */ -#define LOG_TAG "UninstallerImpl" +#define LOG_TAG "InstallerImpl" -#include "uninstaller_impl.h" +#include "installer_impl.h" #include #include #include "bundle_common_event.h" @@ -37,18 +37,20 @@ using namespace OHOS::AppExecFwk; using namespace OHOS::DistributedData; using namespace OHOS::EventFwk; -UninstallEventSubscriber::UninstallEventSubscriber(const CommonEventSubscribeInfo &info, +InstallEventSubscriber::InstallEventSubscriber(const CommonEventSubscribeInfo &info, KvStoreDataService *kvStoreDataService) : CommonEventSubscriber(info), kvStoreDataService_(kvStoreDataService) { - callbacks_ = { { CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, &UninstallEventSubscriber::OnUninstall }, - { OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED, &UninstallEventSubscriber::OnUninstall }, - { CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, &UninstallEventSubscriber::OnUpdate } }; + callbacks_ = { { CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED, &InstallEventSubscriber::OnUninstall }, + { OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED, &InstallEventSubscriber::OnUninstall }, + { CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED, &InstallEventSubscriber::OnUpdate }, + { CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED, &InstallEventSubscriber::OnInstall }, + { OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_ADDED, &InstallEventSubscriber::OnInstall }}; } -void UninstallEventSubscriber::OnReceiveEvent(const CommonEventData &event) +void InstallEventSubscriber::OnReceiveEvent(const CommonEventData &event) { - ZLOGI("Intent Action Rec"); + ZLOGI("Action Rec"); Want want = event.GetWant(); std::string action = want.GetAction(); auto it = callbacks_.find(action); @@ -61,7 +63,7 @@ void UninstallEventSubscriber::OnReceiveEvent(const CommonEventData &event) } } -void UninstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex) +void InstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex) { kvStoreDataService_->OnUninstall(bundleName, userId, appIndex); std::string prefix = StoreMetaData::GetPrefix( @@ -85,7 +87,7 @@ void UninstallEventSubscriber::OnUninstall(const std::string &bundleName, int32_ } } -void UninstallEventSubscriber::OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex) +void InstallEventSubscriber::OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex) { kvStoreDataService_->OnUpdate(bundleName, userId, appIndex); std::string prefix = StoreMetaData::GetPrefix( @@ -103,7 +105,13 @@ void UninstallEventSubscriber::OnUpdate(const std::string &bundleName, int32_t u } } } -UninstallerImpl::~UninstallerImpl() + +void InstallEventSubscriber::OnInstall(const std::string &bundleName, int32_t userId, int32_t appIndex) +{ + kvStoreDataService_->OnInstall(bundleName, userId, appIndex); +} + +InstallerImpl::~InstallerImpl() { ZLOGD("destruct"); auto res = CommonEventManager::UnSubscribeCommonEvent(subscriber_); @@ -112,7 +120,7 @@ UninstallerImpl::~UninstallerImpl() } } -void UninstallerImpl::UnsubscribeEvent() +void InstallerImpl::UnsubscribeEvent() { auto res = CommonEventManager::UnSubscribeCommonEvent(subscriber_); if (!res) { @@ -120,7 +128,7 @@ void UninstallerImpl::UnsubscribeEvent() } } -Status UninstallerImpl::Init(KvStoreDataService *kvStoreDataService, std::shared_ptr executors) +Status InstallerImpl::Init(KvStoreDataService *kvStoreDataService, std::shared_ptr executors) { if (kvStoreDataService == nullptr) { ZLOGW("kvStoreDataService is null."); @@ -130,21 +138,23 @@ Status UninstallerImpl::Init(KvStoreDataService *kvStoreDataService, std::shared matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED); matchingSkills.AddEvent(OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED); matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED); + matchingSkills.AddEvent(CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED); + matchingSkills.AddEvent(OHOS::AppExecFwk::COMMON_EVENT_SANDBOX_PACKAGE_ADDED); CommonEventSubscribeInfo info(matchingSkills); - auto subscriber = std::make_shared(info, kvStoreDataService); + auto subscriber = std::make_shared(info, kvStoreDataService); subscriber_ = subscriber; executors_ = executors; executors_->Execute(GetTask()); return Status::SUCCESS; } -ExecutorPool::Task UninstallerImpl::GetTask() +ExecutorPool::Task InstallerImpl::GetTask() { return [this] { auto succ = CommonEventManager::SubscribeCommonEvent(subscriber_); if (succ) { - ZLOGI("subscribe uninstall event success"); + ZLOGI("subscribe install event success"); return; } ZLOGE("subscribe common event fail, try times:%{public}d", retryTime_); diff --git a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.h b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.h similarity index 68% rename from datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.h rename to datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.h index 3b8a3a7d7544e94f768453f1ea2b5c4535e360be..683ae72999006e46b2217958bcde2b610796eecf 100644 --- a/datamgr_service/services/distributeddataservice/app/src/uninstaller/uninstaller_impl.h +++ b/datamgr_service/services/distributeddataservice/app/src/installer/installer_impl.h @@ -13,21 +13,21 @@ * limitations under the License. */ -#ifndef DISTRIBUTEDDATAMGR_UNINSTALLER_IMPL_H -#define DISTRIBUTEDDATAMGR_UNINSTALLER_IMPL_H +#ifndef DISTRIBUTEDDATAMGR_INSTALLER_IMPL_H +#define DISTRIBUTEDDATAMGR_INSTALLER_IMPL_H #include "common_event_subscriber.h" #include "kvstore_data_service.h" -#include "uninstaller.h" +#include "installer.h" namespace OHOS::DistributedKv { -class UninstallEventSubscriber : public EventFwk::CommonEventSubscriber { +class InstallEventSubscriber : public EventFwk::CommonEventSubscriber { public: -using UninstallEventCallback = void (UninstallEventSubscriber::*) +using InstallEventCallback = void (InstallEventSubscriber::*) (const std::string &bundleName, int32_t userId, int32_t appIndex); - UninstallEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info, KvStoreDataService *kvStoreDataService); + InstallEventSubscriber(const EventFwk::CommonEventSubscribeInfo &info, KvStoreDataService *kvStoreDataService); - ~UninstallEventSubscriber() {} + ~InstallEventSubscriber() {} void OnReceiveEvent(const EventFwk::CommonEventData &event) override; private: @@ -35,14 +35,15 @@ private: static constexpr const char *SANDBOX_APP_INDEX = "sandbox_app_index"; void OnUninstall(const std::string &bundleName, int32_t userId, int32_t appIndex); void OnUpdate(const std::string &bundleName, int32_t userId, int32_t appIndex); - std::map callbacks_; + void OnInstall(const std::string &bundleName, int32_t userId, int32_t appIndex); + std::map callbacks_; KvStoreDataService *kvStoreDataService_; }; -class UninstallerImpl : public Uninstaller { +class InstallerImpl : public Installer { public: - UninstallerImpl() = default; - ~UninstallerImpl(); + InstallerImpl() = default; + ~InstallerImpl(); Status Init(KvStoreDataService *kvStoreDataService, std::shared_ptr executors) override; @@ -53,8 +54,8 @@ private: static constexpr int32_t RETRY_INTERVAL = 100; int32_t retryTime_ = 0; ExecutorPool::Task GetTask(); - std::shared_ptr subscriber_ {}; + std::shared_ptr subscriber_ {}; std::shared_ptr executors_ {}; }; } // namespace OHOS::DistributedKv -#endif // DISTRIBUTEDDATAMGR_UNINSTALLER_IMPL_H +#endif // DISTRIBUTEDDATAMGR_INSTALLER_IMPL_H diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp index 9d70a595c0e4c430681f0c34ea04ccb4f57bbadd..94e1582cf440122ef8128da34fa8b388460251d2 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.cpp @@ -50,7 +50,7 @@ #include "string_ex.h" #include "system_ability_definition.h" #include "task_manager.h" -#include "uninstaller/uninstaller.h" +#include "installer/installer.h" #include "upgrade.h" #include "upgrade_manager.h" #include "user_delegate.h" @@ -107,7 +107,7 @@ void KvStoreDataService::Initialize() #ifndef UT_TEST KvStoreDelegateManager::SetProcessLabel(Bootstrap::GetInstance().GetProcessLabel(), "default"); #endif - CommunicatorContext::getInstance().SetThreadPool(executors_); + CommunicatorContext::GetInstance().SetThreadPool(executors_); auto communicator = std::make_shared(RouteHeadHandlerImpl::Create); auto ret = KvStoreDelegateManager::SetProcessCommunicator(communicator); ZLOGI("set communicator ret:%{public}d.", static_cast(ret)); @@ -305,7 +305,7 @@ void KvStoreDataService::OnAddSystemAbility(int32_t systemAbilityId, const std:: return; } AccountDelegate::GetInstance()->SubscribeAccountEvent(); - Uninstaller::GetInstance().Init(this, executors_); + Installer::GetInstance().Init(this, executors_); } void KvStoreDataService::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string &deviceId) @@ -316,7 +316,7 @@ void KvStoreDataService::OnRemoveSystemAbility(int32_t systemAbilityId, const st return; } AccountDelegate::GetInstance()->UnsubscribeAccountEvent(); - Uninstaller::GetInstance().UnsubscribeEvent(); + Installer::GetInstance().UnsubscribeEvent(); } void KvStoreDataService::StartService() @@ -721,15 +721,28 @@ int32_t KvStoreDataService::OnUpdate(const std::string &bundleName, int32_t user return SUCCESS; } +int32_t KvStoreDataService::OnInstall(const std::string &bundleName, int32_t user, int32_t index) +{ + auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); + staticActs.ForEachCopies([bundleName, user, index](const auto &, const std::shared_ptr& acts) { + acts->OnAppInstall(bundleName, user, index); + return false; + }); + return SUCCESS; +} + int32_t KvStoreDataService::ClearAppStorage(const std::string &bundleName, int32_t userId, int32_t appIndex, int32_t tokenId) { HapTokenInfo hapTokenInfo; if (AccessTokenKit::GetHapTokenInfo(tokenId, hapTokenInfo) != RET_SUCCESS || - hapTokenInfo.tokenID != static_cast(tokenId)) { - ZLOGE("passed wrong tokenId: %{public}d", tokenId); + hapTokenInfo.bundleName != bundleName || hapTokenInfo.userID != userId || + hapTokenInfo.instIndex != appIndex) { + ZLOGE("passed wrong, tokenId: %{public}u, bundleName:%{public}s, user:%{public}d, appIndex:%{public}d", + tokenId, bundleName.c_str(), userId, appIndex); return ERROR; } + auto staticActs = FeatureSystem::GetInstance().GetStaticActs(); staticActs.ForEachCopies( [bundleName, userId, appIndex, tokenId](const auto &, const std::shared_ptr &acts) { @@ -768,7 +781,7 @@ void KvStoreDataService::RegisterStoreInfo() storeInfoConfig.abbrCmd = "-s"; storeInfoConfig.dumpName = "STORE_INFO"; storeInfoConfig.countPrintf = PRINTF_COUNT_2; - storeInfoConfig.infoName = " "; + storeInfoConfig.infoName = " "; storeInfoConfig.minParamsNum = 0; storeInfoConfig.maxParamsNum = MAXIMUM_PARAMETER_LIMIT; // Store contains no more than three parameters storeInfoConfig.parentNode = "BUNDLE_INFO"; diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h index 7e55c06011f1ff2b551566ee2f356c5fcab06537..09f7784e26f57fdfef855da459ac9d5ff13212c3 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_data_service.h @@ -68,7 +68,7 @@ public: bool IsExist(const std::string &infoName, std::map> &filterInfo, std::string &metaParam); void DumpStoreInfo(int fd, std::map> ¶ms); - void FilterData(std::vector &metas, std::map> ¶ms); + void FilterData(std::vector &metas, std::map> &filterInfo); void PrintfInfo(int fd, const std::vector &metas); std::string GetIndentation(int size); @@ -114,6 +114,8 @@ public: int32_t OnUpdate(const std::string &bundleName, int32_t user, int32_t index); + int32_t OnInstall(const std::string &bundleName, int32_t user, int32_t index); + private: void NotifyAccountEvent(const AccountEventInfo &eventInfo); class KvStoreClientDeathObserverImpl { diff --git a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp index 9421b4f55c35d203017737e575368a53e231f26f..349e4d4fda613e9cd04e63a50955ea6f5000abf6 100644 --- a/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/kvstore_meta_manager.cpp @@ -222,6 +222,7 @@ KvStoreMetaManager::NbDelegate KvStoreMetaManager::CreateMetaKvStore() option.createDirByStoreIdOnly = true; option.isEncryptedDb = false; option.isNeedRmCorruptedDb = true; + option.secOption = { DistributedDB::S1, DistributedDB::ECE }; DistributedDB::KvStoreNbDelegate *delegate = nullptr; delegateManager_.GetKvStore(Bootstrap::GetInstance().GetMetaDBName(), option, [&delegate, &dbStatusTmp](DistributedDB::DBStatus dbStatus, DistributedDB::KvStoreNbDelegate *nbDelegate) { diff --git a/datamgr_service/services/distributeddataservice/app/src/security/security.cpp b/datamgr_service/services/distributeddataservice/app/src/security/security.cpp index ef791483894587ccb48d1887cd59fa798ba13ba2..4980234ff9b45e9548096577b62220d8dd293c5c 100644 --- a/datamgr_service/services/distributeddataservice/app/src/security/security.cpp +++ b/datamgr_service/services/distributeddataservice/app/src/security/security.cpp @@ -146,13 +146,17 @@ void Security::OnDeviceChanged(const AppDistributedKv::DeviceInfo &info, return; } - bool isOnline = type == AppDistributedKv::DeviceChangeType::DEVICE_ONLINE; - if (isOnline) { - (void)GetSensitiveByUuid(info.uuid); - ZLOGD("device is online, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str()); - } else { - EraseSensitiveByUuid(info.uuid); - ZLOGD("device is offline, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str()); + switch (type) { + case AppDistributedKv::DeviceChangeType::DEVICE_OFFLINE: + ZLOGD("device is offline, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str()); + EraseSensitiveByUuid(info.uuid); + break; + case AppDistributedKv::DeviceChangeType::DEVICE_ONLINE: + ZLOGD("device is online, deviceId:%{public}s", Anonymous::Change(info.uuid).c_str()); + (void)GetSensitiveByUuid(info.uuid); + break; + default: + break; } } diff --git a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn index cb7573c62394c2eaeae40b5ab061d190eaafbc09..d13ad3869ef1e06b31c01a6913bf2db488a2741a 100644 --- a/datamgr_service/services/distributeddataservice/app/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/BUILD.gn @@ -48,7 +48,7 @@ config("module_private_config") { "../src", "../src/security", "unittest", - "../src/uninstaller", + "../src/installer", "../src/flowctrl_manager", "../../service/backup/include", "../../../../interfaces/innerkits/distributeddata", @@ -106,13 +106,13 @@ ohos_unittest("KvStoreDataServiceTest") { } deps = [ + "${data_service_path}/app/src/installer:distributeddata_installer_static", "${kv_store_path}/interfaces/innerkits/distributeddatamgr:distributeddata_mgr", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter:distributeddata_adapter", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/broadcaster:distributeddata_broadcaster_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/utils:distributeddata_utils_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/checker:distributeddata_checker_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/flowctrl_manager:distributeddata_flowctrl_static", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/app/src/uninstaller:distributeddata_uninstaller_static", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/framework:distributeddatasvcfwk", "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/service:distributeddatasvc", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", @@ -208,6 +208,68 @@ ohos_unittest("KvStoreFlowCtrlManagerTest") { part_name = "datamgr_service" } +ohos_unittest("KvStoreDataServiceClearTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/app/src/feature_stub_impl.cpp", + "${data_service_path}/app/src/kvstore_account_observer.cpp", + "${data_service_path}/app/src/kvstore_data_service.cpp", + "${data_service_path}/app/src/kvstore_data_service_stub.cpp", + "${data_service_path}/app/src/kvstore_device_listener.cpp", + "${data_service_path}/app/src/kvstore_meta_manager.cpp", + "${data_service_path}/app/src/security/security.cpp", + "${data_service_path}/app/src/security/sensitive.cpp", + "${data_service_path}/app/src/session_manager/route_head_handler_impl.cpp", + "${data_service_path}/app/src/session_manager/session_manager.cpp", + "${data_service_path}/app/src/session_manager/upgrade_manager.cpp", + "${data_service_path}/app/src/task_manager.cpp", + "unittest/kvstore_data_service_clear_test.cpp", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "access_token:libtoken_setproc", + "access_token:libtokenid_sdk", + "c_utils:utils", + "dataclassification:data_transit_mgr", + "device_auth:deviceauth_sdk", + "hilog:libhilog", + "hisysevent:libhisysevent", + "hitrace:hitrace_meter", + "hitrace:libhitracechain", + "ipc:ipc_core", + "kv_store:distributeddata_inner", + "kv_store:distributeddata_mgr", + "kv_store:distributeddb", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + if (datamgr_service_power) { + external_deps += [ + "battery_manager:batterysrv_client", + "power_manager:powermgr_client", + ] + } + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/broadcaster:distributeddata_broadcaster_static", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/app/src/checker:distributeddata_checker_static", + "${data_service_path}/app/src/flowctrl_manager:distributeddata_flowctrl_static", + "${data_service_path}/app/src/installer:distributeddata_installer_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${data_service_path}/service:distributeddatasvc", + "//third_party/googletest:gtest_main", + ] + + part_name = "datamgr_service" +} + ############################################################################### group("unittest") { @@ -215,6 +277,7 @@ group("unittest") { deps = [] deps += [ + ":KvStoreDataServiceClearTest", ":KvStoreDataServiceTest", ":KvStoreFlowCtrlManagerTest", ":SessionManagerTest", diff --git a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn index a392044db896312ef36fa8687a86faf82b3ab9a4..d0ecb8236c0dd959860e52859d6215e2a052c05d 100644 --- a/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/app/test/fuzztest/dataservicestub_fuzzer/BUILD.gn @@ -35,14 +35,14 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "${data_service_path}/app/src/flowctrl_manager", "${data_service_path}/app/src/security", "${data_service_path}/app/src/session_manager", - "${data_service_path}/app/src/uninstaller", + "${data_service_path}/app/src/installer", "${data_service_path}/framework/include", "${data_service_path}/service/backup/include", "${data_service_path}/service/dumper/include", "${data_service_path}/service/kvdb", "${data_service_path}/adapter/include/account", "${data_service_path}/adapter/include/permission", - "${data_service_path}/adapter/include/uninstaller", + "${data_service_path}/adapter/include/installer", "${data_service_path}/adapter/include/broadcaster", "${data_service_path}/adapter/include/utils", "${data_service_path}/adapter/include/dfx", @@ -84,7 +84,7 @@ ohos_fuzztest("DataServiceStubFuzzTest") { "${data_service_path}/adapter/utils:distributeddata_utils_static", "${data_service_path}/app/src/checker:distributeddata_checker_static", "${data_service_path}/app/src/flowctrl_manager:distributeddata_flowctrl_static", - "${data_service_path}/app/src/uninstaller:distributeddata_uninstaller_static", + "${data_service_path}/app/src/installer:distributeddata_installer_static", "${data_service_path}/framework:distributeddatasvcfwk", "${data_service_path}/service:distributeddatasvc", "${kv_store_distributeddb_path}:distributeddb", diff --git a/datamgr_service/services/distributeddataservice/app/test/moduletest/distributeddata_account_event_test.cpp b/datamgr_service/services/distributeddataservice/app/test/moduletest/distributeddata_account_event_test.cpp index 57de3e71d55a5cb754df04e57098c2db7f8df4ef..51014a8783a7a2b46e6ae546044259175c17da62 100644 --- a/datamgr_service/services/distributeddataservice/app/test/moduletest/distributeddata_account_event_test.cpp +++ b/datamgr_service/services/distributeddataservice/app/test/moduletest/distributeddata_account_event_test.cpp @@ -14,23 +14,28 @@ */ #include +#include "accesstoken_kit.h" +#include "access_token.h" #include "kvstore_account_observer.h" #include "kvstore_data_service.h" +#include "token_setproc.h" #include "types.h" #include "common_event_subscriber.h" #include "common_event_support.h" #include "common_event_manager.h" #include "gtest/gtest.h" +#include "nativetoken_kit.h" using namespace testing::ext; using namespace OHOS::DistributedKv; using namespace OHOS::DistributedData; using namespace OHOS; using namespace OHOS::EventFwk; +using namespace Security::AccessToken; static const int SYSTEM_USER_ID = 1000; static const int WAIT_TIME_FOR_ACCOUNT_OPERATION = 2; // indicates the wait time in seconds - +namespace OHOS::Test { class DistributedDataAccountEventTest : public testing::Test { public: static void SetUpTestCase(); @@ -39,10 +44,32 @@ public: static void HarmonyAccountLogin(); static void HarmonyAccountLogout(); static void HarmonyAccountDelete(); + + static void SetTokenPermission(); + static uint64_t tokenId_; }; +void DistributedDataAccountEventTest::SetTokenPermission() +{ + const char *perms[] = { "ohos.permission.PUBLISH_SYSTEM_COMMON_EVENT" }; + NativeTokenInfoParams instance = { + .dcapsNum = 0, + .permsNum = 1, + .aclsNum = 0, + .dcaps = nullptr; + .perms = perms; + .acls = nullptr; + .aplStr = "system_core", + }; + instance.processName = "AccountEventTest"; + tokenId_ = GetAccessTokenId(&instance); + SetSelfTokenID(tokenId_); + AccessTokenKit::ReloadNativeTokenInfo(); +} + void DistributedDataAccountEventTest::SetUpTestCase() { + DistributedDataAccountEventTest::SetTokenPermission(); DistributedDataAccountEventTest::ChangeUser(SYSTEM_USER_ID); } @@ -97,3 +124,4 @@ void DistributedDataAccountEventTest::ChangeUser(int uid) std::cout << "error to set uid " << uid << "errno is " << errno << std::endl; } } +} // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_clear_test.cpp b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_clear_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7f5e818fd13d7114b7086927d10a0d2e01a55e46 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/app/test/unittest/kvstore_data_service_clear_test.cpp @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "gtest/gtest.h" +#include "bootstrap.h" +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" +#include "token_setproc.h" +#include "types.h" +#include "device_manager_adapter.h" +#include "kvstore_data_service.h" +#include "kvstore_client_death_observer.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "metadata/store_meta_data_local.h" +#include "metadata/appid_meta_data.h" +#include "metadata/secret_key_meta_data.h" +#include "feature/feature_system.h" +#include "hap_token_info.h" + +using namespace testing::ext; +using namespace OHOS; +using namespace OHOS::DistributedKv; +using namespace OHOS::Security::AccessToken; +using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; +using MetaDataManager = OHOS::DistributedData::MetaDataManager; +using KvStoreDataService = OHOS::DistributedKv::KvStoreDataService; +namespace OHOS::Test { +class KvStoreDataServiceClearTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + + void SetUp(); + void TearDown(); + + NativeTokenInfoParams infoInstance {0}; +protected: + static constexpr const char *TEST_USER = "100"; + static constexpr const char *TEST_BUNDLE = "ohos.test.demo"; + static constexpr const char *TEST_STORE = "test_store"; + static constexpr int32_t TEST_UID = 2000000; + static constexpr int32_t TEST_USERID = 100; + static constexpr const char *BUNDLE_NAME = "ohos.test.demo"; + static constexpr const char *BUNDLENAME_NO = "com.sample.helloworld"; + static constexpr int32_t USER_ID = 100; + static constexpr int32_t USERID_NO = 10; + static constexpr int32_t APP_INDEX = 0; + static constexpr int32_t APPINDEX_NO = 2; + static constexpr int32_t INVALID_TOKEN = 222; + + DistributedData::StoreMetaData metaData_; + DistributedData::StoreMetaDataLocal localMeta_; + + void InitMetaData(); +}; + +void KvStoreDataServiceClearTest::SetUpTestCase(void) +{ +} + +void KvStoreDataServiceClearTest::TearDownTestCase(void) +{ +} + +void KvStoreDataServiceClearTest::SetUp(void) +{ + DistributedData::Bootstrap::GetInstance().LoadComponents(); + DistributedData::Bootstrap::GetInstance().LoadDirectory(); + DistributedData::Bootstrap::GetInstance().LoadCheckers(); + + infoInstance.dcapsNum = 0; + infoInstance.permsNum = 0; + infoInstance.aclsNum = 0; + infoInstance.dcaps = nullptr; + infoInstance.perms = nullptr; + infoInstance.acls = nullptr; + infoInstance.processName = "KvStoreDataServiceClearTest"; + infoInstance.aplStr = "system_core"; + + HapInfoParams info = { + .userID = TEST_USERID, + .bundleName = TEST_BUNDLE, + .instIndex = 0, + .appIDDesc = TEST_BUNDLE + }; + PermissionDef infoManagerTestPermDef = { + .permissionName = "ohos.permission.test", + .bundleName = TEST_BUNDLE, + .grantMode = 1, + .availableLevel = APL_NORMAL, + .label = "label", + .labelId = 1, + .description = "open the door", + .descriptionId = 1 + }; + PermissionStateFull infoManagerTestState = { + .permissionName = "ohos.permission.test", + .isGeneral = true, + .resDeviceID = {"local"}, + .grantStatus = {PermissionState::PERMISSION_GRANTED}, + .grantFlags = {1} + }; + HapPolicyParams policy = { + .apl = APL_NORMAL, + .domain = "test.domain", + .permList = {infoManagerTestPermDef}, + .permStateList = {infoManagerTestState} + }; + AccessTokenKit::AllocHapToken(info, policy); +} + +void KvStoreDataServiceClearTest::TearDown(void) +{ + auto tokenId = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); + AccessTokenKit::DeleteToken(tokenId); +} + +void KvStoreDataServiceClearTest::InitMetaData() +{ + metaData_.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + metaData_.user = TEST_USER; + metaData_.bundleName = TEST_BUNDLE; + metaData_.storeId = TEST_STORE; + metaData_.appId = TEST_BUNDLE; + metaData_.tokenId = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); + metaData_.uid = TEST_UID; + metaData_.storeType = 1; + metaData_.area = EL1; + metaData_.instanceId = 0; + metaData_.isAutoSync = true; + metaData_.version = 1; + metaData_.appType = "default"; + metaData_.dataDir = "/data/service/el1/public/database/kvstore_data_service_clear_test"; + + DistributedData::PolicyValue value; + value.type = OHOS::DistributedKv::PolicyType::IMMEDIATE_SYNC_ON_ONLINE; + localMeta_.policies = { std::move(value) }; +} + +/** + * @tc.name: ClearAppStorage001 + * @tc.desc: Test that the parameters are entered correctly + * @tc.type: FUNC + * @tc.require: + * @tc.author: suoqilong + */ +HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage001, TestSize.Level1) +{ + auto kvDataService = OHOS::DistributedKv::KvStoreDataService(); + auto tokenIdOk = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); + auto ret = + kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, INVALID_TOKEN); + EXPECT_EQ(ret, Status::ERROR); + + ret = kvDataService.ClearAppStorage(BUNDLENAME_NO, USER_ID, APP_INDEX, tokenIdOk); + EXPECT_EQ(ret, Status::ERROR); + + ret = kvDataService.ClearAppStorage(BUNDLE_NAME, USERID_NO, APP_INDEX, tokenIdOk); + EXPECT_EQ(ret, Status::ERROR); + + ret = kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APPINDEX_NO, tokenIdOk); + EXPECT_EQ(ret, Status::ERROR); +} + +/** + * @tc.name: ClearAppStorage002 + * @tc.desc: The parameters are valid but have no metaData + * @tc.type: FUNC + * @tc.require: + * @tc.author: suoqilong + */ +HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage002, TestSize.Level1) +{ + auto kvDataService = OHOS::DistributedKv::KvStoreDataService(); + auto tokenIdOk = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); + + auto ret = + kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, tokenIdOk); + EXPECT_EQ(ret, Status::ERROR); +} + +/** + * @tc.name: ClearAppStorage003 + * @tc.desc: Test that the cleanup is implemented + * @tc.type: FUNC + * @tc.require: + * @tc.author: suoqilong + */ +HWTEST_F(KvStoreDataServiceClearTest, ClearAppStorage003, TestSize.Level1) +{ + auto executors = std::make_shared(12, 5); + // Create an object of the ExecutorPool class and pass 12 and 5 as arguments to the constructor of the class + KvStoreMetaManager::GetInstance().BindExecutor(executors); + KvStoreMetaManager::GetInstance().InitMetaParameter(); + DmAdapter::GetInstance().Init(executors); + KvStoreMetaManager::GetInstance().InitMetaListener(); + + InitMetaData(); + + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKey(), metaData_)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetSecretKey(), metaData_, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetStrategyKey(), metaData_)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.appId, metaData_, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().SaveMeta(metaData_.GetKeyLocal(), localMeta_, true)); + + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData_)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetSecretKey(), metaData_, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetStrategyKey(), metaData_)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.appId, metaData_, true)); + EXPECT_TRUE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKeyLocal(), localMeta_, true)); + + auto tokenIdOk = AccessTokenKit::GetHapTokenID(TEST_USERID, TEST_BUNDLE, 0); + auto kvDataService = OHOS::DistributedKv::KvStoreDataService(); + auto ret = + kvDataService.ClearAppStorage(BUNDLE_NAME, USER_ID, APP_INDEX, tokenIdOk); + EXPECT_EQ(ret, Status::SUCCESS); + + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData_)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetSecretKey(), metaData_, true)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetStrategyKey(), metaData_)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData_.appId, metaData_, true)); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKeyLocal(), localMeta_, true)); + + MetaDataManager::GetInstance().DelMeta(metaData_.GetKey()); + EXPECT_FALSE(MetaDataManager::GetInstance().LoadMeta(metaData_.GetKey(), metaData_)); +} +} // namespace OHOS::Test \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/BUILD.gn b/datamgr_service/services/distributeddataservice/framework/BUILD.gn index 7d106e5ff43e89e8e11f2a87ec033264791ea9d5..474aed8a7312fb6362f41d7f86b615450c4ee279 100644 --- a/datamgr_service/services/distributeddataservice/framework/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/framework/BUILD.gn @@ -23,7 +23,7 @@ config("module_config") { "include", "//third_party/json/single_include", "//third_party/openssl/include/", - "//foundation/distributeddatamgr/datamgr_service/services/distributeddataservice/adapter/include", + "${data_service_path}/adapter/include", "${kv_store_path}/interfaces/innerkits/distributeddata/include", "${kv_store_common_path}", "${kv_store_distributeddb_path}/interfaces/include/", @@ -49,7 +49,10 @@ ohos_shared_library("distributeddatasvcfwk") { "cloud/cloud_event.cpp", "cloud/cloud_info.cpp", "cloud/cloud_server.cpp", + "cloud/cloud_share_event.cpp", + "cloud/make_query_event.cpp", "cloud/schema_meta.cpp", + "cloud/sharing_center.cpp", "cloud/subscription.cpp", "cloud/sync_event.cpp", "directory/directory_manager.cpp", diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp index f2551e1bd8ebccd9ff7cda6db2532b94c134ce0e..70c1b677b4b669d8d35b74184b681272907d2ae6 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/asset_loader.cpp @@ -20,7 +20,8 @@ int32_t AssetLoader::Download(const std::string &tableName, const std::string &g { return E_NOT_SUPPORT; } -int32_t AssetLoader::RemoveLocalAssets(VBucket &assets) +int32_t AssetLoader::RemoveLocalAssets(const std::string &tableName, const std::string &gid, + const Value &prefix, VBucket &assets) { return E_NOT_SUPPORT; } diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp index 145efcdf08e4c234569d06c2280bbafe3f3ce526..330c81ce39db6d8769b13aaa6012d04ae86d8dbc 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_db.cpp @@ -50,6 +50,11 @@ std::shared_ptr CloudDB::Query(GenQuery& query, const VBucket& extend) return nullptr; } +int32_t CloudDB::PreSharing(const std::string& table, VBuckets& extend) +{ + return E_NOT_SUPPORT; +} + int32_t CloudDB::Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait) { return E_NOT_SUPPORT; diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp index db325e4cbf529f707e2375e695ebf54db3d3f672..ef3a75391d177c3ed7e3d0982bf327098e8246a5 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_server.cpp @@ -60,7 +60,7 @@ std::shared_ptr CloudServer::ConnectCloudDB(uint32_t tokenId, const Clo return nullptr; } -std::shared_ptr CloudServer::ConnectSharingCenter(int32_t userId) +std::shared_ptr CloudServer::ConnectSharingCenter(int32_t userId, const std::string &bunleName) { return nullptr; } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/shared_obj/grd_sequence_api_inner.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_share_event.cpp similarity index 55% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/shared_obj/grd_sequence_api_inner.cpp rename to datamgr_service/services/distributeddataservice/framework/cloud/cloud_share_event.cpp index 17e71400af7d3593407347717d2cdd9327bfdac5..a4d3d93dd2ff5a516f0d8b2cad3e3dd5253f4465 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/shared_obj/grd_sequence_api_inner.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/cloud_share_event.cpp @@ -12,20 +12,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "check_common.h" -#include "grd_api_manager.h" -#include "grd_base/grd_error.h" -#include "grd_sequence_api_inner.h" -#include "grd_type_inner.h" -#include "log_print.h" -namespace DocumentDB { -int32_t GRD_CreateSeqInner(GRD_DB *db, const char *sequenceName, uint32_t flags) + +#include "cloud/cloud_share_event.h" + +namespace OHOS::DistributedData { +CloudShareEvent::CloudShareEvent(StoreInfo storeInfo, std::shared_ptr query, Callback callback) + : CloudEvent(CLOUD_SHARE, std::move(storeInfo)), query_(std::move(query)), callback_(std::move(callback)) { - return GRD_NOT_SUPPORT; // No support. } - -int32_t GRD_DropSeqInner(GRD_DB *db, const char *sequenceName, uint32_t flags) +std::shared_ptr CloudShareEvent::GetQuery() const +{ + return query_; +} +CloudShareEvent::Callback CloudShareEvent::GetCallback() const { - return GRD_NOT_SUPPORT; // No support. + return callback_; } -} // namespace DocumentDB \ No newline at end of file +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/shared_obj/grd_sequence_api.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp similarity index 45% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/shared_obj/grd_sequence_api.cpp rename to datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp index bfb8723431072d015fcae94b6d64016efd2abb4f..1c1ee97ec6d0bef80a7f5b7c95c9c88a5fc190b8 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/shared_obj/grd_sequence_api.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/make_query_event.cpp @@ -12,26 +12,28 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "grd_shared_obj/grd_sequence_api.h" -#include "grd_api_manager.h" -#include "grd_base/grd_error.h" -#include "grd_type_inner.h" -#include "log_print.h" -using namespace DocumentDB; -static GRD_APIInfo GRD_SeqApiInfo = GetApiInfoInstance(); -GRD_API int32_t GRD_CreateSeq(GRD_DB *db, const char *sequenceName, uint32_t flags) +#include "cloud/make_query_event.h" + +namespace OHOS::DistributedData { +MakeQueryEvent::MakeQueryEvent(CloudEvent::StoreInfo storeInfo, + std::shared_ptr predicates, const std::vector& columns, + Callback callback) + : CloudEvent(MAKE_QUERY, std::move(storeInfo)), predicates_(std::move(predicates)), columns_(columns), + callback_(std::move(callback)) +{ +} +std::shared_ptr MakeQueryEvent::GetPredicates() const +{ + return predicates_; +} +std::vector MakeQueryEvent::GetColumns() const { - if (GRD_SeqApiInfo.CreateSeqApi == nullptr) { - return GRD_INNER_ERR; - } - return GRD_SeqApiInfo.CreateSeqApi(db, sequenceName, flags); + return columns_; } -GRD_API int32_t GRD_DropSeq(GRD_DB *db, const char *sequenceName, uint32_t flags) +MakeQueryEvent::Callback MakeQueryEvent::GetCallback() const { - if (GRD_SeqApiInfo.DropSeqApi == nullptr) { - return GRD_INNER_ERR; - } - return GRD_SeqApiInfo.DropSeqApi(db, sequenceName, flags); + return callback_; } +} // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp index af5ec17aa0505cdba9236a7e54db234eb81dec30..b819260ea530546b90bc5892b29fa0e21047624e 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/schema_meta.cpp @@ -34,9 +34,11 @@ bool SchemaMeta::Unmarshal(const Serializable::json &node) std::vector Database::GetTableNames() const { std::vector tableNames; - tableNames.reserve(tables.size()); + auto sharedTableSize = tables.size(); + tableNames.reserve(tables.size() + sharedTableSize); for (auto &table : tables) { tableNames.push_back(table.name); + tableNames.push_back(table.sharedTableName); } return tableNames; } @@ -60,6 +62,7 @@ bool Database::Unmarshal(const Serializable::json &node) bool Table::Marshal(Serializable::json &node) const { SetValue(node[GET_NAME(name)], name); + SetValue(node[GET_NAME(sharedTableName)], sharedTableName); SetValue(node[GET_NAME(alias)], alias); SetValue(node[GET_NAME(fields)], fields); return true; @@ -68,6 +71,7 @@ bool Table::Marshal(Serializable::json &node) const bool Table::Unmarshal(const Serializable::json &node) { GetValue(node, GET_NAME(name), name); + GetValue(node, GET_NAME(sharedTableName), sharedTableName); GetValue(node, GET_NAME(alias), alias); GetValue(node, GET_NAME(fields), fields); return true; diff --git a/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp b/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp index ddeb83912f7bba8bd67f6e434aacbe396a4599ef..0986649660c3535769b22b77e9b998a2bb11b613 100644 --- a/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp +++ b/datamgr_service/services/distributeddataservice/framework/cloud/sharing_center.cpp @@ -15,51 +15,51 @@ #include "cloud/sharing_center.h" namespace OHOS::DistributedData { -int32_t SharingCenter::Share(int32_t userId, const std::string &bundleName, const std::string &sharingRes, - const std::vector &participants, Result>> &result) +SharingCenter::Results SharingCenter::Share(int32_t userId, const std::string &bundleName, + const std::string &sharingRes, const Participants &participants) { - return 0; + return {}; } -int32_t SharingCenter::Unshare(int32_t userId, const std::string &bundleName, const std::string &sharingRes, - const std::vector &participants, Result>> &result) +SharingCenter::Results SharingCenter::Unshare(int32_t userId, const std::string &bundleName, + const std::string &sharingRes, const Participants &participants) { - return 0; + return {}; } -int32_t SharingCenter::ExitSharing(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, Result &result) +std::pair SharingCenter::Exit(int32_t userId, const std::string &bundleName, + const std::string &sharingRes) { - return 0; + return {}; } -int32_t SharingCenter::ChangePrivilege(int32_t userId, const std::string &bundleName, const std::string &sharingRes, - const std::vector &participants, Result>> &result) +SharingCenter::Results SharingCenter::ChangePrivilege(int32_t userId, const std::string &bundleName, + const std::string &sharingRes, const Participants &participants) { - return 0; + return {}; } -int32_t SharingCenter::QueryParticipants(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, Result> &result) +SharingCenter::QueryResults SharingCenter::Query(int32_t userId, const std::string &bundleName, + const std::string &sharingRes) { - return 0; + return {}; } -int32_t SharingCenter::QueryParticipantsByInvitation(int32_t userId, const std::string &bundleName, - const std::string &invitationCode, Result> &result) +SharingCenter::QueryResults SharingCenter::QueryByInvitation(int32_t userId, const std::string &bundleName, + const std::string &invitation) { - return 0; + return {}; } -int32_t SharingCenter::ConfirmInvitation(int32_t userId, const std::string &bundleName, - const std::string &invitationCode, Confirmation confirmation, Result &result) +std::tuple SharingCenter::ConfirmInvitation(int32_t userId, + const std::string &bundleName, const std::string &invitation, int32_t confirmation) { - return 0; + return {}; } -int32_t SharingCenter::ChangeConfirmation(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, Confirmation confirmation, Result &result) +std::pair SharingCenter::ChangeConfirmation(int32_t userId, + const std::string &bundleName, const std::string &sharingRes, int32_t confirmation) { - return 0; + return {}; } } // namespace OHOS::DistributedData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp b/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp index b94ef987f3b47793dd9779ec8be40c54718031c3..cde5c6be092c4ad97b1bec97ca5cf210b889ba95 100644 --- a/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp +++ b/datamgr_service/services/distributeddataservice/framework/feature/feature_system.cpp @@ -86,6 +86,11 @@ int32_t FeatureSystem::Feature::OnAppUpdate(const std::string &bundleName, int32 return E_OK; } +int32_t FeatureSystem::Feature::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) +{ + return E_OK; +} + int32_t FeatureSystem::Feature::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) { return E_OK; diff --git a/datamgr_service/services/distributeddataservice/framework/feature/static_acts.cpp b/datamgr_service/services/distributeddataservice/framework/feature/static_acts.cpp index 817441af9ed83be5b95de4792b6a34b147511288..28b4d0c45a4bcee0d4e106db96dc3924c7733e77 100644 --- a/datamgr_service/services/distributeddataservice/framework/feature/static_acts.cpp +++ b/datamgr_service/services/distributeddataservice/framework/feature/static_acts.cpp @@ -28,6 +28,11 @@ int32_t StaticActs::OnAppUpdate(const std::string &bundleName, int32_t user, int return E_OK; } +int32_t StaticActs::OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) +{ + return E_OK; +} + int32_t StaticActs::OnClearAppStorage(const std::string &bundleName, int32_t user, int32_t index, int32_t tokenId) { return E_OK; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h index c2d47a632856e31e273b51cf269af2bd17cae8f1..6ea12ffff1cada7f1414520ddb974545d55294ed 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/asset_loader.h @@ -24,7 +24,8 @@ public: virtual ~AssetLoader() = default; virtual int32_t Download(const std::string &tableName, const std::string &gid, const Value &prefix, VBucket &assets); - virtual int32_t RemoveLocalAssets(VBucket &assets); + virtual int32_t RemoveLocalAssets(const std::string &tableName, const std::string &gid, + const Value &prefix, VBucket &assets); }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_ASSET_LOADER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h index 1853a729101eaa2ef354570810e628f3572f0bc1..b662c06bcdf6b15555a1023392f80cfed5ba3a96 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_db.h @@ -44,6 +44,8 @@ public: virtual std::shared_ptr Query(GenQuery &query, const VBucket &extend); + virtual int32_t PreSharing(const std::string &table, VBuckets &extend); + virtual int32_t Sync(const Devices &devices, int32_t mode, const GenQuery &query, Async async, int32_t wait); virtual int32_t Watch(int32_t origin, Watcher &watcher); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h index 01c2c0988942250ddcd8fa9f7819c4a7d282bba7..9ce38785cb00df0d1ba45e27f960e889b2c477f1 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_event.h @@ -27,6 +27,9 @@ public: GET_SCHEMA, LOCAL_CHANGE, CLOUD_SYNC, + DATA_CHANGE, + CLOUD_SHARE, + MAKE_QUERY, CLOUD_BUTT }; @@ -36,6 +39,7 @@ public: std::string storeName; int32_t instanceId = 0; int32_t user = 0; + std::string deviceId; }; CloudEvent(int32_t evtId, StoreInfo storeInfo); diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h index 1e751b2706c3a29bbe8aa8ad86133269a42c2c3f..dbf8a4901a52921a7d2daa1e25db0aed698f2c57 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_server.h @@ -34,7 +34,7 @@ public: virtual int32_t Unsubscribe(int32_t userId, const std::map> &dbs); virtual std::shared_ptr ConnectAssetLoader(uint32_t tokenId, const Database &dbMeta); virtual std::shared_ptr ConnectCloudDB(uint32_t tokenId, const Database &dbMeta); - virtual std::shared_ptr ConnectSharingCenter(int32_t userId); + virtual std::shared_ptr ConnectSharingCenter(int32_t userId, const std::string &bunleName); virtual void Clean(int32_t userId); virtual void ReleaseUserInfo(int32_t userId); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_shared_obj/grd_sequence_api.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_share_event.h similarity index 41% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_shared_obj/grd_sequence_api.h rename to datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_share_event.h index 7eaf2b4c0f6b227e66d42853bdfad8960d06262f..2ff7d83ff54ccf684138de6441080887be8c393d 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_shared_obj/grd_sequence_api.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/cloud_share_event.h @@ -13,21 +13,24 @@ * limitations under the License. */ -#ifndef GRD_SEQUENCE_API_H -#define GRD_SEQUENCE_API_H +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARE_EVENT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARE_EVENT_H +#include "cloud/cloud_event.h" +#include "store/general_value.h" +#include "store/cursor.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class API_EXPORT CloudShareEvent : public CloudEvent { +public: + using Callback = std::function)>; + CloudShareEvent(StoreInfo storeInfo, std::shared_ptr query, Callback callback); + ~CloudShareEvent() override = default; + std::shared_ptr GetQuery() const; + Callback GetCallback() const; -#include - -#include "grd_base/grd_resultset_api.h" -#include "grd_base/grd_type_export.h" - -#ifdef __cplusplus -extern "C" { -#endif -GRD_API int32_t GRD_CreateSeq(GRD_DB *db, const char *sequenceName, uint32_t flags); - -GRD_API int32_t GRD_DropSeq(GRD_DB *db, const char *sequenceName, uint32_t flags); -#ifdef __cplusplus -} -#endif -#endif // GRD_DOCUMENT_API_H \ No newline at end of file +private: + std::shared_ptr query_; + Callback callback_; +}; +} // namespace OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARE_EVENT_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/make_query_event.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/make_query_event.h new file mode 100644 index 0000000000000000000000000000000000000000..0725d5b6c8aa429ec5439a95534c6753e656fedb --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/make_query_event.h @@ -0,0 +1,44 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_RDB_SHARE_EVENT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_RDB_SHARE_EVENT_H +#include "cloud/cloud_event.h" +#include "store/general_value.h" +#include "store/cursor.h" +#include "visibility.h" +namespace OHOS { +namespace DistributedRdb { +struct PredicatesMemo; +} +namespace DistributedData { +class API_EXPORT MakeQueryEvent : public CloudEvent { +public: + using Callback = std::function)>; + MakeQueryEvent(StoreInfo storeInfo, std::shared_ptr predicates, + const std::vector& columns, Callback callback); + ~MakeQueryEvent() override = default; + std::shared_ptr GetPredicates() const; + std::vector GetColumns() const; + Callback GetCallback() const; + +private: + std::shared_ptr predicates_; + std::vector columns_; + Callback callback_; +}; +} // namespace DistributedData +} // namespace OHOS +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_RDB_SHARE_EVENT_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h index 298a33938773df3e06a05e446450a1ffc7bd3fba..cd612cf216daa4d7e6948b48525c60ca8ebaf6b8 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/schema_meta.h @@ -29,6 +29,7 @@ struct API_EXPORT Field final : public Serializable { struct API_EXPORT Table final : public Serializable { std::string name; + std::string sharedTableName; std::string alias; std::vector fields; bool Marshal(json &node) const override; @@ -55,6 +56,11 @@ public: static constexpr const char *MODIFY_FIELD = "#_modifyTime"; static constexpr const char *CURSOR_FIELD = "#_cursor"; static constexpr const char *ERROR_FIELD = "#_error"; + static constexpr const char *VERSION_FIELD = "#_version"; + static constexpr const char *REFERENCE_FIELD = "#_reference"; + static constexpr const char *CLOUD_OWNER = "cloud_owner"; + static constexpr const char *CLOUD_PRIVILEGE = "cloud_privilege"; + static constexpr const char *SHARING_RESOURCE = "sharing_resource"; int32_t version = 0; std::string bundleName; std::vector databases; diff --git a/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h b/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h index fb4c139ca4506664345ceb9db1b0a75b7287d560..8571619fb92a99f61ef099d067745e33d2243613 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h +++ b/datamgr_service/services/distributeddataservice/framework/include/cloud/sharing_center.h @@ -16,7 +16,9 @@ #ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARING_CENTER_H #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARING_CENTER_H -#include "itypes_util.h" +#include +#include +#include #include "visibility.h" namespace OHOS::DistributedData { class API_EXPORT SharingCenter { @@ -38,8 +40,8 @@ public: }; struct Privilege { + bool writable = false; bool readable = false; - bool writeable = false; bool creatable = false; bool deletable = false; bool shareable = false; @@ -47,27 +49,49 @@ public: struct Participant { std::string identity; - Role role = ROLE_NIL; - Confirmation status = CFM_NIL; + int32_t role = Role::ROLE_NIL; + int32_t state = Confirmation::CFM_NIL; Privilege privilege; + std::string attachInfo; }; - virtual int32_t Share(int32_t userId, const std::string &bundleName, const std::string &sharingRes, - const std::vector &participants, Result>> &result); - virtual int32_t Unshare(int32_t userId, const std::string &bundleName, const std::string &sharingRes, - const std::vector &participants, Result>> &result); - virtual int32_t ExitSharing(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, Result &result); - virtual int32_t ChangePrivilege(int32_t userId, const std::string &bundleName, const std::string &sharingRes, - const std::vector &participants, Result>> &result); - virtual int32_t QueryParticipants(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, Result> &result); - virtual int32_t QueryParticipantsByInvitation(int32_t userId, const std::string &bundleName, - const std::string &invitationCode, Result> &result); - virtual int32_t ConfirmInvitation(int32_t userId, const std::string &bundleName, - const std::string &invitationCode, Confirmation confirmation, Result &result); - virtual int32_t ChangeConfirmation(int32_t userId, const std::string &bundleName, - const std::string &sharingRes, Confirmation confirmation, Result &result); + using Participants = std::vector; + using Results = std::tuple>>; + using QueryResults = std::tuple; + + enum SharingCode : int32_t { + SUCCESS = 0, + REPEATED_REQUEST, + NOT_INVITER, + NOT_INVITER_OR_INVITEE, + OVER_QUOTA, + TOO_MANY_PARTICIPANTS, + INVALID_ARGS, + NETWORK_ERROR, + CLOUD_DISABLED, + SERVER_ERROR, + INNER_ERROR, + INVALID_INVITATION, + RATE_LIMIT, + IPC_ERROR, + CUSTOM_ERROR = 1000, + }; + + virtual Results Share(int32_t userId, const std::string &bundleName, const std::string &sharingRes, + const Participants &participants); + virtual Results Unshare(int32_t userId, const std::string &bundleName, const std::string &sharingRes, + const Participants &participants); + virtual std::pair Exit(int32_t userId, const std::string &bundleName, + const std::string &sharingRes); + virtual Results ChangePrivilege(int32_t userId, const std::string &bundleName, const std::string &sharingRes, + const Participants &participants); + virtual QueryResults Query(int32_t userId, const std::string &bundleName, const std::string &sharingRes); + virtual QueryResults QueryByInvitation(int32_t userId, const std::string &bundleName, + const std::string &invitation); + virtual std::tuple ConfirmInvitation(int32_t userId, + const std::string &bundleName, const std::string &invitation, int32_t confirmation); + virtual std::pair ChangeConfirmation(int32_t userId, + const std::string &bundleName, const std::string &sharingRes, int32_t confirmation); }; } // namespace OHOS::DistributedData #endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_CLOUD_SHARING_CENTER_H diff --git a/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_change_event.h b/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_change_event.h new file mode 100644 index 0000000000000000000000000000000000000000..0c2fc718b4a34595dbcdc104ed7a46e16552f6ab --- /dev/null +++ b/datamgr_service/services/distributeddataservice/framework/include/commonevent/data_change_event.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMON_EVENT_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMON_EVENT_H + +#include "cloud/cloud_event.h" +#include "visibility.h" +namespace OHOS::DistributedData { +class API_EXPORT DataChangeEvent : public CloudEvent { +public: + struct TableChangeProperties { + bool isTrackedDataChange = false; + }; + using TableProperties = std::map; + struct EventInfo { + TableProperties tableProperties; + }; + + DataChangeEvent(StoreInfo storeInfo, EventInfo evtInfo) + : CloudEvent(DATA_CHANGE, std::move(storeInfo)), info_(std::move(evtInfo)) + { + } + + ~DataChangeEvent() override = default; + + TableProperties GetTableProperties() const + { + return info_.tableProperties; + } +private: + EventInfo info_; +}; +} // OHOS::DistributedData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_COMMON_EVENT_H \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/framework/include/dump/dump_manager.h b/datamgr_service/services/distributeddataservice/framework/include/dump/dump_manager.h index eafa51280e1ec1d3bba662f510606cf32bbf867b..6ba5b4cec922812a3f76a84b48eb969954d2f98a 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/dump/dump_manager.h +++ b/datamgr_service/services/distributeddataservice/framework/include/dump/dump_manager.h @@ -35,8 +35,8 @@ public: std::string abbrCmd; int countPrintf = 1; std::string infoName; - int minParamsNum = 0; - int maxParamsNum = 0; + uint32_t minParamsNum = 0; + uint32_t maxParamsNum = 0; std::string parentNode; std::string childNode; std::vector dumpCaption; diff --git a/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h index 575047f7313b7c8c2f278c77a05cf7c5979ef3d2..28d7fdb6ad4850b097f645cf3bab790e156b5846 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h +++ b/datamgr_service/services/distributeddataservice/framework/include/error/general_error.h @@ -33,6 +33,8 @@ enum GeneralError : int32_t { E_UNOPENED, E_RETRY_TIMEOUT, E_PARTIAL_ERROR, + E_USER_UNLOCK, + E_VERSION_CONFLICT, E_BUTT, }; } diff --git a/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h b/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h index cc80359601642cc9c195432752cb963a44fadd2e..04dc76127f3887c2726c4936cd7407d820a7d17d 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h +++ b/datamgr_service/services/distributeddataservice/framework/include/feature/feature_system.h @@ -49,6 +49,7 @@ public: virtual int32_t OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName); virtual int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); + virtual int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m); virtual int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account); virtual int32_t Online(const std::string &device); diff --git a/datamgr_service/services/distributeddataservice/framework/include/feature/static_acts.h b/datamgr_service/services/distributeddataservice/framework/include/feature/static_acts.h index d989f0a5d861234684dd715beed104d867368a5f..92a1977239f0f305ca5b521e044b4c43effdd086 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/feature/static_acts.h +++ b/datamgr_service/services/distributeddataservice/framework/include/feature/static_acts.h @@ -25,6 +25,7 @@ public: virtual ~StaticActs(); virtual int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnAppUpdate(const std::string &bundleName, int32_t user, int32_t index); + virtual int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index); virtual int32_t OnClearAppStorage(const std::string &bundleName, int32_t user, int32_t index, int32_t tokenId); }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h index e9923b631e727b1e92b92be18cf9228664df37bf..cb87217f354f4283633b1467d3ba6aacde30edc2 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h +++ b/datamgr_service/services/distributeddataservice/framework/include/metadata/store_meta_data.h @@ -31,6 +31,8 @@ struct API_EXPORT StoreMetaData final : public Serializable { bool isBackup = false; bool isDirty = false; bool isEncrypt = false; + bool isManualClean = false; + bool isSearchable = false; int32_t storeType = -1; int32_t securityLevel = 0; int32_t area = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h index 36587dff2a20c9557983ff01ecfe29b99d647899..4c529ff6df8ef5ce9b7e27d2762b6c293e999479 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_store.h @@ -17,6 +17,7 @@ #define OHOS_DISTRIBUTED_DATA_SERVICES_FRAMEWORK_STORE_GENERAL_STORE_H #include #include +#include #include "store/cursor.h" #include "store/general_value.h" @@ -43,7 +44,7 @@ public: CLOUD_END, MODE_BUTT = CLOUD_END, }; - enum HighMode { + enum HighMode : uint32_t { MANUAL_SYNC_MODE = 0x00000, AUTO_SYNC_MODE = 0x10000, }; @@ -55,17 +56,17 @@ public: CLEAN_MODE_BUTT }; - static inline int32_t MixMode(int32_t syncMode, int32_t highMode) + static inline uint32_t MixMode(uint32_t syncMode, uint32_t highMode) { return syncMode | highMode; } - static inline int32_t GetSyncMode(int32_t mixMode) + static inline uint32_t GetSyncMode(uint32_t mixMode) { return mixMode & 0xFFFF; } - static inline int32_t GetHighMode(int32_t mixMode) + static inline uint32_t GetHighMode(uint32_t mixMode) { return mixMode & ~0xFFFF; } @@ -86,7 +87,11 @@ public: virtual int32_t Execute(const std::string &table, const std::string &sql) = 0; - virtual int32_t SetDistributedTables(const std::vector &tables, int type) = 0; + virtual int32_t SetDistributedTables(const std::vector &tables, int type, + const std::vector &references) = 0; + + virtual int32_t SetTrackerTable(const std::string& tableName, const std::set& trackerColNames, + const std::string& extendColName) = 0; virtual int32_t BatchInsert(const std::string &table, VBuckets &&values) = 0; @@ -100,6 +105,8 @@ public: virtual int32_t Sync(const Devices &devices, int32_t mode, GenQuery &query, DetailAsync async, int32_t wait) = 0; + virtual std::shared_ptr PreSharing(GenQuery &query) = 0; + virtual int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) = 0; virtual int32_t Watch(int32_t origin, Watcher &watcher) = 0; diff --git a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h index c9c60cb8d1db1e74bdf98cfb04723852e7ca752e..22ee01e9b600a8fa38746fe05b5011d0ee612971 100644 --- a/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h +++ b/datamgr_service/services/distributeddataservice/framework/include/store/general_value.h @@ -74,9 +74,17 @@ struct Asset { std::string hash; std::string path; }; + +struct Reference { + std::string sourceTable; + std::string targetTable; + std::map refFields; +}; + using Assets = std::vector; using Bytes = std::vector; -using Value = std::variant; +using Relations = std::map; +using Value = std::variant; using Values = std::vector; using VBucket = std::map; using VBuckets = std::vector; diff --git a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp index d2a8f002138e2f1e6f4a4b6165571b1dd1833c16..50250a3a57249bf7ff009e1e80521fed1739cd57 100644 --- a/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp +++ b/datamgr_service/services/distributeddataservice/framework/metadata/store_meta_data.cpp @@ -31,7 +31,9 @@ bool StoreMetaData::Marshal(json &node) const SetValue(node[GET_NAME(isAutoSync)], isAutoSync); SetValue(node[GET_NAME(isBackup)], isBackup); SetValue(node[GET_NAME(isEncrypt)], isEncrypt); + SetValue(node[GET_NAME(isManualClean)], isManualClean); SetValue(node[GET_NAME(isDirty)], isDirty); + SetValue(node[GET_NAME(isSearchable)], isSearchable); SetValue(node[GET_NAME(storeType)], storeType); SetValue(node[GET_NAME(securityLevel)], securityLevel); SetValue(node[GET_NAME(area)], area); @@ -66,6 +68,8 @@ bool StoreMetaData::Unmarshal(const json &node) GetValue(node, GET_NAME(isBackup), isBackup); GetValue(node, GET_NAME(isDirty), isDirty); GetValue(node, GET_NAME(isEncrypt), isEncrypt); + GetValue(node, GET_NAME(isManualClean), isManualClean); + GetValue(node, GET_NAME(isSearchable), isSearchable); GetValue(node, GET_NAME(storeType), storeType); GetValue(node, GET_NAME(securityLevel), securityLevel); GetValue(node, GET_NAME(area), area); @@ -110,7 +114,8 @@ StoreMetaData::StoreMetaData(const std::string &userId, const std::string &appId bool StoreMetaData::operator==(const StoreMetaData &metaData) const { if (Constant::NotEqual(isAutoSync, metaData.isAutoSync) || Constant::NotEqual(isBackup, metaData.isBackup) || - Constant::NotEqual(isDirty, metaData.isDirty) || Constant::NotEqual(isEncrypt, metaData.isEncrypt)) { + Constant::NotEqual(isDirty, metaData.isDirty) || Constant::NotEqual(isEncrypt, metaData.isEncrypt) || + Constant::NotEqual(isSearchable, metaData.isSearchable)) { return false; } return (version == metaData.version && storeType == metaData.storeType && diff --git a/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp b/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp index bbf545e939565b7882fead7142754474265a9c14..8dfc80b407d1cd53e3bdfcb16d808e382b864e5b 100644 --- a/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/framework/test/checker_manager_test.cpp @@ -40,7 +40,7 @@ void CheckerManagerTest::SetUp(void) infoInstance.dcaps = nullptr; infoInstance.perms = nullptr; infoInstance.acls = nullptr; - infoInstance.processName = "foundation"; + infoInstance.processName = "CheckerManagerTest"; infoInstance.aplStr = "system_core"; HapInfoParams info = { diff --git a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp index efc99c062d0a9ac0cf185e4e1282557cdfe1046c..2b834643cbe59d5dd4f04c0682daa77aee662560 100644 --- a/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp +++ b/datamgr_service/services/distributeddataservice/framework/utils/constant.cpp @@ -63,23 +63,6 @@ bool Constant::NotEqual(bool first, bool second) bool Constant::IsBackground(pid_t pid) { - std::ifstream ifs("/proc/" + std::to_string(pid) + "/cgroup", std::ios::in); - ZLOGD("pid %d open %d", pid, ifs.good()); - if (!ifs.good()) { - return false; - } - - while (!ifs.eof()) { - const int MAX_LEN = 256; // enough - char buffer[MAX_LEN] = { 0 }; - ifs.getline(buffer, sizeof(buffer)); - std::string line = buffer; - - size_t pos = line.find("background"); - if (pos != std::string::npos) { - return true; - } - } return false; } diff --git a/datamgr_service/services/distributeddataservice/service/BUILD.gn b/datamgr_service/services/distributeddataservice/service/BUILD.gn index 656c16a7d7770dceaf40e283b4b7460b7a0c7c1f..c5d560afb0c5f697efa3935a2363239082e0e35f 100644 --- a/datamgr_service/services/distributeddataservice/service/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/BUILD.gn @@ -63,6 +63,8 @@ ohos_shared_library("distributeddatasvc") { "bootstrap/src/bootstrap.cpp", "cloud/cloud_service_impl.cpp", "cloud/cloud_service_stub.cpp", + "cloud/cloud_types_util.cpp", + "cloud/cloud_value_util.cpp", "cloud/sync_manager.cpp", "config/src/config_factory.cpp", "config/src/model/backup_config.cpp", @@ -91,6 +93,7 @@ ohos_shared_library("distributeddatasvc") { "object/object_service_impl.cpp", "object/object_service_stub.cpp", "permission/src/permit_delegate.cpp", + "rdb/cache_cursor.cpp", "rdb/rdb_asset_loader.cpp", "rdb/rdb_cloud.cpp", "rdb/rdb_cloud_data_translate.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt index db7a56c1dde0fd039ade297e8a8102346e44416a..86648550d3737f9f73f6353ce498910a3160739e 100644 --- a/datamgr_service/services/distributeddataservice/service/CMakeLists.txt +++ b/datamgr_service/services/distributeddataservice/service/CMakeLists.txt @@ -34,6 +34,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/udmf/lifecycle serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/udmf/permission serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/udmf/preprocess serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/udmf/store serviceSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/udmf/utd serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/udmf serviceSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/permission/src serviceSrc) @@ -63,12 +64,13 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../data_share/framework include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../data_share/frameworks/native/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../data_object/frameworks/innerkitsimpl/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../udmf/framework/common) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../udmf/framework/service) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../udmf/framework/innerkitsimpl/data) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../udmf/framework/innerkitsimpl/service) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../utils_native/base/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../utils_native/safwk/native/include) include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) -set(links secure mock kvdb svcFwk adapter data_share udmf document_ut cloud_data relational_store) +set(links secure mock kvdb svcFwk adapter data_share udmf gaussdb cloud_data relational_store) set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/../../../") add_library(service SHARED ${serviceSrc}) target_link_libraries(service ${links}) diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp index 5fdd771538d8368f3c5bd380a0d315f0e7c1d15f..4ec6201eb9901ae5f532f882848415366973c5b2 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.cpp @@ -20,12 +20,18 @@ #include "account/account_delegate.h" #include "checker/checker_manager.h" #include "cloud/cloud_server.h" +#include "cloud/make_query_event.h" +#include "cloud/cloud_share_event.h" +#include "cloud_value_util.h" #include "communicator/device_manager_adapter.h" #include "eventcenter/event_center.h" +#include "hap_token_info.h" #include "ipc_skeleton.h" #include "log_print.h" #include "metadata/meta_data_manager.h" #include "rdb_cloud_data_translate.h" +#include "rdb_types.h" +#include "values_bucket.h" #include "runtime_config.h" #include "store/auto_cache.h" #include "store/general_store.h" @@ -33,11 +39,13 @@ #include "sync_manager.h" namespace OHOS::CloudData { using namespace DistributedData; +using namespace DistributedKv; using namespace std::chrono; +using namespace SharingUtil; +using namespace Security::AccessToken; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using Account = OHOS::DistributedKv::AccountDelegate; using AccessTokenKit = Security::AccessToken::AccessTokenKit; -using namespace Security::AccessToken; __attribute__((used)) CloudServiceImpl::Factory CloudServiceImpl::factory_; CloudServiceImpl::Factory::Factory() noexcept @@ -63,12 +71,15 @@ CloudServiceImpl::CloudServiceImpl() EventCenter::GetInstance().Subscribe(CloudEvent::GET_SCHEMA, [this](const Event &event) { GetSchema(event); }); + EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SHARE, [this](const Event &event) { + CloudShare(event); + }); } int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::map &switches) { auto tokenId = IPCSkeleton::GetCallingTokenID(); - auto user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); + auto user = Account::GetInstance()->GetUserByToken(tokenId); auto [status, cloudInfo] = GetCloudInfo(user); if (status != SUCCESS) { return status; @@ -83,37 +94,43 @@ int32_t CloudServiceImpl::EnableCloud(const std::string &id, const std::mapGetUserByToken(tokenId); + auto [status, cloudInfo] = GetCloudInfo(user); if (status != SUCCESS) { return status; } + if (cloudInfo.id != id) { + ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s", Anonymous::Change(id).c_str(), + Anonymous::Change(cloudInfo.id).c_str()); + return ERROR; + } cloudInfo.enableCloud = false; if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { return ERROR; } - Execute(GenTask(0, cloudInfo.user, { WORK_SUB, WORK_RELEASE })); - syncManager_.StopCloudSync(cloudInfo.user); + Execute(GenTask(0, cloudInfo.user, { WORK_STOP_CLOUD_SYNC, WORK_SUB, WORK_RELEASE })); return SUCCESS; } int32_t CloudServiceImpl::ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) { - CloudInfo cloudInfo; - auto status = GetCloudInfo(IPCSkeleton::GetCallingTokenID(), id, cloudInfo); + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto user = Account::GetInstance()->GetUserByToken(tokenId); + auto [status, cloudInfo] = GetCloudInfo(user); if (status != SUCCESS) { return status; } - if (!cloudInfo.Exist(bundleName)) { - ZLOGE("bundleName:%{public}s", bundleName.c_str()); - return INVALID_ARGUMENT; + if (cloudInfo.id != id || !cloudInfo.Exist(bundleName)) { + ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s, bundleName:%{public}s", + Anonymous::Change(id).c_str(), Anonymous::Change(cloudInfo.id).c_str(), bundleName.c_str()); + return ERROR; } cloudInfo.apps[bundleName].cloudSwitch = (appSwitch == SWITCH_ON); if (!MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true)) { @@ -171,10 +188,10 @@ int32_t CloudServiceImpl::DoClean(CloudInfo &cloudInfo, const std::map &actions) { - CloudInfo cloudInfo; auto tokenId = IPCSkeleton::GetCallingTokenID(); - cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); - if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { + auto user = Account::GetInstance()->GetUserByToken(tokenId); + auto [status, cloudInfo] = GetCloudInfoFromMeta(user); + if (status != SUCCESS) { ZLOGE("get cloud meta failed user:%{public}d", static_cast(cloudInfo.user)); return ERROR; } @@ -191,14 +208,9 @@ int32_t CloudServiceImpl::Clean(const std::string &id, const std::mapGetUserByToken(tokenId); - if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { - return ERROR; - } if (cloudInfo.id != id) { ZLOGE("invalid args, [input] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(id).c_str(), Anonymous::Change(cloudInfo.id).c_str()); @@ -214,10 +226,80 @@ int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::str if (!cloudInfo.apps[bundleName].cloudSwitch) { return CLOUD_DISABLE_SWITCH; } + return SUCCESS; +} + +int32_t CloudServiceImpl::GetDbInfoFromExtraData(const ExtraData &exData, int32_t userId, std::string &storeId, + std::vector &table) +{ + auto schemaKey = CloudInfo::GetSchemaKey(userId, exData.extInfo.bundleName); + SchemaMeta schemaMeta; + if (!MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { + ZLOGE("no exist meta, user:%{public}d", userId); + return ERROR; + } + for (auto &db : schemaMeta.databases) { + if (db.alias != exData.extInfo.containerName) { + continue; + } + storeId = db.name; + for (auto &tb : db.tables) { + const auto &tbs = exData.extInfo.tables; + if (std::find(tbs.begin(), tbs.end(), tb.alias) == tbs.end()) { + continue; + } + table.emplace_back(tb.name); + } + } + return SUCCESS; +} + +int32_t CloudServiceImpl::NotifyDataChange(const std::string &id, const std::string &bundleName) +{ + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto user = Account::GetInstance()->GetUserByToken(tokenId); + auto [status, cloudInfo] = GetCloudInfoFromMeta(user); + if (CheckNotifyConditions(id, bundleName, cloudInfo) != E_OK) { + return INVALID_ARGUMENT; + } syncManager_.DoCloudSync(SyncManager::SyncInfo(cloudInfo.user, bundleName)); return SUCCESS; } +int32_t CloudServiceImpl::NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId) +{ + ZLOGI("notify data change, user:%{public}d", userId); + if (eventId != DATA_CHANGE_EVENT_ID || extraData.empty()) { + return INVALID_ARGUMENT; + } + ExtraData exData; + if (!exData.Unmarshall(extraData)) { + return INVALID_ARGUMENT; + } + std::vector users; + if (userId != INVALID_USER_ID) { + users.emplace_back(userId); + } else { + Account::GetInstance()->QueryUsers(users); + } + for (auto user : users) { + if (user == DEFAULT_USER) { + continue; + } + auto [status, cloudInfo] = GetCloudInfoFromMeta(user); + if (CheckNotifyConditions(exData.extInfo.accountId, exData.extInfo.bundleName, cloudInfo) != E_OK) { + return INVALID_ARGUMENT; + } + std::string storeId; + std::vector table; + if (GetDbInfoFromExtraData(exData, userId, storeId, table) != E_OK) { + return INVALID_ARGUMENT; + } + syncManager_.DoCloudSync(SyncManager::SyncInfo(cloudInfo.user, exData.extInfo.bundleName, storeId, table)); + } + return SUCCESS; +} + int32_t CloudServiceImpl::OnInitialize() { DistributedDB::RuntimeConfig::SetCloudTranslate(std::make_shared()); @@ -239,10 +321,19 @@ int32_t CloudServiceImpl::OnBind(const BindInfo &info) int32_t CloudServiceImpl::OnUserChange(uint32_t code, const std::string &user, const std::string &account) { int32_t userId = atoi(user.c_str()); - if (code == static_cast(DistributedKv::AccountStatus::DEVICE_ACCOUNT_SWITCHED)) { - Execute(GenTask(0, userId, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB })); + switch (code) { + case static_cast(AccountStatus::DEVICE_ACCOUNT_SWITCHED): + Execute(GenTask(0, userId, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB, WORK_DO_CLOUD_SYNC })); + break; + case static_cast(AccountStatus::DEVICE_ACCOUNT_DELETE): + Execute(GenTask(0, userId, { WORK_STOP_CLOUD_SYNC, WORK_RELEASE })); + break; + case static_cast(AccountStatus::DEVICE_ACCOUNT_UNLOCKED): + Execute(GenTask(0, userId, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB, WORK_DO_CLOUD_SYNC })); + break; + default: + break; } - syncManager_.StopCloudSync(userId); return E_OK; } @@ -258,8 +349,7 @@ int32_t CloudServiceImpl::Online(const std::string &device) return SUCCESS; } auto it = users.begin(); - syncManager_.DoCloudSync({ *it }); - Execute(GenTask(0, *it, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB })); + Execute(GenTask(0, *it, { WORK_CLOUD_INFO_UPDATE, WORK_SCHEMA_UPDATE, WORK_SUB, WORK_DO_CLOUD_SYNC })); return SUCCESS; } @@ -279,53 +369,37 @@ int32_t CloudServiceImpl::Offline(const std::string &device) return SUCCESS; } -int32_t CloudServiceImpl::GetCloudInfo(uint32_t tokenId, const std::string &id, CloudInfo &cloudInfo) -{ - cloudInfo.user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(tokenId); - if (GetCloudInfoFromMeta(cloudInfo) != SUCCESS) { - auto status = GetCloudInfoFromServer(cloudInfo); - if (status != SUCCESS) { - ZLOGE("user:%{public}d", cloudInfo.user); - return status; - } - } - if (cloudInfo.id != id) { - ZLOGE("invalid args, [input] id:%{public}s, [exist] id:%{public}s", Anonymous::Change(id).c_str(), - Anonymous::Change(cloudInfo.id).c_str()); - return INVALID_ARGUMENT; - } - return SUCCESS; -} - -int32_t CloudServiceImpl::GetCloudInfoFromMeta(CloudInfo &cloudInfo) +std::pair CloudServiceImpl::GetCloudInfoFromMeta(int32_t userId) { + CloudInfo cloudInfo; + cloudInfo.user = userId; if (!MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { ZLOGE("no exist meta, user:%{public}d", cloudInfo.user); - return ERROR; + return { ERROR, cloudInfo }; } - return SUCCESS; + return { SUCCESS, cloudInfo }; } -int32_t CloudServiceImpl::GetCloudInfoFromServer(CloudInfo &cloudInfo) +std::pair CloudServiceImpl::GetCloudInfoFromServer(int32_t userId) { + CloudInfo cloudInfo; + cloudInfo.user = userId; auto instance = CloudServer::GetInstance(); if (instance == nullptr) { - return NOT_SUPPORT; + return { SERVER_UNAVAILABLE, cloudInfo }; } cloudInfo = instance->GetServerInfo(cloudInfo.user); if (!cloudInfo.IsValid()) { ZLOGE("cloud is empty, user%{public}d", cloudInfo.user); - return ERROR; + return { ERROR, cloudInfo }; } - return SUCCESS; + return { SUCCESS, cloudInfo }; } bool CloudServiceImpl::UpdateCloudInfo(int32_t user) { - CloudInfo cloudInfo; - cloudInfo.user = user; - if (GetCloudInfoFromServer(cloudInfo) != SUCCESS) { - ZLOGE("failed, user:%{public}d", user); + auto [status, cloudInfo] = GetCloudInfoFromServer(user); + if (status != SUCCESS) { return false; } CloudInfo oldInfo; @@ -333,6 +407,7 @@ bool CloudServiceImpl::UpdateCloudInfo(int32_t user) MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); return true; } + MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); if (oldInfo.id != cloudInfo.id) { ZLOGE("different id, [server] id:%{public}s, [meta] id:%{public}s", Anonymous::Change(cloudInfo.id).c_str(), Anonymous::Change(oldInfo.id).c_str()); @@ -342,47 +417,40 @@ bool CloudServiceImpl::UpdateCloudInfo(int32_t user) } DoClean(oldInfo, actions); } - if (cloudInfo.enableCloud) { - for (auto &[bundle, app] : cloudInfo.apps) { - if (app.cloudSwitch && !oldInfo.apps[bundle].cloudSwitch) { - syncManager_.DoCloudSync({ cloudInfo.user, bundle }); - } - } - } - MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); return true; } bool CloudServiceImpl::UpdateSchema(int32_t user) { - CloudInfo cloudInfo; - cloudInfo.user = user; - if (GetCloudInfoFromServer(cloudInfo) != SUCCESS) { - ZLOGE("failed, user:%{public}d", user); + auto [status, cloudInfo] = GetCloudInfoFromServer(user); + if (status != SUCCESS) { return false; } auto keys = cloudInfo.GetSchemaKey(); for (const auto &[bundle, key] : keys) { SchemaMeta schemaMeta; - if (MetaDataManager::GetInstance().LoadMeta(key, schemaMeta, true)) { + std::tie(status, schemaMeta) = GetAppSchemaFromServer(user, bundle); + if (status != SUCCESS) { continue; } - if (GetAppSchema(cloudInfo.user, bundle, schemaMeta) != SUCCESS) { - return false; - } MetaDataManager::GetInstance().SaveMeta(key, schemaMeta, true); } return true; } -int32_t CloudServiceImpl::GetAppSchema(int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta) +std::pair CloudServiceImpl::GetAppSchemaFromServer(int32_t user, const std::string& bundleName) { + SchemaMeta schemaMeta; auto instance = CloudServer::GetInstance(); if (instance == nullptr) { - return SERVER_UNAVAILABLE; + return { SERVER_UNAVAILABLE, schemaMeta }; } schemaMeta = instance->GetAppSchema(user, bundleName); - return SUCCESS; + if (!schemaMeta.IsValid()) { + ZLOGE("schema is InValid, user:%{public}d, bundleName:%{public}s", user, bundleName.c_str()); + return { ERROR, schemaMeta }; + } + return { SUCCESS, schemaMeta }; } ExecutorPool::Task CloudServiceImpl::GenTask(int32_t retry, int32_t user, Handles handles) @@ -406,6 +474,9 @@ ExecutorPool::Task CloudServiceImpl::GenTask(int32_t retry, int32_t user, Handle auto handle = works.front(); for (auto user : users) { + if (user == 0 || !Account::GetInstance()->IsVerified(user)) { + continue; + } finished = (this->*handle)(user) && finished; } if (!finished || users.empty()) { @@ -419,54 +490,48 @@ ExecutorPool::Task CloudServiceImpl::GenTask(int32_t retry, int32_t user, Handle }; } -SchemaMeta CloudServiceImpl::GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId) +std::pair CloudServiceImpl::GetSchemaMeta(int32_t userId, const std::string& bundleName, + int32_t instanceId) { SchemaMeta schemaMeta; - auto [status, cloudInfo] = GetCloudInfo(userId); + auto [status, cloudInfo] = GetCloudInfoFromMeta(userId); if (status != SUCCESS) { // GetCloudInfo has print the log info. so we don`t need print again. - return schemaMeta; + return { status, schemaMeta }; } - if (!bundleName.empty() && !cloudInfo.Exist(bundleName, instanceId)) { ZLOGD("bundleName:%{public}s instanceId:%{public}d is not exist", bundleName.c_str(), instanceId); - return schemaMeta; + return { ERROR, schemaMeta }; } std::string schemaKey = cloudInfo.GetSchemaKey(bundleName, instanceId); if (MetaDataManager::GetInstance().LoadMeta(schemaKey, schemaMeta, true)) { - return schemaMeta; + return { SUCCESS, schemaMeta }; } - - auto instance = CloudServer::GetInstance(); - if (instance == nullptr) { - return schemaMeta; + if (!Account::GetInstance()->IsVerified(userId)) { + return { ERROR, schemaMeta }; } - schemaMeta = instance->GetAppSchema(userId, bundleName); - if (!schemaMeta.IsValid()) { - ZLOGE("download schema from cloud failed, user:%{public}d, bundleName:%{public}s", userId, bundleName.c_str()); + std::tie(status, schemaMeta) = GetAppSchemaFromServer(userId, bundleName); + if (status != SUCCESS) { + return { status, schemaMeta }; } MetaDataManager::GetInstance().SaveMeta(schemaKey, schemaMeta, true); - return schemaMeta; + return { SUCCESS, schemaMeta }; } std::pair CloudServiceImpl::GetCloudInfo(int32_t userId) { - CloudInfo cloudInfo; - cloudInfo.user = userId; - if (MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetKey(), cloudInfo, true)) { - return { SUCCESS, cloudInfo }; + auto [status, cloudInfo] = GetCloudInfoFromMeta(userId); + if (status == SUCCESS) { + return { status, cloudInfo }; } - auto instance = CloudServer::GetInstance(); - if (instance == nullptr) { - return { SERVER_UNAVAILABLE, cloudInfo }; - } - - cloudInfo = instance->GetServerInfo(userId); - if (!cloudInfo.IsValid()) { - ZLOGE("no cloud info %{public}d", userId); + if (!Account::GetInstance()->IsVerified(userId)) { + ZLOGW("user:%{public}d is locked!", userId); return { ERROR, cloudInfo }; } - + std::tie(status, cloudInfo) = GetCloudInfoFromServer(userId); + if (status == SUCCESS) { + return { status, cloudInfo }; + } MetaDataManager::GetInstance().SaveMeta(cloudInfo.GetKey(), cloudInfo, true); return { SUCCESS, cloudInfo }; } @@ -488,6 +553,50 @@ void CloudServiceImpl::GetSchema(const Event &event) GetSchemaMeta(storeInfo.user, storeInfo.bundleName, storeInfo.instanceId); } +void CloudServiceImpl::CloudShare(const Event& event) +{ + auto& cloudShareEvent = static_cast(event); + auto& storeInfo = cloudShareEvent.GetStoreInfo(); + auto query = cloudShareEvent.GetQuery(); + auto callback = cloudShareEvent.GetCallback(); + if (query == nullptr) { + ZLOGE("query is null, bundleName:%{public}s, storeName:%{public}s, instanceId:%{public}d", + storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId); + if (callback) { + callback(GeneralError::E_ERROR, nullptr); + } + } + ZLOGD("Start PreShare, bundleName:%{public}s, storeName:%{public}s, instanceId:%{public}d", + storeInfo.bundleName.c_str(), Anonymous::Change(storeInfo.storeName).c_str(), storeInfo.instanceId); + auto [status, cursor] = PreShare(storeInfo, *query); + + if (callback) { + callback(status, cursor); + } +} + +std::pair> CloudServiceImpl::PreShare( + const CloudEvent::StoreInfo& storeInfo, GenQuery& query) +{ + StoreMetaData meta; + meta.bundleName = storeInfo.bundleName; + meta.storeId = storeInfo.storeName; + meta.user = std::to_string(storeInfo.user); + meta.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + meta.instanceId = storeInfo.instanceId; + if (!MetaDataManager::GetInstance().LoadMeta(meta.GetKey(), meta)) { + ZLOGE("failed, no store meta bundleName:%{public}s, storeId:%{public}s", meta.bundleName.c_str(), + meta.GetStoreAlias().c_str()); + return { GeneralError::E_ERROR, nullptr }; + } + AutoCache::Store store = SyncManager::GetStore(meta, storeInfo.user, true); + if (store == nullptr) { + ZLOGE("store null, storeId:%{public}s", meta.GetStoreAlias().c_str()); + return { GeneralError::E_ERROR, nullptr }; + } + return { GeneralError::E_OK, store->PreSharing(query) }; +} + bool CloudServiceImpl::ReleaseUserInfo(int32_t user) { auto instance = CloudServer::GetInstance(); @@ -498,6 +607,18 @@ bool CloudServiceImpl::ReleaseUserInfo(int32_t user) return true; } +bool CloudServiceImpl::DoCloudSync(int32_t user) +{ + syncManager_.DoCloudSync(user); + return true; +} + +bool CloudServiceImpl::StopCloudSync(int32_t user) +{ + syncManager_.StopCloudSync(user); + return true; +} + bool CloudServiceImpl::DoSubscribe(int32_t user) { Subscription sub; @@ -593,86 +714,235 @@ std::map CloudServiceImpl::ConvertAction(const std::map &participants, - Result>> &result) +std::pair> CloudServiceImpl::AllocResourceAndShare( + const std::string& storeId, const DistributedRdb::PredicatesMemo& predicates, + const std::vector& columns, const Participants& participants) +{ + auto tokenId = IPCSkeleton::GetCallingTokenID(); + auto [bundleName, instanceId] = GetHapInfo(tokenId); + if (bundleName.empty()) { + ZLOGE("bundleName is empty, storeId:%{public}s", Anonymous::Change(storeId).c_str()); + return { E_ERROR, {} }; + } + if (predicates.tables_.empty()) { + ZLOGE("tables size:%{public}zu, storeId:%{public}s", predicates.tables_.size(), + Anonymous::Change(storeId).c_str()); + return { E_ERROR, {} }; + } + auto memo = std::make_shared(predicates); + CloudEvent::StoreInfo storeInfo; + storeInfo.bundleName = bundleName; + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); + storeInfo.storeName = storeId; + std::shared_ptr query; + MakeQueryEvent::Callback asyncCallback = [&query](std::shared_ptr genQuery) { + query = genQuery; + }; + auto evt = std::make_unique(storeInfo, memo, columns, asyncCallback); + EventCenter::GetInstance().PostEvent(std::move(evt)); + if (query == nullptr) { + ZLOGE("query is null, storeId:%{public}s,", Anonymous::Change(storeId).c_str()); + return { E_ERROR, {} }; + } + auto [status, cursor] = PreShare(storeInfo, *query); + if (status != GeneralError::E_OK || cursor == nullptr) { + ZLOGE("PreShare fail, storeId:%{public}s, status:%{public}d", Anonymous::Change(storeId).c_str(), status); + return { E_ERROR, {} }; + } + auto valueBuckets = ConvertCursor(cursor); + Results results; + for (auto& valueBucket : valueBuckets) { + NativeRdb::ValueObject object; + if (!valueBucket.GetObject(SchemaMeta::SHARING_RESOURCE, object)) { + continue; + } + std::string shareRes; + if (object.GetString(shareRes) != E_OK) { + continue; + } + Share(shareRes, participants, results); + } + return { SUCCESS, std::move(valueBuckets) }; +} + +std::vector CloudServiceImpl::ConvertCursor(std::shared_ptr cursor) const +{ + std::vector valueBuckets; + int32_t count = cursor->GetCount(); + valueBuckets.reserve(count); + auto err = cursor->MoveToFirst(); + while (err == E_OK && count > 0) { + VBucket entry; + err = cursor->GetEntry(entry); + if (err != E_OK) { + break; + } + NativeRdb::ValuesBucket bucket; + for (auto& [key, value] : entry) { + NativeRdb::ValueObject object; + DistributedData::Convert(std::move(value), object.value); + bucket.values_.insert_or_assign(key, std::move(object)); + } + valueBuckets.emplace_back(std::move(bucket)); + err = cursor->MoveToNext(); + count--; + } + return valueBuckets; +} + +std::pair CloudServiceImpl::GetHapInfo(uint32_t tokenId) +{ + if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) { + return { "", -1 }; + } + HapTokenInfo tokenInfo; + tokenInfo.instIndex = -1; + int errCode = AccessTokenKit::GetHapTokenInfo(tokenId, tokenInfo); + if (errCode != RET_SUCCESS) { + ZLOGE("GetHapTokenInfo error:%{public}d, tokenId:0x%{public}x bundleName:%{public}s", errCode, tokenId, + tokenInfo.bundleName.c_str()); + return { tokenInfo.bundleName, tokenInfo.instIndex }; + } + return { tokenInfo.bundleName, tokenInfo.instIndex }; +} + +bool CloudServiceImpl::ExtraData::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(header)], header); + SetValue(node[GET_NAME(data)], data); + return true; +} + +bool CloudServiceImpl::ExtraData::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(header), header); + GetValue(node, GET_NAME(data), data); + return extInfo.Unmarshall(data); +} + +bool CloudServiceImpl::ExtraData::ExtInfo::Marshal(Serializable::json &node) const +{ + SetValue(node[GET_NAME(accountId)], accountId); + SetValue(node[GET_NAME(bundleName)], bundleName); + SetValue(node[GET_NAME(containerName)], containerName); + SetValue(node[GET_NAME(recordTypes)], recordTypes); + return true; +} + +bool CloudServiceImpl::ExtraData::ExtInfo::Unmarshal(const Serializable::json &node) +{ + GetValue(node, GET_NAME(accountId), accountId); + GetValue(node, GET_NAME(bundleName), bundleName); + GetValue(node, GET_NAME(containerName), containerName); + GetValue(node, GET_NAME(recordTypes), recordTypes); + return Unmarshall(recordTypes, tables); +} + +int32_t CloudServiceImpl::Share( + const std::string &sharingRes, const Participants &participants, Results &results) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + results = instance->Share(hapInfo.user, hapInfo.bundleName, sharingRes, Convert(participants)); + int32_t status = std::get<0>(results); + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } -int32_t CloudServiceImpl::Unshare(const std::string &sharingRes, const std::vector &participants, - Result>> &result) +int32_t CloudServiceImpl::Unshare( + const std::string &sharingRes, const Participants &participants, Results &results) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + results = instance->Unshare(hapInfo.user, hapInfo.bundleName, sharingRes, Convert(participants)); + int32_t status = std::get<0>(results); + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } -int32_t CloudServiceImpl::ExitSharing(const std::string &sharingRes, Result &result) +int32_t CloudServiceImpl::Exit(const std::string &sharingRes, std::pair &result) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + result = instance->Exit(hapInfo.user, hapInfo.bundleName, sharingRes); + int32_t status = result.first; + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } -int32_t CloudServiceImpl::ChangePrivilege(const std::string &sharingRes, const std::vector &participants, - Result>> &result) +int32_t CloudServiceImpl::ChangePrivilege( + const std::string &sharingRes, const Participants &participants, Results &results) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + results = instance->ChangePrivilege(hapInfo.user, hapInfo.bundleName, sharingRes, Convert(participants)); + int32_t status = std::get<0>(results); + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } -int32_t CloudServiceImpl::QueryParticipants(const std::string &sharingRes, Result> &result) +int32_t CloudServiceImpl::Query(const std::string &sharingRes, QueryResults &results) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + auto queryResults = instance->Query(hapInfo.user, hapInfo.bundleName, sharingRes); + results = Convert(queryResults); + int32_t status = std::get<0>(queryResults); + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } -int32_t CloudServiceImpl::QueryParticipantsByInvitation(const std::string &invitationCode, - Result> &result) +int32_t CloudServiceImpl::QueryByInvitation(const std::string &invitation, QueryResults &results) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + auto queryResults = instance->QueryByInvitation(hapInfo.user, hapInfo.bundleName, invitation); + results = Convert(queryResults); + int32_t status = std::get<0>(queryResults); + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } -int32_t CloudServiceImpl::ConfirmInvitation(const std::string &invitationCode, Confirmation confirmation, - Result &result) +int32_t CloudServiceImpl::ConfirmInvitation(const std::string &invitation, int32_t confirmation, + std::tuple &result) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + result = instance->ConfirmInvitation(hapInfo.user, hapInfo.bundleName, invitation, confirmation); + int32_t status = std::get<0>(result); + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } int32_t CloudServiceImpl::ChangeConfirmation( - const std::string &sharingRes, Confirmation confirmation, Result &result) + const std::string &sharingRes, int32_t confirmation, std::pair &result) { auto [instance, hapInfo] = GetSharingHandle(); if (instance == nullptr) { return NOT_SUPPORT; } - return SUCCESS; + result = instance->ChangeConfirmation(hapInfo.user, hapInfo.bundleName, sharingRes, confirmation); + int32_t status = result.first; + ZLOGD("status:%{public}d", status); + return Convert(static_cast(status)); } -std::pair, CloudServiceImpl::HapInfo> - CloudServiceImpl::GetSharingHandle() +std::pair, CloudServiceImpl::HapInfo> CloudServiceImpl::GetSharingHandle() { auto tokenId = IPCSkeleton::GetCallingTokenID(); HapTokenInfo tokenInfo; @@ -685,7 +955,7 @@ std::pair, CloudServiceImpl::Hap if (instance == nullptr) { return { nullptr, {} }; } - auto handle = instance->ConnectSharingCenter(tokenInfo.userID); + auto handle = instance->ConnectSharingCenter(tokenInfo.userID, tokenInfo.bundleName); return { handle, { tokenInfo.userID, tokenInfo.bundleName } }; } } // namespace OHOS::CloudData \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h index 09df857bc4c2295efb8dbcc5843c5fde10a8c370..c1cfdc485766c83cdc12adc37bbd66fc7255e0a0 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_impl.h @@ -26,6 +26,7 @@ #include "cloud_service_stub.h" #include "feature/static_acts.h" #include "sync_manager.h" +#include "values_bucket.h" namespace OHOS::CloudData { class CloudServiceImpl : public CloudServiceStub { public: @@ -37,26 +38,27 @@ public: int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; int32_t Clean(const std::string &id, const std::map &actions) override; int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; + int32_t NotifyDataChange(const std::string& eventId, const std::string& extraData, int32_t userId) override; int32_t OnInitialize() override; int32_t OnBind(const BindInfo &info) override; int32_t OnUserChange(uint32_t code, const std::string &user, const std::string &account) override; int32_t Online(const std::string &device) override; int32_t Offline(const std::string &device) override; - int32_t Share(const std::string &sharingRes, const std::vector &participants, - Result>> &result) override; - int32_t Unshare(const std::string &sharingRes, const std::vector &participants, - Result>> &result) override; - int32_t ExitSharing(const std::string &sharingRes, Result &result) override; - int32_t ChangePrivilege(const std::string &sharingRes, const std::vector &participants, - Result>> &result) override; - int32_t QueryParticipants(const std::string &sharingRes, Result> &result) override; - int32_t QueryParticipantsByInvitation(const std::string &invitationCode, - Result> &result) override; - int32_t ConfirmInvitation(const std::string &invitationCode, Confirmation confirmation, - Result &result) override; + std::pair> AllocResourceAndShare(const std::string& storeId, + const DistributedRdb::PredicatesMemo& predicates, const std::vector& columns, + const Participants& participants) override; + int32_t Share(const std::string &sharingRes, const Participants &participants, Results &results) override; + int32_t Unshare(const std::string &sharingRes, const Participants &participants, Results &results) override; + int32_t Exit(const std::string &sharingRes, std::pair &result) override; + int32_t ChangePrivilege( + const std::string &sharingRes, const Participants &participants, Results &results) override; + int32_t Query(const std::string &sharingRes, QueryResults &results) override; + int32_t QueryByInvitation(const std::string &invitation, QueryResults &results) override; + int32_t ConfirmInvitation(const std::string &invitation, int32_t confirmation, + std::tuple &result) override; int32_t ChangeConfirmation( - const std::string &sharingRes, Confirmation confirmation, Result &result) override; + const std::string &sharingRes, int32_t confirmation, std::pair &result) override; private: using StaticActs = DistributedData::StaticActs; @@ -78,16 +80,38 @@ private: using CloudInfo = DistributedData::CloudInfo; using SchemaMeta = DistributedData::SchemaMeta; using Event = DistributedData::Event; + using CloudEvent = DistributedData::CloudEvent; using Subscription = DistributedData::Subscription; using Handle = bool (CloudServiceImpl::*)(int32_t); using Handles = std::deque; using Task = ExecutorPool::Task; + struct ExtraData final : public DistributedData::Serializable { + struct ExtInfo final : public Serializable { + std::string accountId; + std::string bundleName; + std::string containerName; + std::string recordTypes; + std::vector tables; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + std::string header; + std::string data; + ExtInfo extInfo; + bool Marshal(json &node) const override; + bool Unmarshal(const json &node) override; + }; + static std::map ConvertAction(const std::map &actions); + static std::pair GetHapInfo(uint32_t tokenId); static constexpr int32_t RETRY_TIMES = 3; static constexpr int32_t RETRY_INTERVAL = 60; static constexpr int32_t EXPIRE_INTERVAL = 2 * 24; // 2 day + static constexpr int32_t WAIT_TIME = 30; // 30 seconds + static constexpr int32_t DEFAULT_USER = 0; + static constexpr const char *DATA_CHANGE_EVENT_ID = "cloud_data_change"; struct HapInfo { int32_t user; std::string bundleName; @@ -95,19 +119,31 @@ private: bool UpdateCloudInfo(int32_t user); bool UpdateSchema(int32_t user); - SchemaMeta GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId); + bool DoSubscribe(int32_t user); + bool ReleaseUserInfo(int32_t user); + bool DoCloudSync(int32_t user); + bool StopCloudSync(int32_t user); + std::pair GetCloudInfo(int32_t userId); - int32_t GetCloudInfo(uint32_t tokenId, const std::string &id, CloudInfo &cloudInfo); - int32_t GetCloudInfoFromMeta(CloudInfo &cloudInfo); - int32_t GetCloudInfoFromServer(CloudInfo &cloudInfo); - int32_t GetAppSchema(int32_t user, const std::string &bundleName, SchemaMeta &schemaMeta); + std::pair GetCloudInfoFromMeta(int32_t userId); + std::pair GetCloudInfoFromServer(int32_t userId); + + std::pair GetSchemaMeta(int32_t userId, const std::string &bundleName, int32_t instanceId); + std::pair GetAppSchemaFromServer(int32_t user, const std::string &bundleName); + void GetSchema(const Event &event); + void CloudShare(const Event &event); + Task GenTask(int32_t retry, int32_t user, Handles handles = { WORK_SUB }); void Execute(Task task); void CleanSubscription(Subscription &sub); - bool DoSubscribe(int32_t user); - bool ReleaseUserInfo(int32_t user); int32_t DoClean(CloudInfo &cloudInfo, const std::map &actions); + std::pair> PreShare(const CloudEvent::StoreInfo& storeInfo, + DistributedData::GenQuery& query); + std::vector ConvertCursor(std::shared_ptr cursor) const; + int32_t CheckNotifyConditions(const std::string &id, const std::string &bundleName, CloudInfo &cloudInfo); + int32_t GetDbInfoFromExtraData(const ExtraData &exData, int32_t userId, std::string &storeId, + std::vector &table); std::pair, HapInfo> GetSharingHandle(); std::shared_ptr executor_; SyncManager syncManager_; @@ -116,6 +152,8 @@ private: static constexpr Handle WORK_SCHEMA_UPDATE = &CloudServiceImpl::UpdateSchema; static constexpr Handle WORK_SUB = &CloudServiceImpl::DoSubscribe; static constexpr Handle WORK_RELEASE = &CloudServiceImpl::ReleaseUserInfo; + static constexpr Handle WORK_DO_CLOUD_SYNC = &CloudServiceImpl::DoCloudSync; + static constexpr Handle WORK_STOP_CLOUD_SYNC = &CloudServiceImpl::StopCloudSync; }; } // namespace OHOS::DistributedData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp index 2390ac353cf98359e12bc4e28e19c90a82b3b241..ee9b71ad2e340ccf97e7b3feffe0fa80d5c3b15e 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.cpp @@ -19,6 +19,7 @@ #include "itypes_util.h" #include "log_print.h" #include "permission/permission_validator.h" +#include "rdb_types.h" #include "utils/anonymous.h" #include "tokenid_kit.h" namespace OHOS::CloudData { @@ -30,12 +31,14 @@ const CloudServiceStub::Handler CloudServiceStub::HANDLERS[TRANS_BUTT] = { &CloudServiceStub::OnChangeAppSwitch, &CloudServiceStub::OnClean, &CloudServiceStub::OnNotifyDataChange, + &CloudServiceStub::OnNotifyChange, + &CloudServiceStub::OnAllocResourceAndShare, &CloudServiceStub::OnShare, &CloudServiceStub::OnUnshare, - &CloudServiceStub::OnExitSharing, + &CloudServiceStub::OnExit, &CloudServiceStub::OnChangePrivilege, - &CloudServiceStub::OnQueryParticipants, - &CloudServiceStub::OnQueryParticipantsByInvitation, + &CloudServiceStub::OnQuery, + &CloudServiceStub::OnQueryByInvitation, &CloudServiceStub::OnConfirmInvitation, &CloudServiceStub::OnChangeConfirmation, }; @@ -61,7 +64,7 @@ int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } - if(code >= TRANS_HEAD && code < TRANS_SHARE) { + if (code >= TRANS_HEAD && code < TRANS_ALLOC_RESOURCE_AND_SHARE) { auto permit = DistributedKv::PermissionValidator::GetInstance().IsCloudConfigPermit(IPCSkeleton::GetCallingTokenID()); if (!permit) { @@ -71,12 +74,12 @@ int CloudServiceStub::OnRemoteRequest(uint32_t code, OHOS::MessageParcel &data, } } - std::string first; - if (!ITypesUtil::Unmarshal(data, first)) { - ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(first).c_str()); + std::string id; + if (!ITypesUtil::Unmarshal(data, id)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - return (this->*HANDLERS[code])(first, data, reply); + return (this->*HANDLERS[code])(id, data, reply); } int32_t CloudServiceStub::OnEnableCloud(const std::string &id, MessageParcel &data, MessageParcel &reply) @@ -130,86 +133,112 @@ int32_t CloudServiceStub::OnNotifyDataChange(const std::string &id, MessageParce return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnShare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnAllocResourceAndShare(const std::string& storeId, MessageParcel& data, + MessageParcel& reply) { + DistributedRdb::PredicatesMemo predicatesMemo; + std::vector columns; std::vector participants; + if (!ITypesUtil::Unmarshal(data, predicatesMemo, columns, participants)) { + ZLOGE("Unmarshal storeId:%{public}s", Anonymous::Change(storeId).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto [status, resultSet] = AllocResourceAndShare(storeId, predicatesMemo, columns, participants); + return ITypesUtil::Marshal(reply, status, resultSet) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t CloudServiceStub::OnNotifyChange(const std::string &id, MessageParcel &data, MessageParcel &reply) +{ + std::string extraData; + int32_t userId; + if (!ITypesUtil::Unmarshal(data, extraData, userId)) { + ZLOGE("Unmarshal id:%{public}s", Anonymous::Change(id).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + auto result = NotifyDataChange(id, extraData, userId); + return ITypesUtil::Marshal(reply, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; +} + +int32_t CloudServiceStub::OnShare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +{ + Participants participants; if (!ITypesUtil::Unmarshal(data, participants)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - Result>> result; - auto status = Share(sharingRes, participants, result); - return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; + Results results; + auto status = Share(sharingRes, participants, results); + return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } int32_t CloudServiceStub::OnUnshare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) { - std::vector participants; + Participants participants; if (!ITypesUtil::Unmarshal(data, participants)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - Result>> result; - auto status = Unshare(sharingRes, participants, result); - return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; + Results results; + auto status = Unshare(sharingRes, participants, results); + return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnExitSharing(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnExit(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) { - Result result; - auto status = ExitSharing(sharingRes, result); + std::pair result; + auto status = Exit(sharingRes, result); return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } int32_t CloudServiceStub::OnChangePrivilege(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) { - std::vector participants; + Participants participants; if (!ITypesUtil::Unmarshal(data, participants)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - Result>> result; - auto status = ChangePrivilege(sharingRes, participants, result); - return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; + Results results; + auto status = ChangePrivilege(sharingRes, participants, results); + return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnQueryParticipants(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnQuery(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) { - Result> result; - auto status = QueryParticipants(sharingRes, result); - return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; + QueryResults results; + auto status = Query(sharingRes, results); + return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } -int32_t CloudServiceStub::OnQueryParticipantsByInvitation( - const std::string &invitationCode, MessageParcel &data, MessageParcel &reply) +int32_t CloudServiceStub::OnQueryByInvitation( + const std::string &invitation, MessageParcel &data, MessageParcel &reply) { - Result> result; - auto status = QueryParticipantsByInvitation(invitationCode, result); - return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; + QueryResults results; + auto status = QueryByInvitation(invitation, results); + return ITypesUtil::Marshal(reply, status, results) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } int32_t CloudServiceStub::OnConfirmInvitation( - const std::string &invitationCode, MessageParcel &data, MessageParcel &reply) + const std::string &invitation, MessageParcel &data, MessageParcel &reply) { - Confirmation confirmation; + int32_t confirmation; if (!ITypesUtil::Unmarshal(data, confirmation)) { - ZLOGE("Unmarshal invitationCode:%{public}s", Anonymous::Change(invitationCode).c_str()); + ZLOGE("Unmarshal invitation:%{public}s", Anonymous::Change(invitation).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - Result result; - auto status = ConfirmInvitation(invitationCode, confirmation, result); + std::tuple result; + auto status = ConfirmInvitation(invitation, confirmation, result); return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } int32_t CloudServiceStub::OnChangeConfirmation( const std::string &sharingRes, MessageParcel &data, MessageParcel &reply) { - Confirmation confirmation; + int32_t confirmation; if (!ITypesUtil::Unmarshal(data, confirmation)) { ZLOGE("Unmarshal sharingRes:%{public}s", Anonymous::Change(sharingRes).c_str()); return IPC_STUB_INVALID_DATA_ERR; } - Result result; + std::pair result; auto status = ChangeConfirmation(sharingRes, confirmation, result); return ITypesUtil::Marshal(reply, status, result) ? ERR_NONE : IPC_STUB_WRITE_PARCEL_ERR; } diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h index 347db56f461da5359983c1dffbaafd0a358f68c0..0b5717ab8d14b9efe26d244f1aeffb3f978a2d62 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_service_stub.h @@ -31,15 +31,16 @@ private: int32_t OnChangeAppSwitch(const std::string &id, MessageParcel &data, MessageParcel &reply); int32_t OnClean(const std::string &id, MessageParcel &data, MessageParcel &reply); int32_t OnNotifyDataChange(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnNotifyChange(const std::string &id, MessageParcel &data, MessageParcel &reply); + int32_t OnAllocResourceAndShare(const std::string &storeId, MessageParcel &data, MessageParcel &reply); int32_t OnShare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); int32_t OnUnshare(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnExitSharing(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); + int32_t OnExit(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); int32_t OnChangePrivilege(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnQueryParticipants(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); - int32_t OnQueryParticipantsByInvitation( - const std::string &invitationCode, MessageParcel &data, MessageParcel &reply); - int32_t OnConfirmInvitation(const std::string &invitationCode, MessageParcel &data, MessageParcel &reply) ; + int32_t OnQuery(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); + int32_t OnQueryByInvitation(const std::string &invitation, MessageParcel &data, MessageParcel &reply); + int32_t OnConfirmInvitation(const std::string &invitation, MessageParcel &data, MessageParcel &reply); int32_t OnChangeConfirmation(const std::string &sharingRes, MessageParcel &data, MessageParcel &reply); static const Handler HANDLERS[TRANS_BUTT]; }; diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..12484fd057ea9fd02149ba10deb39f48cf3b212a --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cloud_types_util.h" + +namespace OHOS::ITypesUtil { +template<> +bool Marshalling(const Participant &input, MessageParcel &data) +{ + return ITypesUtil::Marshal( + data, input.identity, input.role, input.state, input.privilege, input.attachInfo); +} + +template<> +bool Unmarshalling(Participant &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal( + data, output.identity, output.role, output.state, output.privilege, output.attachInfo); +} + +template<> +bool Marshalling(const Privilege &input, MessageParcel &data) +{ + return ITypesUtil::Marshal(data, input.writable, input.readable, + input.creatable, input.deletable, input.shareable); +} + +template<> +bool Unmarshalling(Privilege &output, MessageParcel &data) +{ + return ITypesUtil::Unmarshal(data, output.writable, output.readable, + output.creatable, output.deletable, output.shareable); +} + +template<> +bool Marshalling(const Asset &input, MessageParcel &data) +{ + return Marshal(data, input.version, input.name, input.size, input.modifyTime, input.uri); +} +template<> +bool Unmarshalling(Asset &output, MessageParcel &data) +{ + return Unmarshal(data, output.version, output.name, output.size, output.modifyTime, output.uri); +} +template<> +bool Marshalling(const ValueObject &input, MessageParcel &data) +{ + return Marshal(data, input.value); +} +template<> +bool Unmarshalling(ValueObject &output, MessageParcel &data) +{ + return Unmarshal(data, output.value); +} +template<> +bool Marshalling(const ValuesBucket &input, MessageParcel &data) +{ + return Marshal(data, input.values_); +} +template<> +bool Unmarshalling(ValuesBucket &output, MessageParcel &data) +{ + return Unmarshal(data, output.values_); +} +} // namespace OHOS::ITypesUtil \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h new file mode 100644 index 0000000000000000000000000000000000000000..e70f487394c5471ec84a6d9fe07d441f3d2895c3 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_types_util.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H +#include "itypes_util.h" +#include "cloud_types.h" +#include "values_bucket.h" + +namespace OHOS::ITypesUtil { +using Participant = OHOS::CloudData::Participant; +using Privilege = OHOS::CloudData::Privilege; +using Role = OHOS::CloudData::Role; +using Confirmation = OHOS::CloudData::Confirmation; +using SharingCode = OHOS::CloudData::SharingCode; +using Asset = OHOS::NativeRdb::AssetValue; +using ValueObject = OHOS::NativeRdb::ValueObject; +using ValuesBucket = OHOS::NativeRdb::ValuesBucket; + +template<> +bool Marshalling(const Participant &input, MessageParcel &data); +template<> +bool Unmarshalling(Participant &output, MessageParcel &data); + +template<> +bool Marshalling(const Privilege &input, MessageParcel &data); +template<> +bool Unmarshalling(Privilege &output, MessageParcel &data); + +template<> +bool Marshalling(const Asset &input, MessageParcel &data); +template<> +bool Unmarshalling(Asset &output, MessageParcel &data); +template<> +bool Marshalling(const ValueObject &input, MessageParcel &data); +template<> +bool Unmarshalling(ValueObject &output, MessageParcel &data); +template<> +bool Marshalling(const ValuesBucket &input, MessageParcel &data); +template<> +bool Unmarshalling(ValuesBucket &output, MessageParcel &data); +} // namespace OHOS::ITypesUtil +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_TYPES_UTIL_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.cpp b/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b8579a38b6277b285bfbc6fcf1a32c3ef060003 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.cpp @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cloud_value_util.h" + +namespace OHOS::CloudData { +namespace SharingUtil { +SharingPlege Convert(const Privilege &privilege) +{ + SharingPlege result; + result.writable = privilege.writable; + result.readable = privilege.readable ; + result.creatable = privilege.creatable; + result.deletable = privilege.deletable; + result.shareable = privilege.shareable; + return result; +} + +SharingPtpant Convert(const Participant &participant) +{ + SharingPtpant result; + result.identity = participant.identity; + result.role = participant.role; + result.state = participant.state; + result.privilege = Convert(participant.privilege); + result.attachInfo = participant.attachInfo; + return result; +} + +SharingCfm Convert(const Confirmation &cfm) +{ + switch (cfm) { + case Confirmation::CFM_UNKNOWN: + return SharingCfm::CFM_UNKNOWN; + case Confirmation::CFM_ACCEPTED: + return SharingCfm::CFM_ACCEPTED; + case Confirmation::CFM_REJECTED: + return SharingCfm::CFM_REJECTED; + case Confirmation::CFM_SUSPENDED: + return SharingCfm::CFM_SUSPENDED; + default: + break; + } + return SharingCfm::CFM_UNKNOWN; +} + +Participant Convert(const SharingPtpant &participant) +{ + Participant result; + result.identity = participant.identity; + result.role = participant.role; + result.state = participant.state; + result.privilege = Convert(participant.privilege); + result.attachInfo = participant.attachInfo; + return result; +} + +Confirmation Convert(const SharingCfm &cfm) +{ + switch (cfm) { + case SharingCfm::CFM_UNKNOWN: + return Confirmation::CFM_UNKNOWN; + case SharingCfm::CFM_ACCEPTED: + return Confirmation::CFM_ACCEPTED; + case SharingCfm::CFM_REJECTED: + return Confirmation::CFM_REJECTED; + case SharingCfm::CFM_SUSPENDED: + return Confirmation::CFM_SUSPENDED; + default: + break; + } + return Confirmation::CFM_UNKNOWN; +} + +Privilege Convert(const SharingPlege &privilege) +{ + Privilege result; + result.writable = privilege.writable; + result.readable = privilege.readable ; + result.creatable = privilege.creatable; + result.deletable = privilege.deletable; + result.shareable = privilege.shareable; + return result; +} + +QueryResults Convert(const SharingResults &results) +{ + return { std::get<0>(results), std::get<1>(results), + Convert(std::get<2>(results)) }; +} + +std::vector Convert(const std::vector &participants) +{ + return Convert(participants); +} + +std::vector Convert(const std::vector &input) +{ + return Convert(input); +} + +template +std::vector Convert(const std::vector &data) +{ + std::vector out; + out.reserve(data.size()); + for (const auto &v : data) { + out.emplace_back(Convert(v)); + } + return out; +} + +SharingCode Convert(CenterCode code) +{ + switch (code) { + case CenterCode::IPC_ERROR: + return SharingCode::INNER_ERROR; + default: + break; + } + return SharingCode::SUCCESS; +} +} // namespace::SharingUtil +} // namespace OHOS::CloudData diff --git a/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.h b/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.h new file mode 100644 index 0000000000000000000000000000000000000000..ce099aae054abf06fb8a4698bd16ebbf167df277 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/cloud/cloud_value_util.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_VALUE_UTIL_H +#define OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_VALUE_UTIL_H + +#include "cloud_types.h" +#include "cloud/sharing_center.h" + +namespace OHOS::CloudData { +namespace SharingUtil { +using SharingPtpant = OHOS::DistributedData::SharingCenter::Participant; +using SharingPlege = OHOS::DistributedData::SharingCenter::Privilege; +using SharingCfm = OHOS::DistributedData::SharingCenter::Confirmation; +using SharingRole = OHOS::DistributedData::SharingCenter::Role; +using SharingResults = OHOS::DistributedData::SharingCenter::QueryResults; +using CenterCode = OHOS::DistributedData::SharingCenter::SharingCode; + +template +std::vector Convert(const std::vector &data); + +SharingPlege Convert(const Privilege &privilege); +SharingPtpant Convert(const Participant &participant); +SharingCfm Convert(const Confirmation &cfm); + +Privilege Convert(const SharingPlege &privilege); +Participant Convert(const SharingPtpant &participant); +Confirmation Convert(const SharingCfm &cfm); + +QueryResults Convert(const SharingResults &results); + +std::vector Convert(const std::vector &participants); + +std::vector Convert(const std::vector &input); + +SharingCode Convert(CenterCode code); +} // namespace SharingUtil +} // namespace OHOS::CloudData +#endif // OHOS_DISTRIBUTED_DATA_SERVICES_CLOUD_CLOUD_VALUE_UTIL_H diff --git a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp index 5ec0c5b94ef44dffbf9155150fc63552f7250f60..4dba478c09784bf54dc2a91915ee43a91ac761d3 100644 --- a/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/cloud/sync_manager.cpp @@ -15,6 +15,7 @@ #define LOG_TAG "SyncManager" #include "sync_manager.h" +#include "account/account_delegate.h" #include "cloud/cloud_info.h" #include "cloud/cloud_server.h" #include "cloud/schema_meta.h" @@ -27,6 +28,8 @@ #include "utils/anonymous.h" namespace OHOS::CloudData { using namespace DistributedData; +using namespace DistributedKv; +using Account = OHOS::DistributedKv::AccountDelegate; using DmAdapter = OHOS::DistributedData::DeviceManagerAdapter; using Defer = EventCenter::Defer; std::atomic SyncManager::genId_ = 0; @@ -146,12 +149,12 @@ int32_t SyncManager::DoCloudSync(SyncInfo syncInfo) if (executor_ == nullptr) { return E_NOT_INIT; } - - actives_.Compute(GenerateId(syncInfo.user_), [this, &syncInfo](const uint64_t &key, TaskId &taskId) mutable { - taskId = executor_->Execute(GetSyncTask(0, true, GenSyncRef(key), std::move(syncInfo))); + auto syncId = GenerateId(syncInfo.user_); + auto ref = GenSyncRef(syncId); + actives_.Compute(syncId, [this, &ref, &syncInfo](const uint64_t &key, TaskId &taskId) mutable { + taskId = executor_->Execute(GetSyncTask(0, true, ref, std::move(syncInfo))); return true; }); - return E_OK; } @@ -172,7 +175,7 @@ int32_t SyncManager::StopCloudSync(int32_t user) ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount ref, SyncInfo &&syncInfo) { times++; - return [this, times, retry, ref = std::move(ref), info = std::move(syncInfo)]() mutable { + return [this, times, retry, keep = std::move(ref), info = std::move(syncInfo)]() mutable { activeInfos_.Erase(info.syncId_); CloudInfo cloud; cloud.user = info.user_; @@ -189,7 +192,10 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount info.SetError(E_NETWORK_ERROR); return; } - + if (!Account::GetInstance()->IsVerified(info.user_)) { + info.SetError(E_USER_UNLOCK); + return; + } std::vector schemas; auto key = cloud.GetSchemaPrefix(info.bundleName_); auto retryer = GetRetryer(times, info); @@ -198,7 +204,6 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount retryer(RETRY_INTERVAL, E_RETRY_TIMEOUT); return; } - Defer defer(GetSyncHandler(std::move(retryer)), CloudEvent::CLOUD_SYNC); for (auto &schema : schemas) { if (!cloud.IsOn(schema.bundleName)) { @@ -208,11 +213,8 @@ ExecutorPool::Task SyncManager::GetSyncTask(int32_t times, bool retry, RefCount if (!info.Contains(database.name)) { continue; } - CloudEvent::StoreInfo storeInfo; - storeInfo.bundleName = schema.bundleName; - storeInfo.user = cloud.user; - storeInfo.storeName = database.name; - storeInfo.instanceId = cloud.apps[schema.bundleName].instanceId; + CloudEvent::StoreInfo storeInfo = { 0, schema.bundleName, database.name, + cloud.apps[schema.bundleName].instanceId, cloud.user }; auto query = info.GenerateQuery(database.name, database.GetTableNames()); auto evt = std::make_unique(std::move(storeInfo), SyncEvent::EventInfo { info.mode_, info.wait_, retry, std::move(query), info.async_ }); @@ -301,8 +303,9 @@ SyncManager::Retryer SyncManager::GetRetryer(int32_t times, const SyncInfo &sync activeInfos_.ComputeIfAbsent(info.syncId_, [this, times, interval, &info](uint64_t key) mutable { auto syncId = GenerateId(info.user_); - actives_.Compute(syncId, [this, times, interval, &info](const uint64_t &key, TaskId &value) mutable { - value = executor_->Schedule(interval, GetSyncTask(times, true, GenSyncRef(key), std::move(info))); + auto ref = GenSyncRef(syncId); + actives_.Compute(syncId, [this, times, interval, &ref, &info](const uint64_t &key, TaskId &value) mutable { + value = executor_->Schedule(interval, GetSyncTask(times, true, ref, std::move(info))); return true; }); return syncId; @@ -340,6 +343,10 @@ void SyncManager::UpdateSchema(const SyncManager::SyncInfo &syncInfo) AutoCache::Store SyncManager::GetStore(const StoreMetaData &meta, int32_t user, bool mustBind) { + if (!Account::GetInstance()->IsVerified(user)) { + ZLOGW("user:%{public}d is locked!", user); + return nullptr; + } auto instance = CloudServer::GetInstance(); if (instance == nullptr) { ZLOGD("not support cloud sync"); diff --git a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp index d65d8f87f92087f471e4ea4c2bba18ca3551ebfc..efae1f74021f7e3a25708e667da67b71c90c2f3e 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/common/scheduler_manager.cpp @@ -16,6 +16,8 @@ #include "scheduler_manager.h" +#include + #include "log_print.h" #include "uri_utils.h" #include "utils/anonymous.h" diff --git a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp index 861f878507f1a4cb7088f22fa165a2312448ee9b..f9695e25887218eb4943a0f3007a21b4eac83252 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/data_share_service_impl.cpp @@ -183,7 +183,7 @@ std::vector DataShareServiceImpl::Publish(const Data &data, con context->calledBundleName = bundleNameOfProvider; int32_t result = publishStrategy_.Execute(context, item); results.emplace_back(item.key_, result); - if (result != EOK) { + if (result != E_OK) { ZLOGE("publish error, key is %{public}s", DistributedData::Anonymous::Change(item.key_).c_str()); continue; } @@ -435,7 +435,7 @@ int32_t DataShareServiceImpl::OnBind(const BindInfo &binderInfo) KvDBDelegate::GetInstance(false, saveMeta.dataDir, binderInfo.executors); SchedulerManager::GetInstance().SetExecutorPool(binderInfo.executors); SubscribeTimeChanged(); - return EOK; + return E_OK; } void DataShareServiceImpl::OnConnectDone() @@ -456,7 +456,7 @@ int32_t DataShareServiceImpl::DataShareStatic::OnAppUninstall(const std::string PublishedData::ClearAging(); TemplateData::Delete(bundleName, user); RdbHelper::ClearCache(); - return EOK; + return E_OK; } int32_t DataShareServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, const std::string &bundleName) @@ -465,7 +465,7 @@ int32_t DataShareServiceImpl::OnAppExit(pid_t uid, pid_t pid, uint32_t tokenId, uid, pid, tokenId, bundleName.c_str()); RdbSubscriberManager::GetInstance().Delete(tokenId); PublishedDataSubscriberManager::GetInstance().Delete(tokenId); - return EOK; + return E_OK; } void DataShareServiceImpl::NotifyObserver(const std::string &uri) diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp index a2ad08c8ca57da620302dced521b4d39e227b6f6..4b4f62e6b58fc0d81dbda50da0683da7a9608480 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/published_data_subscriber_manager.cpp @@ -16,6 +16,8 @@ #include "published_data_subscriber_manager.h" +#include + #include "ipc_skeleton.h" #include "general/load_config_data_info_strategy.h" #include "log_print.h" diff --git a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp index 10411c55229d35cabf2e5e2985ae5b9736c30036..07e69cf7e3788ba114aa74a0c213d125e9986037 100644 --- a/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/data_share/subscriber_managers/rdb_subscriber_manager.cpp @@ -16,6 +16,8 @@ #include "rdb_subscriber_manager.h" +#include + #include "ipc_skeleton.h" #include "general/load_config_data_info_strategy.h" #include "log_print.h" @@ -152,7 +154,7 @@ int RdbSubscriberManager::Delete(const Key &key, uint32_t firstCallerTokenId) it++; } } - if (GetEnableObserverCount(key) == 0) { + if (value.empty()) { SchedulerManager::GetInstance().RemoveTimer(key); } return !value.empty(); @@ -172,7 +174,7 @@ void RdbSubscriberManager::Delete(uint32_t callerTokenId) it++; } } - if (GetEnableObserverCount(key) == 0) { + if (value.empty()) { SchedulerManager::GetInstance().RemoveTimer(key); } return value.empty(); diff --git a/datamgr_service/services/distributeddataservice/service/dumper/include/dump_helper.h b/datamgr_service/services/distributeddataservice/service/dumper/include/dump_helper.h index 6eadb2b4e2e1fc59a34a6da60586c151fb55f14b..df777c619a7f6a01ec563c4ea2fb419ccf645003 100644 --- a/datamgr_service/services/distributeddataservice/service/dumper/include/dump_helper.h +++ b/datamgr_service/services/distributeddataservice/service/dumper/include/dump_helper.h @@ -35,8 +35,8 @@ public: struct CommandNode { std::string dumpName; std::vector param; - int minParamsNum = 0; - int maxParamsNum = 0; + uint32_t minParamsNum = 0; + uint32_t maxParamsNum = 0; std::string parentNode; std::string childNode; std::vector handlers; @@ -64,7 +64,7 @@ private: void AddHeadNode(std::shared_ptr &command, std::shared_ptr &realHeadNode, bool &isAdded); void AddNode(std::shared_ptr &command, std::shared_ptr &realHeadNode, bool &isAdded); void ParseCommand(const std::vector &args, std::vector> &filterInfo); - int GetFormatMaxSize(); + uint32_t GetFormatMaxSize(); void RegisterErrorInfo(); void DumpErrorInfo(int fd, std::map> ¶ms); @@ -74,7 +74,7 @@ private: void DumpAllInfo(int fd, std::map> ¶ms); std::string FormatHelpInfo(const std::string &cmdAbbr, const std::string &cmd, const std::string ¶Ext, - const std::string &info, int &formatMaxSize); + const std::string &info, uint32_t &formatMaxSize); mutable std::mutex hidumperMutex_; static constexpr int32_t MAX_FILTER_COUNT = 3; static constexpr int32_t MAX_RECORED_ERROR = 10; diff --git a/datamgr_service/services/distributeddataservice/service/dumper/src/dump_helper.cpp b/datamgr_service/services/distributeddataservice/service/dumper/src/dump_helper.cpp index 01a3e1408224c9de49bdcc6524572fa238fe7b44..092d5b85e064cd3e8961cc50e0b3102ed47646c3 100644 --- a/datamgr_service/services/distributeddataservice/service/dumper/src/dump_helper.cpp +++ b/datamgr_service/services/distributeddataservice/service/dumper/src/dump_helper.cpp @@ -50,13 +50,13 @@ bool DumpHelper::Dump(int fd, const std::vector &args) GetCommandNodes(fd, commands); if (!(commands.empty())) { std::shared_ptr tmpCommandNode; - for (auto& command : commands) { + for (auto const &command : commands) { std::map> params; tmpCommandNode = command; while (tmpCommandNode != nullptr) { params.emplace(tmpCommandNode->dumpName, tmpCommandNode->param); if (tmpCommandNode->nextNode == nullptr) { - for (auto& handler : tmpCommandNode->handlers) { + for (auto const &handler : tmpCommandNode->handlers) { handler(fd, params); } } @@ -125,18 +125,14 @@ DumpHelper::CommandNode DumpHelper::GetCommand(const std::string &name) void DumpHelper::GetCommandNodes(int fd, std::vector> &commands) { - for (auto i = 0; i < commands.size();) { + for (uint32_t i = 1; i < commands.size();) { bool isAdded = false; - if (i == 0) { - i++; - continue; - } if (commands[i]->parentNode.empty()) { - for (auto j = 0; j < i; j++) { + for (uint32_t j = 0; j < i; j++) { AddHeadNode(commands[i], commands[j], isAdded); } } else { - for (auto j = 0; j < i; j++) { + for (uint32_t j = 0; j < i; j++) { AddNode(commands[i], commands[j], isAdded); } } @@ -205,7 +201,7 @@ void DumpHelper::DumpErrorInfo(int fd, std::map dumpCaption = { "| Display all the user statistics\n", "| Display the user statistics by " - "UserId\n" }; DumpManager::GetInstance().AddConfig(helpInfoConfig.dumpName, helpInfoConfig); } void DumpHelper::DumpHelpInfo(int fd, std::map> ¶ms) { std::string info; - int formatMaxSize = GetFormatMaxSize(); + uint32_t formatMaxSize = GetFormatMaxSize(); auto dumpFactory = DumpManager::GetInstance().LoadConfig(); dumpFactory.ForEach([this, &info, &formatMaxSize](const auto &key, auto &value) { if (key == "ALL_INFO") { @@ -308,7 +302,7 @@ void DumpHelper::AddErrorInfo(int32_t errorCode, const std::string &errorInfo) error.errorCode = errorCode; error.errorInfo = errorInfo; auto now = std::chrono::system_clock::now(); - uint64_t millSeconds = std::chrono::duration_cast(now.time_since_epoch()).count() - + int64_t millSeconds = std::chrono::duration_cast(now.time_since_epoch()).count() - (std::chrono::duration_cast(now.time_since_epoch()).count() * 1000); time_t tt = std::chrono::system_clock::to_time_t(now); auto ptm = localtime(&tt); diff --git a/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp b/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp index a911a5f8d3bd7362782a421c331c4a17d7fca20b..9f46f2fe85452915e60da0694c7b7cac6a0bae47 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/object/object_manager.cpp @@ -23,10 +23,16 @@ #include "kvstore_utils.h" #include "log_print.h" #include "object_data_listener.h" +#include "metadata/meta_data_manager.h" +#include "metadata/store_meta_data.h" +#include "account/account_delegate.h" namespace OHOS { namespace DistributedObject { using namespace OHOS::DistributedKv; +using StoreMetaData = OHOS::DistributedData::StoreMetaData; +using AccountDelegate = DistributedKv::AccountDelegate; + ObjectStoreManager::ObjectStoreManager() {} DistributedDB::KvStoreNbDelegate *ObjectStoreManager::OpenObjectKvStore() @@ -97,6 +103,7 @@ int32_t ObjectStoreManager::Save(const std::string &appId, const std::string &se } ZLOGD("start SaveToStore"); + SaveUserToMeta(); result = SaveToStore(appId, sessionId, deviceId, data); if (result != OBJECT_SUCCESS) { ZLOGE("Save to store failed, please check DB errCode, errCode = %{public}d", result); @@ -194,6 +201,29 @@ int32_t ObjectStoreManager::Retrieve( int32_t ObjectStoreManager::Clear() { ZLOGI("enter"); + std::string userId = GetCurrentUser(); + if (userId.empty()) { + return OBJECT_INNER_ERROR; + } + std::vector metaData; + std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + std::string metaKey = GetMetaUserIdKey(userId, appId); + if (!DistributedData::MetaDataManager::GetInstance().LoadMeta(metaKey, metaData, true)) { + ZLOGE("no store of %{public}s", appId.c_str()); + return OBJECT_STORE_NOT_FOUND; + } + for (const auto &storeMeta : metaData) { + if (storeMeta.storeType < StoreMetaData::StoreType::STORE_OBJECT_BEGIN + || storeMeta.storeType > StoreMetaData::StoreType::STORE_OBJECT_END) { + continue; + } + if (storeMeta.user == userId) { + ZLOGI("user is same, not need to change, mate user:%{public}s::user:%{public}s.", + storeMeta.user.c_str(), userId.c_str()); + return OBJECT_SUCCESS; + } + } + ZLOGD("user is change, need to change"); int32_t result = Open(); if (result != OBJECT_SUCCESS) { ZLOGE("Open objectStore DB failed,please check DB status"); @@ -217,6 +247,13 @@ int32_t ObjectStoreManager::DeleteByAppId(const std::string &appId) ZLOGE("RevokeSaveToStore failed"); } Close(); + + std::string userId = GetCurrentUser(); + if (userId.empty()) { + return OBJECT_INNER_ERROR; + } + std::string metaKey = GetMetaUserIdKey(userId, appId); + DistributedData::MetaDataManager::GetInstance().DelMeta(metaKey, true); return result; } @@ -269,6 +306,7 @@ void ObjectStoreManager::UnregisterRemoteCallback(const std::string &bundleName, void ObjectStoreManager::NotifyChange(std::map> &changedData) { ZLOGD("ObjectStoreManager::NotifyChange start"); + SaveUserToMeta(); std::map>> data; for (const auto &item : changedData) { std::string prefix = GetBundleName(item.first) + GetSessionId(item.first); @@ -529,6 +567,34 @@ void ObjectStoreManager::ProcessKeyByIndex(std::string &key, uint8_t index) i++; } while (i < index); } +std::string ObjectStoreManager::GetCurrentUser() +{ + std::vector users; + AccountDelegate::GetInstance()->QueryUsers(users); + if (users.empty()) { + return ""; + } + return std::to_string(users[0]); +} + +void ObjectStoreManager::SaveUserToMeta() +{ + ZLOGD("start."); + std::string userId = GetCurrentUser(); + if (userId.empty()) { + return; + } + std::string appId = DistributedData::Bootstrap::GetInstance().GetProcessLabel(); + StoreMetaData userMeta; + userMeta.storeId = DistributedObject::ObjectCommon::OBJECTSTORE_DB_STOREID; + userMeta.user = userId; + userMeta.storeType = ObjectDistributedType::OBJECT_SINGLE_VERSION; + std::string userMetaKey = GetMetaUserIdKey(userId, appId); + auto saved = DistributedData::MetaDataManager::GetInstance().SaveMeta(userMetaKey, userMeta, true); + if (!saved) { + ZLOGE("userMeta save failed"); + } +} std::string ObjectStoreManager::GetPropertyName(const std::string &key) { diff --git a/datamgr_service/services/distributeddataservice/service/object/object_manager.h b/datamgr_service/services/distributeddataservice/service/object/object_manager.h index d3d924def8660977b38927d9256b76913ba4fc46..7cd1a992c4fe79d0a9453f79cd2fa3fac34e2ce0 100644 --- a/datamgr_service/services/distributeddataservice/service/object/object_manager.h +++ b/datamgr_service/services/distributeddataservice/service/object/object_manager.h @@ -95,6 +95,7 @@ public: private: constexpr static const char *SEPERATOR = "_"; constexpr static const char *LOCAL_DEVICE = "local"; + constexpr static const char *USERID = "USERID"; constexpr static int8_t MAX_OBJECT_SIZE_PER_APP = 16; constexpr static int8_t DECIMAL_BASE = 10; struct CallbackInfo { @@ -127,6 +128,8 @@ private: void ProcessOldEntry(const std::string &appId); void ProcessSyncCallback(const std::map &results, const std::string &appId, const std::string &sessionId, const std::string &deviceId); + void SaveUserToMeta(); + std::string GetCurrentUser(); inline std::string GetPropertyPrefix(const std::string &appId, const std::string &sessionId) { return appId + SEPERATOR + sessionId + SEPERATOR + DmAdaper::GetInstance().GetLocalDevice().udid + SEPERATOR; @@ -141,6 +144,11 @@ private: { return appId + SEPERATOR + sessionId + SEPERATOR; }; + inline std::string GetMetaUserIdKey(const std::string &userId, const std::string &appId) + { + return std::string(USERID) + SEPERATOR + userId + SEPERATOR + appId + SEPERATOR + + DmAdaper::GetInstance().GetLocalDevice().udid; + }; std::recursive_mutex kvStoreMutex_; std::mutex mutex_; DistributedDB::KvStoreDelegateManager *kvStoreDelegateManager_ = nullptr; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1bbdcf07d14f24e7d42092c36c2a33e01c6b6937 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cache_cursor.h" +#include "value_proxy.h" + +namespace OHOS::DistributedRdb { +using namespace OHOS::DistributedData; + +CacheCursor::CacheCursor(std::vector &&records) + : row_(0), maxCol_(0), records_(std::move(records)) +{ + maxRow_ = records_.size(); + if (maxRow_ > 0) { + for (auto it = records_[0].begin(); it != records_[0].end(); it++) { + colNames_.push_back(it->first); + colTypes_.push_back(it->second.index()); + } + maxCol_ = colNames_.size(); + } +} + +int32_t CacheCursor::GetColumnNames(std::vector &names) const +{ + names = colNames_; + return GeneralError::E_OK; +} + + +int32_t CacheCursor::GetColumnName(int32_t col, std::string &name) const +{ + if (col < 0 || col >= maxCol_) { + return GeneralError::E_INVALID_ARGS; + } + name = colNames_[col]; + return GeneralError::E_OK; +} + +int32_t CacheCursor::GetColumnType(int32_t col) const +{ + if (col < 0 || col >= maxCol_) { + return DistributedDB::ResultSet::ColumnType::INVALID_TYPE; + } + return colTypes_[col]; +} + +int32_t CacheCursor::GetCount() const +{ + return maxRow_; +} + +int32_t CacheCursor::MoveToFirst() +{ + row_ = 0; + return GeneralError::E_OK; +} + +int32_t CacheCursor::MoveToNext() +{ + auto row = row_; + if (row >= maxRow_ - 1) { + return GeneralError::E_ERROR; + } + row++; + row_ = row; + return GeneralError::E_OK; +} + +int32_t CacheCursor::MoveToPrev() +{ + return GeneralError::E_NOT_SUPPORT; +} + +int32_t CacheCursor::GetEntry(DistributedData::VBucket &entry) +{ + return GetRow(entry); +} + +int32_t CacheCursor::GetRow(DistributedData::VBucket &data) +{ + auto row = row_; + if (row >= maxRow_) { + return GeneralError::E_RECODE_LIMIT_EXCEEDED; + } + data = records_[row]; + return GeneralError::E_OK; +} + +int32_t CacheCursor::Get(int32_t col, DistributedData::Value &value) +{ + if (col < 0 || col >= maxCol_) { + return GeneralError::E_INVALID_ARGS; + } + return Get(colNames_[col], value); +} + +int32_t CacheCursor::Get(const std::string &col, DistributedData::Value &value) +{ + auto row = row_; + if (row >= maxRow_) { + return GeneralError::E_RECODE_LIMIT_EXCEEDED; + } + auto it = records_[row].find(col); + if (it == records_[row].end()) { + return GeneralError::E_INVALID_ARGS; + } + value = it->second; + return GeneralError::E_OK; +} + +int32_t CacheCursor::Close() +{ + return GeneralError::E_OK; +} + +bool CacheCursor::IsEnd() +{ + return false; +} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.h b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.h new file mode 100644 index 0000000000000000000000000000000000000000..d18607a055823856f341f0fd06e4616030e38211 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/rdb/cache_cursor.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_CACHE_CURSOR_H +#define OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_CACHE_CURSOR_H +#include "store/cursor.h" + +namespace OHOS::DistributedRdb { +class CacheCursor : public DistributedData::Cursor { +public: + explicit CacheCursor(std::vector &&records); + ~CacheCursor() = default; + int32_t GetColumnNames(std::vector &names) const override; + int32_t GetColumnName(int32_t col, std::string &name) const override; + int32_t GetColumnType(int32_t col) const override; + int32_t GetCount() const override; + int32_t MoveToFirst() override; + int32_t MoveToNext() override; + int32_t MoveToPrev() override; + int32_t GetEntry(DistributedData::VBucket &entry) override; + int32_t GetRow(DistributedData::VBucket &data) override; + int32_t Get(int32_t col, DistributedData::Value &value) override; + int32_t Get(const std::string &col, DistributedData::Value &value) override; + int32_t Close() override; + bool IsEnd() override; + +private: + int32_t row_; + int32_t maxRow_; + int32_t maxCol_; + std::vector records_; + std::vector colNames_; + std::vector colTypes_; +}; +} // namespace OHOS::DistributedRdb +#endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_CACHE_CURSOR_H + diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp index 5612e8a9bafcf02a07d8329588185cd9960ad1b5..977856748e53bbdc75627c7864dcfea33cf160fc 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.cpp @@ -39,4 +39,11 @@ DBStatus RdbAssetLoader::Download(const std::string &tableName, const std::strin } return RdbCloud::ConvertStatus(static_cast(error)); } + +DBStatus RdbAssetLoader::RemoveLocalAssets(const std::vector &assets) +{ + DistributedData::VBucket deleteAssets = ValueProxy::Convert(std::map{{ "", assets }}); + auto error = assetLoader_->RemoveLocalAssets("", "", {}, deleteAssets); + return RdbCloud::ConvertStatus(static_cast(error)); +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h index 0197afbf918a03959532e35e23a0aec3de34fe18..a7ffb15309f41bc71ce0711041c5d983c4782aa5 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_asset_loader.h @@ -34,9 +34,9 @@ public: DBStatus Download(const std::string &tableName, const std::string &gid, const Type &prefix, std::map> &assets) override; -private: - DBStatus ConvertStatus(DistributedData::GeneralError error); + DBStatus RemoveLocalAssets(const std::vector &assets) override; +private: std::shared_ptr assetLoader_; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp index 61144f095ab752ea1686aa6bc4db4a42a1cc1b13..ea9180e98cf8c14e502e4ce69b1d74763314fe5a 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.cpp @@ -94,6 +94,11 @@ DBStatus RdbCloud::Query(const std::string &tableName, DBVBucket &extend, std::v return ConvertStatus(static_cast(err)); } +DistributedData::GeneralError RdbCloud::PreSharing(const std::string& tableName, VBuckets& extend) +{ + return static_cast(cloudDB_->PreSharing(tableName, extend)); +} + std::pair RdbCloud::Lock() { auto error = cloudDB_->Lock(); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h index dbe0563d5474f1dbc95a149a1946aa8395f1ff37..121eb837be87024cf8329f4e6092527190897cc5 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud.h @@ -35,6 +35,7 @@ public: std::vector &extend) override; DBStatus BatchDelete(const std::string &tableName, std::vector &extend) override; DBStatus Query(const std::string &tableName, DBVBucket &extend, std::vector &data) override; + DistributedData::GeneralError PreSharing(const std::string &tableName, DistributedData::VBuckets &extend); std::pair Lock() override; DBStatus UnLock() override; DBStatus HeartBeat() override; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp index 15b2868ce1d21caf210b994d623286a9c5c22adc..e4bedeacb559525f24101714d58b68348bfdf70e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_cloud_data_translate.cpp @@ -28,7 +28,7 @@ std::vector RdbCloudDataTranslate::AssetToBlob(const Asset &asset) std::vector rawData; Asset dbAsset = asset; dbAsset.flag = static_cast(DistributedDB::AssetOpType::NO_CHANGE); - DataAsset dataAsset = ValueProxy::Asset(std::move(dbAsset)); + DataAsset dataAsset = ValueProxy::TempAsset(std::move(dbAsset)); InnerAsset innerAsset(dataAsset); auto data = Serializable::Marshall(innerAsset); auto size = DistributedData::HostToNet((uint16_t)data.length()); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp index cc2b54c20ff7c7d6d177408913bef0dce2c2769f..47bb3963bd6fc50e291abc76408a257fd75ee14b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.cpp @@ -14,9 +14,11 @@ */ #define LOG_TAG "RdbGeneralStore" #include "rdb_general_store.h" +#include "cache_cursor.h" #include "cloud_service.h" #include "cloud/asset_loader.h" #include "cloud/cloud_db.h" +#include "cloud/cloud_store_types.h" #include "cloud/schema_meta.h" #include "crypto_manager.h" #include "log_print.h" @@ -62,6 +64,11 @@ RdbGeneralStore::RdbGeneralStore(const StoreMetaData &meta) : manager_(meta.appI } option.observer = &observer_; manager_.OpenStore(meta.dataDir, meta.storeId, option, delegate_); + if (delegate_ != nullptr && meta.isManualClean) { + PragmaData data = + static_cast(const_cast(static_cast(&meta.isManualClean))); + delegate_->Pragma(PragmaCmd::LOGIC_DELETE_SYNC_DATA, data); + } } RdbGeneralStore::~RdbGeneralStore() @@ -96,6 +103,7 @@ int32_t RdbGeneralStore::Bind(const Database &database, BindInfo bindInfo) const Table &table = database.tables[i]; DBTable &dbTable = schema.tables[i]; dbTable.name = table.name; + dbTable.sharedTableName = table.sharedTableName; for (auto &field : table.fields) { DBField dbField; dbField.colName = field.colName; @@ -166,9 +174,16 @@ int32_t RdbGeneralStore::Delete(const std::string &table, const std::string &sql return 0; } -std::shared_ptr RdbGeneralStore::Query(const std::string &table, const std::string &sql, Values &&args) +std::shared_ptr RdbGeneralStore::Query(__attribute__((unused))const std::string &table, + const std::string &sql, Values &&args) { - return std::shared_ptr(); + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("database already closed!"); + return nullptr; + } + std::vector records = ExecuteSql(sql, std::move(args)); + return std::make_shared(std::move(records)); } std::shared_ptr RdbGeneralStore::Query(const std::string &table, GenQuery &query) @@ -219,11 +234,84 @@ int32_t RdbGeneralStore::Sync(const Devices &devices, int32_t mode, GenQuery &qu ? delegate_->Sync(devices, dbMode, dbQuery, GetDBBriefCB(std::move(async)), wait != 0) : (syncMode > NEARBY_END && syncMode < CLOUD_END) ? delegate_->Sync({ devices, dbMode, dbQuery, wait, isPriority }, GetDBProcessCB(std::move(async), - GetHighMode(mode))) + GetHighMode(static_cast(mode)))) : DistributedDB::INVALID_ARGS; return status == DistributedDB::OK ? GeneralError::E_OK : GeneralError::E_ERROR; } +std::shared_ptr RdbGeneralStore::PreSharing(GenQuery& query) +{ + RdbQuery* rdbQuery = nullptr; + auto ret = query.QueryInterface(rdbQuery); + if (ret != GeneralError::E_OK || rdbQuery == nullptr) { + ZLOGE("not RdbQuery!"); + return nullptr; + } + auto tables = rdbQuery->GetTables(); + auto statement = rdbQuery->GetStatement(); + if (statement.empty() || tables.empty()) { + ZLOGE("statement size:%{public}zu, tables size:%{public}zu", statement.size(), tables.size()); + return nullptr; + } + std::string sql = BuildSql(*tables.begin(), statement, rdbQuery->GetColumns()); + VBuckets values; + { + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("database already closed!"); + return nullptr; + } + values = ExecuteSql(sql, rdbQuery->GetBindArgs()); + } + if (rdbCloud_ == nullptr || values.empty()) { + ZLOGE("rdbCloud is nullptr:%{public}d, values size:%{public}zu", rdbCloud_ == nullptr, values.size()); + return nullptr; + } + VBuckets extends = ExtractExtend(values); + rdbCloud_->PreSharing(*tables.begin(), extends); + for (auto value = values.begin(), extend = extends.begin(); value != values.end() && extend != extends.end(); + ++value, ++extend) { + value->insert_or_assign(DistributedRdb::Field::SHARING_RESOURCE_FIELD, (*extend)[SchemaMeta::SHARING_RESOURCE]); + value->erase(CLOUD_GID); + } + return std::make_shared(std::move(values)); +} + +VBuckets RdbGeneralStore::ExtractExtend(VBuckets& values) const +{ + VBuckets extends(values.size()); + for (auto value = values.begin(), extend = extends.begin(); value != values.end() && extend != extends.end(); + ++value, ++extend) { + auto it = value->find(CLOUD_GID); + if (it == value->end()) { + continue; + } + auto gid = std::get_if(&(it->second)); + if (gid == nullptr || gid->empty()) { + continue; + } + extend->insert_or_assign(SchemaMeta::GID_FIELD, std::move(*gid)); + } + return extends; +} + +std::string RdbGeneralStore::BuildSql(const std::string& table, const std::string& statement, + const std::vector& columns) const +{ + std::string sql = "select "; + sql.append(CLOUD_GID); + std::string sqlNode = "select rowid"; + for (auto& column : columns) { + sql.append(", ").append(column); + sqlNode.append(", ").append(column); + } + sqlNode.append(" from ").append(table).append(statement); + auto logTable = RelationalStoreManager::GetDistributedLogTableName(table); + sql.append(" from ").append(logTable).append(", (").append(sqlNode); + sql.append(") where ").append(DATE_KEY).append(" = rowid"); + return sql; +} + int32_t RdbGeneralStore::Clean(const std::vector &devices, int32_t mode, const std::string &tableName) { if (mode < 0 || mode > CLEAN_MODE_BUTT) { @@ -241,9 +329,19 @@ int32_t RdbGeneralStore::Clean(const std::vector &devices, int32_t switch (mode) { case CLOUD_INFO: status = delegate_->RemoveDeviceData("", static_cast(CLOUD_INFO)); + if (status == DistributedDB::OK) { + status = delegate_->RemoveDeviceData("", ClearMode::CLEAR_SHARED_TABLE); + break; + } + (void)delegate_->RemoveDeviceData("", ClearMode::CLEAR_SHARED_TABLE); break; case CLOUD_DATA: status = delegate_->RemoveDeviceData("", static_cast(CLOUD_DATA)); + if (status == DistributedDB::OK) { + status = delegate_->RemoveDeviceData("", ClearMode::CLEAR_SHARED_TABLE); + break; + } + (void)delegate_->RemoveDeviceData("", ClearMode::CLEAR_SHARED_TABLE); break; case NEARBY_DATA: if (devices.empty()) { @@ -301,7 +399,7 @@ RdbGeneralStore::DBBriefCB RdbGeneralStore::GetDBBriefCB(DetailAsync async) }; } -RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, int32_t highMode) +RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, uint32_t highMode) { if (!async && (highMode == MANUAL_SYNC_MODE || !async_)) { return [](auto&) {}; @@ -328,7 +426,7 @@ RdbGeneralStore::DBProcessCB RdbGeneralStore::GetDBProcessCB(DetailAsync async, if (async) { async(details); } - + if (highMode == AUTO_SYNC_MODE && autoAsync) { autoAsync(details); } @@ -361,7 +459,8 @@ int32_t RdbGeneralStore::AddRef() return ++ref_; } -int32_t RdbGeneralStore::SetDistributedTables(const std::vector &tables, int32_t type) +int32_t RdbGeneralStore::SetDistributedTables(const std::vector &tables, int32_t type, + const std::vector &references) { std::shared_lock lock(rwMutex_); if (delegate_ == nullptr) { @@ -377,6 +476,33 @@ int32_t RdbGeneralStore::SetDistributedTables(const std::vector &ta return GeneralError::E_ERROR; } } + std::vector properties; + for (const auto &reference : references) { + DistributedDB::TableReferenceProperty referenceProperty = + { reference.sourceTable, reference.targetTable, reference.refFields }; + properties.emplace_back(referenceProperty); + } + auto status = delegate_->SetReference(properties); + if (status != DistributedDB::DBStatus::OK) { + ZLOGE("distributed table set reference failed, err:%{public}d", status); + return GeneralError::E_ERROR; + } + return GeneralError::E_OK; +} + +int32_t RdbGeneralStore::SetTrackerTable(const std::string& tableName, const std::set& trackerColNames, + const std::string& extendColName) +{ + std::shared_lock lock(rwMutex_); + if (delegate_ == nullptr) { + ZLOGE("database already closed! tables name:%{public}s", tableName.c_str()); + return GeneralError::E_ALREADY_CLOSED; + } + auto status = delegate_->SetTrackerTable({ tableName, extendColName, trackerColNames }); + if (status != DBStatus::OK) { + ZLOGE("Set tracker table failed! ret:%{public}d", status); + return GeneralError::E_ERROR; + } return GeneralError::E_OK; } @@ -431,6 +557,19 @@ int32_t RdbGeneralStore::UnregisterDetailProgressObserver() return GenErr::E_OK; } +VBuckets RdbGeneralStore::ExecuteSql(const std::string& sql, Values &&args) +{ + std::vector changedData; + std::vector bindArgs = ValueProxy::Convert(std::move(args)); + auto status = delegate_->ExecuteSql({ sql, std::move(bindArgs) }, changedData); + if (status != DBStatus::OK) { + ZLOGE("Failed! ret:%{public}d, sql:%{public}s, data size:%{public}zu", status, Anonymous::Change(sql).c_str(), + changedData.size()); + return {}; + } + return ValueProxy::Convert(std::move(changedData)); +} + void RdbGeneralStore::ObserverProxy::OnChange(const DBChangedIF &data) { if (!HasWatcher()) { @@ -480,4 +619,4 @@ void RdbGeneralStore::ObserverProxy::OnChange(DBOrigin origin, const std::string } watcher_->OnChange(genOrigin, fields, std::move(changeInfo)); } -} // namespace OHOS::DistributedRdb +} // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h index 5a8ea4b468f04ea5c5e7a1dc13998836d523934d..d1c9a69574d450df59a9b84fb57766b63a17290b 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_general_store.h @@ -40,6 +40,7 @@ public: using Database = DistributedData::Database; using GenErr = DistributedData::GeneralError; using RdbStore = OHOS::NativeRdb::RdbStore; + using Reference = DistributedData::Reference; explicit RdbGeneralStore(const StoreMetaData &meta); ~RdbGeneralStore(); @@ -47,13 +48,17 @@ public: bool IsBound() override; bool IsValid(); int32_t Execute(const std::string &table, const std::string &sql) override; - int32_t SetDistributedTables(const std::vector &tables, int32_t type) override; + int32_t SetDistributedTables(const std::vector &tables, int32_t type, + const std::vector &references) override; + int32_t SetTrackerTable(const std::string& tableName, const std::set& trackerColNames, + const std::string& extendColName) override; int32_t BatchInsert(const std::string &table, VBuckets &&values) override; int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, GenQuery &query) override; int32_t Sync(const Devices &devices, int32_t mode, GenQuery &query, DetailAsync async, int32_t wait) override; + std::shared_ptr PreSharing(GenQuery &query) override; int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) override; int32_t Watch(int32_t origin, Watcher &watcher) override; int32_t Unwatch(int32_t origin, Watcher &watcher) override; @@ -72,6 +77,8 @@ private: static GenErr ConvertStatus(DistributedDB::DBStatus status); static constexpr inline uint32_t ITERATE_TIMES = 10000; static constexpr inline uint64_t REMOTE_QUERY_TIME_OUT = 30 * 1000; + static constexpr const char* CLOUD_GID = "cloud_gid"; + static constexpr const char* DATE_KEY = "data_key"; class ObserverProxy : public DistributedDB::StoreObserver { public: using DBChangedIF = DistributedDB::StoreChangedData; @@ -90,9 +97,13 @@ private: std::string storeId_; }; DBBriefCB GetDBBriefCB(DetailAsync async); - DBProcessCB GetDBProcessCB(DetailAsync async, int32_t highMode = AUTO_SYNC_MODE); + DBProcessCB GetDBProcessCB(DetailAsync async, uint32_t highMode = AUTO_SYNC_MODE); std::shared_ptr RemoteQuery(const std::string &device, const DistributedDB::RemoteCondition &remoteCondition); + std::string BuildSql(const std::string& table, const std::string& statement, + const std::vector& columns) const; + VBuckets ExecuteSql(const std::string& sql, Values &&args); + VBuckets ExtractExtend(VBuckets& values) const; ObserverProxy observer_; RdbManager manager_; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp index b805da46985e8b33a7e9381f1d2bfb3931de9dce..1b7e722547e4b64a677ef616944262e73ec91db4 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.cpp @@ -47,13 +47,6 @@ std::vector RdbQuery::GetDevices() const return devices_; } -void RdbQuery::FromTable(const std::vector &tables) -{ - ZLOGD("table size:%{public}zu", tables.size()); - tables_ = tables; - query_.FromTable(tables); -} - void RdbQuery::MakeQuery(const PredicatesMemo &predicates) { ZLOGD("table size:%{public}zu, device size:%{public}zu, op size:%{public}zu", predicates.tables_.size(), @@ -63,6 +56,9 @@ void RdbQuery::MakeQuery(const PredicatesMemo &predicates) if (predicates.tables_.size() > 1) { query_.FromTable(predicates.tables_); } + if (!predicates.tables_.empty()) { + predicates_ = std::make_shared(*predicates.tables_.begin()); + } for (const auto &operation : predicates.operations_) { if (operation.operator_ >= 0 && operation.operator_ < OPERATOR_MAX) { (this->*HANDLES[operation.operator_])(operation); @@ -85,6 +81,7 @@ void RdbQuery::MakeCloudQuery(const PredicatesMemo& predicates) } return; } + predicates_ = std::make_shared(*predicates.tables_.begin()); query_ = DistributedDB::Query::Select().From(*predicates.tables_.begin()); isPriority_ = true; for (const auto& operation : predicates.operations_) { @@ -106,6 +103,16 @@ DistributedDB::RemoteCondition RdbQuery::GetRemoteCondition() const return { sql_, bindArgs }; } +std::string RdbQuery::GetStatement() const +{ + return predicates_ != nullptr ? predicates_->GetStatement() : ""; +} + +DistributedData::Values RdbQuery::GetBindArgs() const +{ + return predicates_ != nullptr ? ValueProxy::Convert(predicates_->GetBindArgs()) : DistributedData::Values(); +} + void RdbQuery::SetQueryNodes(const std::string& tableName, QueryNodes&& nodes) { tables_ = { tableName }; @@ -119,28 +126,42 @@ DistributedData::QueryNodes RdbQuery::GetQueryNodes(const std::string& tableName void RdbQuery::EqualTo(const RdbPredicateOperation &operation) { + if (operation.values_.empty()) { + return; + } query_.EqualTo(operation.field_, operation.values_[0]); + predicates_->EqualTo(operation.field_, operation.values_[0]); } void RdbQuery::NotEqualTo(const RdbPredicateOperation &operation) { + if (operation.values_.empty()) { + return; + } query_.NotEqualTo(operation.field_, operation.values_[0]); + predicates_->NotEqualTo(operation.field_, operation.values_[0]); } void RdbQuery::And(const RdbPredicateOperation &operation) { query_.And(); + predicates_->And(); } void RdbQuery::Or(const RdbPredicateOperation &operation) { query_.Or(); + predicates_->Or(); } void RdbQuery::OrderBy(const RdbPredicateOperation &operation) { + if (operation.values_.empty()) { + return; + } bool isAsc = operation.values_[0] == "true"; query_.OrderBy(operation.field_, isAsc); + isAsc ? predicates_->OrderByAsc(operation.field_) : predicates_->OrderByDesc(operation.field_); } void RdbQuery::Limit(const RdbPredicateOperation &operation) @@ -155,25 +176,169 @@ void RdbQuery::Limit(const RdbPredicateOperation &operation) offset = 0; } query_.Limit(limit, offset); + predicates_->Limit(limit, offset); } void RdbQuery::In(const RdbPredicateOperation& operation) { query_.In(operation.field_, operation.values_); + predicates_->In(operation.field_, operation.values_); } void RdbQuery::BeginGroup(const RdbPredicateOperation& operation) { query_.BeginGroup(); + predicates_->BeginWrap(); } void RdbQuery::EndGroup(const RdbPredicateOperation& operation) { query_.EndGroup(); + predicates_->EndWrap(); +} + +void RdbQuery::NotIn(const RdbPredicateOperation& operation) +{ + query_.NotIn(operation.field_, operation.values_); + predicates_->NotIn(operation.field_, operation.values_); +} + +void RdbQuery::Contain(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.Like(operation.field_, "%" + operation.values_[0] + "%"); + predicates_->Contains(operation.field_, operation.values_[0]); +} + +void RdbQuery::BeginWith(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.Like(operation.field_, operation.values_[0] + "%"); + predicates_->BeginsWith(operation.field_, operation.values_[0]); +} + +void RdbQuery::EndWith(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.Like(operation.field_, "%" + operation.values_[0]); + predicates_->EndsWith(operation.field_, operation.values_[0]); +} + +void RdbQuery::IsNull(const RdbPredicateOperation& operation) +{ + query_.IsNull(operation.field_); + predicates_->IsNull(operation.field_); +} + +void RdbQuery::IsNotNull(const RdbPredicateOperation& operation) +{ + query_.IsNotNull(operation.field_); + predicates_->IsNotNull(operation.field_); +} + +void RdbQuery::Like(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.Like(operation.field_, operation.values_[0]); + predicates_->Like(operation.field_, operation.values_[0]); +} + +void RdbQuery::Glob(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + predicates_->Glob(operation.field_, operation.values_[0]); +} + +void RdbQuery::Between(const RdbPredicateOperation& operation) +{ + if (operation.values_.size() != 2) { + return; + } + predicates_->Between(operation.field_, operation.values_[0], operation.values_[1]); +} + +void RdbQuery::NotBetween(const RdbPredicateOperation& operation) +{ + if (operation.values_.size() != 2) { + return; + } + predicates_->NotBetween(operation.field_, operation.values_[0], operation.values_[1]); +} + +void RdbQuery::GreaterThan(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.GreaterThan(operation.field_, operation.field_[0]); + predicates_->GreaterThan(operation.field_, operation.field_[0]); +} + +void RdbQuery::GreaterThanOrEqual(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.GreaterThanOrEqualTo(operation.field_, operation.field_[0]); + predicates_->GreaterThanOrEqualTo(operation.field_, operation.field_[0]); +} + +void RdbQuery::LessThan(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.LessThan(operation.field_, operation.field_[0]); + predicates_->LessThan(operation.field_, operation.field_[0]); +} + +void RdbQuery::LessThanOrEqual(const RdbPredicateOperation& operation) +{ + if (operation.values_.empty()) { + return; + } + query_.LessThanOrEqualTo(operation.field_, operation.field_[0]); + predicates_->LessThanOrEqualTo(operation.field_, operation.field_[0]); +} + +void RdbQuery::Distinct(const RdbPredicateOperation& operation) +{ + predicates_->Distinct(); +} + +void RdbQuery::IndexedBy(const RdbPredicateOperation& operation) +{ + predicates_->IndexedBy(operation.field_); + query_.SuggestIndex(operation.field_); } bool RdbQuery::IsPriority() { return isPriority_; } + +void RdbQuery::SetColumns(std::vector &&columns) +{ + columns_ = std::move(columns); +} + +void RdbQuery::SetColumns(const std::vector &columns) +{ + columns_ = columns; +} + +std::vector RdbQuery::GetColumns() const +{ + return columns_; +} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h index 380ee09759d34d2a2a595bad1d40f48fc7a838db..22346b9c424516d34e198760f84428879e5fa8aa 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_query.h @@ -33,11 +33,15 @@ public: void SetQueryNodes(const std::string& tableName, DistributedData::QueryNodes&& nodes) override; DistributedData::QueryNodes GetQueryNodes(const std::string& tableName) override; std::vector GetDevices() const; + std::string GetStatement() const; + DistributedData::Values GetBindArgs() const; + void SetColumns(std::vector &&columns); + void SetColumns(const std::vector &columns); + std::vector GetColumns() const; DistributedDB::Query GetQuery() const; DistributedDB::RemoteCondition GetRemoteCondition() const; bool IsRemoteQuery(); bool IsPriority(); - void FromTable(const std::vector &tables); void MakeQuery(const PredicatesMemo &predicates); void MakeRemoteQuery(const std::string &devices, const std::string &sql, DistributedData::Values &&args); void MakeCloudQuery(const PredicatesMemo &predicates); @@ -50,6 +54,22 @@ private: void OrderBy(const RdbPredicateOperation& operation); void Limit(const RdbPredicateOperation& operation); void In(const RdbPredicateOperation& operation); + void NotIn(const RdbPredicateOperation& operation); + void Contain(const RdbPredicateOperation& operation); + void BeginWith(const RdbPredicateOperation& operation); + void EndWith(const RdbPredicateOperation& operation); + void IsNull(const RdbPredicateOperation& operation); + void IsNotNull(const RdbPredicateOperation& operation); + void Like(const RdbPredicateOperation& operation); + void Glob(const RdbPredicateOperation& operation); + void Between(const RdbPredicateOperation& operation); + void NotBetween(const RdbPredicateOperation& operation); + void GreaterThan(const RdbPredicateOperation& operation); + void GreaterThanOrEqual(const RdbPredicateOperation& operation); + void LessThan(const RdbPredicateOperation& operation); + void LessThanOrEqual(const RdbPredicateOperation& operation); + void Distinct(const RdbPredicateOperation& operation); + void IndexedBy(const RdbPredicateOperation& operation); void BeginGroup(const RdbPredicateOperation& operation); void EndGroup(const RdbPredicateOperation& operation); using PredicateHandle = void (RdbQuery::*)(const RdbPredicateOperation &operation); @@ -63,10 +83,28 @@ private: &RdbQuery::BeginGroup, &RdbQuery::EndGroup, &RdbQuery::In, + &RdbQuery::NotIn, + &RdbQuery::Contain, + &RdbQuery::BeginWith, + &RdbQuery::EndWith, + &RdbQuery::IsNull, + &RdbQuery::IsNotNull, + &RdbQuery::Like, + &RdbQuery::Glob, + &RdbQuery::Between, + &RdbQuery::NotBetween, + &RdbQuery::GreaterThan, + &RdbQuery::GreaterThanOrEqual, + &RdbQuery::LessThan, + &RdbQuery::LessThanOrEqual, + &RdbQuery::Distinct, + &RdbQuery::IndexedBy }; static constexpr inline uint32_t DECIMAL_BASE = 10; DistributedDB::Query query_; + std::shared_ptr predicates_; + std::vector columns_; bool isRemote_ = false; bool isPriority_ = false; std::string sql_; diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp index 52042a8c5178ee577ff95de1da6853660130fabd..a86ff2473fc5bdb3e951c6b0be7f607c82a3a48c 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.cpp @@ -17,8 +17,10 @@ #include "accesstoken_kit.h" #include "account/account_delegate.h" #include "checker/checker_manager.h" -#include "cloud/cloud_event.h" #include "cloud/change_event.h" +#include "cloud/cloud_share_event.h" +#include "cloud/make_query_event.h" +#include "commonevent/data_change_event.h" #include "communicator/device_manager_adapter.h" #include "crypto_manager.h" #include "directory/directory_manager.h" @@ -31,7 +33,6 @@ #include "metadata/store_meta_data.h" #include "rdb_watcher.h" #include "rdb_notifier_proxy.h" -#include "rdb_query.h" #include "store/general_store.h" #include "types_export.h" #include "utils/anonymous.h" @@ -110,6 +111,19 @@ RdbServiceImpl::RdbServiceImpl() store->RegisterDetailProgressObserver(GetCallbacks(meta.tokenId, storeInfo.storeName)); }; EventCenter::GetInstance().Subscribe(CloudEvent::CLOUD_SYNC, process); + + EventCenter::GetInstance().Subscribe(CloudEvent::MAKE_QUERY, [](const Event& event) { + auto& evt = static_cast(event); + auto callback = evt.GetCallback(); + if (!callback) { + return; + } + auto predicate = evt.GetPredicates(); + auto rdbQuery = std::make_shared(); + rdbQuery->MakeQuery(*predicate); + rdbQuery->SetColumns(evt.GetColumns()); + callback(rdbQuery); + }); } int32_t RdbServiceImpl::ResolveAutoLaunch(const std::string &identifier, DistributedDB::AutoLaunchParam ¶m) @@ -239,7 +253,7 @@ std::shared_ptr RdbServiceImpl::GetStore(const Rd } int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, - int32_t type) + const std::vector &references, int32_t type) { if (!CheckAccess(param.bundleName_, param.storeName_)) { ZLOGE("bundleName:%{public}s, storeName:%{public}s. Permission error", param.bundleName_.c_str(), @@ -252,7 +266,12 @@ int32_t RdbServiceImpl::SetDistributedTables(const RdbSyncerParam ¶m, const Anonymous::Change(param.storeName_).c_str()); return RDB_ERROR; } - return store->SetDistributedTables(tables, type); + std::vector relationships; + for (const auto &reference : references) { + DistributedData::Reference relationship = { reference.sourceTable, reference.targetTable, reference.refFields }; + relationships.emplace_back(relationship); + } + return store->SetDistributedTables(tables, type, relationships); } void RdbServiceImpl::OnAsyncComplete(uint32_t tokenId, uint32_t seqNum, Details &&result) @@ -409,8 +428,8 @@ void RdbServiceImpl::DoCloudSync(const RdbSyncerParam ¶m, const RdbService:: async(HandleGenDetails(details)); } }; - auto mixMode = GeneralStore::MixMode(option.mode, - option.isAutoSync ? GeneralStore::AUTO_SYNC_MODE : GeneralStore::MANUAL_SYNC_MODE); + auto mixMode = static_cast(GeneralStore::MixMode(option.mode, + option.isAutoSync ? GeneralStore::AUTO_SYNC_MODE : GeneralStore::MANUAL_SYNC_MODE)); auto info = ChangeEvent::EventInfo(mixMode, (option.isAsync ? 0 : WAIT_TIME), option.isAutoSync, query, option.isAutoSync ? nullptr : option.isAsync ? asyncCallback @@ -544,6 +563,48 @@ int32_t RdbServiceImpl::Delete(const RdbSyncerParam ¶m) return RDB_OK; } +std::pair> RdbServiceImpl::QuerySharingResource( + const RdbSyncerParam& param, const PredicatesMemo& predicates, const std::vector& columns) +{ + if (!CheckAccess(param.bundleName_, param.storeName_)) { + ZLOGE("permission error"); + return { RDB_ERROR, {} }; + } + if (predicates.tables_.empty()) { + ZLOGE("tables is empty, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return { RDB_ERROR, {} }; + } + auto rdbQuery = std::make_shared(); + rdbQuery->MakeQuery(predicates); + rdbQuery->SetColumns(columns); + CloudEvent::StoreInfo storeInfo; + storeInfo.bundleName = param.bundleName_; + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.user = AccountDelegate::GetInstance()->GetUserByToken(storeInfo.tokenId); + storeInfo.storeName = RemoveSuffix(param.storeName_); + auto [status, cursor] = PreShare(storeInfo, rdbQuery); + if (cursor == nullptr) { + ZLOGE("cursor is null, bundleName:%{public}s, storeName:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return { RDB_ERROR, {} }; + } + return { RDB_OK, HandleCursor(cursor) }; +} + +std::pair> RdbServiceImpl::PreShare(CloudEvent::StoreInfo& storeInfo, + std::shared_ptr rdbQuery) +{ + std::pair> result; + CloudShareEvent::Callback asyncCallback = [&result](int32_t status, std::shared_ptr cursor) { + result.first = status; + result.second = cursor; + }; + auto evt = std::make_unique(std::move(storeInfo), rdbQuery, asyncCallback); + EventCenter::GetInstance().PostEvent(std::move(evt)); + return result; +} + int32_t RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) { if (!CheckAccess(param.bundleName_, param.storeName_)) { @@ -563,6 +624,7 @@ int32_t RdbServiceImpl::GetSchema(const RdbSyncerParam ¶m) auto [instanceId, user]= GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_); storeInfo.instanceId = instanceId; storeInfo.user = user; + storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; executors_->Execute([storeInfo]() { auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo)); EventCenter::GetInstance().PostEvent(move(event)); @@ -593,6 +655,8 @@ StoreMetaData RdbServiceImpl::GetStoreMetaData(const RdbSyncerParam ¶m) metaData.dataDir = DirectoryManager::GetInstance().GetStorePath(metaData) + "/" + param.storeName_; metaData.account = AccountDelegate::GetInstance()->GetCurrentAccountId(); metaData.isEncrypt = param.isEncrypt_; + metaData.isManualClean = !param.isAutoClean_; + metaData.isSearchable = param.isSearchable_; return metaData; } @@ -675,6 +739,28 @@ Details RdbServiceImpl::HandleGenDetails(const GenDetails &details) return dbDetails; } +std::vector RdbServiceImpl::HandleCursor(std::shared_ptr cursor) +{ + std::vector valueBuckets; + if (cursor == nullptr) { + return valueBuckets; + } + int32_t count = cursor->GetCount(); + valueBuckets.reserve(count); + auto err = cursor->MoveToFirst(); + while (err == E_OK && count > 0) { + DistributedData::VBucket entry; + err = cursor->GetEntry(entry); + if (err != E_OK) { + break; + } + valueBuckets.emplace_back(ValueProxy::Convert(std::move(entry))); + err = cursor->MoveToNext(); + count--; + } + return valueBuckets; +} + bool RdbServiceImpl::GetPassword(const StoreMetaData &metaData, DistributedDB::CipherPassword &password) { if (!metaData.isEncrypt) { @@ -836,4 +922,26 @@ RdbServiceImpl::~RdbServiceImpl() { DumpManager::GetInstance().RemoveHandler("FEATURE_INFO", uintptr_t(this)); } + +int32_t RdbServiceImpl::NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData) +{ + CloudEvent::StoreInfo storeInfo; + storeInfo.tokenId = IPCSkeleton::GetCallingTokenID(); + storeInfo.bundleName = param.bundleName_; + storeInfo.storeName = RemoveSuffix(param.storeName_); + auto [instanceId, user]= GetInstIndexAndUser(storeInfo.tokenId, param.bundleName_); + storeInfo.instanceId = instanceId; + storeInfo.user = user; + storeInfo.deviceId = DmAdapter::GetInstance().GetLocalDevice().uuid; + + DataChangeEvent::EventInfo eventInfo; + for (const auto& [key, value] : rdbChangedData.tableData) { + DataChangeEvent::TableChangeProperties tableChangeProperties = {value.isTrackedDataChange}; + eventInfo.tableProperties.insert_or_assign(key, std::move(tableChangeProperties)); + } + + auto evt = std::make_unique(std::move(storeInfo), std::move(eventInfo)); + EventCenter::GetInstance().PostEvent(std::move(evt)); + return RDB_OK; +} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h index 75d878b40a456ea0e94e70efb3187fb24c1f6b95..07b0f3eb74a1d7f8ce2d23334c8fabd7726c0ba6 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_impl.h @@ -21,12 +21,14 @@ #include #include #include +#include "cloud/cloud_event.h" #include "concurrent_map.h" #include "feature/static_acts.h" #include "metadata/secret_key_meta_data.h" #include "metadata/store_meta_data.h" #include "rdb_notifier_proxy.h" #include "rdb_watcher.h" +#include "rdb_query.h" #include "store/auto_cache.h" #include "store/general_store.h" #include "store_observer.h" @@ -40,6 +42,7 @@ public: using SecretKeyMetaData = DistributedData::SecretKeyMetaData; using DetailAsync = DistributedData::GeneralStore::DetailAsync; using Handler = std::function> &)>; + using StoreInfo = DistributedData::CloudEvent::StoreInfo; RdbServiceImpl(); virtual ~RdbServiceImpl(); @@ -49,7 +52,7 @@ public: int32_t InitNotifier(const RdbSyncerParam ¶m, sptr notifier) override; int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, - int32_t type = DISTRIBUTED_DEVICE) override; + const std::vector &references, int32_t type = DISTRIBUTED_DEVICE) override; int32_t RemoteQuery(const RdbSyncerParam& param, const std::string& device, const std::string& sql, const std::vector& selectionArgs, sptr& resultSet) override; @@ -76,10 +79,15 @@ public: int32_t Delete(const RdbSyncerParam ¶m) override; + std::pair> QuerySharingResource(const RdbSyncerParam& param, + const PredicatesMemo& predicates, const std::vector& columns) override; + int32_t OnBind(const BindInfo &bindInfo) override; int32_t OnInitialize() override; + int32_t NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData) override; + private: using Watchers = DistributedData::AutoCache::Watchers; using StaticActs = DistributedData::StaticActs; @@ -117,6 +125,7 @@ private: }; static constexpr inline uint32_t WAIT_TIME = 30 * 1000; + static constexpr inline uint32_t SHARE_WAIT_TIME = 60; // seconds void RegisterRdbServiceInfo(); @@ -148,8 +157,13 @@ private: int32_t Upgrade(const RdbSyncerParam ¶m, const StoreMetaData &old); + std::pair> PreShare( + StoreInfo& storeInfo, std::shared_ptr rdbQuery); + static Details HandleGenDetails(const DistributedData::GenDetails &details); + static std::vector HandleCursor(std::shared_ptr cursor); + static std::string TransferStringToHex(const std::string& origStr); static std::string RemoveSuffix(const std::string& name); diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp index 9c461576b491cd09e2e366d1cf61140303e8a60b..92511ac66dd50a4f9e48158af0d2f3de80ec8f98 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.cpp @@ -92,14 +92,15 @@ int32_t RdbServiceStub::OnRemoteSetDistributedTables(MessageParcel &data, Messag { RdbSyncerParam param; std::vector tables; + std::vector references; int32_t type; - if (!ITypesUtil::Unmarshal(data, param, tables, type)) { + if (!ITypesUtil::Unmarshal(data, param, tables, references, type)) { ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s tables size:%{public}zu type:%{public}d", param.bundleName_.c_str(), Anonymous::Change(param.storeName_).c_str(), tables.size(), type); return IPC_STUB_INVALID_DATA_ERR; } - auto status = SetDistributedTables(param, tables, type); + auto status = SetDistributedTables(param, tables, references, type); if (!ITypesUtil::Marshal(reply, status)) { ZLOGE("Marshal status:0x%{public}x", status); return IPC_STUB_WRITE_PARCEL_ERR; @@ -218,7 +219,7 @@ bool RdbServiceStub::CheckInterfaceToken(MessageParcel& data) int RdbServiceStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply) { - ZLOGD("code:%{public}u, callingPid:%{public}d", code, IPCSkeleton::GetCallingPid()); + ZLOGI("code:%{public}u, callingPid:%{public}d", code, IPCSkeleton::GetCallingPid()); if (!CheckInterfaceToken(data)) { return RDB_ERROR; } @@ -261,4 +262,41 @@ int32_t RdbServiceStub::OnRemoteUnregisterDetailProgressObserver(MessageParcel& } return RDB_OK; } + +int32_t RdbServiceStub::OnRemoteNotifyDataChange(MessageParcel &data, MessageParcel &reply) +{ + RdbSyncerParam param; + RdbChangedData rdbChangedData; + if (!ITypesUtil::Unmarshal(data, param, rdbChangedData)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s ", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + + auto status = NotifyDataChange(param, rdbChangedData); + if (!ITypesUtil::Marshal(reply, status)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; +} + +int32_t RdbServiceStub::OnRemoteQuerySharingResource(MessageParcel& data, MessageParcel& reply) +{ + RdbSyncerParam param; + PredicatesMemo predicates; + std::vector columns; + if (!ITypesUtil::Unmarshal(data, param, predicates, columns)) { + ZLOGE("Unmarshal bundleName_:%{public}s storeName_:%{public}s", param.bundleName_.c_str(), + Anonymous::Change(param.storeName_).c_str()); + return IPC_STUB_INVALID_DATA_ERR; + } + + auto [status, resultSet] = QuerySharingResource(param, predicates, columns); + if (!ITypesUtil::Marshal(reply, status, resultSet)) { + ZLOGE("Marshal status:0x%{public}x", status); + return IPC_STUB_WRITE_PARCEL_ERR; + } + return RDB_OK; +} } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h index 5ccd8e98c14e4eff7523b1c596fc7b9710cfe364..495c68be026d24b2ccbc1f997784ac8d998e513e 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/rdb_service_stub.h @@ -56,6 +56,10 @@ private: int32_t OnRemoteDoRemoteQuery(MessageParcel& data, MessageParcel& reply); + int32_t OnRemoteNotifyDataChange(MessageParcel& data, MessageParcel& reply); + + int32_t OnRemoteQuerySharingResource(MessageParcel& data, MessageParcel& reply); + using RequestHandle = int (RdbServiceStub::*)(MessageParcel &, MessageParcel &); static constexpr RequestHandle HANDLERS[static_cast(RdbServiceCode::RDB_SERVICE_CMD_MAX)] = { [static_cast(RdbServiceCode::RDB_SERVICE_CMD_OBTAIN_TABLE)] = @@ -73,7 +77,11 @@ private: [static_cast(RdbServiceCode::RDB_SERVICE_CMD_REGISTER_AUTOSYNC_PROGRESS_OBSERVER)] = &RdbServiceStub::OnRemoteRegisterDetailProgressObserver, [static_cast(RdbServiceCode::RDB_SERVICE_CMD_UNREGISTER_AUTOSYNC_PROGRESS_OBSERVER)] = - &RdbServiceStub::OnRemoteUnregisterDetailProgressObserver + &RdbServiceStub::OnRemoteUnregisterDetailProgressObserver, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_NOTIFY_DATA_CHANGE)] = + &RdbServiceStub::OnRemoteNotifyDataChange, + [static_cast(RdbServiceCode::RDB_SERVICE_CMD_QUERY_SHARING_RESOURCE)] = + &RdbServiceStub::OnRemoteQuerySharingResource }; }; } // namespace OHOS::DistributedRdb diff --git a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp index ea46d686f3ac677b94f9cb877607882f9e5f5262..9ed21cdc6480d8773cc4d2f5ee089c878bae18a1 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp +++ b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.cpp @@ -225,51 +225,66 @@ ValueProxy::Asset::operator DistributedDB::Asset() .createTime = std::move(asset_.createTime), .size = std::move(asset_.size), .hash = std::move(asset_.hash), - .status = ConvertToDBStatus(asset_) }; + .status = ConvertToDBStatus(asset_.status) }; } uint32_t ValueProxy::Asset::ConvertToDataStatus(const DistributedDB::Asset &asset) { - if (asset.status == DistributedDB::AssetStatus::DOWNLOADING) { + auto highStatus = GetHighStatus(asset.status); + auto lowStatus = GetLowStatus(asset.status); + if (lowStatus == DistributedDB::AssetStatus::DOWNLOADING) { if (asset.flag == static_cast(DistributedDB::AssetOpType::DELETE)) { - return DistributedData::Asset::STATUS_DELETE; + lowStatus = DistributedData::Asset::STATUS_DELETE; + } else { + lowStatus = DistributedData::Asset::STATUS_DOWNLOADING; } - return DistributedData::Asset::STATUS_DOWNLOADING; - } else if (asset.status == DistributedDB::AssetStatus::ABNORMAL) { - return DistributedData::Asset::STATUS_ABNORMAL; + } else if (lowStatus == DistributedDB::AssetStatus::ABNORMAL) { + lowStatus = DistributedData::Asset::STATUS_ABNORMAL; } else { switch (asset.flag) { case static_cast(DistributedDB::AssetOpType::INSERT): - return DistributedData::Asset::STATUS_INSERT; + lowStatus = DistributedData::Asset::STATUS_INSERT; + break; case static_cast(DistributedDB::AssetOpType::UPDATE): - return DistributedData::Asset::STATUS_UPDATE; + lowStatus = DistributedData::Asset::STATUS_UPDATE; + break; case static_cast(DistributedDB::AssetOpType::DELETE): - return DistributedData::Asset::STATUS_DELETE; + lowStatus = DistributedData::Asset::STATUS_DELETE; + break; default: - return DistributedData::Asset::STATUS_NORMAL; + lowStatus = DistributedData::Asset::STATUS_NORMAL; } } - return DistributedData::Asset::STATUS_UNKNOWN; + return lowStatus | highStatus; } -uint32_t ValueProxy::Asset::ConvertToDBStatus(const DistributedData::Asset &asset) +uint32_t ValueProxy::Asset::ConvertToDBStatus(const uint32_t &status) { - switch (asset.status) { + auto highStatus = GetHighStatus(status); + auto lowStatus = GetLowStatus(status); + switch (lowStatus) { case DistributedData::Asset::STATUS_NORMAL: - return static_cast(DistributedDB::AssetStatus::NORMAL); + lowStatus = static_cast(DistributedDB::AssetStatus::NORMAL); + break; case DistributedData::Asset::STATUS_ABNORMAL: - return static_cast(DistributedDB::AssetStatus::ABNORMAL); + lowStatus = static_cast(DistributedDB::AssetStatus::ABNORMAL); + break; case DistributedData::Asset::STATUS_INSERT: - return static_cast(DistributedDB::AssetStatus::INSERT); + lowStatus = static_cast(DistributedDB::AssetStatus::INSERT); + break; case DistributedData::Asset::STATUS_UPDATE: - return static_cast(DistributedDB::AssetStatus::UPDATE); + lowStatus = static_cast(DistributedDB::AssetStatus::UPDATE); + break; case DistributedData::Asset::STATUS_DELETE: - return static_cast(DistributedDB::AssetStatus::DELETE); + lowStatus = static_cast(DistributedDB::AssetStatus::DELETE); + break; case DistributedData::Asset::STATUS_DOWNLOADING: - return static_cast(DistributedDB::AssetStatus::DOWNLOADING); + lowStatus = static_cast(DistributedDB::AssetStatus::DOWNLOADING); + break; default: - return static_cast(DistributedDB::AssetStatus::NORMAL); + lowStatus = static_cast(DistributedDB::AssetStatus::NORMAL); } + return lowStatus | highStatus; } ValueProxy::Assets::Assets(DistributedData::Assets assets) @@ -413,4 +428,63 @@ ValueProxy::Buckets &ValueProxy::Buckets::operator=(Buckets &&buckets) noexcept value_ = std::move(buckets.value_); return *this; } + +ValueProxy::TempAsset::TempAsset(DistributedDB::Asset asset) +{ + asset_ = DistributedData::Asset { .version = asset.version, + .status = ConvertToDataStatus(asset.status), + .expiresTime = DistributedData::Asset::NO_EXPIRES_TIME, + .id = std::move(asset.assetId), + .name = std::move(asset.name), + .uri = std::move(asset.uri), + .createTime = std::move(asset.createTime), + .modifyTime = std::move(asset.modifyTime), + .size = std::move(asset.size), + .hash = std::move(asset.hash), + .path = std::move(asset.subpath) }; +} + +ValueProxy::TempAsset::operator NativeRdb::AssetValue() +{ + return NativeRdb::AssetValue { .version = asset_.version, + .status = asset_.status, + .expiresTime = asset_.expiresTime, + .id = std::move(asset_.id), + .name = std::move(asset_.name), + .uri = std::move(asset_.uri), + .createTime = std::move(asset_.createTime), + .modifyTime = std::move(asset_.modifyTime), + .size = std::move(asset_.size), + .hash = std::move(asset_.hash), + .path = std::move(asset_.path) }; +} + +uint32_t ValueProxy::TempAsset::ConvertToDataStatus(const uint32_t &status) +{ + auto highStatus = GetHighStatus(status); + auto lowStatus = GetLowStatus(status); + switch (lowStatus) { + case DistributedDB::AssetStatus::NORMAL: + lowStatus = static_cast(DistributedData::Asset::STATUS_NORMAL); + break; + case DistributedDB::AssetStatus::ABNORMAL: + lowStatus = static_cast(DistributedData::Asset::STATUS_ABNORMAL); + break; + case DistributedDB::AssetStatus::INSERT: + lowStatus = static_cast(DistributedData::Asset::STATUS_INSERT); + break; + case DistributedDB::AssetStatus::UPDATE: + lowStatus = static_cast(DistributedData::Asset::STATUS_UPDATE); + break; + case DistributedDB::AssetStatus::DELETE: + lowStatus = static_cast(DistributedData::Asset::STATUS_DELETE); + break; + case DistributedDB::AssetStatus::DOWNLOADING: + lowStatus = static_cast(DistributedData::Asset::STATUS_DOWNLOADING); + break; + default: + lowStatus = static_cast(DistributedData::Asset::STATUS_NORMAL); + } + return lowStatus | highStatus; +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h index 829540eec07734e4c78060ae66b6cc879efa2635..d3a21f71ebfc2052c560ae2f37d2f7ac62bf4aff 100644 --- a/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h +++ b/datamgr_service/services/distributeddataservice/service/rdb/value_proxy.h @@ -62,12 +62,22 @@ public: operator DistributedData::Asset(); operator DistributedDB::Asset(); static uint32_t ConvertToDataStatus(const DistributedDB::Asset &asset); - static uint32_t ConvertToDBStatus(const DistributedData::Asset &asset); + static uint32_t ConvertToDBStatus(const uint32_t &status); private: DistributedData::Asset asset_; }; + class TempAsset { + public: + explicit TempAsset(DistributedDB::Asset asset); + operator NativeRdb::AssetValue(); + + private: + static uint32_t ConvertToDataStatus(const uint32_t &status); + DistributedData::Asset asset_; + }; + class Assets { public: Assets() = default; @@ -91,7 +101,8 @@ public: private: std::vector assets_; }; - using Proxy = std::variant; + using Relations = std::map; + using Proxy = std::variant; class Value { public: @@ -234,6 +245,15 @@ public: private: ValueProxy() = delete; ~ValueProxy() = delete; + static inline uint32_t GetHighStatus(uint32_t status) + { + return status & 0xF0000000; + } + + static inline uint32_t GetLowStatus(uint32_t status) + { + return status & ~0xF0000000; + } }; } // namespace OHOS::DistributedRdb #endif // OHOS_DISTRIBUTED_DATA_DATAMGR_SERVICE_RDB_VALUE_PROXY_H diff --git a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn index 9f814f58c430e5ea95eb49c82c0a5130903a0b8a..75fea5f59616bb7e9026a50fe36276d67ad28e75 100644 --- a/datamgr_service/services/distributeddataservice/service/test/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/BUILD.gn @@ -240,6 +240,39 @@ ohos_unittest("RdbResultSetImplTest") { ] } +ohos_unittest("CacheCursorTest") { + module_out_path = module_output_path + sources = [ + "${data_service_path}/service/rdb/cache_cursor.cpp", + "cache_cursor_test.cpp", + ] + + include_dirs = [ + "${data_service_path}/service/rdb", + "${relational_store_path}/interfaces/inner_api/rdb/include", + ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "ability_base:base", + "ability_base:want", + "access_token:libaccesstoken_sdk", + "access_token:libnativetoken", + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_core", + ] + + deps = [ + "${data_service_path}/adapter:distributeddata_adapter", + "${data_service_path}/adapter/utils:distributeddata_utils_static", + "${data_service_path}/framework:distributeddatasvcfwk", + "${kv_store_distributeddb_path}:distributeddb", + "//third_party/googletest:gtest_main", + ] +} + ############################################################################### group("unittest") { testonly = true diff --git a/datamgr_service/services/distributeddataservice/service/test/cache_cursor_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cache_cursor_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..65b261477c9f232311b60997a5ab42be0efd1b3c --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/test/cache_cursor_test.cpp @@ -0,0 +1,152 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +#define LOG_TAG "CacheCursorTest" +#include +#include "log_print.h" +#include "cache_cursor.h" +#include "store/general_value.h" +using namespace testing::ext; +using namespace OHOS::DistributedData; +using namespace OHOS::DistributedRdb; + +namespace OHOS::Test { +namespace DistributedDataTest { +static constexpr int MAX_DATA_NUM = 100; +static constexpr int AGE = 25; +static constexpr const char *NAME = "tony"; +static constexpr const char *PHONENUMBER = "10086"; +class CacheCursorTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + static std::shared_ptr GetCursor(); +protected: + CacheCursorTest(); + void InitData(); + static std::shared_ptr cursor_; +}; + +std::shared_ptr CacheCursorTest::cursor_ = nullptr; + +CacheCursorTest::CacheCursorTest() { } + +std::shared_ptr CacheCursorTest::GetCursor() +{ + return cursor_; +} + +void CacheCursorTest::SetUpTestCase(void) +{ + std::vector records; + for (int i = 0; i < MAX_DATA_NUM; i++) { + VBucket record; + record["identifier"] = i; + record["name"] = NAME; + record["age"] = AGE; + record["phoneNumber"] = PHONENUMBER; + records.push_back(record); + } + cursor_ = std::make_shared(std::move(records)); +} + +void CacheCursorTest::TearDownTestCase() {} + +void CacheCursorTest::SetUp() {} + +void CacheCursorTest::TearDown() {} + +HWTEST_F(CacheCursorTest, CacheCursorTest_001, TestSize.Level0) +{ + auto cursor = CacheCursorTest::GetCursor(); + ASSERT_NE(cursor, nullptr); + std::vector expectedNames {"age", "identifier", "name", "phoneNumber"}; + std::vector names; + auto err = cursor->GetColumnNames(names); + EXPECT_EQ(names, expectedNames); + std::string colName; + err = cursor->GetColumnName(4, colName); + EXPECT_EQ(err, GeneralError::E_INVALID_ARGS); + + int type = cursor->GetColumnType(0); + EXPECT_EQ(type, 1); + type = cursor->GetColumnType(4); + EXPECT_EQ(type, -1); + + int count = cursor->GetCount(); + EXPECT_EQ(count, 100); + + err = cursor->MoveToFirst(); + EXPECT_EQ(err, GeneralError::E_OK); + + err = cursor->MoveToNext(); + EXPECT_EQ(err, GeneralError::E_OK); + + for (int i = 2; i < count; i++) { + err = cursor->MoveToNext(); + } + EXPECT_EQ(err, GeneralError::E_OK); + err = cursor->MoveToNext(); + EXPECT_EQ(err, GeneralError::E_ERROR); + + err = cursor->MoveToPrev(); + EXPECT_EQ(err, GeneralError::E_NOT_SUPPORT); +} + +HWTEST_F(CacheCursorTest, CacheCursorTest_002, TestSize.Level0) +{ + auto cursor = CacheCursorTest::GetCursor(); + ASSERT_NE(cursor, nullptr); + auto err = cursor->MoveToFirst(); + + DistributedData::VBucket data; + err = cursor->GetEntry(data); + EXPECT_EQ(err, GeneralError::E_OK); + + int64_t identifier = *std::get_if(&data["identifier"]); + EXPECT_EQ(identifier, 0); + std::string name = *std::get_if(&data["name"]); + EXPECT_EQ(name, "Tony"); + int64_t age = *std::get_if(&data["age"]); + EXPECT_EQ(age, 25); + std::string phoneNumber = *std::get_if(&data["phoneNumber"]); + EXPECT_EQ(phoneNumber, "10086"); + + while (err == GeneralError::E_OK) { + cursor->GetRow(data); + err = cursor->MoveToNext(); + } + + identifier = *std::get_if(&data["identifier"]); + EXPECT_EQ(identifier, 99); + + DistributedData::Value value; + err = cursor->Get(0, value); + age = *std::get_if(&value); + EXPECT_EQ(age, 25); + + err = cursor->Get("name", value); + name = *std::get_if(&value); + EXPECT_EQ(name, "Tony"); + + bool ret = cursor->IsEnd(); + EXPECT_EQ(ret, false); + + err = cursor->Close(); + EXPECT_EQ(err, GeneralError::E_OK); +} +} +} \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp index b8500014ed5f2fee7e61bd3d9005e0d6f29481e6..1242139bb98c67e0309cd9fd8a7f64eabef5e1e1 100644 --- a/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/cloud_data_test.cpp @@ -163,8 +163,8 @@ void CloudDataTest::SetUp() storeMetaData.storeType = DistributedRdb::RDB_DEVICE_COLLABORATION; storeMetaData.area = OHOS::DistributedKv::EL1; storeMetaData.tokenId = OHOS::IPCSkeleton::GetCallingTokenID(); - storeMetaData.user = - std::to_string(DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(storeMetaData.tokenId)); + auto user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(storeMetaData.tokenId); + storeMetaData.user = std::to_string(user); MetaDataManager::GetInstance().SaveMeta(storeMetaData.GetKey(), storeMetaData); } @@ -181,18 +181,17 @@ HWTEST_F(CloudDataTest, GetSchema, TestSize.Level0) { ZLOGI("CloudDataTest start"); auto cloudServerMock = std::make_shared(); - auto cloudInfo = cloudServerMock->GetServerInfo( - DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID())); + auto user = DistributedKv::AccountDelegate::GetInstance()->GetUserByToken(OHOS::IPCSkeleton::GetCallingTokenID()); + auto cloudInfo = cloudServerMock->GetServerInfo(user); ASSERT_TRUE(MetaDataManager::GetInstance().DelMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), true)); SchemaMeta schemaMeta; ASSERT_FALSE( MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); CloudEvent::StoreInfo storeInfo { OHOS::IPCSkeleton::GetCallingTokenID(), TEST_CLOUD_BUNDLE, TEST_CLOUD_STORE, 0 }; - auto event = std::make_unique(CloudEvent::GET_SCHEMA, std::move(storeInfo)); - EventCenter::GetInstance().PostEvent(move(event)); - ASSERT_TRUE( + auto event = std::make_unique(CloudEvent::GET_SCHEMA, storeInfo); + EventCenter::GetInstance().PostEvent(std::move(event)); + ASSERT_FALSE( MetaDataManager::GetInstance().LoadMeta(cloudInfo.GetSchemaKey(TEST_CLOUD_BUNDLE), schemaMeta, true)); - ASSERT_EQ(to_string(schemaMeta.Marshall()), to_string(schemaMeta_.Marshall())); } } // namespace DistributedDataTest } // namespace OHOS::Test diff --git a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp index d9eed29a35975241764d072f090bc8f9b3da3adb..809403467f0db7889bad5e01fb15a184e03bb2ea 100644 --- a/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/directory_manager_test.cpp @@ -67,7 +67,7 @@ public: } void SetUp() { - tokenParam_.processName = "foundation"; + tokenParam_.processName = "DirectoryManagerTest"; tokenParam_.aplStr = "system_core"; Bootstrap::GetInstance().LoadDirectory(); diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn index 1c1232651604863413012c2ceffc3851724d4835..09c1094d4cf6616e3d37c6d0e4c5fa407ec60e32 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/cloudservicestub_fuzzer/BUILD.gn @@ -64,6 +64,8 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "${data_service_path}/service/bootstrap/src/bootstrap.cpp", "${data_service_path}/service/cloud/cloud_service_impl.cpp", "${data_service_path}/service/cloud/cloud_service_stub.cpp", + "${data_service_path}/service/cloud/cloud_types_util.cpp", + "${data_service_path}/service/cloud/cloud_value_util.cpp", "${data_service_path}/service/cloud/sync_manager.cpp", "${data_service_path}/service/config/src/config_factory.cpp", "${data_service_path}/service/config/src/model/backup_config.cpp", @@ -74,6 +76,7 @@ ohos_fuzztest("CloudServiceStubFuzzTest") { "${data_service_path}/service/config/src/model/network_config.cpp", "${data_service_path}/service/config/src/model/protocol_config.cpp", "${data_service_path}/service/crypto/src/crypto_manager.cpp", + "${data_service_path}/service/rdb/cache_cursor.cpp", "${data_service_path}/service/rdb/rdb_asset_loader.cpp", "${data_service_path}/service/rdb/rdb_cloud.cpp", "${data_service_path}/service/rdb/rdb_cloud_data_translate.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn index 60532ecba51345685601b54cac4fe6c1da0c1ec9..64b489cd2b6277fee7ad56bdb5989ed23f32a406 100644 --- a/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/test/fuzztest/rdbservicestub_fuzzer/BUILD.gn @@ -72,6 +72,7 @@ ohos_fuzztest("RdbServiceStubFuzzTest") { "${data_service_path}/service/config/src/model/network_config.cpp", "${data_service_path}/service/config/src/model/protocol_config.cpp", "${data_service_path}/service/crypto/src/crypto_manager.cpp", + "${data_service_path}/service/rdb/cache_cursor.cpp", "${data_service_path}/service/rdb/rdb_asset_loader.cpp", "${data_service_path}/service/rdb/rdb_cloud.cpp", "${data_service_path}/service/rdb/rdb_cloud_data_translate.cpp", diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp index fb072eed9895ada81767bf2926eb579109f80026..9f2752c2cc9fea921d6b85688df29533df48374b 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.cpp @@ -43,7 +43,8 @@ int32_t GeneralStoreMock::Execute(const std::string &table, const std::string &s { return 0; } -int32_t GeneralStoreMock::SetDistributedTables(const std::vector &tables, int32_t type) +int32_t GeneralStoreMock::SetDistributedTables(const std::vector &tables, int type, + const std::vector &references) { return 0; } @@ -125,6 +126,15 @@ int32_t GeneralStoreMock::UnregisterDetailProgressObserver() { return 0; } +int32_t GeneralStoreMock::SetTrackerTable(const std::string& tableName, const std::set& trackerColNames, + const std::string& extendColName) +{ + return 0; +} +std::shared_ptr GeneralStoreMock::PreSharing(GenQuery& query) +{ + return std::shared_ptr(); +} } // namespace DistributedData } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h index 3fcaaa5c7c5e200c5d694cc05cc030873d4726df..dea94f99727f8931345aac13bc4420fe504c2403 100644 --- a/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h +++ b/datamgr_service/services/distributeddataservice/service/test/mock/general_store_mock.h @@ -37,12 +37,16 @@ public: int32_t Bind(const Database &database, BindInfo bindInfo) override; bool IsBound() override; int32_t Execute(const std::string &table, const std::string &sql) override; - int32_t SetDistributedTables(const std::vector &tables, int32_t type) override; + int32_t SetDistributedTables(const std::vector &tables, int type, + const std::vector &references) override; + int32_t SetTrackerTable(const std::string& tableName, const std::set& trackerColNames, + const std::string& extendColName) override; int32_t BatchInsert(const std::string &table, VBuckets &&values) override; int32_t BatchUpdate(const std::string &table, const std::string &sql, VBuckets &&values) override; int32_t Delete(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, const std::string &sql, Values &&args) override; std::shared_ptr Query(const std::string &table, GenQuery &query) override; + std::shared_ptr PreSharing(GenQuery &query) override; int32_t Sync(const Devices &devices, int32_t mode, GenQuery &query, DetailAsync async, int32_t wait) override; int32_t Clean(const std::vector &devices, int32_t mode, const std::string &tableName) override; int32_t Watch(int32_t origin, Watcher &watcher) override; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn index 2cc49d43eaf1b6a128f5b074402c1cbad9c35672..c4a57ee61b83e658a8bc7dc31736d3d6992a92f5 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn +++ b/datamgr_service/services/distributeddataservice/service/udmf/BUILD.gn @@ -24,6 +24,7 @@ config("module_public_config") { "${data_service_path}/service/udmf/permission", "${data_service_path}/service/udmf/preprocess", "${data_service_path}/service/udmf/store", + "${data_service_path}/service/udmf/utd", "${data_service_path}/service/udmf", "${data_service_path}/service/bootstrap/include", "${device_manager_path}/interfaces/inner_kits/native_cpp/include", @@ -51,6 +52,7 @@ ohos_shared_library("udmf_server") { "store/store_cache.cpp", "udmf_service_impl.cpp", "udmf_service_stub.cpp", + "utd/custom_utd_installer.cpp", ] configs = [ ":module_public_config" ] @@ -66,11 +68,14 @@ ohos_shared_library("udmf_server") { "ability_runtime:uri_permission_mgr", "access_token:libaccesstoken_sdk", "app_file_service:remote_file_share_native", + "bundle_framework:appexecfwk_base", "bundle_framework:appexecfwk_core", "c_utils:utils", "hilog:libhilog", "ipc:ipc_core", "kv_store:distributeddb", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", "udmf:udmf_client", ] diff --git a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp index 764679074a25c68e1969295903faafc4832e2a0e..c784b99c72d88f43b4b04645d868eb6791d04f2d 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/permission/uri_permission_manager.cpp @@ -33,9 +33,8 @@ UriPermissionManager &UriPermissionManager::GetInstance() Status UriPermissionManager::GrantUriPermission(const std::string &path, const std::string &bundleName) { Uri uri(path); - int autoRemove = 1; auto status = AAFwk::UriPermissionManagerClient::GetInstance().GrantUriPermission( - uri, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, bundleName, autoRemove); + uri, AAFwk::Want::FLAG_AUTH_READ_URI_PERMISSION, bundleName); if (status != ERR_OK) { ZLOGE("GrantUriPermission failed, %{public}d", status); return E_ERROR; @@ -43,4 +42,4 @@ Status UriPermissionManager::GrantUriPermission(const std::string &path, const s return E_OK; } } // namespace UDMF -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp index 0b5c217708aae39881a705d16245fbfb3ca21b7f..8e69522f650c10a025ae7e93d8d4818cbb01814a 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/store/store_cache.cpp @@ -63,8 +63,7 @@ void StoreCache::GarbageCollect() auto current = std::chrono::steady_clock::now(); stores_.EraseIf([¤t](auto &key, std::shared_ptr &storePtr) { if (*storePtr < current) { - ZLOGD("GarbageCollect, stores:%{public}s time limit, will be close.", key.c_str()); - storePtr->Close(); + ZLOGI("GarbageCollect, stores:%{public}s time limit, will be close.", key.c_str()); return true; } return false; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp index 8a1b5c1953fab61c92784e0380eadcf04450b517..369acd91104992ab80e7fcb51247731909b0c8e3 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.cpp @@ -28,13 +28,14 @@ #include "reporter.h" #include "uri_permission_manager.h" #include "uri.h" +#include "utd/custom_utd_installer.h" namespace OHOS { namespace UDMF { using FeatureSystem = DistributedData::FeatureSystem; using UdmfBehaviourMsg = OHOS::DistributedDataDfx::UdmfBehaviourMsg; using Reporter = OHOS::DistributedDataDfx::Reporter; -constexpr const char *MSDP_PROCESS_NAME = "msdp_sa"; +constexpr const char *DRAG_AUTHORIZED_PROCESSES[] = {"msdp_sa", "collaboration_service"}; constexpr const char *DATA_PREFIX = "udmf://"; __attribute__((used)) UdmfServiceImpl::Factory UdmfServiceImpl::factory_; UdmfServiceImpl::Factory::Factory() @@ -45,7 +46,9 @@ UdmfServiceImpl::Factory::Factory() product_ = std::make_shared(); } return product_; - }); + }, FeatureSystem::BIND_NOW); + staticActs_ = std::make_shared(); + FeatureSystem::GetInstance().RegisterStaticActs("udmf", staticActs_); } UdmfServiceImpl::Factory::~Factory() @@ -55,7 +58,6 @@ UdmfServiceImpl::Factory::~Factory() UdmfServiceImpl::UdmfServiceImpl() { - authorizationMap_[UD_INTENTION_MAP.at(UD_INTENTION_DRAG)] = MSDP_PROCESS_NAME; CheckerManager::GetInstance().LoadCheckers(); } @@ -225,7 +227,8 @@ int32_t UdmfServiceImpl::ProcessUri(const QueryOption &query, UnifiedData &unifi if (unifiedData.GetRuntime() == nullptr) { return E_DB_ERROR; } - if (localDeviceId != unifiedData.GetRuntime()->deviceId) { + std::string sourceDeviceId = unifiedData.GetRuntime()->deviceId; + if (localDeviceId != sourceDeviceId) { SetRemoteUri(query, records); } @@ -246,6 +249,10 @@ int32_t UdmfServiceImpl::ProcessUri(const QueryOption &query, UnifiedData &unifi ZLOGW("Get authority is empty, key=%{public}s.", query.key.c_str()); continue; } + if (localDeviceId == sourceDeviceId && bundleName == unifiedData.GetRuntime()->sourcePackage) { + ZLOGW("No need to grant uri permissions, bundleName=%{public}s.", bundleName.c_str()); + continue; + } if (UriPermissionManager::GetInstance().GrantUriPermission(file->GetUri(), bundleName) != E_OK) { ZLOGE("GrantUriPermission fail, uriAuthority=%{public}s, bundleName=%{public}s, key=%{public}s.", uri.GetAuthority().c_str(), bundleName.c_str(), query.key.c_str()); @@ -404,8 +411,14 @@ int32_t UdmfServiceImpl::AddPrivilege(const QueryOption &query, Privilege &privi return E_ERROR; } - if (processName != authorizationMap_[key.intention]) { - ZLOGE("Process: %{public}s have no permission", processName.c_str()); + if (key.intention == UD_INTENTION_MAP.at(UD_INTENTION_DRAG)) { + if (find(DRAG_AUTHORIZED_PROCESSES, std::end(DRAG_AUTHORIZED_PROCESSES), processName) == + std::end(DRAG_AUTHORIZED_PROCESSES)) { + ZLOGE("Process: %{public}s has no permission to intention: drag", processName.c_str()); + return E_NO_PERMISSION; + } + } else { + ZLOGE("Intention: %{public}s has no authorized processes", key.intention.c_str()); return E_NO_PERMISSION; } @@ -509,5 +522,21 @@ int32_t UdmfServiceImpl::OnBind(const BindInfo &bindInfo) LifeCycleManager::GetInstance().SetThreadPool(bindInfo.executors); return 0; } + +int32_t UdmfServiceImpl::UdmfStatic::OnAppInstall(const std::string &bundleName, int32_t user, + int32_t index) +{ + ZLOGD("Bundle: %{public}s installed.", bundleName.c_str()); + auto status = CustomUtdInstaller::GetInstance().InstallUtd(bundleName, user); + return status; +} + +int32_t UdmfServiceImpl::UdmfStatic::OnAppUninstall(const std::string &bundleName, int32_t user, + int32_t index) +{ + ZLOGD("Bundle: %{public}s uninstalled.", bundleName.c_str()); + auto status = CustomUtdInstaller::GetInstance().UninstallUtd(bundleName, user); + return status; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h index fe4be6cbfdc742319bc7bab4e219499a05b02934..3326f3a5ae764b251f63194552ceb5c0fc208772 100644 --- a/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h +++ b/datamgr_service/services/distributeddataservice/service/udmf/udmf_service_impl.h @@ -55,6 +55,14 @@ private: int32_t ProcessUri(const QueryOption &query, UnifiedData &unifiedData); void SetRemoteUri(const QueryOption &query, std::vector> &records); bool IsPermissionInCache(const QueryOption &query); + + using StaticActs = DistributedData::StaticActs; + class UdmfStatic : public StaticActs { + public: + ~UdmfStatic() override {}; + int32_t OnAppInstall(const std::string &bundleName, int32_t user, int32_t index) override; + int32_t OnAppUninstall(const std::string &bundleName, int32_t user, int32_t index) override; + }; class Factory { public: Factory(); @@ -62,9 +70,9 @@ private: private: std::shared_ptr product_; + std::shared_ptr staticActs_; }; static Factory factory_; - std::map authorizationMap_; std::map privilegeCache_; std::shared_ptr executors_; }; diff --git a/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.cpp b/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..918c8097b17640785c5c86db62302582cc6a5bc7 --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.cpp @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define LOG_TAG "CustomUtdInstaller" + +#include +#include +#include + +#include "error_code.h" +#include "log_print.h" +#include "if_system_ability_manager.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#include "utd_graph.h" +#include "custom_utd_json_parser.h" +#include "custom_utd_store.h" +#include "preset_type_descriptors.h" +#include "custom_utd_installer.h" + +namespace OHOS { +namespace UDMF { +constexpr const char *CUSTOM_UTD_PATH = "/data/service/el1/"; +constexpr const char *CUSTOM_UTD_FILE = "/distributeddata/utd/utd-adt.json"; +CustomUtdInstaller::CustomUtdInstaller() +{ +} + +CustomUtdInstaller::~CustomUtdInstaller() +{ +} + +CustomUtdInstaller &CustomUtdInstaller::GetInstance() +{ + static CustomUtdInstaller instance; + return instance; +} + +sptr CustomUtdInstaller::GetBundleManager() +{ + auto samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (samgrProxy == nullptr) { + ZLOGE("samgrProxy is null."); + return nullptr; + } + auto bmsProxy = samgrProxy->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (bmsProxy == nullptr) { + ZLOGE("failed to get bms from samgrProxy."); + } + return iface_cast(bmsProxy); +} + +int32_t CustomUtdInstaller::InstallUtd(const std::string &bundleName, int32_t user) +{ + std::string path = CUSTOM_UTD_PATH + std::to_string(user) + CUSTOM_UTD_FILE; + std::vector customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(path); + std::vector presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + std::vector modules = GetHapModules(bundleName, user); + for (std::string module : modules) { + auto utdTypes = GetModuleCustomUtdTypes(bundleName, module, user); + if (!UtdCfgsChecker::GetInstance().CheckTypeDescriptors(utdTypes, presetTypes, customTyepCfgs, bundleName)) { + ZLOGE("Parse json failed, moduleName: %{public}s, bundleName: %{public}s.", module.c_str(), + bundleName.c_str()); + continue; + } + // Update customTyepCfgs used for subsequent persistence of type definitions. + for (TypeDescriptorCfg &declarationType : utdTypes.first) { + for (auto iter = customTyepCfgs.begin(); iter != customTyepCfgs.end();) { + if (iter->typeId == declarationType.typeId) { + declarationType.installerBundles = iter->installerBundles; + iter = customTyepCfgs.erase(iter); + } else { + iter ++; + } + } + declarationType.installerBundles.emplace(bundleName); + declarationType.ownerBundle = bundleName; + customTyepCfgs.push_back(declarationType); + } + for (TypeDescriptorCfg &referenceType : utdTypes.second) { + bool found = false; + for (auto &typeCfg : customTyepCfgs) { + if (typeCfg.typeId == referenceType.typeId) { + typeCfg.installerBundles.emplace(bundleName); + found = true; + break; + } + } + if (!found) { + referenceType.installerBundles.emplace(bundleName); + customTyepCfgs.push_back(referenceType); + } + } + CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, path); + } + return E_OK; +} + +int32_t CustomUtdInstaller::UninstallUtd(const std::string &bundleName, int32_t user) +{ + std::string path = CUSTOM_UTD_PATH + std::to_string(user) + CUSTOM_UTD_FILE; + std::vector customTyepCfgs = CustomUtdStore::GetInstance().GetTypeCfgs(path); + std::vector deletionMock; + if (!customTyepCfgs.empty()) { + deletionMock.insert(deletionMock.end(), customTyepCfgs.begin(), customTyepCfgs.end()); + } + for (auto iter = deletionMock.begin(); iter != deletionMock.end();) { + auto it = find (iter->installerBundles.begin(), iter->installerBundles.end(), bundleName); + if (it != iter->installerBundles.end()) { + iter->installerBundles.erase(it); + } + if (iter->installerBundles.empty()) { + iter = deletionMock.erase(iter); + } else { + iter++; + } + } + std::vector presetTypes = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + if (!UtdCfgsChecker::GetInstance().CheckBelongingToTypes(deletionMock, presetTypes)) { + ZLOGW("Uninstall error, because of belongingToTypes check failed."); + return E_ERROR; + } + for (auto customIter = customTyepCfgs.begin(); customIter != customTyepCfgs.end();) { + auto InstallerIter = find (customIter->installerBundles.begin(), customIter->installerBundles.end(), + bundleName); + if (InstallerIter != customIter->installerBundles.end()) { + customIter->installerBundles.erase(InstallerIter); + } + if (customIter->installerBundles.empty()) { + customIter = customTyepCfgs.erase(customIter); + } else { + customIter++; + } + } + CustomUtdStore::GetInstance().SaveTypeCfgs(customTyepCfgs, path); + return E_OK; +} + +std::vector CustomUtdInstaller::GetHapModules(const std::string &bundleName, int32_t user) +{ + std::vector modules; + auto bundlemgr = GetBundleManager(); + AppExecFwk::BundleInfo bundleInfo; + if (!bundlemgr->GetBundleInfo(bundleName, AppExecFwk::BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo, user)) { + ZLOGE("Get local bundle info failed, bundleName: %{public}s.", bundleName.c_str()); + } + return bundleInfo.hapModuleNames; +} + +std::pair, std::vector> CustomUtdInstaller::GetModuleCustomUtdTypes( + const std::string &bundleName, const std::string &moduleName, int32_t user) +{ + auto bundlemgr = GetBundleManager(); + std::string jsonStr; + std::pair, std::vector> typeCfgs; + auto status = bundlemgr->GetJsonProfile(AppExecFwk::ProfileType::UTD_SDT_PROFILE, bundleName, moduleName, jsonStr, + user); + if (status != NO_ERROR) { + ZLOGE("get local bundle info failed, jsonStr is %{public}s.", jsonStr.c_str()); + return typeCfgs; + } + std::vector declarationType; + std::vector referenceType; + + CustomUtdJsonParser customUtdJsonParser_; + bool res = customUtdJsonParser_.ParseUserCustomUtdJson(jsonStr, declarationType, referenceType); + if (!jsonStr.empty() && res) { + typeCfgs.first = declarationType; + typeCfgs.second = referenceType; + } + return typeCfgs; +} +} +} diff --git a/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.h b/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.h new file mode 100644 index 0000000000000000000000000000000000000000..40a5c3bd4421e52e90798377ad36a4c3a0e48a4b --- /dev/null +++ b/datamgr_service/services/distributeddataservice/service/udmf/utd/custom_utd_installer.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DATAMGR_SERVICE_UTD_MANAGER_H +#define DATAMGR_SERVICE_UTD_MANAGER_H + +#include +#include + +#include "bundlemgr/bundle_mgr_proxy.h" +#include "utd_common.h" +#include "utd_cfgs_checker.h" +#include "system_ability.h" + +namespace OHOS { +namespace UDMF { +class CustomUtdInstaller { +public: + static CustomUtdInstaller &GetInstance(); + int32_t InstallUtd(const std::string &bundleName, int32_t user); + int32_t UninstallUtd(const std::string &bundleName, int32_t user); + +private: + CustomUtdInstaller(); + ~CustomUtdInstaller(); + CustomUtdInstaller(const CustomUtdInstaller &obj) = delete; + CustomUtdInstaller &operator=(const CustomUtdInstaller &obj) = delete; + sptr GetBundleManager(); + std::vector GetHapModules(const std::string &bundleName, int32_t user); + std::pair, std::vector> GetModuleCustomUtdTypes( + const std::string &bundleName, const std::string &moduleName, int32_t user); +}; +} // namespace UDMF +} // namespace OHOS +#endif // DATAMGR_SERVICE_UTD_MANAGER_H diff --git a/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn b/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn deleted file mode 100644 index 92344ab4c02b9b97f49192a543f9048af666b183..0000000000000000000000000000000000000000 --- a/datamgr_service/test/fuzztest/autolaunch_fuzzer/BUILD.gn +++ /dev/null @@ -1,105 +0,0 @@ -# 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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") - -##############################fuzztest########################################## -ohos_fuzztest("AutoLaunchFuzzTest") { - module_out_path = "datamgr_service/distributeddatafwk" - - include_dirs = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/src/sqlite", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/src/multiver", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - ] - - fuzz_config_file = "//foundation/distributeddatamgr/datamgr_service/test/fuzztest/autolaunch_fuzzer" - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - ] - sources = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common/distributeddb_tools_test.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.cpp", - "autolaunch_fuzzer.cpp", - ] - - defines = [ - "SQLITE_ENABLE_SNAPSHOT", - "_LARGEFILE64_SOURCE", - "_FILE_OFFSET_BITS=64", - "SQLITE_HAS_CODEC", - "SQLITE_ENABLE_JSON1", - "USING_HILOG_LOGGER", - "USE_SQLITE_SYMBOLS", - "USING_DB_JSON_EXTRACT_AUTOMATICALLY", - "LOW_LEVEL_MEM_DEV", - "JSONCPP_USE_BUILDER", - "OMIT_FLATBUFFER", - "RELATIONAL_STORE", - "SQLITE_DISTRIBUTE_RELATIONAL", - "OPENSSL_SUPPRESS_DEPRECATED", - ] - - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - ] -} - -############################################################################### -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":AutoLaunchFuzzTest", - ] -} -############################################################################### diff --git a/datamgr_service/test/fuzztest/autolaunch_fuzzer/autolaunch_fuzzer.cpp b/datamgr_service/test/fuzztest/autolaunch_fuzzer/autolaunch_fuzzer.cpp deleted file mode 100644 index a5cc1fad5222c6b782e85156de2e882b637fd055..0000000000000000000000000000000000000000 --- a/datamgr_service/test/fuzztest/autolaunch_fuzzer/autolaunch_fuzzer.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 "autolaunch_fuzzer.h" -#include "distributeddb_data_generate_unit_test.h" -#include "distributeddb_tools_test.h" - -using namespace DistributedDB; -using namespace DistributedDBTest; -using namespace DistributedDBUnitTest; -namespace OHOS { -static auto g_kvManager = KvStoreDelegateManager(APP_ID, USER_ID); - -void EnableAutoLaunchFuzz(const uint8_t *data, size_t size) -{ - KvStoreConfig config; - DistributedDBToolsTest::TestDirInit(config.dataDir); - g_kvManager.SetKvStoreConfig(config); - std::string rawString(reinterpret_cast(data), size); - CipherPassword passwd; - passwd.SetValue(data, size); - AutoLaunchOption launchOption; - KvStoreDelegateManager::EnableKvStoreAutoLaunch(USER_ID, APP_ID, rawString, launchOption, nullptr); - AutoLaunchOption launchOption1 {true, false, CipherType::DEFAULT, passwd, "", false, config.dataDir, nullptr}; - KvStoreDelegateManager::EnableKvStoreAutoLaunch(USER_ID, APP_ID, "StoreId1", launchOption1, nullptr); - AutoLaunchOption launchOption2 {true, true, CipherType::DEFAULT, passwd, "", false, config.dataDir, nullptr}; - KvStoreDelegateManager::EnableKvStoreAutoLaunch(USER_ID, APP_ID, "StoreId2", launchOption2, nullptr); - AutoLaunchOption launchOption3 {false, true, CipherType::DEFAULT, passwd, "", false, config.dataDir, nullptr}; - KvStoreDelegateManager::EnableKvStoreAutoLaunch(USER_ID, APP_ID, "StoreId3", launchOption3, nullptr); - AutoLaunchOption launchOption4 {false, false, CipherType::DEFAULT, passwd, "", false, config.dataDir, nullptr}; - KvStoreDelegateManager::EnableKvStoreAutoLaunch(USER_ID, APP_ID, "StoreId4", launchOption4, nullptr); -} - -void DisableAutoLaunchFUzz(const uint8_t *data, size_t size) -{ - KvStoreConfig config; - DistributedDBToolsTest::TestDirInit(config.dataDir); - g_kvManager.SetKvStoreConfig(config); - std::string rawString(reinterpret_cast(data), size); - CipherPassword passwd; - passwd.SetValue(data, size); - KvStoreDelegateManager::DisableKvStoreAutoLaunch(USER_ID, APP_ID, rawString); - passwd.SetValue(data, size); - KvStoreNbDelegate::Option option {true, true, false, CipherType::DEFAULT, passwd}; - KvStoreNbDelegate *kvNbDelegatePtr = nullptr; - g_kvManager.GetKvStore(rawString, option, - [&kvNbDelegatePtr](DBStatus status, KvStoreNbDelegate* kvNbDelegate) { - if (status == DBStatus::OK) { - kvNbDelegatePtr = kvNbDelegate; - } - }); - KvStoreDelegateManager::DisableKvStoreAutoLaunch(USER_ID, APP_ID, rawString); -} -} - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - /* Run your code on data */ - OHOS::EnableAutoLaunchFuzz(data, size); - OHOS::DisableAutoLaunchFUzz(data, size); - return 0; -} - diff --git a/datamgr_service/test/fuzztest/autolaunch_fuzzer/project.xml b/datamgr_service/test/fuzztest/autolaunch_fuzzer/project.xml deleted file mode 100644 index be92381e05fc528d2fba5603365ee6df71b5b840..0000000000000000000000000000000000000000 --- a/datamgr_service/test/fuzztest/autolaunch_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 30 - - 4096 - - diff --git a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn deleted file mode 100644 index d6de3de8e84b3ce70dae1eb3e0860047fc55e02c..0000000000000000000000000000000000000000 --- a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/BUILD.gn +++ /dev/null @@ -1,106 +0,0 @@ -# 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. - -#####################hydra-fuzz################### -import("//build/config/features.gni") -import("//build/test.gni") - -##############################fuzztest########################################## -ohos_fuzztest("KvStoreDiskSizeFuzzTest") { - module_out_path = "datamgr_service/distributeddatafwk" - - include_dirs = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/interfaces/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/src/sqlite", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/storage/src/multiver", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/communicator/src", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/syncer/src", - "//commonlibrary/c_utils/base/include", - "//third_party/sqlite/include", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/include/relational", - "//third_party/jsoncpp/include/json", - "//third_party/skia/third_party/externals/spirv-headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/skia/third_party/externals/swiftshader/third_party/SPIRV-Headers/tools/buildHeaders/jsoncpp/dist/json", - "//third_party/jsoncpp/include/json", - "//third_party/grpc/src/core/lib/json", - ] - - fuzz_config_file = "//foundation/distributeddatamgr/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer" - - cflags = [ - "-g", - "-O0", - "-Wno-unused-variable", - "-fno-omit-frame-pointer", - ] - - sources = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common/distributeddb_tools_test.cpp", - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_data_generate_unit_test.cpp", - "kvstoredisksize_fuzzer.cpp", - ] - - defines = [ - "SQLITE_ENABLE_SNAPSHOT", - "_LARGEFILE64_SOURCE", - "_FILE_OFFSET_BITS=64", - "SQLITE_HAS_CODEC", - "SQLITE_ENABLE_JSON1", - "USING_HILOG_LOGGER", - "USE_SQLITE_SYMBOLS", - "USING_DB_JSON_EXTRACT_AUTOMATICALLY", - "LOW_LEVEL_MEM_DEV", - "JSONCPP_USE_BUILDER", - "OMIT_FLATBUFFER", - "RELATIONAL_STORE", - "SQLITE_DISTRIBUTE_RELATIONAL", - "OPENSSL_SUPPRESS_DEPRECATED", - ] - - deps = [ - "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", - "//third_party/jsoncpp:jsoncpp", - "//third_party/openssl:libcrypto_shared", - ] - - external_deps = [ - "c_utils:utils", - "hilog:libhilog", - ] -} - -############################################################################### -group("fuzztest") { - testonly = true - deps = [] - deps += [ - # deps file - ":KvStoreDiskSizeFuzzTest", - ] -} -############################################################################### diff --git a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/corpus/init b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/corpus/init deleted file mode 100644 index 8eb5a7d6eb6b7d71f0c70c244e5768d62bee6ac5..0000000000000000000000000000000000000000 --- a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/corpus/init +++ /dev/null @@ -1,16 +0,0 @@ -/* - * 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. - */ - -FUZZ \ No newline at end of file diff --git a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/kvstoredisksize_fuzzer.cpp b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/kvstoredisksize_fuzzer.cpp deleted file mode 100644 index 30ecbee14ffc435a1c3189dcf4b912d7980c7437..0000000000000000000000000000000000000000 --- a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/kvstoredisksize_fuzzer.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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 "kvstoredisksize_fuzzer.h" -#include "distributeddb_tools_test.h" - -using namespace DistributedDB; -using namespace DistributedDBTest; -namespace OHOS { -static auto g_kvManager = KvStoreDelegateManager("APP_ID", "USER_ID"); -void NbDbTest(const uint8_t *data, size_t size) -{ - std::string rawString(reinterpret_cast(data), size); - CipherPassword passwd; - passwd.SetValue(data, size); - KvStoreNbDelegate::Option nbOption {true, true, false, CipherType::DEFAULT, passwd}; - KvStoreNbDelegate *kvNbDelegatePtr = nullptr; - g_kvManager.GetKvStore(rawString, nbOption, - [&kvNbDelegatePtr](DBStatus status, KvStoreNbDelegate* kvNbDelegate) { - if (status == DBStatus::OK) { - kvNbDelegatePtr = kvNbDelegate; - } - }); - - if (kvNbDelegatePtr != nullptr) { - Key key; - Value value; - DistributedDBToolsTest::GetRandomKeyValue(key, DBConstant::MAX_KEY_SIZE); - DistributedDBToolsTest::GetRandomKeyValue(value, DBConstant::MAX_VALUE_SIZE); - kvNbDelegatePtr->Put(key, value); - g_kvManager.CloseKvStore(kvNbDelegatePtr); - } - uint64_t dbSize = 0; - g_kvManager.GetKvStoreDiskSize(rawString, dbSize); - g_kvManager.DeleteKvStore(rawString); -} -} - -/* Fuzzer entry point */ -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) -{ - /* Run your code on data */ - std::string rawString(reinterpret_cast(data), size); - KvStoreDelegateManager::SetProcessLabel(rawString, rawString); - KvStoreConfig config; - DistributedDBToolsTest::TestDirInit(config.dataDir); - OHOS::g_kvManager.SetKvStoreConfig(config); - OHOS::NbDbTest(data, size); - DistributedDBToolsTest::RemoveTestDbFiles(config.dataDir); - return 0; -} - diff --git a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/project.xml b/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/project.xml deleted file mode 100644 index be92381e05fc528d2fba5603365ee6df71b5b840..0000000000000000000000000000000000000000 --- a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/project.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - 1000 - - 30 - - 4096 - - diff --git a/datamgr_service/test/resource/distributeddb/baseline.xml b/datamgr_service/test/resource/distributeddb/baseline.xml deleted file mode 100644 index a8b2364c9584265885642617a24f7493cad81506..0000000000000000000000000000000000000000 --- a/datamgr_service/test/resource/distributeddb/baseline.xml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/datamgr_service/test/resource/distributeddb/ohos_test.xml b/datamgr_service/test/resource/distributeddb/ohos_test.xml deleted file mode 100644 index 21fc76dca56ce7c1989678453b7245b2e39a8e07..0000000000000000000000000000000000000000 --- a/datamgr_service/test/resource/distributeddb/ohos_test.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - diff --git a/interface_sdk/api/@ohos.data.cloudData.d.ts b/interface_sdk/api/@ohos.data.cloudData.d.ts index cc985208092da81566b42736026f1ff72f411dfe..46ae94b9756bbb2e03058011020e1b486ab671e4 100644 --- a/interface_sdk/api/@ohos.data.cloudData.d.ts +++ b/interface_sdk/api/@ohos.data.cloudData.d.ts @@ -14,11 +14,10 @@ */ import { AsyncCallback } from './@ohos.base'; -import relationalStore from "./@ohos.data.relationalStore"; declare namespace cloudData { /** - * Enumerates the types of the clear action. + * Describes the clear action type. * * @enum { number } * @syscap SystemCapability.DistributedDataManager.CloudSync.Config @@ -27,8 +26,7 @@ declare namespace cloudData { */ enum ClearAction { /** - * Clear cloud-related data only, which includes the cloud meta data and - * local cloud-related data. + * Indicates clearing cloud-related data only, which includes cloud meta data and cloud-related local data. * * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi @@ -37,7 +35,7 @@ declare namespace cloudData { CLEAR_CLOUD_INFO, /** - * Clear all cloud-related file data, which is synchronized with the cloud. + * Indicates clearing all cloud-related file data,which synchronized with the cloud. * * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi @@ -47,7 +45,59 @@ declare namespace cloudData { } /** - * Provides methods to set cloud-device synchronization. + * ID of the event, which indicates the change of the data in the cloud. + * + * @constant + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @since 11 + */ + const DATA_CHANGE_EVENT_ID = 'cloud_data_change'; + + /** + * Extra data for data change notification. + * + * @interface ExtraData + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 11 + */ + interface ExtraData { + /** + * Event ID. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 11 + */ + eventId: string; + + /** + * Extra data, which contains the following fields. + * { + * "accountId": "aaa", + * "bundleName": "com.bbb.xxx", + * "containerName": "alias", + * "databaseScopes": ["private", "shared"], + * "recordTypes": ["xxx", "yyy", "zzz"], + * "properties": { + * "key": "value" + * }, + * "keyId": "", + * "signV3": "" + * } + * accountId and bundleName are mandatory. + * + * @type { string } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @systemapi + * @since 11 + */ + extraData: string; + } + + /** + * Provides methods to set CloudSync config. * * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi @@ -58,19 +108,13 @@ declare namespace cloudData { * Enables the cloud function. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is - * a value obtained by hashing the cloud account ID. - * @param { { [bundleName:string]:boolean } } switches - Indicates switches - * of all applications. It overwrites the saved application switch information. - * If an application switch changes, the {@link changeAppCloudSwitch - * (accountId: string, bundleName: string, status: boolean)} method will be - * called to notify the data manager service. - * @param { AsyncCallback } callback - Indicates the callback invoked - * to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. + * @param { object } switches - Indicates switches information of all applications. + * switches will overwrite the saved application switch information.If the specific application switch changes, + * the {@link changeAppCloudSwitch(accountId: string, bundleName: string, status: boolean)} method will notify the data manager service. + * @param { AsyncCallback } callback - the callback of enableCloud. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config @@ -87,18 +131,13 @@ declare namespace cloudData { * Enables the cloud function. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is - * a value obtained by hashing the cloud account ID. - * @param { { [bundleName:string]:boolean } } switches - Indicates switches - * of all applications. It overwrites the saved application switch information. - * If an application switch changes, the {@link changeAppCloudSwitch - * (accountId: string, bundleName: string, status: boolean)} method will be - * called to notify the data manager service. - * @returns { Promise } Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. + * @param { object } switches - Indicates switches information of all applications. + * switches will overwrite the saved application switch information.If the specific application switch changes, + * the {@link changeAppCloudSwitch(accountId: string, bundleName: string, status: boolean)} method will notify the data manager service. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config @@ -111,14 +150,10 @@ declare namespace cloudData { * Disables the cloud function. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is - * a value obtained by hashing the cloud account ID. - * @param { AsyncCallback } callback - Indicates the callback invoked - * to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. + * @param { AsyncCallback } callback - the callback of disableCloud. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config @@ -131,13 +166,10 @@ declare namespace cloudData { * Disables the cloud function. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is - * a value obtained by hashing the cloud account ID. - * @returns { Promise } Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config @@ -150,18 +182,12 @@ declare namespace cloudData { * Changes the cloud switch of a single application. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is a value - * obtained by hashing the cloud account ID. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. * @param { string } bundleName - Indicates the name of application. - * @param { boolean } status - Indicates whether to enable cloud-device - * synchronization. The value true means to enable cloud-device - * synchronization; the value false means the opposite. - * @param { AsyncCallback } callback - Indicates the callback invoked - * to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @param { boolean } status - Indicates the condition of cloud sync switch.true means the switch is on,false means switch is off. + * @param { AsyncCallback } callback - the callback of changeAppCloudSwitch. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config @@ -179,17 +205,12 @@ declare namespace cloudData { * Changes the cloud switch of a single application. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is a value - * obtained by hashing the cloud account ID. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. * @param { string } bundleName - Indicates the name of application. - * @param { boolean } status - Indicates whether to enable cloud-device - * synchronization. The value true means to enable cloud-device - * synchronization; the value false means the opposite. - * @returns { Promise } Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @param { boolean } status - Indicates the condition of cloud sync switch.true means the switch is on,false means switch is off. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config @@ -199,56 +220,47 @@ declare namespace cloudData { static changeAppCloudSwitch(accountId: string, bundleName: string, status: boolean): Promise; /** - * Notifies changes of the cloud records. + * notifies changes of the cloud records * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is a value - * obtained by hashing the cloud account ID. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. * @param { string } bundleName - Indicates the name of application. - * @param { AsyncCallback } callback - Indicates the callback invoked - * to report the data changes. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @param { AsyncCallback } callback - the callback of notifyDataChange. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @syscap SystemCapability.DistributedDataManager.CloudSync.Server * @systemapi * @since 10 */ static notifyDataChange(accountId: string, bundleName: string, callback: AsyncCallback): void; /** - * Notifies changes of the cloud records. + * notifies changes of the cloud records * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is a value - * obtained by hashing the cloud account ID. + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. * @param { string } bundleName - Indicates the name of application. - * @returns { Promise } Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudSync.Config + * @syscap SystemCapability.DistributedDataManager.CloudSync.Server * @systemapi * @since 10 */ static notifyDataChange(accountId: string, bundleName: string): Promise; /** - * Clears cloud information from the local device. + * Notifies changes of the cloud records. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is a value - * obtained by hashing the cloud account ID. - * @param { { [bundleName: string]: ClearAction } } appActions - Indicates - * the clear operation to perform. + * @param { ExtraData } extInfo - Indicates the extra data for + * notification {@link ExtraData}. * @param { AsyncCallback } callback - Indicates the callback invoked - * to return the result. + * to return the data changes. * @throws { BusinessError } 201 - Permission verification failed, which * is usually returned by VerifyAccessToken. * @throws { BusinessError } 202 - Permission verification failed, which is @@ -257,23 +269,19 @@ declare namespace cloudData { * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi - * @since 10 + * @since 11 */ - static clear( - accountId: string, - appActions: { [bundleName: string]: ClearAction }, - callback: AsyncCallback - ): void; + static notifyDataChange(extInfo: ExtraData, callback: AsyncCallback): void; /** - * Clears cloud information from a local device. + * Notifies changes of the cloud records. * * @permission ohos.permission.CLOUDDATA_CONFIG - * @param { string } accountId - Indicates the account ID, which is a value - * obtained by hashing the cloud account ID. - * @param { { [bundleName: string]: ClearAction } } appActions - Indicates - * the clear operation to perform. - * @returns { Promise } Promise used to return the result. + * @param { ExtraData } extInfo - Indicates the extra data for + * notification {@link ExtraData}. + * @param { number } userId - Indicates the user ID. + * @param { AsyncCallback } callback - Indicates the callback invoked + * to return the data changes. * @throws { BusinessError } 201 - Permission verification failed, which * is usually returned by VerifyAccessToken. * @throws { BusinessError } 202 - Permission verification failed, which is @@ -282,639 +290,68 @@ declare namespace cloudData { * @throws { BusinessError } 801 - Capability not supported. * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi - * @since 10 - */ - static clear(accountId: string, appActions: { [bundleName: string]: ClearAction }): Promise; - } - - /** - * Provides methods to implement cloud sharing. - * - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - export namespace sharing { - /** - * Enumerates the roles. - * - * @enum { number } - * @syscap systemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - enum Role { - /** - * Inviter of cloud sharing. - * - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - ROLE_INVITER, - - /** - * Invitee of cloud sharing. - * - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - ROLE_INVITEE - } - - /** - * Enumerates the statuses of sharing invitation. - * - * @enum { number } - * @syscap systemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - enum Status { - /** - * Unknown status. - * - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - STATUS_UNKNOWN, - - /** - * Accept the sharing invitation. - * - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - STATUS_ACCEPTED, - - /** - * Reject the sharing invitation. - * - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - STATUS_REJECTED, - - /** - * Suspend the sharing process. - * - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - STATUS_SUSPENDED, - } - - /** - * Result interface. - * - * @interface Result - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @StageModelOnly - * @since 11 - */ - export interface Result { - /** - * Error code. - * - * @type { number } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - code: number; - - /** - * The result value. - * - * @type { T } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - value: T; - } - - /** - * Privilege for the shared data. - * - * @interface Privilege - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - export interface Privilege { - /** - * Whether the participants can write the shared data. The value true - * means the participants can write the shared data; the value false - * means the opposite. - * - * @type { ?boolean } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - writeable?: boolean; - - /** - * Whether the participants can read the shared data. The value true - * means the participants can read the shared data; the value false - * means the opposite. - * - * @type { ?boolean } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - readable?: boolean; - - /** - * Whether the participants can create data. The value true - * means the participants can create data; the value false - * means the opposite. - * - * @type { ?boolean } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - creatable?: boolean; - - /** - * Whether the participants can delete the shared data. The value true - * means the participants can delete the shared data; the value false - * means the opposite. - * - * @type { ?boolean } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - deletable?: boolean; - - /** - * Whether the participants can share the data. The value true - * means the participants can share the data; the value false - * means the opposite. - * - * @type { ?boolean } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - shareable?: boolean; - } - - /** - * Participants in cloud sharing. - * - * @interface Participant - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - export interface Participant { - /** - * Identity of participant. - * - * @type { string } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - identity: string; - - /** - * Role of the participant, which can be inviter or invitee. - * - * @type { ?Role } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - role?: Role; - - /** - * Status of the sharing invitation. - * - * @type { ?Status } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - status?: Status; - - /** - * Permissions for the shared data. - * - * @type { ?Privilege } - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - privilege?: Privilege; - } - - /** - * Allocates shared resources based on conditions, - * and shares data with the specified privilege to participants. - * - * @param { string } storeId - Indicates relational store name. - * @param { relationalStore.RdbPredicates } predicates - See {@link relationalStore.RdbPredicates}. - * @param { Array } participants - Participants to share. - * @param { AsyncCallback } callback - Indicates the - * callback invoked to return the {@link relationalStore.ResultSet}. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function allocResourceAndShare( - storeId: string, - predicates: relationalStore.RdbPredicates, - participants: Array, - callback: AsyncCallback - ): void; - - /** - * Allocates shared resources based on conditions, - * and shares data with the specified privilege to participants. - * - * @param { string } storeId - Indicates relational store name. - * @param { relationalStore.RdbPredicates } predicates - See {@link relationalStore.RdbPredicates}. - * @param { Array } columns - Columns to be shared. - * @param { Array } participants - Participants to share. - * @param { AsyncCallback } callback - Indicates the - * callback invoked to return the {@link relationalStore.ResultSet}. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function allocResourceAndShare( - storeId: string, - predicates: relationalStore.RdbPredicates, - participants: Array, - columns: Array, - callback: AsyncCallback - ): void; - - /** - * Allocates shared resources based on conditions, - * and shares data with the specified privilege to participants. - * - * @param { string } storeId - Indicates relational store name. - * @param { relationalStore.RdbPredicates } predicates - See {@link relationalStore.RdbPredicates}. - * @param { Array } participants - Participants to share. - * @param { Array } [columns] - Columns to be shared. - * @param { Promise } - Promise used to return {@link relationalStore.ResultSet}. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function allocResourceAndShare( - storeId: string, - predicates: relationalStore.RdbPredicates, - participants: Array, - columns?: Array - ): Promise; - - /** - * Shares data with the specified privilege to participants. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Array } participants - Indicates the participants - * involved in the data sharing. - * @param { AsyncCallback>> } callback - Indicates the - * callback invoked to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function share( - sharingRes: string, - participants: Array, - callback: AsyncCallback>>> - ): void; - - /** - * Shares data with the specified privilege to participants. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Array } participants - Indicates the participants - * involved in the data sharing. - * @Returns { Promise>> } - Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function share(sharingRes: string, participants: Array): Promise>>>; - - /** - * Unshares data. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Array } participants - Indicates the participants - * involved. - * @param { AsyncCallback>> } callback - Indicates the callback invoked - * to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function unshare( - sharingRes: string, - participants: Array, - callback: AsyncCallback>>> - ): void; - - /** - * Unshares data. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Array } participants - Indicates the participants - * involved. - * @Returns { Promise>> } - Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function unshare( - sharingRes: string, - participants: Array - ): Promise>>>; - - /** - * Exit sharing. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { AsyncCallback } callback - The callback of exit. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function exit(sharingRes: string, callback: AsyncCallback>): void; - - /** - * Exit sharing. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @Returns { Promise } - The promise returned by the function. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function exit(sharingRes: string): Promise>; - - /** - * Changes the permissions for the shared data. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Array } participants - Indicates the participants - * whose permissions are to be changed. - * @param { AsyncCallback>> } callback - Indicates the - * callback invoked to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi * @since 11 */ - function changePrivilege( - sharingRes: string, - participants: Array, - callback: AsyncCallback>>> - ): void; + static notifyDataChange(extInfo: ExtraData, userId: number, callback: AsyncCallback): void; /** - * Changes the permissions for the shared data. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Array } participants - Indicates the participants - * whose permissions are to be changed. - * @Returns { Promise>> } - Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function changePrivilege( - sharingRes: string, - participants: Array - ): Promise>>>; - - /** - * Queries the participants based on the specified shared data. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { AsyncCallback>> } callback - Indicates the - * callback invoked to return the participants obtained. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function queryParticipants(sharingRes: string, callback: AsyncCallback>>): void; - - /** - * Queries the participants based on the specified shared data. + * Notifies changes of the cloud records. * - * @param { string } sharingRes - Indicates the sharing resource. - * @Returns { Promise>> } - Promise used to return the result. + * @permission ohos.permission.CLOUDDATA_CONFIG + * @param { ExtraData } extInfo - Indicates the extra data for + * notification {@link ExtraData}. + * @param { number } [userId] - Indicates the user ID. + * @returns { Promise } Promise used to return the result. * @throws { BusinessError } 201 - Permission verification failed, which * is usually returned by VerifyAccessToken. * @throws { BusinessError } 202 - Permission verification failed, which is * returned when the system API is not called by a system application. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi * @since 11 */ - function queryParticipants(sharingRes: string): Promise>>; + static notifyDataChange(extInfo: ExtraData, userId?: number): Promise; /** - * Queries the participants based on the specified invitation code. + * deletes cloud information from local data. * - * @param { string } invitationCode - Indicates the invitation code. - * @param { AsyncCallback>> } callback - Indicates the - * callback invoked to return the participants obtained. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @permission ohos.permission.CLOUDDATA_CONFIG + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing cloud account. + * @param { object } appActions - Indicates the way in which the application data is to be cleared. + * @param { AsyncCallback } callback - the callback of clear. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi - * @since 11 + * @since 10 */ - function queryParticipantsByInvitation( - invitationCode: string, - callback: AsyncCallback>> + static clear( + accountId: string, + appActions: { [bundleName: string]: ClearAction }, + callback: AsyncCallback ): void; /** - * Queries the participants based on the specified invitation code. - * - * @param { string } invitationCode - Indicates the invitation code. - * @Returns { Promise>> } - Promise used to return the result. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function queryParticipantsByInvitation(invitationCode: string): Promise>>; - - /** - * Confirms the invitation of cloud sharing. + * deletes cloud information from local data. * - * @param { string } invitationCode - Indicates the invitation code. - * @param { Status } status - Indicates the status of invitation. - * @param { AsyncCallback> } callback - Indicates the callback - * invoked to return the sharing resource. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function confirmInvitation(invitationCode: string, status: Status, callback: AsyncCallback>): void; - - /** - * Confirms the invitation of cloud sharing. - * - * @param { string } invitationCode - Indicates the invitation code. - * @param { Status } status - Indicates the status of invitation. - * @Returns { Promise> } - Promise used to return the sharing resource. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function confirmInvitation(invitationCode: string, status: Status): Promise>; - - /** - * Changes confirmation of shared record. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Status } status - Indicates the status of invitation. - * @param { AsyncCallback } callback - Indicates the callback. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. - * @throws { BusinessError } 401 - Parameter error. - * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing - * @systemapi - * @since 11 - */ - function changeConfirmation(sharingRes: string, status: Status, callback: AsyncCallback>): void; - - /** - * Changes confirmation of shared record. - * - * @param { string } sharingRes - Indicates the sharing resource. - * @param { Status } status - Indicates the status of invitation. - * @Returns { Promise } - The promise returned by the function. - * @throws { BusinessError } 201 - Permission verification failed, which - * is usually returned by VerifyAccessToken. - * @throws { BusinessError } 202 - Permission verification failed, which is - * returned when the system API is not called by a system application. + * @permission ohos.permission.CLOUDDATA_CONFIG + * @param { string } accountId - Indicates the account ID. The account ID is required by hashing the information of specific opened cloud. + * @param { object } appActions - Indicates the way in which the application data is to be cleared. + * @returns { Promise } the promise returned by the function. + * @throws { BusinessError } 201 - Permission verification failed, usually the result returned by VerifyAccessToken. + * @throws { BusinessError } 202 - Permission verification failed, application which is not a system application uses system API. * @throws { BusinessError } 401 - Parameter error. * @throws { BusinessError } 801 - Capability not supported. - * @syscap SystemCapability.DistributedDataManager.CloudData.Sharing + * @syscap SystemCapability.DistributedDataManager.CloudSync.Config * @systemapi - * @since 11 + * @since 10 */ - function changeConfirmation(sharingRes: string, status: Status): Promise>; + static clear(accountId: string, appActions: { [bundleName: string]: ClearAction }): Promise; } } -export default cloudData; \ No newline at end of file +export default cloudData; diff --git a/interface_sdk/api/@ohos.data.distributedDataObject.d.ts b/interface_sdk/api/@ohos.data.distributedDataObject.d.ts index f0cdbe67d0790fbe0287c8115d310212c80322a2..ca989b6a6fdb0ace93c29368fbd6d5f7d0cf2c56 100644 --- a/interface_sdk/api/@ohos.data.distributedDataObject.d.ts +++ b/interface_sdk/api/@ohos.data.distributedDataObject.d.ts @@ -85,7 +85,7 @@ declare namespace distributedDataObject { /** * deviceid that data saved * data is "local", means save in local device - * otherwise, means the networkId of device + * otherwise, means the deviceId of others device * * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 9 @@ -141,7 +141,7 @@ declare namespace distributedDataObject { * @param { Function } callback * Indicates the observer of object data changed. * {string} sessionId - The sessionId of the changed object. - * {Array} fields - Changed data. + * {Array} fields - Attribute names of changed data. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 8 * @deprecated since 9 @@ -156,7 +156,7 @@ declare namespace distributedDataObject { * @param { Function } callback * Indicates the observer of object data changed. * {string} sessionId - The sessionId of the changed object. - * {Array} fields - Changed data. + * {Array} fields - Attribute names of changed data. * callback If not null, off the callback, if undefined, off all callbacks. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject * @since 8 @@ -232,10 +232,9 @@ declare namespace distributedDataObject { setSessionId(sessionId: string, callback: AsyncCallback): void; /* - * Change object session. + * Leave all session. * * @permission ohos.permission.DISTRIBUTED_DATASYNC - * @param {string} sessionId - sessionId The sessionId to be joined, if empty, leave all session. * @param {AsyncCallback} callback - The callback of setSessionId. * @throws {BusinessError} 201 - Permission verification failed. * @throws {BusinessError} 401 - Parameter error. @@ -264,10 +263,9 @@ declare namespace distributedDataObject { * * @param { 'change' } type - event type, fixed as 'change', indicates data change. * @param { Function } callback - * * indicates the observer of object data changed. * {string} sessionId - the sessionId of the changed object. - * {Array} fields - changed data. + * {Array} fields - Attribute names of changed data. * sessionId The sessionId of the changed object. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject @@ -282,7 +280,7 @@ declare namespace distributedDataObject { * @param { Function } callback * indicates the observer of object data changed. * {string} sessionId - The sessionId of the changed object. - * {Array} fields - Changed data. + * {Array} fields - Attribute names of changed data. * callback If not null, off the callback, if undefined, off all callbacks. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.DataObject.DistributedObject diff --git a/interface_sdk/api/@ohos.data.distributedKVStore.d.ts b/interface_sdk/api/@ohos.data.distributedKVStore.d.ts index 80d31f19a722dc3681c76a14dbf9dea193a72595..836cdacdcf981c23d9a7f4687c5a0c8c08dfda42 100644 --- a/interface_sdk/api/@ohos.data.distributedKVStore.d.ts +++ b/interface_sdk/api/@ohos.data.distributedKVStore.d.ts @@ -750,7 +750,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is equal to the specified long value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -762,7 +762,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is not equal to the specified int value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -775,7 +775,7 @@ declare namespace distributedKVStore { * Constructs a {@code Query} object to query entries with the specified field whose value is greater than or equal to the * specified int value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string | boolean } value - Indicates the value to be compared. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -787,7 +787,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is less than the specified int value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string } value - Indicates the value to be compared. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -800,7 +800,7 @@ declare namespace distributedKVStore { * Constructs a {@code Query} object to query entries with the specified field whose value is greater than or * equal to the specified int value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string } value - Indicates the value to be compared. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -813,7 +813,7 @@ declare namespace distributedKVStore { * Constructs a {@code Query} object to query entries with the specified field whose value is less than or equal to the * specified int value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number | string } value - Indicates the value to be compared. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -825,7 +825,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is null. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -836,7 +836,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified int value list. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number[] } valueList - Indicates the int value list. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -848,7 +848,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is within the specified string value list. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { string[] } valueList - Indicates the string value list. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -860,7 +860,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is not within the specified int value list. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { number[] } valueList - Indicates the int value list. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -872,7 +872,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is not within the specified string value list. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { string[] } valueList - Indicates the string value list. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -884,7 +884,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is similar to the specified string value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { string } value - Indicates the string value. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -896,7 +896,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to query entries with the specified field whose value is not similar to the specified string value. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @param { string } value - Indicates the string value. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. @@ -928,7 +928,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to sort the query results in ascending order. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.KVStore.Core @@ -939,7 +939,7 @@ declare namespace distributedKVStore { /** * Constructs a {@code Query} object to sort the query results in descending order. * - * @param { string } field - Indicates the field, which must start with $. and cannot contain ^. + * @param { string } field - Indicates the field, which cannot contain ^. * @returns { Query } Returns the {@coed Query} object. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.KVStore.Core diff --git a/interface_sdk/api/@ohos.data.preferences.d.ts b/interface_sdk/api/@ohos.data.preferences.d.ts index 8d538eae8d38a0e9150334fb395a9bb3e9d98d10..a0cd2710d499d2086906544ccfa3520d6c44e825 100644 --- a/interface_sdk/api/@ohos.data.preferences.d.ts +++ b/interface_sdk/api/@ohos.data.preferences.d.ts @@ -33,6 +33,16 @@ import Context from './application/BaseContext'; * @since 10 * @name preferences */ +/** + * Provides interfaces to obtain and modify preferences data. + * + * @namespace preferences + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + * @name preferences + */ declare namespace preferences { /** * Indicates possible value types @@ -46,7 +56,14 @@ declare namespace preferences { * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 10 */ - type ValueType = number | string | boolean | Array | Array | Array; + /** + * Indicates possible value types + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 11 + */ + type ValueType = number | string | boolean | Array | Array | Array | Uint8Array; /** * Indicates the maximum length of a key (80 characters). @@ -63,6 +80,15 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Indicates the maximum length of a key (80 characters). + * + * @constant + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ const MAX_KEY_LENGTH: 80; /** @@ -80,6 +106,15 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Indicates the maximum length of a string (8192 characters). + * + * @constant + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ const MAX_VALUE_LENGTH: 8192; /** @@ -90,6 +125,15 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Manages preferences file configurations. + * + * @interface Options + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ interface Options { /** * The preferences file name. @@ -98,6 +142,14 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * The preferences file name. + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ name: string; /** @@ -107,6 +159,14 @@ declare namespace preferences { * @StageModelOnly * @since 10 */ + /** + * Application Group Id. + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @StageModelOnly + * @atomicservice + * @since 11 + */ dataGroupId?: string; } @@ -137,6 +197,21 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains a {@link Preferences} instance matching a specified preferences file name. + *

The {@link references} instance loads all data of the preferences file and + * resides in the memory. You can use removePreferencesFromCache to remove the instance from the memory. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the preferences file name. + * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function getPreferences(context: Context, name: string, callback: AsyncCallback): void; /** @@ -156,6 +231,24 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains a {@link Preferences} instance matching a specified preferences file name. + *

The {@link references} instance loads all data of the preferences file and + * resides in the memory. You can use removePreferencesFromCache to remove the instance from the memory. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @param { AsyncCallback } callback - The {@link Preferences} instance matching the specified + * preferences file name. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function getPreferences(context: Context, options: Options, callback: AsyncCallback): void; /** @@ -183,6 +276,20 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains a {@link Preferences} instance matching a specified preferences file name. + *

The {@link references} instance loads all data of the preferences file and + * resides in the memory. You can use removePreferencesFromCache to remove the instance from the memory. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the preferences file name. + * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function getPreferences(context: Context, name: string): Promise; /** @@ -201,6 +308,23 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains a {@link Preferences} instance matching a specified preferences file name. + *

The {@link references} instance loads all data of the preferences file and + * resides in the memory. You can use removePreferencesFromCache to remove the instance from the memory. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @returns { Promise } The {@link Preferences} instance matching the specified preferences file name. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function getPreferences(context: Context, options: Options): Promise; /** @@ -220,6 +344,24 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains a {@link Preferences} instance matching a specified preferences file name. + * This interface is executed synchronously. + *

The {@link references} instance loads all data of the preferences file and + * resides in the memory. You can use removePreferencesFromCache to remove the instance from the memory. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @returns { Preferences } The {@link Preferences} instance matching the specified preferences file name. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function getPreferencesSync(context: Context, options: Options): Preferences; /** @@ -255,6 +397,24 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache which is performed by removePreferencesFromCache and deletes the + * preferences file. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the preferences file name. + * @param { AsyncCallback } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function deletePreferences(context: Context, name: string, callback: AsyncCallback): void; /** @@ -277,6 +437,27 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache which is performed by removePreferencesFromCache and deletes the + * preferences file. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @param { AsyncCallback } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function deletePreferences(context: Context, options: Options, callback: AsyncCallback): void; /** @@ -312,6 +493,24 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache which is performed by removePreferencesFromCache and deletes the + * preferences file. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the preferences file name. + * @returns { Promise } A promise object. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function deletePreferences(context: Context, name: string): Promise; /** @@ -334,6 +533,27 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache which is performed by removePreferencesFromCache and deletes the + * preferences file. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @returns { Promise } A promise object. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15500010 - Failed to delete preferences file. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function deletePreferences(context: Context, options: Options): Promise; /** @@ -365,6 +585,22 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the preferences file name. + * @param { AsyncCallback } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function removePreferencesFromCache(context: Context, name: string, callback: AsyncCallback): void; /** @@ -385,6 +621,25 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @param { AsyncCallback } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function removePreferencesFromCache(context: Context, options: Options, callback: AsyncCallback): void; /** @@ -416,6 +671,22 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the preferences file name. + * @returns { Promise } A promise object. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function removePreferencesFromCache(context: Context, name: string): Promise; /** @@ -436,6 +707,25 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @returns { Promise } A promise object. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function removePreferencesFromCache(context: Context, options: Options): Promise; /** @@ -452,6 +742,21 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache. This interface is executed synchronously. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { string } name - Indicates the preferences file name. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ function removePreferencesFromCacheSync(context: Context, name: string): void; /** @@ -468,11 +773,40 @@ declare namespace preferences { * @throws { BusinessError } 15501001 - Only supported in stage mode. * @throws { BusinessError } 15501002 - The data group id is not valid. * @syscap SystemCapability.DistributedDataManager.Preferences.Core - * @crossplatform - * @since 10 + * @crossplatform + * @since 10 + */ + /** + * Deletes a {@link Preferences} instance matching a specified preferences file name + * from the cache. This interface is executed synchronously. + *

When deleting the {@link Preferences} instance, you must release all references + * of the instance. In addition, do not use the instance to perform data operations. Otherwise, data inconsistency + * will occur. + * + * @param { Context } context - Indicates the context of application or capability. + * @param { Options } options - Indicates the {@link Options} option of preferences file position. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 801 - Capability not supported. + * @throws { BusinessError } 15501001 - Only supported in stage mode. + * @throws { BusinessError } 15501002 - The data group id is not valid. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ + function removePreferencesFromCacheSync(context: Context, options: Options): void; + + /** + * Provides interfaces to obtain and modify preferences data. + *

The preferences data is stored in a file, which matches only one {@link Preferences} instance in the memory. + * You can use getPreferences to obtain the {@link Preferences} instance matching + * the file that stores preferences data, and use movePreferencesFromCache + * to remove the {@link Preferences} instance from the memory. + * + * @interface Preferences + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @since 9 */ - function removePreferencesFromCacheSync(context: Context, options: Options): void; - /** * Provides interfaces to obtain and modify preferences data. *

The preferences data is stored in a file, which matches only one {@link Preferences} instance in the memory. @@ -482,7 +816,8 @@ declare namespace preferences { * * @interface Preferences * @syscap SystemCapability.DistributedDataManager.Preferences.Core - * @since 9 + * @crossplatform + * @since 10 */ /** * Provides interfaces to obtain and modify preferences data. @@ -494,7 +829,8 @@ declare namespace preferences { * @interface Preferences * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform - * @since 10 + * @atomicservice + * @since 11 */ interface Preferences { /** @@ -522,6 +858,20 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains the value of a preferences in the ValueType format. + *

If the value is {@code null} or not in the ValueType format, the default value is returned. + * + * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. + * @param { ValueType } defValue - Indicates the default value to return. + * @param { AsyncCallback } callback - The value matching the specified key if it is found; + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ get(key: string, defValue: ValueType, callback: AsyncCallback): void; /** @@ -549,6 +899,20 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains the value of a preferences in the ValueType format. + *

If the value is {@code null} or not in the ValueType format, the default value is returned. + * + * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. + * @param { ValueType } defValue - Indicates the default value to return. + * @returns { Promise } The value matching the specified key if it is found; + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ get(key: string, defValue: ValueType): Promise; /** @@ -564,6 +928,20 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains the value of a preferences in the ValueType format. This interface is executed synchronously. + *

If the value is {@code null} or not in the ValueType format, the default value is returned. + * + * @param { string } key - Indicates the key of the preferences. It cannot be {@code null} or empty. + * @param { ValueType } defValue - Indicates the default value to return. + * @returns { ValueType } The value matching the specified key if it is found; + * returns the default value otherwise. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ getSync(key: string, defValue: ValueType): ValueType; /** @@ -583,6 +961,16 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains all the keys and values of a preferences in an object. + * + * @param { AsyncCallback } callback - The values and keys in an object. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ getAll(callback: AsyncCallback): void; /** @@ -602,6 +990,16 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains all the keys and values of a preferences in an object. + * + * @returns { Promise } The values and keys in an object. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ getAll(): Promise; /** @@ -614,6 +1012,17 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Obtains all the keys and values of a preferences in an object. This interface + * is executed synchronously. + * + * @returns { Object } The values and keys in an object. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ getAllSync(): Object; /** @@ -637,6 +1046,18 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Checks whether the {@link Preferences} object contains a preferences matching a specified key. + * + * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. + * @param { AsyncCallback } callback - {@code true} if the {@link Preferences} object contains a preferences + * with the specified key;returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ has(key: string, callback: AsyncCallback): void; /** @@ -660,6 +1081,18 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Checks whether the {@link Preferences} object contains a preferences matching a specified key. + * + * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. + * @returns { Promise } {@code true} if the {@link Preferences} object contains + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ has(key: string): Promise; /** @@ -674,6 +1107,19 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Checks whether the {@link Preferences} object contains a preferences matching a specified key. This interface + * is executed synchronously. + * + * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. + * @returns { boolean } {@code true} if the {@link Preferences} object contains + * a preferences with the specified key; returns {@code false} otherwise. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ hasSync(key: string): boolean; /** @@ -682,8 +1128,9 @@ declare namespace preferences { * file. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * @param { ValueType } value - Indicates the value of the preferences. * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core @@ -695,14 +1142,31 @@ declare namespace preferences { * file. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * @param { ValueType } value - Indicates the value of the preferences. * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. * @param { AsyncCallback } callback - Indicates the callback function. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 */ + /** + * Sets an int value for the key in the {@link Preferences} object. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the + * file. + * + * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. + * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. + * @param { AsyncCallback } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ put(key: string, value: ValueType, callback: AsyncCallback): void; /** @@ -711,8 +1175,9 @@ declare namespace preferences { * file. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * @param { ValueType } value - Indicates the value of the preferences. * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core @@ -724,14 +1189,31 @@ declare namespace preferences { * file. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * @param { ValueType } value - Indicates the value of the preferences. * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. * @returns { Promise } A promise object. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 */ + /** + * Sets an int value for the key in the {@link Preferences} object. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the + * file. + * + * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. + * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. + * @returns { Promise } A promise object. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ put(key: string, value: ValueType): Promise; /** @@ -740,13 +1222,29 @@ declare namespace preferences { * file. * * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. - * @param { ValueType } value - Indicates the value of the preferences. * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. * @throws { BusinessError } 401 - Parameter error. * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @crossplatform * @since 10 */ + /** + * Sets an int value for the key in the {@link Preferences} object. This interface is executed synchronously. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the + * file. + * + * @param { string } key - Indicates the key of the preferences to modify. It cannot be {@code null} or empty. + * MAX_KEY_LENGTH. + * @param { ValueType } value - Indicates the value of the preferences. + * MAX_VALUE_LENGTH. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ putSync(key: string, value: ValueType): void; /** @@ -774,6 +1272,20 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes the preferences with a specified key from the {@link Preferences} object. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the + * file. + * + * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. + * MAX_KEY_LENGTH. + * @param { AsyncCallback } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ delete(key: string, callback: AsyncCallback): void; /** @@ -801,6 +1313,20 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes the preferences with a specified key from the {@link Preferences} object. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the + * file. + * + * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. + * MAX_KEY_LENGTH. + * @returns { Promise } A promise object. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ delete(key: string): Promise; /** @@ -815,6 +1341,19 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Deletes the preferences with a specified key from the {@link Preferences} object. This interface is + * executed synchronously.

You can call the {@link #flush} method to save the {@link Preferences} + * object to the file. + * + * @param { string } key - Indicates the key of the preferences to delete. It cannot be {@code null} or empty. + * MAX_KEY_LENGTH. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ deleteSync(key: string): void; /** @@ -834,6 +1373,16 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Clears all preferences from the {@link Preferences} object. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. + * + * @param { AsyncCallback } callback - Indicates the callback function. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ clear(callback: AsyncCallback): void; /** @@ -853,6 +1402,16 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Clears all preferences from the {@link Preferences} object. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. + * + * @returns { Promise } A promise object. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ clear(): Promise; /** @@ -863,6 +1422,15 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Clears all preferences from the {@link Preferences} object. This interface is executed synchronously. + *

You can call the {@link #flush} method to save the {@link Preferences} object to the file. + * + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ clearSync(): void; /** @@ -880,6 +1448,15 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Asynchronously saves the {@link Preferences} object to the file. + * + * @param { AsyncCallback } callback - Indicates the callback function. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ flush(callback: AsyncCallback): void; /** @@ -897,6 +1474,15 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Asynchronously saves the {@link Preferences} object to the file. + * + * @returns { Promise } A promise object. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ flush(): Promise; /** @@ -918,6 +1504,17 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Registers an observer to listen for the change of a {@link Preferences} object. + * + * @param { 'change' } type - Indicates the callback when preferences changes. + * @param { Function } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ on(type: 'change', callback: (key: string) => void): void; /** @@ -930,6 +1527,17 @@ declare namespace preferences { * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 10 */ + /** + * Registers an observer to listen for the change of a {@link Preferences} object. + * + * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. + * @param { Function } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @throws { BusinessError } 15500019 - Failed to obtain subscription service. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 11 + */ on(type: 'multiProcessChange', callback: (key: string) => void): void; /** @@ -951,6 +1559,17 @@ declare namespace preferences { * @crossplatform * @since 10 */ + /** + * Unregisters an existing observer. + * + * @param { 'change' } type - Indicates the callback when preferences changes. + * @param { Function } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @crossplatform + * @atomicservice + * @since 11 + */ off(type: 'change', callback?: (key: string) => void): void; /** @@ -962,6 +1581,16 @@ declare namespace preferences { * @syscap SystemCapability.DistributedDataManager.Preferences.Core * @since 10 */ + /** + * Unregisters an existing observer. + * + * @param { 'multiProcessChange' } type - Indicates the callback when preferences changed in multiple processes. + * @param { Function } callback - Indicates the callback function. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.Preferences.Core + * @atomicservice + * @since 11 + */ off(type: 'multiProcessChange', callback?: (key: string) => void): void; } } diff --git a/interface_sdk/api/@ohos.data.relationalStore.d.ts b/interface_sdk/api/@ohos.data.relationalStore.d.ts index a3f2e3630230181dc73a5acb1e0d143dc4737b85..da0091ce6fa10b5b71980ecaac17289be64c19c0 100644 --- a/interface_sdk/api/@ohos.data.relationalStore.d.ts +++ b/interface_sdk/api/@ohos.data.relationalStore.d.ts @@ -299,6 +299,26 @@ declare namespace relationalStore { * @since 11 */ customDir?: string; + + /** + * Specifies whether to clean up dirty data that is synchronized to + * the local but deleted in the cloud. + * + * @type { ?boolean } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + autoCleanDirtyData?: boolean; + + /** + * Specifies whether data can be searched. + * + * @type { ?boolean } + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @systemapi + * @since 11 + */ + isSearchable?: boolean; } /** @@ -823,6 +843,89 @@ declare namespace relationalStore { ON_CONFLICT_REPLACE = 5 } + /** + * Describes the data origin sources. + * + * @enum { number } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + enum Origin { + /** + * Indicates the data source is local. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + LOCAL, + + /** + * Indicates the data source is cloud. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + CLOUD, + + /** + * Indicates the data source is remote. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + REMOTE, + } + + /** + * Enumerates the field. + * + * @enum { string } + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + enum Field { + /** + * Cursor field. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + CURSOR_FIELD = '#_cursor', + + /** + * Origin field. For details, see {@link Origin}. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + ORIGIN_FIELD = '#_origin', + + /** + * Deleted flag field. + * Indicates whether data has deleted in cloud. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + DELETED_FLAG_FIELD = '#_deleted_flag', + + /** + * Owner field. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + OWNER_FIELD = '#_cloud_owner', + + /** + * Privilege field. + * + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client + * @since 11 + */ + PRIVILEGE_FIELD = '#_cloud_privilege' + } + /** * Manages relational database configurations. * @@ -2018,6 +2121,17 @@ declare namespace relationalStore { */ getAssets(columnIndex: number): Assets; + /** + * Obtains the values of all columns in the specified row. + * + * @returns { ValuesBucket } Indicates the row of data {@link ValuesBucket} to be inserted into the table. + * @throws { BusinessError } 14800000 - Inner error. + * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core + * @crossplatform + * @since 11 + */ + getRow(): ValuesBucket; + /** * Checks whether the value of the specified column in the current row is null. * @@ -2750,73 +2864,50 @@ declare namespace relationalStore { ): void; /** - * SHARING_RESOURCE_FIELD. - * - * @readonly - * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @systemapi - * @since 11 - */ - readonly SHARING_RESOURCE_FIELD: string; - - /** - * SHARING_RESULT_FIELD. + * Cleans the dirty data, which is the data deleted in the cloud. * - * @readonly - * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @systemapi - * @since 11 - */ - readonly SHARING_RESULT_FIELD: string; - - /** - * Obtains sharing resource of rows corresponding to the predicates. + * Data with a cursor smaller than the specified cursor will be cleaned up. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { AsyncCallback } callback - The callback of querySharingResource. - * {@link ResultSet} is query result. + * @param { string } table - Indicates the name of the table to check. + * @param { number } cursor - Indicates the position of the data to be cleaned up. + * @param { AsyncCallback } callback - Indicates the callback invoked to return the result. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. * @throws { BusinessError } 401 - Parameter error. - * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @systemapi + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 - */ - querySharingResource(predicates: RdbPredicates, callback: AsyncCallback): void; + cleanDirtyData(table: string, cursor: number, callback: AsyncCallback): void; /** - * Obtains sharing resource of rows corresponding to the predicates. + * Cleans all dirty data deleted in the cloud. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns - The specified columns to query. - * @param { AsyncCallback } callback - The callback of querySharingResource. - * {@link ResultSet} is query result. + * @param { string } table - Indicates the name of the table to check. + * @param { AsyncCallback } callback - The callback of clean. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. * @throws { BusinessError } 401 - Parameter error. - * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @systemapi + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 */ - querySharingResource(predicates: RdbPredicates, columns: Array, callback: AsyncCallback): void; + cleanDirtyData(table: string, callback: AsyncCallback): void; /** - * Obtains sharing resource of rows corresponding to the predicates. + * Cleans dirty data deleted in the cloud. * - * @param { RdbPredicates } predicates - The specified query condition by the instance object of {@link RdbPredicates}. - * @param { Array } columns? - The specified columns to query. - * @returns { Promise } -The promise returned by the function. - * {@link ResultSet} is query result. + * If a cursor is specified, data with a cursor smaller than the specified cursor will be cleaned up. + * otherwise clean all. + * + * @param { string } table - Indicates the name of the table to check. + * @param { number } [cursor] - Indicates the cursor. + * @returns { Promise } -The promise returned by the function. * @throws { BusinessError } 801 - Capability not supported. * @throws { BusinessError } 14800000 - Inner error. * @throws { BusinessError } 401 - Parameter error. - * @syscap SystemCapability.DistributedDataManager.RelationalStore.Core - * @systemapi + * @syscap SystemCapability.DistributedDataManager.CloudSync.Client * @since 11 - */ - querySharingResource(predicates: RdbPredicates, columns?: Array): Promise; + cleanDirtyData(table: string, cursor?: number): Promise; /** * Executes a SQL statement that contains specified parameters but returns no value. diff --git a/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts b/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts index c3141f7af3031b46b0f1e850324cfcd9d82eb46a..7b66fd9e57eb5010db80bb2fb4a40b728b9ef353 100644 --- a/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts +++ b/interface_sdk/api/@ohos.data.uniformTypeDescriptor.d.ts @@ -29,6 +29,30 @@ declare namespace uniformTypeDescriptor { * @since 10 */ enum UniformDataType { + /** + * Base data type for physical hierarchy, which identifies the physical representation of the data type. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + ENTITY = 'general.entity', + + /** + * Base data type for logical hierarchy, which identifies the logical content representation of the data type. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + OBJECT = 'general.object', + + /** + * Base data type for mixed object. For example, a PDF file contains both text and special formatting data. + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + COMPOSITE_OBJECT = 'general.composite-object', + /** * Text data type. * @@ -731,7 +755,24 @@ declare namespace uniformTypeDescriptor { * @syscap SystemCapability.DistributedDataManager.UDMF.Core * @since 11 */ - OPENHARMONY_ATOMIC_SERVICE = 'openharmony.atomic-service' + OPENHARMONY_ATOMIC_SERVICE = 'openharmony.atomic-service', + + /** + * OpenHarmony system defined package, which is a directory presented to the user as a file(the data is provided + *
and bound to OpenHarmony system). + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + OPENHARMONY_PACKAGE = 'openharmony.package', + + /** + * OpenHarmony system defined ability package(the data is provided and bound to OpenHarmony system). + * + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + OPENHARMONY_HAP = 'openharmony.hap' } /** @@ -792,6 +833,39 @@ declare namespace uniformTypeDescriptor { */ readonly iconFile: string; + /** + * Checks whether the uniform data type belongs to the given uniform data type. + * + * @param { string } type - A uniform data type to be compared. + * @returns { boolean } Returns true if the data type belongs to the given data type, else false. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + belongsTo(type: string): boolean; + + /** + * Checks whether the uniform data type is the lower level type of the given uniform data type. + * + * @param { string } type - A uniform data type to be compared. + * @returns { boolean } Returns true if the data type is the lower level type of the given data type, else false. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + isLowerLevelType(type: string): boolean; + + /** + * Checks whether the uniform data type is the higher level type of the given uniform data type. + * + * @param { string } type - A uniform data type to be compared. + * @returns { boolean } Returns true if the data type is the higher level type of the given data type, else false. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + isHigherLevelType(type: string): boolean; + /** * Checks whether the uniform type descriptor is equal to the given uniform type descriptor. * @@ -815,6 +889,32 @@ declare namespace uniformTypeDescriptor { * @since 11 */ function getTypeDescriptor(typeId: string): TypeDescriptor; + + /** + * Queries and returns the uniform type descriptor by the given filename extension and the uniform data type it belongs to. + * + * @param { string } filenameExtension - Filename extension. + * @param { string } [belongsTo] - A uniform data type ID it belongs to. + * @returns { string } Returns the uniform data type ID corresponding to the given filename extension and the + *
uniform data type it belongs to(If the 'belongsTo' parameter is set) or null if the uniform data type does not exist. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + function getUniformDataTypeByFilenameExtension(filenameExtension: string, belongsTo?: string): string; + + /** + * Queries and returns the uniform type descriptor by the given MIME type and the uniform data type it belongs to. + * + * @param { string } mimeType - MIME type. + * @param { string } [belongsTo] - A uniform data type ID it belongs to. + * @returns { string } Returns the uniform data type ID corresponding to the given MIME type and the uniform data type + *
it belongs to(If the 'belongsTo' parameter is set) or null if the uniform data type does not exist. + * @throws { BusinessError } 401 - Parameter error. + * @syscap SystemCapability.DistributedDataManager.UDMF.Core + * @since 11 + */ + function getUniformDataTypeByMIMEType(mimeType: string, belongsTo?: string): string; } export default uniformTypeDescriptor; diff --git a/kv_store/bundle.json b/kv_store/bundle.json index 854af90eeb88840d1cf64648af5c9b42364f52e8..0b5a986f853f2d0baeb1776e5a437d281e28ef87 100644 --- a/kv_store/bundle.json +++ b/kv_store/bundle.json @@ -54,7 +54,8 @@ "libuv", "openssl", "sqlite", - "zlib" + "zlib", + "googletest" ], "kernel_special": {}, "board_special": {}, @@ -83,7 +84,8 @@ "//foundation/distributeddatamgr/kv_store/interfaces/jskits/distributeddata:build_module", "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/jskits/distributeddata:build_module", "//foundation/distributeddatamgr/kv_store/interfaces/jskits/distributedkvstore:build_module", - "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/jskits/distributedkvstore:build_module" + "//foundation/distributeddatamgr/kv_store/kvstoremock/interfaces/jskits/distributedkvstore:build_module", + "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata:distributeddata_client_sync" ], "inner_kits": [ { @@ -106,7 +108,8 @@ "executor.h", "executor_pool.h", "pool.h", - "priority_queue.h" + "priority_queue.h", + "end_point.h" ], "header_base": "//foundation/distributeddatamgr/kv_store/interfaces/innerkits/distributeddata/include" } @@ -162,6 +165,7 @@ "name": "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb:distributeddb", "header": { "header_files": [ + "relational_store_client.h", "relational_store_delegate.h", "relational_store_manager.h", "relational_store_sqlite_ext.h" diff --git a/kv_store/frameworks/common/itypes_util.h b/kv_store/frameworks/common/itypes_util.h index 1e1ca51bde3d06b8f16c65dd5b013f4e6543e3ee..ceebec5d6aa353428ae14eecc7744ced5ac49884 100644 --- a/kv_store/frameworks/common/itypes_util.h +++ b/kv_store/frameworks/common/itypes_util.h @@ -35,12 +35,6 @@ struct is_container> : std::true_type { template struct is_container> : std::true_type { }; -template -struct Result { - int32_t errCode; - using value_type = typename std::conditional::value, std::nullptr_t, T>::type; - value_type value; -}; namespace ITypesUtil { inline constexpr size_t MAX_COUNT = 100000; inline constexpr size_t MAX_SIZE = 1 * 1024 * 1024 * 1024; //1G @@ -190,6 +184,16 @@ bool Marshalling(const std::map &result, MessageParcel &parcel); template bool Unmarshalling(std::map &val, MessageParcel &parcel); +template +bool Marshalling(const std::tuple &result, MessageParcel &parcel); +template +bool Unmarshalling(std::tuple &val, MessageParcel &parcel); + +template +bool Marshalling(const std::pair &result, MessageParcel &parcel); +template +bool Unmarshalling(std::pair &val, MessageParcel &parcel); + template bool Marshalling(const std::vector &val, MessageParcel &parcel); template @@ -210,11 +214,6 @@ bool Marshalling(const T &input, MessageParcel &data); template bool Unmarshalling(T &output, MessageParcel &data); -template -bool Marshalling(const Result &val, MessageParcel &data); -template -bool Unmarshalling(Result &val, MessageParcel &data); - template{}, int>::type = 0> bool MarshalToContainer(const T &val, MessageParcel &parcel); template{}, int>::type = 0> @@ -237,24 +236,6 @@ template bool Unmarshal(MessageParcel &parcel, T &first, Types &...others); } // namespace ITypesUtil -template -bool ITypesUtil::Marshalling(const Result &val, MessageParcel &data) -{ - if (!data.WriteInt32(val.errCode)) { - return false; - } - return std::is_null_pointer::value ? true : Marshalling(val.value, data); -} - -template -bool ITypesUtil::Unmarshalling(Result &val, MessageParcel &data) -{ - if (!data.ReadInt32(val.errCode)) { - return false; - } - return std::is_null_pointer::value ? true : Unmarshalling(val.value, data); -} - template bool ITypesUtil::ReadVariant(uint32_t step, uint32_t index, const _OutTp &output, MessageParcel &data) { @@ -355,6 +336,67 @@ bool ITypesUtil::Unmarshalling(std::map &val, MessageParcel &parcel) return true; } +template +bool ITypesUtil::Marshalling(const std::tuple &result, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshalling(std::get<0>(result), parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(std::get<1>(result), parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(std::get<2>(result), parcel)) { + return false; + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::tuple &val, MessageParcel &parcel) +{ + F first; + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + S second; + if (!ITypesUtil::Unmarshalling(second, parcel)) { + return false; + } + T third; + if (!ITypesUtil::Unmarshalling(third, parcel)) { + return false; + } + val = { first, second, third }; + return true; +} + +template +bool ITypesUtil::Marshalling(const std::pair &result, MessageParcel &parcel) +{ + if (!ITypesUtil::Marshalling(result.first, parcel)) { + return false; + } + if (!ITypesUtil::Marshalling(result.second, parcel)) { + return false; + } + return true; +} + +template +bool ITypesUtil::Unmarshalling(std::pair &val, MessageParcel &parcel) +{ + F first; + if (!ITypesUtil::Unmarshalling(first, parcel)) { + return false; + } + S second; + if (!ITypesUtil::Unmarshalling(second, parcel)) { + return false; + } + val = { first, second }; + return true; +} + template bool ITypesUtil::Marshalling(const std::vector &val, MessageParcel &parcel) { diff --git a/kv_store/frameworks/common/log_print.h b/kv_store/frameworks/common/log_print.h index dbbe8e8236455b5f877295c84820dae467223056..b2ab441fca6b24939e0a1bbeaab8c59f3bde228e 100644 --- a/kv_store/frameworks/common/log_print.h +++ b/kv_store/frameworks/common/log_print.h @@ -83,6 +83,13 @@ static inline OHOS::HiviewDFX::HiLogLabel LogLabel() return { LOG_CORE, 0xD001654, "DOBJECT" }; } } // end namespace DistributedObject + +namespace DataSearchable { +static inline OHOS::HiviewDFX::HiLogLabel LogLabel() +{ + return { LOG_CORE, 0xD001656, "DSRCH" }; +} +} // end namespace DataSearchable } // end namespace OHOS #define ZLOGD(fmt, ...) \ diff --git a/kv_store/frameworks/common/test/BUILD.gn b/kv_store/frameworks/common/test/BUILD.gn index d75f7b802e240c025f455c969c17097a300ab14d..6029e40392d41be792d59d4b4a1d40c0d49865b8 100644 --- a/kv_store/frameworks/common/test/BUILD.gn +++ b/kv_store/frameworks/common/test/BUILD.gn @@ -92,6 +92,24 @@ ohos_unittest("TraitsTest") { deps = [ "//third_party/googletest:gtest" ] } +ohos_unittest("PoolTest") { + module_out_path = module_output_path + + sources = [ "pool_test.cpp" ] + + configs = [ ":module_private_config" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + "ipc:ipc_single", + "safwk:system_ability_fwk", + "samgr:samgr_proxy", + ] + + deps = [ "//third_party/googletest:gtest" ] +} + ############################################################################### group("unittest") { testonly = true @@ -101,6 +119,7 @@ group("unittest") { ":ConcurrentMapTest", ":ExecutorPoolTest", ":LruBucketTest", + ":PoolTest", ":TaskSchedulerTest", ":TraitsTest", ] diff --git a/kv_store/frameworks/common/test/pool_test.cpp b/kv_store/frameworks/common/test/pool_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fe3c84de7ac88982f36ac65193b8b94b26050d76 --- /dev/null +++ b/kv_store/frameworks/common/test/pool_test.cpp @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "gtest/gtest.h" +#include "pool.h" +#include "log_print.h" + +using namespace testing::ext; +using namespace OHOS; +namespace OHOS::Test { +class PoolTest : public testing::Test { +public: + struct Node { + int value; + bool operator==(Node &other) + { + return value == other.value; + } + }; + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + +protected: + static constexpr uint32_t CAPABILITY_TEST = 3; // capability + static constexpr uint32_t MIN_TEST = 1; // min + static Pool pool_; +}; +Pool PoolTest::pool_ = Pool(CAPABILITY_TEST, MIN_TEST); + +void PoolTest::SetUpTestCase(void) +{} + +void PoolTest::TearDownTestCase(void) +{} + +void PoolTest::SetUp(void) +{} + +void PoolTest::TearDown(void) +{ + auto close = [](std::shared_ptr data) { + pool_.Idle(data); + pool_.Release(data); + }; + pool_.Clean(close); +} + +/** +* @tc.name: Get_001 +* @tc.desc: test the std::shared_ptr Get(bool isForce = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Get_001, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_EQ(ret, nullptr); +} + +/** +* @tc.name: Get_002 +* @tc.desc: test the std::shared_ptr Get(bool isForce = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Get_002, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(true); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_EQ(ret, nullptr); +} + +/** +* @tc.name: Release_001 +* @tc.desc: test the int32_t Release(std::shared_ptr data, bool force = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Release_001, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + + pool_.Idle(ret); + auto retRelease = pool_.Release(ret); + EXPECT_EQ(retRelease, true); +} + +/** +* @tc.name: Release_002 +* @tc.desc: test the int32_t Release(std::shared_ptr data, bool force = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Release_002, TestSize.Level1) +{ + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + + pool_.Idle(ret); + auto retRelease = pool_.Release(ret); + EXPECT_EQ(retRelease, false); +} + +/** +* @tc.name: Release_003 +* @tc.desc: test the int32_t Release(std::shared_ptr data, bool force = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Release_003, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + + pool_.Idle(ret); + auto retRelease = pool_.Release(ret); + EXPECT_EQ(retRelease, true); +} + +/** +* @tc.name: Release_004 +* @tc.desc: test the int32_t Release(std::shared_ptr data, bool force = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Release_004, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(true); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_EQ(ret, nullptr); + + pool_.Idle(ret); + auto retRelease = pool_.Release(ret); + EXPECT_EQ(retRelease, false); +} + +/** +* @tc.name: Release_005 +* @tc.desc: test the int32_t Release(std::shared_ptr data, bool force = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Release_005, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + + auto data = std::make_shared(); + pool_.Idle(ret); + auto retRelease = pool_.Release(data); + EXPECT_EQ(retRelease, false); +} + +/** +* @tc.name: Release_006 +* @tc.desc: test the int32_t Release(std::shared_ptr data, bool force = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Release_006, TestSize.Level1) +{ + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + + pool_.Idle(ret); + auto retRelease = pool_.Release(ret, true); + EXPECT_EQ(retRelease, true); +} + +/** +* @tc.name: Release_007 +* @tc.desc: test the int32_t Release(std::shared_ptr data, bool force = false) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Release_007, TestSize.Level1) +{ + auto ret = nullptr; + auto retRelease = pool_.Release(ret, true); + EXPECT_EQ(retRelease, false); +} + +/** +* @tc.name: Idle_001 +* @tc.desc: test the void Idle(std::shared_ptr data) function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Idle_001, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + + pool_.Idle(ret); + auto retRelease = pool_.Release(ret); + EXPECT_EQ(retRelease, true); +} + +/** +* @tc.name: Clean_001 +* @tc.desc: test the int32_t Clean(std::function)> close) noexcept function. +* @tc.type: FUNC +* @tc.require: +* @tc.author: suoqilong +*/ +HWTEST_F(PoolTest, Clean_001, TestSize.Level1) +{ + int index = 0; + auto ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + ret->value = index++; + + ret = pool_.Get(); + EXPECT_NE(ret, nullptr); + + auto close = [](std::shared_ptr data) { + pool_.Idle(data); + pool_.Release(data); + }; + auto retClean = pool_.Clean(close); + EXPECT_EQ(retClean, true); +} +} // namespace OHOS::Test diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp index 2644a83aa4fd50f326092d01ade33827baa8b33c..3923637f603abe4d3ef47458d33992ce7e8248fb 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/data_query.cpp @@ -344,6 +344,16 @@ DataQuery& DataQuery::LessThanOrEqualTo(const std::string &field, const std::str return *this; } +DataQuery& DataQuery::Between(const std::string &valueLow, const std::string &valueHigh) +{ + std::vector keyBegin; + keyBegin.assign(valueLow.begin(), valueLow.end()); + std::vector keyEnd; + keyEnd.assign(valueHigh.begin(), valueHigh.end()); + query_->Range(keyBegin, keyEnd); + return *this; +} + DataQuery& DataQuery::IsNull(const std::string &field) { std::string myField = field; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp index 73a7aefc2d316f1b7bf9f391333312d445897895..925acf10b37895b354da5945ed9f498cbfbf030b 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/src/distributed_kv_data_manager.cpp @@ -23,10 +23,17 @@ #include "refbase.h" #include "store_manager.h" #include "task_executor.h" +#include "store_util.h" +#include "runtime_config.h" +#include "kv_store_delegate_manager.h" +#include "process_communication_impl.h" +#include "process_system_api_adapter_impl.h" +#include "store_factory.h" namespace OHOS { namespace DistributedKv { using namespace OHOS::DistributedDataDfx; +bool DistributedKvDataManager::isAlreadySet_ = false; DistributedKvDataManager::DistributedKvDataManager() {} @@ -40,12 +47,17 @@ Status DistributedKvDataManager::GetSingleKvStore(const Options &options, const TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); singleKvStore = nullptr; + if (options.securityLevel == INVALID_LABEL) { + ZLOGE("invalid security level, appId = %{private}s, storeId = %{private}s, kvStoreType = %{private}d", + appId.appId.c_str(), storeId.storeId.c_str(), options.kvStoreType); + return Status::INVALID_ARGUMENT; + } if (!storeId.IsValid()) { ZLOGE("invalid storeId."); return Status::INVALID_ARGUMENT; } - if (options.baseDir.empty()) { - ZLOGE("base dir empty."); + if (!options.IsPathValid()) { + ZLOGE("invalid path."); return Status::INVALID_ARGUMENT; } KvStoreServiceDeathNotifier::SetAppId(appId); @@ -106,7 +118,6 @@ Status DistributedKvDataManager::DeleteKvStore(const AppId &appId, const StoreId { DdsTrace trace(std::string(LOG_TAG "::") + std::string(__FUNCTION__), TraceSwitch::BYTRACE_ON | TraceSwitch::TRACE_CHAIN_ON); - if (!storeId.IsValid()) { ZLOGE("invalid storeId."); return Status::INVALID_ARGUMENT; @@ -170,5 +181,59 @@ void DistributedKvDataManager::SetExecutors(std::shared_ptr execut { TaskExecutor::GetInstance().SetExecutors(std::move(executors)); } + +Status DistributedKvDataManager::SetEndpoint(std::shared_ptr endpoint) +{ + std::lock_guard lock(mutex_); + if (endpoint == nullptr) { + ZLOGE("Endpoint is nullptr."); + return INVALID_ARGUMENT; + } + + if (isAlreadySet_) { + ZLOGW("Endpoint already set"); + return SUCCESS; + } + + auto dbStatus = DistributedDB::KvStoreDelegateManager::SetProcessLabel("default", "default"); + auto status = StoreUtil::ConvertStatus(dbStatus); + if (status != SUCCESS) { + ZLOGE("SetProcessLabel failed: %d", status); + return status; + } + + auto communicator = std::make_shared(endpoint); + dbStatus = DistributedDB::KvStoreDelegateManager::SetProcessCommunicator(communicator); + status = StoreUtil::ConvertStatus(dbStatus); + if (status != SUCCESS) { + ZLOGE("SetProcessCommunicator failed: %d", status); + return status; + } + + auto systemApi = std::make_shared(endpoint); + dbStatus = DistributedDB::KvStoreDelegateManager::SetProcessSystemAPIAdapter(systemApi); + status = StoreUtil::ConvertStatus(dbStatus); + if (status != SUCCESS) { + ZLOGE("SetProcessSystemAPIAdapter failed: %d", status); + return status; + } + + auto permissionCallback = [endpoint](const DistributedDB::PermissionCheckParam ¶m, uint8_t flag) -> bool { + StoreBriefInfo params = { + std::move(param.userId), std::move(param.appId), std::move(param.storeId), std::move(param.deviceId), + std::move(param.instanceId), std::move(param.extraConditions) + }; + return endpoint->HasDataSyncPermission(params, flag); + }; + + dbStatus = DistributedDB::RuntimeConfig::SetPermissionCheckCallback(permissionCallback); + status = StoreUtil::ConvertStatus(dbStatus); + if (status != SUCCESS) { + ZLOGE("SetPermissionCheckCallback failed: %d", status); + return status; + } + isAlreadySet_ = true; + return status; +} } // namespace DistributedKv } // namespace OHOS diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp index 53b6c29b8dfb6a2e513b13a51fd91a311339341b..fede017944d30b0bb1972578532f357f238c0fee 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/device_kvstore_test.cpp @@ -62,6 +62,7 @@ void DeviceKvStoreTest::SetUpTestCase(void) DistributedKvDataManager manager; options_.area = EL1; options_.baseDir = std::string("/data/service/el1/public/database/odmf"); + options_.securityLevel = S1; mkdir(options_.baseDir.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)); AppId appId = { "odmf" }; StoreId storeId = { "student_device" }; // define kvstore(database) name. @@ -516,6 +517,7 @@ HWTEST_F(DeviceKvStoreTest, TestSchemaStoreC001, TestSize.Level1) DistributedKvDataManager manager; Options options; options.encrypt = true; + options.securityLevel = S1; options.schema = VALID_SCHEMA; options.area = EL1; options.baseDir = std::string("/data/service/el1/public/database/odmf"); @@ -1178,6 +1180,7 @@ HWTEST_F(DeviceKvStoreTest, DeviceSync001, TestSize.Level1) DistributedKvDataManager manager; Options options; options.encrypt = true; + options.securityLevel = S1; options.area = EL1; options.baseDir = std::string("/data/service/el1/public/database/odmf"); AppId appId = { "odmf" }; @@ -1205,6 +1208,7 @@ HWTEST_F(DeviceKvStoreTest, DeviceSync002, TestSize.Level1) DistributedKvDataManager manager; Options options; options.encrypt = true; + options.securityLevel = S1; options.area = EL1; options.baseDir = std::string("/data/service/el1/public/database/odmf"); AppId appId = { "odmf" }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp index 93dc51b0bd0cc3986330169ba040d32fff1ec727..5fb49261cb5f467fc722d1fadf47092f461844b6 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_encrypt_test.cpp @@ -37,7 +37,7 @@ public: static void SetUpTestCase(void); static void TearDownTestCase(void); - static void RemoveAllStore(DistributedKvDataManager manager); + static void RemoveAllStore(DistributedKvDataManager &manager); void SetUp(); void TearDown(); @@ -60,7 +60,7 @@ UserId DistributedKvDataManagerEncryptTest::userId; AppId DistributedKvDataManagerEncryptTest::appId; StoreId DistributedKvDataManagerEncryptTest::storeId; -void DistributedKvDataManagerEncryptTest::RemoveAllStore(DistributedKvDataManager manager) +void DistributedKvDataManagerEncryptTest::RemoveAllStore(DistributedKvDataManager &manager) { manager.CloseAllKvStore(appId); manager.DeleteKvStore(appId, storeId, createEnc.baseDir); @@ -70,6 +70,7 @@ void DistributedKvDataManagerEncryptTest::SetUpTestCase(void) { createEnc.createIfMissing = true; createEnc.encrypt = true; + createEnc.securityLevel = S1; createEnc.autoSync = true; createEnc.kvStoreType = SINGLE_VERSION; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp index 579f428a9979cb75cda8db6d6d8eb12b7c4b5079..1a2c9d8aeaf78708d7aa8a9a53b8c1da7ae05707 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/distributed_kv_data_manager_test.cpp @@ -43,7 +43,7 @@ public: static void SetUpTestCase(void); static void TearDownTestCase(void); - static void RemoveAllStore(DistributedKvDataManager manager); + static void RemoveAllStore(DistributedKvDataManager &manager); void SetUp(); void TearDown(); @@ -72,7 +72,7 @@ StoreId DistributedKvDataManagerTest::storeIdEmpty; Entry DistributedKvDataManagerTest::entryA; Entry DistributedKvDataManagerTest::entryB; -void DistributedKvDataManagerTest::RemoveAllStore(DistributedKvDataManager manager) +void DistributedKvDataManagerTest::RemoveAllStore(DistributedKvDataManager &manager) { manager.CloseAllKvStore(appId); manager.DeleteAllKvStore(appId, create.baseDir); @@ -83,6 +83,7 @@ void DistributedKvDataManagerTest::SetUpTestCase(void) appId.appId = "ohos.kvdatamanager.test"; create.createIfMissing = true; create.encrypt = false; + create.securityLevel = S1; create.autoSync = true; create.kvStoreType = SINGLE_VERSION; create.area = EL1; @@ -91,6 +92,7 @@ void DistributedKvDataManagerTest::SetUpTestCase(void) noCreate.createIfMissing = false; noCreate.encrypt = false; + noCreate.securityLevel = S1; noCreate.autoSync = true; noCreate.kvStoreType = SINGLE_VERSION; noCreate.area = EL1; @@ -246,6 +248,25 @@ HWTEST_F(DistributedKvDataManagerTest, GetKvStore007, TestSize.Level1) EXPECT_EQ(notExistKvStore, nullptr); } +/** +* @tc.name: GetKvStoreInvalidSecurityLevel +* @tc.desc: Get a SingleKvStore with a 64 + * -byte storeId, the callback function should receive INVALID_ARGUMENT +* @tc.type: FUNC +* @tc.require: SR000IIM2J AR000IIMLL +* @tc.author: wangkai +*/ +HWTEST_F(DistributedKvDataManagerTest, GetKvStoreInvalidSecurityLevel, TestSize.Level1) +{ + ZLOGI("GetKvStoreInvalidSecurityLevel begin."); + std::shared_ptr notExistKvStore; + Options invalidOption = create; + invalidOption.securityLevel = INVALID_LABEL; + Status status = manager.GetSingleKvStore(invalidOption, appId, storeId64, notExistKvStore); + ASSERT_EQ(status, Status::INVALID_ARGUMENT); + EXPECT_EQ(notExistKvStore, nullptr); +} + /** * @tc.name: GetAllKvStore001 * @tc.desc: Get all KvStore IDs when no KvStore exists, and the callback function should receive a 0-length vector. diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kv_utils_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kv_utils_test.cpp index 2c271b6d83449ff1663e99e59720d4286c66e441..bee8cb970e9dbcb9d989b6db14a372e870f8dd73 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kv_utils_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kv_utils_test.cpp @@ -124,6 +124,7 @@ void KvUtilTest::SetUpTestCase(void) Options options = {.createIfMissing = true, .encrypt = false, .autoSync = false, .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE}; options.area = EL1; + options.securityLevel = S1; options.baseDir = std::string("/data/service/el1/public/database/kvUtilTest"); AppId appId = { "kvUtilTest" }; StoreId storeId = { "test_single" }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kvstore_datashare_bridge_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kvstore_datashare_bridge_test.cpp index 47a0d0a448ba9af4230f81d3853328370d8d63b3..f04742b77a3afffa73ad4e64fb42c6eddd3d4bd6 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kvstore_datashare_bridge_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/kvstore_datashare_bridge_test.cpp @@ -125,6 +125,7 @@ void KvstoreDatashareBridgeTest::SetUpTestCase(void) Options options = { .createIfMissing = true, .encrypt = false, .autoSync = false, .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; options.area = EL1; + options.securityLevel = S1; options.baseDir = std::string("/data/service/el1/public/database/KvstoreDatashareBridgeTest"); AppId appId = { "KvstoreDatashareBridgeTest" }; StoreId storeId = { "test_single" }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp index 436a95a78be7b662144a054040abbebf8ed2b217..1da928321ae061be42f97a120bf30b4ea0fd31ea 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_device_store_test.cpp @@ -62,6 +62,7 @@ void LocalSubscribeDeviceStoreTest::TearDownTestCase(void) void LocalSubscribeDeviceStoreTest::SetUp(void) { Options options; + options.securityLevel = S1; options.baseDir = std::string("/data/service/el1/public/database/dev_local_sub"); appId_.appId = "dev_local_sub"; // define app name. storeId_.storeId = "student"; // define kvstore(database) name diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp index 27b75941035c9b5c1a98955161ccc75e8f489749..517324f2f10f22bd2f2866c9a11d60c1bfbb3f98 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/local_subscribe_store_test.cpp @@ -64,6 +64,7 @@ void LocalSubscribeStoreTest::SetUp(void) Options options; options.createIfMissing = true; options.encrypt = false; // not supported yet. + options.securityLevel = S1; options.autoSync = true; // not supported yet. options.kvStoreType = KvStoreType::SINGLE_VERSION; options.area = EL1; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_query_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_query_test.cpp index b53dc18fc06885be4927bdf4608380eb68aca682..fce33602f25ce60d7dce64610ed021b7c9d4d4eb 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_query_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_query_test.cpp @@ -753,6 +753,7 @@ HWTEST_F(SingleKvStoreClientQueryTest, SingleKvStoreQueryNotEqualTo, TestSize.Le Options options = { .createIfMissing = true, .encrypt = true, .autoSync = true, .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; options.area = EL1; + options.securityLevel = S1; options.baseDir = "/data/service/el1/public/database/SingleKvStoreClientQueryTest"; AppId appId = { "SingleKvStoreClientQueryTest" }; StoreId storeId = { "SingleKvStoreClientQueryTestStoreId1" }; @@ -817,6 +818,7 @@ HWTEST_F(SingleKvStoreClientQueryTest, SingleKvStoreQueryNotEqualToAndEqualTo, T Options options = { .createIfMissing = true, .encrypt = true, .autoSync = true, .kvStoreType = KvStoreType::SINGLE_VERSION, .schema = VALID_SCHEMA_STRICT_DEFINE }; options.area = EL1; + options.securityLevel = S1; options.baseDir = "/data/service/el1/public/database/SingleKvStoreClientQueryTest"; AppId appId = { "SingleKvStoreClientQueryTest" }; StoreId storeId = { "SingleKvStoreClientQueryTestStoreId2" }; diff --git a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp index ea78fb1192c01bbb4cdb4cbe520ddfb91b54d3d1..91379f2c9c95f22639dedda9c1d16a7f295f3c42 100644 --- a/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/distributeddatafwk/test/unittest/single_kvstore_client_test.cpp @@ -58,6 +58,7 @@ void SingleKvStoreClientTest::SetUpTestCase(void) Options options = { .createIfMissing = true, .encrypt = false, .autoSync = true, .kvStoreType = KvStoreType::SINGLE_VERSION }; options.area = EL1; + options.securityLevel = S1; options.baseDir = std::string("/data/service/el1/public/database/odmf"); AppId appId = { "odmf" }; StoreId storeId = { "student_single" }; // define kvstore(database) name. @@ -405,6 +406,7 @@ HWTEST_F(SingleKvStoreClientTest, TestSchemaStoreC001, TestSize.Level1) DistributedKvDataManager manager; Options options; options.encrypt = true; + options.securityLevel = S1; options.area = EL1; options.kvStoreType = KvStoreType::SINGLE_VERSION; options.baseDir = "/data/service/el1/public/database/odmf"; @@ -1066,6 +1068,7 @@ HWTEST_F(SingleKvStoreClientTest, DeviceSync001, TestSize.Level1) DistributedKvDataManager manager; Options options; options.encrypt = true; + options.securityLevel = S1; options.area = EL1; options.kvStoreType = KvStoreType::SINGLE_VERSION; options.baseDir = "/data/service/el1/public/database/odmf"; @@ -1094,6 +1097,7 @@ HWTEST_F(SingleKvStoreClientTest, DeviceSync002, TestSize.Level1) DistributedKvDataManager manager; Options options; options.encrypt = true; + options.securityLevel = S1; options.area = EL1; options.kvStoreType = KvStoreType::SINGLE_VERSION; options.baseDir = "/data/service/el1/public/database/odmf"; @@ -1125,6 +1129,7 @@ HWTEST_F(SingleKvStoreClientTest, DisableCapability, TestSize.Level1) DistributedKvDataManager manager; Options options; options.encrypt = true; + options.securityLevel = S1; options.area = EL1; options.kvStoreType = KvStoreType::SINGLE_VERSION; options.baseDir = "/data/service/el1/public/database/odmf"; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/process_communication_impl.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/process_communication_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..902b63a8782e5472bad79f211887354f555eefe5 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/process_communication_impl.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021 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 PROCESS_COMMUNICATION_IMPL_H +#define PROCESS_COMMUNICATION_IMPL_H + +#include "iprocess_communicator.h" +#include "types.h" +#include "end_point.h" + +namespace OHOS { +namespace DistributedKv { + +class ProcessCommunicationImpl : public DistributedDB::IProcessCommunicator { +public: + using DBStatus = DistributedDB::DBStatus; + using OnDeviceChange = DistributedDB::OnDeviceChange; + using OnDataReceive = DistributedDB::OnDataReceive; + + API_EXPORT explicit ProcessCommunicationImpl(std::shared_ptr endpoint); + API_EXPORT ~ProcessCommunicationImpl() override; + + DBStatus Start(const std::string &processLabel) override; + DBStatus Stop() override; + + DBStatus RegOnDeviceChange(const OnDeviceChange &callback) override; + DBStatus RegOnDataReceive(const OnDataReceive &callback) override; + + DBStatus SendData(const DistributedDB::DeviceInfos &dstDevInfo, const uint8_t *data, uint32_t length) override; + uint32_t GetMtuSize() override; + uint32_t GetMtuSize(const DistributedDB::DeviceInfos &devInfo) override; + DistributedDB::DeviceInfos GetLocalDeviceInfos() override; + std::vector GetRemoteOnlineDeviceInfosList() override; + bool IsSameProcessLabelStartedOnPeerDevice(const DistributedDB::DeviceInfos &peerDevInfo) override; + std::shared_ptr GetExtendHeaderHandle( + const DistributedDB::ExtendInfo ¶mInfo) override; +private: + + std::shared_ptr endpoint_; + bool isCreateSessionServer_ = false; +}; +} // namespace AppDistributedKv +} // namespace OHOS +#endif // PROCESS_COMMUNICATION_IMPL_H \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/process_system_api_adapter_impl.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/process_system_api_adapter_impl.h new file mode 100644 index 0000000000000000000000000000000000000000..81cc940229425c6cc6eda9a22011572f2123fdd3 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/process_system_api_adapter_impl.h @@ -0,0 +1,39 @@ +/* + * 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 PROCESS_SYSTEM_API_ADAPTER_IMPL_H +#define PROCESS_SYSTEM_API_ADAPTER_IMPL_H +#include +#include "iprocess_system_api_adapter.h" +#include "end_point.h" + +namespace OHOS::DistributedKv { +class ProcessSystemApiAdapterImpl : public DistributedDB::IProcessSystemApiAdapter { +public: + using AccessEventHanle = DistributedDB::OnAccessControlledEvent; + using DBStatus = DistributedDB::DBStatus; + using DBOption = DistributedDB::SecurityOption; + API_EXPORT explicit ProcessSystemApiAdapterImpl(std::shared_ptr endpoint); + API_EXPORT ~ProcessSystemApiAdapterImpl(); + DBStatus RegOnAccessControlledEvent(const AccessEventHanle &callback) override; + bool IsAccessControlled() const override; + DBStatus SetSecurityOption(const std::string &filePath, const DBOption &option) override; + DBStatus GetSecurityOption(const std::string &filePath, DBOption &option) const override; + bool CheckDeviceSecurityAbility(const std::string &devId, const DBOption &option) const override; +private: + std::shared_ptr endpoint_; +}; +} +#endif // PROCESS_SYSTEM_API_ADAPTER_IMPL_H diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h index 772fcbe716d8e6da4236d9c83d397eb67820dce4..cb5d44ed689744d3d972bcf0a7d01f32f3eff130 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -27,6 +27,7 @@ #include "single_kvstore.h" #include "sync_observer.h" #include "task_executor.h" +#include "kvstore_sync_callback_client.h" namespace OHOS::DistributedKv { class SingleStoreImpl : public SingleKvStore, @@ -73,7 +74,8 @@ public: // normal function int32_t Close(bool isForce = false); int32_t AddRef(); - + Status SetIdentifier(const std::string &accountId, const std::string &appId, + const std::string &storeId, const std::vector &tagretDev) override; // IPC interface Status Sync(const std::vector &devices, SyncMode mode, uint32_t delay) override; Status Sync(const std::vector &devices, SyncMode mode, const DataQuery &query, @@ -87,7 +89,6 @@ public: const std::vector &remote) const override; Status SubscribeWithQuery(const std::vector &devices, const DataQuery &query) override; Status UnsubscribeWithQuery(const std::vector &devices, const DataQuery &query) override; - protected: std::shared_ptr PutIn(uint32_t &realType, std::shared_ptr observer); std::shared_ptr TakeOut(uint32_t &realType, std::shared_ptr observer); @@ -100,15 +101,18 @@ private: Status RetryWithCheckPoint(std::function lambda); std::function BridgeReleaser(); Status DoSync(const SyncInfo &syncInfo, std::shared_ptr observer); + Status DoClientSync(const SyncInfo &syncInfo, std::shared_ptr observer); void DoAutoSync(); void Register(); bool autoSync_ = false; + bool isClientSync_ = false; int32_t ref_ = 1; mutable std::shared_mutex rwMutex_; const Convertor &convertor_; std::string appId_; std::string storeId_; + uint32_t roleType_ = 0; std::shared_ptr dbStore_ = nullptr; std::shared_ptr syncObserver_ = nullptr; ConcurrentMap>> observers_; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/process_communication_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_communication_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb60a394b2c57de888741c8464576a409d79e048 --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_communication_impl.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2021 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. + */ + +#define LOG_TAG "ProcessCommunicationImpl" + +#include "process_communication_impl.h" +#include "log_print.h" + +namespace OHOS { +namespace DistributedKv { +using namespace DistributedDB; +ProcessCommunicationImpl::ProcessCommunicationImpl(std::shared_ptr endpoint) + : endpoint_(endpoint) +{ +} + +ProcessCommunicationImpl::~ProcessCommunicationImpl() +{ +} + +DBStatus ProcessCommunicationImpl::Start(const std::string &processLabel) +{ + Status errCode = endpoint_->Start(); + if (errCode != Status::SUCCESS) { + ZLOGE("endpoint Start Fail: %{public}d", errCode); + return DBStatus::DB_ERROR; + } + isCreateSessionServer_ = true; + return DBStatus::OK; +} + +DBStatus ProcessCommunicationImpl::Stop() +{ + Status errCode = endpoint_->Stop(); + if (errCode != Status::SUCCESS) { + ZLOGE("endpoint Stop Fail: %{public}d", errCode); + return DBStatus::DB_ERROR; + } + isCreateSessionServer_ = false; + return DBStatus::OK; +} + +DBStatus ProcessCommunicationImpl::RegOnDeviceChange(const OnDeviceChange &callback) +{ + return DBStatus::OK; +} + +DBStatus ProcessCommunicationImpl::RegOnDataReceive(const OnDataReceive &callback) +{ + auto dataReciveCallback = [callback](const std::string &identifier, const uint8_t *data, uint32_t length) { + DistributedDB::DeviceInfos devInfo = { + identifier + }; + callback(devInfo, data, length); + }; + + Status errCode = endpoint_->RegOnDataReceive(dataReciveCallback); + if (errCode != Status::SUCCESS) { + ZLOGE("RegOnDataReceive Fail."); + return DBStatus::DB_ERROR; + } + + return DBStatus::OK; +} + +DBStatus ProcessCommunicationImpl::SendData(const DistributedDB::DeviceInfos &dstDevInfo, const uint8_t *data, + uint32_t length) +{ + std::string dtsIdentifier = dstDevInfo.identifier; + Status errCode = endpoint_->SendData(dtsIdentifier, data, length); + if (errCode != Status::SUCCESS) { + ZLOGE("SendData Fail."); + return DBStatus::DB_ERROR; + } + + return DBStatus::OK; +} + +uint32_t ProcessCommunicationImpl::GetMtuSize() +{ + return endpoint_->GetMtuSize({""}); +} + +uint32_t ProcessCommunicationImpl::GetMtuSize(const DistributedDB::DeviceInfos &devInfo) +{ + std::string identifier = devInfo.identifier; + return endpoint_->GetMtuSize(identifier); +} + +DistributedDB::DeviceInfos ProcessCommunicationImpl::GetLocalDeviceInfos() +{ + std::string identifier = endpoint_->GetLocalDeviceInfos(); + DistributedDB::DeviceInfos devInfos = { + identifier + }; + return devInfos; +} + +std::vector ProcessCommunicationImpl::GetRemoteOnlineDeviceInfosList() +{ + return {}; +} + +bool ProcessCommunicationImpl::IsSameProcessLabelStartedOnPeerDevice(__attribute__((unused)) + const DistributedDB::DeviceInfos &peerDevInfo) +{ + return isCreateSessionServer_; +} + +std::shared_ptr ProcessCommunicationImpl::GetExtendHeaderHandle( + __attribute__((unused)) const DistributedDB::ExtendInfo ¶mInfo) +{ + return std::make_shared(); +} +} // namespace AppDistributedKv +} // namespace OHOS + diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cdb3746e1c83d564b81b715b812836595b3e10cf --- /dev/null +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp @@ -0,0 +1,114 @@ +/* + * 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. + */ +#define LOG_TAG "ProcessSystemApiAdapterImpl" +#include "process_system_api_adapter_impl.h" +#include +#include +#include +#include "log_print.h" +#include "security_label.h" + +namespace OHOS::DistributedKv { +using Label = DistributedDB::SecurityLabel; +using Flag = DistributedDB::SecurityFlag; +using SecurityLabel = DistributedFS::ModuleSecurityLabel::SecurityLabel; +constexpr int32_t HEAD_SIZE = 3; +constexpr int32_t END_SIZE = 3; +constexpr const char *REPLACE_CHAIN = "***"; +ProcessSystemApiAdapterImpl::ProcessSystemApiAdapterImpl(std::shared_ptr endpoint) + : endpoint_(endpoint) +{ +} + +ProcessSystemApiAdapterImpl::~ProcessSystemApiAdapterImpl() +{ +} + +ProcessSystemApiAdapterImpl::DBStatus ProcessSystemApiAdapterImpl::RegOnAccessControlledEvent( + const AccessEventHanle &callback) +{ + return DBStatus::NOT_SUPPORT; +} + +bool ProcessSystemApiAdapterImpl::IsAccessControlled() const +{ + return false; +} + +ProcessSystemApiAdapterImpl::DBStatus ProcessSystemApiAdapterImpl::SetSecurityOption(const std::string &filePath, + const DBOption &option) +{ + if (filePath.empty() || option.securityLabel < Label::NOT_SET || option.securityLabel > Label::S4) { + return DBStatus::INVALID_ARGS; + } + + struct stat curStat; + stat(filePath.c_str(), &curStat); + if (S_ISDIR(curStat.st_mode)) { + return DBStatus::NOT_SUPPORT; + } + + if (access(filePath.c_str(), F_OK) != 0) { + return DBStatus::INVALID_ARGS; + } + + if (option.securityLabel == Label::NOT_SET) { + return DBStatus::OK; + } + + auto secLevel = std::string("s") + std::to_string(option.securityLabel - 1); + bool result = SecurityLabel::SetSecurityLabel(filePath, secLevel); + if (!result) { + auto fPath = filePath.substr(0, HEAD_SIZE) + REPLACE_CHAIN + + filePath.substr(filePath.length() - END_SIZE, END_SIZE); + ZLOGE("set label failed! level:%{public}s, file:%{public}s", secLevel.c_str(), fPath.c_str()); + return DBStatus::DB_ERROR; + } + return DBStatus::OK; +} + +ProcessSystemApiAdapterImpl::DBStatus ProcessSystemApiAdapterImpl::GetSecurityOption(const std::string &filePath, + DBOption &option) const +{ + if (filePath.empty()) { + return DBStatus::INVALID_ARGS; + } + + struct stat curStat; + stat(filePath.c_str(), &curStat); + if (S_ISDIR(curStat.st_mode)) { + return DBStatus::NOT_SUPPORT; + } + + if (access(filePath.c_str(), F_OK) != 0) { + option = {Label::NOT_SET, Flag::ECE}; + return DBStatus::OK; + } + + std::string value = SecurityLabel::GetSecurityLabel(filePath); + if (!std::regex_match(value, std::regex("s([01234])"))) { + option = {Label::NOT_SET, Flag::ECE}; + return DBStatus::OK; + } + option = { (value[1] - '0') + 1, value[1] == '3' ? Flag::SECE : Flag::ECE}; + return DBStatus::OK; +} + +bool ProcessSystemApiAdapterImpl::CheckDeviceSecurityAbility(const std::string &devId, const DBOption &option) const +{ + auto securityLabel = option.securityLabel; + return endpoint_->IsSaferThanDevice(securityLabel, devId); +} +} // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index 2eaf335f04b38242b7ff03f53a8a832e827b3b84..254bddf9e6a64efac4a06afe806d0fd85d096126 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -31,12 +31,15 @@ SingleStoreImpl::SingleStoreImpl( std::shared_ptr dbStore, const AppId &appId, const Options &options, const Convertor &cvt) : convertor_(cvt), dbStore_(std::move(dbStore)) { + std::string path = options.GetDatabaseDir(); appId_ = appId.appId; storeId_ = dbStore_->GetStoreId(); autoSync_ = options.autoSync; + isClientSync_ = options.isClientSync; syncObserver_ = std::make_shared(); + roleType_ = options.role; if (options.backup) { - BackupManager::GetInstance().Prepare(options.baseDir, storeId_); + BackupManager::GetInstance().Prepare(path, storeId_); } } @@ -240,8 +243,13 @@ Status SingleStoreImpl::SubscribeKvStore(SubscribeType type, std::shared_ptrRegisterObserver({}, DistributedDB::OBSERVER_CHANGES_NATIVE, bridge.get()); + auto dbStatus = dbStore_->RegisterObserver({}, mode, bridge.get()); status = StoreUtil::ConvertStatus(dbStatus); } @@ -279,6 +287,7 @@ Status SingleStoreImpl::UnSubscribeKvStore(SubscribeType type, std::shared_ptrUnRegisterObserver(bridge.get()); status = StoreUtil::ConvertStatus(dbStatus); @@ -662,6 +671,7 @@ std::function SingleStoreImpl::BridgeReleaser() status = StoreUtil::ConvertStatus(dbStatus); } } + Status remote = obj->UnregisterRemoteObserver(); if (status != SUCCESS || remote != SUCCESS) { ZLOGE("status:0x%{public}x remote:0x%{public}x observer:0x%{public}x", status, remote, @@ -760,8 +770,31 @@ Status SingleStoreImpl::GetEntries(const DBQuery &query, std::vector &ent return status; } +Status SingleStoreImpl::DoClientSync(const SyncInfo &syncInfo, std::shared_ptr observer) +{ + auto complete = [observer](const std::map &devicesMap) { + std::map result; + for (auto &[key, dbStatus] : devicesMap) { + result[key] = StoreUtil::ConvertStatus(dbStatus); + } + observer->SyncCompleted(result); + }; + + auto dbStatus = dbStore_->Sync(syncInfo.devices, StoreUtil::GetDBMode(SyncMode(syncInfo.mode)), complete); + Status status = StoreUtil::ConvertStatus(dbStatus); + if (status != Status::SUCCESS) { + ZLOGE("client Sync failed: %{public}d", status); + } + return status; +} + Status SingleStoreImpl::DoSync(const SyncInfo &syncInfo, std::shared_ptr observer) { + Status cStatus = Status::SUCCESS; + if (isClientSync_) { + cStatus = DoClientSync(syncInfo, observer); + } + auto service = KVDBServiceClient::GetInstance(); if (service == nullptr) { return SERVER_UNAVAILABLE; @@ -779,7 +812,16 @@ Status SingleStoreImpl::DoSync(const SyncInfo &syncInfo, std::shared_ptrDeleteSyncCallback(syncInfo.seqId); } - return status; + + if (!isClientSync_) { + return status; + } + if (cStatus == SUCCESS || status == SUCCESS) { + return SUCCESS; + } else { + ZLOGE("sync failed!: %{public}d, %{public}d", cStatus, status); + return ERROR; + } } void SingleStoreImpl::DoAutoSync() @@ -829,4 +871,16 @@ void SingleStoreImpl::Register() taskId_ = 0; } } + +Status SingleStoreImpl::SetIdentifier(const std::string &accountId, const std::string &appId, + const std::string &storeId, const std::vector &tagretDev) +{ + auto syncIdentifier = DistributedDB::KvStoreDelegateManager::GetKvStoreIdentifier(accountId, appId, storeId); + auto dbStatus = dbStore_->SetEqualIdentifier(syncIdentifier, tagretDev); + auto status = StoreUtil::ConvertStatus(dbStatus); + if (status != SUCCESS) { + ZLOGE("SetIdentifier failed, status:0x%{public}x", status); + } + return status; +} } // namespace OHOS::DistributedKv diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp index fda4ce8611bbdece689c93b01e9707443ab7b43f..0ece9ee6e4635378249617b65416154eba5303f1 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_factory.cpp @@ -39,6 +39,7 @@ StoreFactory::StoreFactory() convertors_[DEVICE_COLLABORATION] = new DeviceConvertor(); convertors_[SINGLE_VERSION] = new Convertor(); convertors_[MULTI_VERSION] = new Convertor(); + convertors_[LOCAL_ONLY] = new Convertor(); DistributedDB::RuntimeConfig::SetThreadPool(std::make_shared()); if (DBManager::IsProcessSystemApiAdapterValid()) { return; @@ -68,10 +69,10 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, status = SUCCESS; return !stores.empty(); } - - auto dbManager = GetDBManager(options.baseDir, appId); + std::string path = options.GetDatabaseDir(); + auto dbManager = GetDBManager(path, appId); auto dbPassword = - SecurityManager::GetInstance().GetDBPassword(storeId.storeId, options.baseDir, options.encrypt); + SecurityManager::GetInstance().GetDBPassword(storeId.storeId, path, options.encrypt); if (options.encrypt && !dbPassword.IsValid()) { status = CRYPT_ERROR; ZLOGE("Crypt kvStore failed to get password, storeId is %{public}s, error is %{public}d", @@ -79,14 +80,14 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, return !stores.empty(); } if (options.encrypt) { - status = RekeyRecover(storeId, options.baseDir, dbPassword, dbManager, options); + status = RekeyRecover(storeId, path, dbPassword, dbManager, options); if (status != SUCCESS) { ZLOGE("KvStore password error, storeId is %{public}s, error is %{public}d", StoreUtil::Anonymous(storeId.storeId).c_str(), static_cast(status)); return !stores.empty(); } if (dbPassword.isKeyOutdated) { - ReKey(storeId, options.baseDir, dbPassword, dbManager, options); + ReKey(storeId, path, dbPassword, dbManager, options); } } DBStatus dbStatus = DBStatus::DB_ERROR; @@ -105,7 +106,7 @@ std::shared_ptr StoreFactory::GetOrOpenStore(const AppId &appId, status = StoreUtil::ConvertStatus(dbStatus); if (kvStore == nullptr) { ZLOGE("failed! status:%{public}d appId:%{public}s storeId:%{public}s path:%{public}s", dbStatus, - appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), options.baseDir.c_str()); + appId.appId.c_str(), StoreUtil::Anonymous(storeId.storeId).c_str(), path.c_str()); return !stores.empty(); } isCreate = true; @@ -171,9 +172,11 @@ std::shared_ptr StoreFactory::GetDBManager(const std::s StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const DBPassword &dbPassword) const { DBOption dbOption; - dbOption.syncDualTupleMode = true; // tuple of (appid+storeid) - dbOption.createIfNecessary = options.createIfMissing; - dbOption.isNeedRmCorruptedDb = options.rebuild; + dbOption.syncDualTupleMode = + (options.kvStoreType == KvStoreType::LOCAL_ONLY ? false : true); // tuple of (appid+storeid) + dbOption.createIfNecessary = (options.role == VISITOR ? false : options.createIfMissing); + dbOption.isNeedRmCorruptedDb = (options.role == VISITOR ? false : options.rebuild); + dbOption.rdconfig.readOnly = (options.role == VISITOR ? true : false); dbOption.isMemoryDb = (!options.persistent); dbOption.isEncryptedDb = options.encrypt; if (options.encrypt) { @@ -185,6 +188,8 @@ StoreFactory::DBOption StoreFactory::GetDBOption(const Options &options, const D dbOption.conflictResolvePolicy = DistributedDB::LAST_WIN; } else if (options.kvStoreType == KvStoreType::DEVICE_COLLABORATION) { dbOption.conflictResolvePolicy = DistributedDB::DEVICE_COLLABORATION; + } else if (options.kvStoreType == KvStoreType::LOCAL_ONLY) { + dbOption.storageEngineType = DistributedDB::GAUSSDB_RD; } dbOption.schema = options.schema; diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp index 1611501d7841478b86230e95d00378ca4465f2bc..3acf56b88262322df5b9dc71a18f74bfed141d84 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/src/store_manager.cpp @@ -30,8 +30,9 @@ StoreManager &StoreManager::GetInstance() std::shared_ptr StoreManager::GetKVStore(const AppId &appId, const StoreId &storeId, const Options &options, Status &status) { + std::string path = options.GetDatabaseDir(); ZLOGD("appId:%{public}s, storeId:%{public}s type:%{public}d area:%{public}d dir:%{public}s", appId.appId.c_str(), - StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, options.baseDir.c_str()); + StoreUtil::Anonymous(storeId.storeId).c_str(), options.kvStoreType, options.area, path.c_str()); status = ILLEGAL_STATE; if (!appId.IsValid() || !storeId.IsValid() || !options.IsValidType()) { status = INVALID_ARGUMENT; @@ -53,7 +54,7 @@ std::shared_ptr StoreManager::GetKVStore(const AppId &appId, cons auto kvStore = StoreFactory::GetInstance().GetOrOpenStore(appId, storeId, options, status, isCreate); if (isCreate && options.persistent) { auto dbPassword = SecurityManager::GetInstance().GetDBPassword(storeId.storeId, - options.baseDir, options.encrypt); + path, options.encrypt); std::vector pwd(dbPassword.GetData(), dbPassword.GetData() + dbPassword.GetSize()); if (service != nullptr) { // delay notify diff --git a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_get_top_test.cpp b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_get_top_test.cpp index 21f09dae8957ce87cb635a391b2720c04f38346d..eed7e194bf7422093612babdc80d8cc37e9365b1 100644 --- a/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_get_top_test.cpp +++ b/kv_store/frameworks/innerkitsimpl/kvdb/test/single_store_impl_get_top_test.cpp @@ -56,6 +56,7 @@ void SingleStoreImplGetTopTest::SetUpTestCase(void) Options options = { .createIfMissing = true, .encrypt = false, .autoSync = true, .kvStoreType = KvStoreType::SINGLE_VERSION }; options.area = EL1; + options.securityLevel = S1; options.baseDir = std::string("/data/service/el1/public/database/odmf"); AppId appId = { "odmf" }; StoreId storeId = { "test_single" }; // define kvstore(database) name. diff --git a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp index 7afeffc9142dd8ea0122ecf4010ea675486d4b57..2864faa9ab0d26cefbee6bcc6cf41740f22ab3b9 100644 --- a/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp +++ b/kv_store/frameworks/jskitsimpl/distributeddata/src/js_kv_store.cpp @@ -15,13 +15,11 @@ #define LOG_TAG "JsKVStore" #include "js_kv_store.h" #include "js_util.h" -#include "js_kv_store_resultset.h" #include "log_print.h" #include "napi_queue.h" #include "datashare_values_bucket.h" #include "datashare_predicates.h" #include "single_kvstore.h" -#include "kv_utils.h" using namespace OHOS::DistributedKv; using namespace OHOS::DataShare; diff --git a/kv_store/frameworks/libs/CMakeLists.txt b/kv_store/frameworks/libs/CMakeLists.txt index 69458e7a1b28e9c43346f20dd1c0ce72c4a6087e..6d5a356c49b29d58e1a586d3c4c66b58c8bf8bfe 100644 --- a/kv_store/frameworks/libs/CMakeLists.txt +++ b/kv_store/frameworks/libs/CMakeLists.txt @@ -12,6 +12,7 @@ add_definitions(-DWINDOWS_PLATFORM -DSQLITE_HAS_CODEC -DJSONCPP_USE_BUILDER -DEK add_definitions(-Dfseeko64=fseeko) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/src/evloop/src distributeddbSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/src/cloud distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/src/relational distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/src distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/communicator/src distributeddbSrc) @@ -23,14 +24,15 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/opera aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/sqlite/relational distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/sqlite distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/upgrader distributeddbSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/gaussdb_rd distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/syncer/src/cloud distributeddbSrc) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/syncer/src distributeddbSrc) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/include/cloud) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/include/relational) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/include) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/src/evloop/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/common/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/communicator/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/communicator/src) @@ -41,17 +43,23 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/operat include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/sqlite) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/sqlite/relational) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/upgrader) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/cloud) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src/gaussdb_rd) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/storage/src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/syncer/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/syncer/src/cloud) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/syncer/src) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/gaussdb_rd/include) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/gaussdb_rd/include/grd_base) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/gaussdb_rd/include/grd_document) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/gaussdb_rd/include/grd_kv) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../utils_native/base/include) include_directories(/usr/include/jsoncpp) include_directories(${MOCK_DIR}) include_directories(${MOCK_DIR}/sqlite/include) include_directories(${MOCK_DIR}/innerkits/hilog_native/libhilog/include) -set(links secure mock jsoncpp crypto) +set(links secure mock jsoncpp crypto gaussdb) add_library(distributeddb SHARED ${distributeddbSrc}) target_link_libraries(distributeddb ${links}) target_include_directories(distributeddb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/distributeddb/interfaces/include/cloud) diff --git a/kv_store/frameworks/libs/distributeddb/BUILD.gn b/kv_store/frameworks/libs/distributeddb/BUILD.gn index 0d3b550c50b32c92377f137c830cc3d7ce08bc4e..6c4d513c13c0a64b32fe2bed3fcacbb5a8db9b5f 100644 --- a/kv_store/frameworks/libs/distributeddb/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/BUILD.gn @@ -24,11 +24,13 @@ config("distrdb_config") { "common/include", "common/include/cloud", "common/include/relational", + "common/src/cloud", "communicator/include", "storage/include", "storage/src", "storage/src/multiver", "storage/src/operation", + "storage/src/gaussdb_rd", "storage/src/sqlite", "storage/src/sqlite/relational", "storage/src/upgrader", @@ -69,6 +71,9 @@ config("distrdb_public_config") { "interfaces/include/relational", "include", "gaussdb_rd/include", + "gaussdb_rd/include/grd_base", + "gaussdb_rd/include/grd_document", + "gaussdb_rd/include/grd_kv", ] } diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/asset_operation_utils.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/asset_operation_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..d7bf99e9c0d14c2f427814b9eb4826bf25b36c03 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/asset_operation_utils.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ASSET_OPERATION_UTILS_H +#define ASSET_OPERATION_UTILS_H +#include "cloud/cloud_store_types.h" + +namespace DistributedDB { +class AssetOperationUtils { +public: + enum class AssetOpType { + HANDLE, + NOT_HANDLE, + }; + enum class CloudSyncAction : uint16_t { + START_DOWNLOAD = 0, + START_UPLOAD, + END_DOWNLOAD, + END_UPLOAD, + DEFAULT_ACTION + }; + using RecordAssetOpType = std::map>; + static RecordAssetOpType CalAssetOperation(const VBucket &cacheAssets, const VBucket &dbAssets, + const CloudSyncAction &action); + static AssetOperationUtils::AssetOpType CalAssetOperation(const std::string &colName, const Asset &cacheAsset, + const VBucket &dbAssets, const CloudSyncAction &action); + static uint32_t EraseBitMask(uint32_t status); + static void UpdateAssetsFlag(std::vector &from, std::vector &target); +private: + static void Init(); + static AssetOperationUtils::AssetOpType DefaultOperation(const Asset &, const Assets &); + static AssetOperationUtils::AssetOpType CheckBeforeDownload(const Asset &cacheAsset, const Assets &dbAssets); + static AssetOperationUtils::AssetOpType CheckAfterDownload(const Asset &cacheAsset, const Assets &dbAssets); + static AssetOperationUtils::AssetOpType CheckWithDownload(bool before, const Asset &cacheAsset, + const Assets &dbAssets); + static AssetOperationUtils::AssetOpType CheckAfterUpload(const Asset &cacheAsset, const Assets &dbAssets); + static AssetOperationUtils::AssetOpType HandleIfExistAndSameStatus(const Asset &cacheAsset, const Assets &dbAssets); + static Assets GetAssets(const std::string &colName, const VBucket &rowData); + static void MergeAssetsFlag(const Assets &from, Type &target); + static void MergeAssetFlag(const Assets &from, Asset &target); + static constexpr uint32_t BIT_MASK_COUNT = 16; +}; +} +#endif // ASSET_OPERATION_UTILS_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h index a484460edb3a1bb1aa348699fb75c4621d28d120..bbac5d3256ad97789731585c0b0a6fecb05359b9 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_constant.h @@ -30,7 +30,15 @@ public: static constexpr const char *CURSOR_FIELD = "#_cursor"; static constexpr const char *TYPE_FIELD = "#_type"; static constexpr const char *QUERY_FIELD = "#_query"; + static constexpr const char *REFERENCE_FIELD = "#_reference"; + static constexpr const char *VERSION_FIELD = "#_version"; + static constexpr const char *ERROR_FIELD = "#_error"; static constexpr const char *ROW_ID_FIELD_NAME = "rowid"; + static constexpr const char *ASSET = "asset"; + static constexpr const char *ASSETS = "assets"; + static constexpr const char *SHARED = "_shared"; + static constexpr const char *CLOUD_OWNER = "cloud_owner"; + static constexpr const char *CLOUD_PRIVILEGE = "cloud_privilege"; static constexpr uint32_t MAX_UPLOAD_SIZE = 1024 * 512 * 3; // 1.5M // cloud data timestamp is utc ms precision // used for 100ns to ms when handle cloud data timestamp diff --git a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h index 7af68da602b4692c60fd01bd197bfacdef81c4f1..afda517396c5bd827c0ba03ab8f8ec3c0ef615db 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/cloud/cloud_db_types.h @@ -26,6 +26,7 @@ struct CloudSyncBatch { std::vector rowid; std::vector timestamp; std::vector assets; + std::vector hashKey; }; struct CloudSyncData { @@ -34,11 +35,16 @@ struct CloudSyncData { CloudSyncBatch updData; CloudSyncBatch delData; bool isCloudForcePushStrategy = false; + bool isShared = false; int ignoredCount = 0; CloudSyncData() = default; CloudSyncData(const std::string &_tableName) : tableName(_tableName) {}; }; +struct CloudTaskConfig { + bool allowLogicDelete = false; +}; + template struct index_of : std::integral_constant {}; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h index 52120c555f9f4c13b89bb2aca4443b8927537535..1fc3b39944c7fa45b6ab88082ef8803ad54d2fec 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_common.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_common.h @@ -87,11 +87,27 @@ public: static std::string ToUpperCase(const std::string &str); - static bool CaseInsensitiveCompare(std::string first, std::string second); + static bool CaseInsensitiveCompare(const std::string &first, const std::string &second); static bool CheckIsAlnumOrUnderscore(const std::string &text); static bool CheckQueryWithoutMultiTable(const Query &query); + + static bool IsCircularDependency(int size, const std::vector> &dependency); + + static int SerializeWaterMark(Timestamp localMark, const std::string &cloudMark, Value &blobMeta); + + static Key GetPrefixTableName(const TableName &tableName); + + static std::list GenerateNodesByNodeWeight(const std::vector &nodes, + const std::map> &graph, + const std::map &nodeWeight); + + static bool HasPrimaryKey(const std::vector &fields); +private: + static void InsertNodesByScore(const std::map> &graph, + const std::vector &generateNodes, const std::map &scoreGraph, + std::list &insertTarget); }; // Define short macro substitute for original long expression for convenience of using diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h index 005394b9900a7472eadd2491990090f66b2b3203..a99f76b3b14545b06fc1027a5eee44ed9e783a47 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_constant.h @@ -78,10 +78,13 @@ public: static const std::string SINGLE_VER_CACHE_STORE; static const std::string SQLITE_URL_PRE; - static const std::string SQLITE_DB_EXTENSION; + static const std::string DB_EXTENSION; static const std::string SQLITE_MEMDB_IDENTIFY; static const std::string SCHEMA_KEY; static const std::string RELATIONAL_SCHEMA_KEY; + static const std::string RELATIONAL_TRACKER_SCHEMA_KEY; + + static const std::string RD_KV_COLLECTION_MODE; static const std::string PATH_POSTFIX_UNPACKED; static const std::string PATH_POSTFIX_IMPORT_BACKUP; @@ -157,6 +160,7 @@ public: static const std::string LOG_TABLE_VERSION_2; static constexpr const char *LOG_TABLE_VERSION_3 = "3.0"; static constexpr const char *LOG_TABLE_VERSION_4 = "4.0"; + static constexpr const char *LOG_TABLE_VERSION_5 = "5.0"; static const std::string LOG_TABLE_VERSION_CURRENT; static const std::string LOG_TABLE_VERSION_KEY; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_dfx_adapter.h b/kv_store/frameworks/libs/distributeddb/common/include/db_dfx_adapter.h index b1b67e048c2f494b39a605c6326c3b9c5d88c514..c3f9968ed1c1e19eeb447151e723b17142e935e6 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_dfx_adapter.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_dfx_adapter.h @@ -42,7 +42,7 @@ public: static void StartTrace(const std::string &action); static void FinishTrace(); - static void StartTraceSQL(); + static void StartTracing(); static void FinishTraceSQL(); static void StartAsyncTrace(const std::string &action, int32_t taskId); diff --git a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h index 932f902c94ed7036ca24809e6d6675f789643c20..a6c8d42de097c608df583ce2f8d411e975309a74 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/db_errno.h @@ -137,6 +137,7 @@ constexpr int E_CLOUD_LOCK_ERROR = (E_BASE + 116); // cloud failed to get sync l constexpr int E_CLOUD_ASSET_SPACE_INSUFFICIENT = (E_BASE + 117); // cloud failed to download asset constexpr int E_CLOUD_INVALID_ASSET = (E_BASE + 118); // the asset is invalid constexpr int E_TASK_PAUSED = (E_BASE + 119); // the task was paused, don't finished it +constexpr int E_CLOUD_VERSION_CONFLICT = (E_BASE + 120); // cloud failed to update version // Num 150+ is reserved for schema related errno, since it may be added regularly constexpr int E_JSON_PARSE_FAIL = (E_BASE + 150); // Parse json fail in grammatical level constexpr int E_JSON_INSERT_PATH_EXIST = (E_BASE + 151); // Path already exist before insert @@ -159,12 +160,14 @@ 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 +constexpr int E_REBUILD_DATABASE = (E_BASE + 190); // database is rebuilt // 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 +constexpr int E_TABLE_REFERENCE_CHANGED = (E_BASE + 204); // table reference is changed } // namespace DistributedDB #endif // DISTRIBUTEDDB_ERRNO_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/param_check_utils.h b/kv_store/frameworks/libs/distributeddb/common/include/param_check_utils.h index ae0053e0ab0e4457dabe75b3791130e9255353f5..a0f5897fd54082796a048363a28c40b0f51791e2 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/param_check_utils.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/param_check_utils.h @@ -52,6 +52,12 @@ public: static uint8_t GetValidCompressionRate(uint8_t compressionRate); static bool CheckRelationalTableName(const std::string &tableName); + + static bool CheckTableReference(const std::vector &tableReferenceProperty); + + static bool CheckSharedTableName(const DataBaseSchema &schema); + + static void TransferSchemaToLower(DataBaseSchema &schema); }; } // namespace DistributedDB #endif // PARAM_CHECK_UTILS_H diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h index 001e65eca412be26c9f4460689a52831467d13f8..934b986fb8a2f86f52c03fea0eb27129c4d02de5 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/relational_schema_object.h @@ -17,9 +17,9 @@ #ifdef RELATIONAL_STORE #include #include "data_value.h" +#include "ischema.h" #include "json_object.h" #include "parcel.h" -#include "ischema.h" #include "schema_constant.h" #include "table_info.h" @@ -54,6 +54,18 @@ public: DistributedTableMode GetTableMode() const; void SetTableMode(DistributedTableMode mode); + void InsertTrackerSchema(const TrackerSchema &schema); + void RemoveTrackerSchema(const TrackerSchema &schema); + TrackerTable GetTrackerTable(const std::string &tableName) const; + int ParseFromTrackerSchemaString(const std::string &inSchemaString); + const TableInfoMap &GetTrackerTables() const; + + void SetReferenceProperty(const std::vector &referenceProperty); + const std::vector &GetReferenceProperty() const; + std::set GetSharedTableForChangeTable(std::set &changeTables) const; + std::set CompareReferenceProperty(const std::vector &others) const; + std::map> GetReachableRef(); + std::map GetTableWeight(); private: int CompareAgainstSchemaObject(const std::string &inSchemaString, std::map &cmpRst) const; @@ -67,21 +79,46 @@ private: int ParseCheckSchemaTableDefine(const JsonObject &inJsonObject); int ParseCheckTableInfo(const JsonObject &inJsonObject); int ParseCheckTableName(const JsonObject &inJsonObject, TableInfo &resultTable); + int ParseCheckOriginTableName(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableDefine(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableFieldInfo(const JsonObject &inJsonObject, const FieldPath &path, FieldInfo &table); int ParseCheckTableAutoInc(const JsonObject &inJsonObject, TableInfo &resultTable); + int ParseCheckSharedTableMark(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableSyncType(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTableUnique(const JsonObject &inJsonObject, TableInfo &resultTable); int ParseCheckTablePrimaryKey(const JsonObject &inJsonObject, TableInfo &resultTable); + int ParseCheckReferenceProperty(const JsonObject &inJsonObject); // parse all reference + int ParseCheckReference(const JsonObject &inJsonObject); // parse one reference + // parse reference columns + int ParseCheckReferenceColumns(const JsonObject &inJsonObject, TableReferenceProperty &tableReferenceProperty); + // parse one reference column pair + int ParseCheckReferenceColumn(const JsonObject &inJsonObject, TableReferenceProperty &tableReferenceProperty); void GenerateSchemaString(); + void GenerateTrackerSchemaString(); + std::string GetReferencePropertyString(); + std::string GetOneReferenceString(const TableReferenceProperty &reference); + int ParseTrackerSchema(const JsonObject &inJsonObject); + int ParseCheckTrackerTable(const JsonObject &inJsonObject); + int ParseCheckTrackerTableName(const JsonObject &inJsonObject, TrackerTable &resultTable); + int ParseCheckTrackerExtendName(const JsonObject &inJsonObject, TrackerTable &resultTable); + int ParseCheckTrackerName(const JsonObject &inJsonObject, TrackerTable &resultTable); + void GenerateReachableRef(); + void GenerateTableInfoReferenced(); + void RefreshReachableRef(const TableReferenceProperty &referenceProperty); + void CalculateTableWeight(const std::set &startNodes, + const std::map> &nextNodes); bool isValid_ = false; // set to true after parse success from string or add at least one relational table SchemaType schemaType_ = SchemaType::RELATIVE; // Default RELATIVE std::string schemaString_; // The minified and valid schemaString std::string schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION_V2; // Default version 2.0 TableInfoMap tables_; + TableInfoMap trackerTables_; + std::vector referenceProperty_; + std::map> reachableReference_; + std::map tableWeight_; DistributedTableMode tableMode_ = DistributedTableMode::SPLIT_BY_DEVICE; }; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h index 31f079703d06d5bdfffcc76461926d211063b4d1..63f04732d54d160e045d1262cee60aedbb3d5554 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/table_info.h @@ -20,10 +20,11 @@ #include #include "cloud/cloud_store_types.h" -#include "db_types.h" -#include "schema_constant.h" #include "data_value.h" +#include "db_types.h" #include "ischema.h" +#include "schema_constant.h" +#include "tracker_table.h" namespace DistributedDB { using CompositeFields = std::vector; @@ -74,6 +75,8 @@ using IndexInfoMap = std::map &GetUniqueDefine() const; void SetTableName(const std::string &tableName); + void SetOriginTableName(const std::string &originTableName); + void SetSharedTableMark(bool sharedTableMark); void SetAutoIncrement(bool autoInc); void SetTableSyncType(TableSyncType tableSyncType); void SetCreateTableSql(const std::string &sql); // set 'autoInc_' flag when set sql @@ -91,6 +96,12 @@ public: void SetPrimaryKey(const std::map &key); void SetPrimaryKey(const FieldName &fieldName, int keyIndex); std::string ToTableInfoString(const std::string &schemaVersion) const; + void SetTrackerTable(const TrackerTable &table); + int CheckTrackerTable(); + const TrackerTable &GetTrackerTable() const; + void AddTableReferenceProperty(const TableReferenceProperty &tableRefProperty); + void SetSourceTableReference(const std::vector &tableReference); + const std::vector &GetTableReference() const; void SetUniqueDefine(const std::vector &uniqueDefine); @@ -128,6 +139,8 @@ private: int CompareWithLiteTableFields(const FieldInfoMap &liteTableFields) const; std::string tableName_; + std::string originTableName_ = ""; + bool sharedTableMark_ = false; bool autoInc_ = false; // only 'INTEGER PRIMARY KEY' could be defined as 'AUTOINCREMENT' TableSyncType tableSyncType_ = DEVICE_COOPERATION; std::string sql_; @@ -138,6 +151,11 @@ private: std::vector uniqueDefines_; int id_ = -1; + TrackerTable trackerTable_; + // a + // b c + // d e f ,table_info[a] = {b,c} [b] = {d, e} [c] = {f} + std::vector sourceTableReferenced_; }; } // namespace DistributedDB #endif // TABLE_INFO_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h new file mode 100644 index 0000000000000000000000000000000000000000..609f20913bb4622fccc194c32298c0fd86f9d44c --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/include/relational/tracker_table.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef TRACKER_TABLE_H +#define TRACKER_TABLE_H +#include +#include "store_types.h" +#include "db_types.h" +#include "db_errno.h" +#include "json_object.h" + +#ifdef RELATIONAL_STORE +namespace DistributedDB { +class TrackerTable { +public: + TrackerTable() = default; + virtual ~TrackerTable() {}; + + std::string GetTableName() const; + const std::set &GetTrackerColNames() const; + void Init(const TrackerSchema &schema); + const std::string GetAssignValSql(bool isDelete = false) const; + const std::string GetExtendAssignValSql(bool isDelete = false) const; + const std::string GetDiffTrackerValSql() const; + const std::string GetExtendName() const; + std::string ToString() const; + const std::vector GetDropTempTriggerSql() const; + const std::string GetTempInsertTriggerSql() const; + const std::string GetTempUpdateTriggerSql() const; + const std::string GetTempDeleteTriggerSql() const; + const std::string GetUpgradedExtendValSql() const; + void SetTableName(const std::string &tableName); + void SetExtendName(const std::string &colName); + void SetTrackerNames(const std::set &trackerNames); + bool IsEmpty() const; + bool IsChanging(const TrackerSchema &schema); + +private: + std::string tableName_; + std::string extendColName_; + std::set trackerColNames_; +}; + +} // namespace DistributedDB +#endif // RELATIONAL_STORE +#endif // TRACKER_TABLE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h b/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h index 0fb0e6b75aaec18c6ecf58cf7dc60897f2bbc6fa..b71b96006a328fdc3d7c1fa918815baefc1931de 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/schema_constant.h @@ -41,6 +41,7 @@ public: 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_TYPE_BOOLEAN; static const std::string KEYWORD_ATTR_NOT_NULL; static const std::string KEYWORD_ATTR_DEFAULT; @@ -57,6 +58,13 @@ public: static const std::string SCHEMA_SUPPORT_VERSION_V2_1; static const std::string SCHEMA_CURRENT_VERSION; + static constexpr const char *REFERENCE_PROPERTY = "REFERENCE_PROPERTY"; + static constexpr const char *SOURCE_TABLE_NAME = "SOURCE_TABLE_NAME"; + static constexpr const char *TARGET_TABLE_NAME = "TARGET_TABLE_NAME"; + static constexpr const char *COLUMNS = "COLUMNS"; + static constexpr const char *SOURCE_COL = "SOURCE_COL"; + static constexpr const char *TARGET_COL = "TARGET_COL"; + 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; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h b/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h index 0f353c28a7447bf908a508ad978f7dbfc374cf1e..dd6eb4a24272c3158d47e65a102d35d04a860d74 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/schema_utils.h @@ -51,6 +51,8 @@ public: // Restore to string representation of fieldPath with $. prefix static std::string FieldPathString(const FieldPath &inPath); + static void TransTrackerSchemaToLower(const TrackerSchema &srcSchema, TrackerSchema &destSchema); + SchemaUtils() = delete; ~SchemaUtils() = delete; diff --git a/kv_store/frameworks/libs/distributeddb/common/include/version.h b/kv_store/frameworks/libs/distributeddb/common/include/version.h index 857d186f2412d7e423abd7d3f4e001612b9baee2..1429350dc8408be102a27ef304658571638f0916 100644 --- a/kv_store/frameworks/libs/distributeddb/common/include/version.h +++ b/kv_store/frameworks/libs/distributeddb/common/include/version.h @@ -38,12 +38,10 @@ constexpr uint32_t SOFTWARE_VERSION_RELEASE_3_0 = SOFTWARE_VERSION_BASE + 3; // constexpr uint32_t SOFTWARE_VERSION_RELEASE_4_0 = SOFTWARE_VERSION_BASE + 4; // 4 for fourth released version constexpr uint32_t SOFTWARE_VERSION_RELEASE_5_0 = SOFTWARE_VERSION_BASE + 5; // 5 for fifth released version constexpr uint32_t SOFTWARE_VERSION_RELEASE_6_0 = SOFTWARE_VERSION_BASE + 6; // 6 for sixth released version +// check both device has security label at 107 +constexpr uint32_t SOFTWARE_VERSION_RELEASE_7_0 = SOFTWARE_VERSION_BASE + 7; // 7 for sixth released version constexpr uint32_t SOFTWARE_VERSION_EARLIEST = SOFTWARE_VERSION_RELEASE_1_0; -#ifdef RELATIONAL_STORE -constexpr uint32_t SOFTWARE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_6_0; -#else -constexpr uint32_t SOFTWARE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_5_0; -#endif +constexpr uint32_t SOFTWARE_VERSION_CURRENT = SOFTWARE_VERSION_RELEASE_7_0; constexpr int VERSION_INVALID = INT32_MAX; // Storage Related Version diff --git a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp index 11e61d77f22b67a639759d9f0e48a21f86dac84e..8d0ff7c1f2b5f245b849dc44f1b69a762b6cdbdb 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/auto_launch.cpp @@ -993,7 +993,7 @@ int AutoLaunch::GetAutoLaunchKVProperties(const AutoLaunchParam ¶m, 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->SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); propertiesPtr->SetSchema(schemaObject); if (RuntimeContext::GetInstance()->IsProcessSystemApiAdapterValid()) { propertiesPtr->SetIntProp(KvDBProperties::SECURITY_LABEL, param.option.secOption.securityLabel); @@ -1005,6 +1005,8 @@ int AutoLaunch::GetAutoLaunchKVProperties(const AutoLaunchParam ¶m, ParamCheckUtils::GetValidCompressionRate(param.option.compressionRate)); } propertiesPtr->SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, param.option.syncDualTupleMode); + propertiesPtr->SetBoolProp(KvDBProperties::READ_ONLY_MODE, false); + propertiesPtr->SetBoolProp(KvDBProperties::SHARED_MODE, false); DBCommon::SetDatabaseIds(*propertiesPtr, param.appId, param.userId, param.storeId); return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/cloud/asset_operation_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/cloud/asset_operation_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8aeb06b6e9ba1d10443f94d61bac94dea281dc47 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/src/cloud/asset_operation_utils.cpp @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "cloud/asset_operation_utils.h" + +#include +#include "cloud/cloud_db_types.h" +#include "runtime_context.h" +namespace DistributedDB { +using RecordAssetOpType = AssetOperationUtils::RecordAssetOpType; +using CloudSyncAction = AssetOperationUtils::CloudSyncAction; +namespace { +std::once_flag g_init; +using Reaction = std::function; +std::map g_reactions; +Reaction GetReaction(const CloudSyncAction &action) +{ + if (g_reactions.find(action) != g_reactions.end()) { + return g_reactions[action]; + } else { + return g_reactions[CloudSyncAction::DEFAULT_ACTION]; + } +} +} + +RecordAssetOpType AssetOperationUtils::CalAssetOperation(const VBucket &cacheAssets, + const VBucket &dbAssets, const CloudSyncAction &action) +{ + std::call_once(g_init, Init); + // switch produce function by action + Reaction reaction = GetReaction(action); + RecordAssetOpType res; + // check each cache asset with db asset by same col name and asset name + for (const auto &[colName, colData] : cacheAssets) { + auto checkAssets = GetAssets(colName, dbAssets); + if (TYPE_INDEX == colData.index()) { + auto asset = std::get(colData); + res[colName][asset.name] = reaction(asset, checkAssets); + } else if (TYPE_INDEX == colData.index()) { + auto assets = std::get(colData); + for (const auto &asset : assets) { + res[colName][asset.name] = reaction(asset, checkAssets); + } + } + } + return res; +} + +AssetOperationUtils::AssetOpType AssetOperationUtils::CalAssetOperation(const std::string &colName, + const Asset &cacheAsset, const VBucket &dbAssets, const AssetOperationUtils::CloudSyncAction &action) +{ + std::call_once(g_init, Init); + // switch produce function by action + Reaction reaction = GetReaction(action); + return reaction(cacheAsset, GetAssets(colName, dbAssets)); +} + +uint32_t AssetOperationUtils::EraseBitMask(uint32_t status) +{ + return ((status << BIT_MASK_COUNT) >> BIT_MASK_COUNT); +} + +void AssetOperationUtils::UpdateAssetsFlag(std::vector &from, std::vector &target) +{ + if (from.size() != target.size()) { + LOGE("the num of VBucket are not equal when update assets flag."); + return; + } + for (size_t i = 0; i < from.size(); ++i) { + VBucket &fromRecord = from[i]; + VBucket &targetRecord = target[i]; + if (targetRecord.empty()) { + continue; + } + for (auto &[colName, colData] : targetRecord) { + auto fromAssets = GetAssets(colName, fromRecord); + MergeAssetsFlag(fromAssets, colData); + } + } +} + +void AssetOperationUtils::Init() +{ + g_reactions[CloudSyncAction::DEFAULT_ACTION] = DefaultOperation; + g_reactions[CloudSyncAction::START_DOWNLOAD] = CheckBeforeDownload; + g_reactions[CloudSyncAction::START_UPLOAD] = HandleIfExistAndSameStatus; + g_reactions[CloudSyncAction::END_DOWNLOAD] = CheckAfterDownload; + g_reactions[CloudSyncAction::END_UPLOAD] = CheckAfterUpload; +} + +AssetOperationUtils::AssetOpType AssetOperationUtils::DefaultOperation(const Asset &, const Assets &) +{ + return AssetOpType::HANDLE; +} + +AssetOperationUtils::AssetOpType AssetOperationUtils::CheckBeforeDownload(const Asset &cacheAsset, + const Assets &dbAssets) +{ + return CheckWithDownload(true, cacheAsset, dbAssets); +} + +AssetOperationUtils::AssetOpType AssetOperationUtils::CheckAfterDownload(const Asset &cacheAsset, + const Assets &dbAssets) +{ + return CheckWithDownload(false, cacheAsset, dbAssets); +} + +AssetOperationUtils::AssetOpType AssetOperationUtils::CheckWithDownload(bool before, const Asset &cacheAsset, + const Assets &dbAssets) +{ + for (const auto &dbAsset : dbAssets) { + if (dbAsset.name != cacheAsset.name) { + continue; + } + if (EraseBitMask(dbAsset.status) == AssetStatus::DOWNLOADING) { + return AssetOpType::HANDLE; + } + return AssetOpType::NOT_HANDLE; + } + if (before) { + return cacheAsset.flag == static_cast(DistributedDB::AssetOpType::DELETE) ? + AssetOpType::HANDLE : AssetOpType::NOT_HANDLE; + } + return AssetOpType::NOT_HANDLE; +} + +AssetOperationUtils::AssetOpType AssetOperationUtils::CheckAfterUpload(const Asset &cacheAsset, const Assets &dbAssets) +{ + for (const auto &dbAsset : dbAssets) { + if (dbAsset.name != cacheAsset.name) { + continue; + } + if ((dbAsset.status & static_cast(AssetStatus::UPLOADING)) == + static_cast(AssetStatus::UPLOADING)) { + return AssetOpType::HANDLE; + } + return AssetOpType::NOT_HANDLE; + } + return AssetOpType::NOT_HANDLE; +} + +Assets AssetOperationUtils::GetAssets(const std::string &colName, const VBucket &rowData) +{ + if (rowData.find(colName) == rowData.end()) { + return {}; + } + Assets res; + auto value = rowData.at(colName); + if (TYPE_INDEX == value.index()) { + res.push_back(std::get(value)); + } else if (TYPE_INDEX == value.index()) { + for (const auto &asset : std::get(value)) { + res.push_back(asset); + } + } + return res; +} + +AssetOperationUtils::AssetOpType AssetOperationUtils::HandleIfExistAndSameStatus(const Asset &cacheAsset, + const Assets &dbAssets) +{ + for (const auto &dbAsset : dbAssets) { + if (dbAsset.name != cacheAsset.name) { + continue; + } + if (dbAsset.status == cacheAsset.status) { + return AssetOpType::HANDLE; + } + return AssetOpType::NOT_HANDLE; + } + return AssetOpType::NOT_HANDLE; +} + +void AssetOperationUtils::MergeAssetsFlag(const Assets &from, Type &target) +{ + if (TYPE_INDEX == target.index()) { + MergeAssetFlag(from, std::get(target)); + } else if (TYPE_INDEX == target.index()) { + for (auto &targetAsset : std::get(target)) { + MergeAssetFlag(from, targetAsset); + } + } +} + +void AssetOperationUtils::MergeAssetFlag(const Assets &from, Asset &target) +{ + for (const auto &fromAsset : from) { + if (fromAsset.name == target.name) { + target.flag = fromAsset.flag; + } + } +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp index 801428dce444741e7eb9e2bb9557f4aa6e0e9aba..7e84c1be136a17cca692e470979ffe42bcb76bfb 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_common.cpp @@ -17,7 +17,9 @@ #include #include +#include +#include "cloud/cloud_db_constant.h" #include "db_errno.h" #include "platform_specific.h" #include "query_sync_object.h" @@ -316,9 +318,11 @@ void DBCommon::SetDatabaseIds(KvDBProperties &properties, const std::string &app std::string DBCommon::StringMasking(const std::string &oriStr, size_t remain) { +#ifndef DB_DEBUG_ENV if (oriStr.size() > remain) { return oriStr.substr(0, remain); } +#endif return oriStr; } @@ -441,11 +445,9 @@ std::string DBCommon::ToUpperCase(const std::string &str) return res; } -bool DBCommon::CaseInsensitiveCompare(std::string first, std::string second) +bool DBCommon::CaseInsensitiveCompare(const std::string &first, const std::string &second) { - std::transform(first.begin(), first.end(), first.begin(), ::tolower); - std::transform(second.begin(), second.end(), second.begin(), ::tolower); - return first == second; + return (strcasecmp(first.c_str(), second.c_str()) == 0); } bool DBCommon::CheckIsAlnumOrUnderscore(const std::string &text) @@ -460,13 +462,141 @@ bool DBCommon::CheckQueryWithoutMultiTable(const Query &query) { QuerySyncObject syncObject(query); if (!syncObject.GetRelationTableNames().empty()) { - LOGE("check query from tables failed!"); + LOGE("check query table names from tables failed!"); return false; } if (!QuerySyncObject::GetQuerySyncObject(query).empty()) { - LOGE("check query from table failed!"); + LOGE("check query object from table failed!"); return false; } return true; } + +/* this function us topology sorting algorithm to detect whether a ring exists in the dependency + * the algorithm main procedure as below: + * 1. select a point which in-degree is 0 in the graph and record it; + * 2. delete the point and all edges starting from this point; + * 3. repeat step 1 and 2, until the graph is empty or there is no point with a zero degree + * */ +bool DBCommon::IsCircularDependency(int size, const std::vector> &dependency) +{ + std::vector inDegree(size, 0); // save in-degree of every point + std::vector> adjacencyList(size); + for (size_t i = 0; i < dependency.size(); i++) { + adjacencyList[dependency[i][0]].push_back(dependency[i][1]); // update adjacencyList + inDegree[dependency[i][1]]++; + } + std::queue que; + for (size_t i = 0; i < inDegree.size(); i++) { + if (inDegree[i] == 0) { + que.push(i); // push all point which in-degree = 0 + } + } + + int zeroDegreeCnt = static_cast(que.size()); + while (!que.empty()) { + int index = que.front(); + que.pop(); + for (size_t i = 0; i < adjacencyList[index].size(); ++i) { + int j = adjacencyList[index][i]; // adjacencyList[index] save the point which is connected to index + inDegree[j]--; + if (inDegree[j] == 0) { + zeroDegreeCnt++; + que.push(j); + } + } + } + return zeroDegreeCnt != size; +} + +int DBCommon::SerializeWaterMark(Timestamp localMark, const std::string &cloudMark, Value &blobMeta) +{ + uint64_t length = Parcel::GetUInt64Len() + Parcel::GetStringLen(cloudMark); + blobMeta.resize(length); + Parcel parcel(blobMeta.data(), blobMeta.size()); + parcel.WriteUInt64(localMark); + parcel.WriteString(cloudMark); + if (parcel.IsError()) { + LOGE("[DBCommon] Parcel error while serializing cloud meta data."); + return -E_PARSE_FAIL; + } + return E_OK; +} + +Key DBCommon::GetPrefixTableName(const TableName &tableName) +{ + TableName newName = CloudDbConstant::CLOUD_META_TABLE_PREFIX + tableName; + Key prefixedTableName(newName.begin(), newName.end()); + return prefixedTableName; +} + +void DBCommon::InsertNodesByScore(const std::map> &graph, + const std::vector &generateNodes, const std::map &scoreGraph, + std::list &insertTarget) +{ + auto copyGraph = graph; + // insert all nodes into res + for (const auto &generateNode : generateNodes) { + auto iterator = insertTarget.begin(); + for (; iterator != insertTarget.end(); iterator++) { + // don't compare two no reachable node + if (!copyGraph[*iterator][generateNode] && !copyGraph[generateNode][*iterator]) { + continue; + } + if (scoreGraph.find(*iterator) == scoreGraph.end() || scoreGraph.find(generateNode) == scoreGraph.end()) { + // should not happen + LOGW("[DBCommon] not find score in graph"); + continue; + } + if (scoreGraph.at(*iterator) <= scoreGraph.at(generateNode)) { + break; + } + } + insertTarget.insert(iterator, generateNode); + } +} + +std::list DBCommon::GenerateNodesByNodeWeight(const std::vector &nodes, + const std::map> &graph, + const std::map &nodeWeight) +{ + std::list res; + std::set paramNodes; + std::set visitNodes; + for (const auto &node : nodes) { + res.push_back(node); + paramNodes.insert(node); + visitNodes.insert(node); + } + // find all node which can be reached by param nodes + for (const auto &source : paramNodes) { + if (graph.find(source) == graph.end()) { + continue; + } + for (const auto &[target, reach] : graph.at(source)) { + if (reach) { + visitNodes.insert(target); + } + } + } + std::vector generateNodes; + for (const auto &node : visitNodes) { + // ignore the node which is param + if (paramNodes.find(node) == paramNodes.end()) { + generateNodes.push_back(node); + } + } + InsertNodesByScore(graph, generateNodes, nodeWeight, res); + return res; +} + +bool DBCommon::HasPrimaryKey(const std::vector &fields) +{ + for (const auto &field : fields) { + if (field.primary) { + return true; + } + } + return false; +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp index 6bc209c20e0c6e3e525817fa9ea08fa4b3f8f342..23f894ea49f5084bceaef34f550ed709effdba9a 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_constant.cpp @@ -34,11 +34,14 @@ const std::string DBConstant::SINGLE_VER_META_STORE = "meta"; const std::string DBConstant::SINGLE_VER_CACHE_STORE = "cache"; const std::string DBConstant::SQLITE_URL_PRE = "file:"; -const std::string DBConstant::SQLITE_DB_EXTENSION = ".db"; +const std::string DBConstant::DB_EXTENSION = ".db"; const std::string DBConstant::SQLITE_MEMDB_IDENTIFY = "?mode=memory&cache=shared"; const std::string DBConstant::SCHEMA_KEY = "schemaKey"; const std::string DBConstant::RELATIONAL_SCHEMA_KEY = "relational_schema"; +const std::string DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY = "relational_tracker_schema"; + +const std::string DBConstant::RD_KV_COLLECTION_MODE = "{\"mode\" : \"kv\"}"; const std::string DBConstant::PATH_POSTFIX_UNPACKED = "_unpacked"; const std::string DBConstant::PATH_POSTFIX_IMPORT_BACKUP = "_import_bak"; @@ -72,7 +75,7 @@ const std::string DBConstant::LOG_POSTFIX = "_log"; const std::string DBConstant::LOG_TABLE_VERSION_1 = "1.0"; const std::string DBConstant::LOG_TABLE_VERSION_2 = "2.0"; -const std::string DBConstant::LOG_TABLE_VERSION_CURRENT = "4.0"; +const std::string DBConstant::LOG_TABLE_VERSION_CURRENT = LOG_TABLE_VERSION_5; const std::string DBConstant::LOG_TABLE_VERSION_KEY = "log_table_version"; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp index 4fe6c6f96b1fc3dd76e71f3cdc4c5f51c04310a3..6777efc9d7c224c2f8e95650b3fc2c4b1b35e108 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/db_dfx_adapter.cpp @@ -95,7 +95,7 @@ void DBDfxAdapter::FinishTrace() ::FinishTrace(HITRACE_LABEL); } -void DBDfxAdapter::StartTraceSQL() +void DBDfxAdapter::StartTracing() { #ifdef TRACE_SQLITE_EXECUTE ::StartTrace(HITRACE_LABEL, SQLITE_EXECUTE); @@ -149,7 +149,7 @@ void DBDfxAdapter::FinishAsyncTrace(const std::string &action, int32_t taskId) (void) taskId; } -void DBDfxAdapter::StartTraceSQL() +void DBDfxAdapter::StartTracing() { } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp b/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp index 6519f3d5e4370ec2c0119b03074e10e2497f4e79..62ed583525bd2c904f11182021070823b89f3963 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/evloop/src/event_loop_epoll.cpp @@ -120,7 +120,7 @@ int EventLoopEpoll::WakeUp() while (true) { int nWrite = write(wakeUpFd_, &incValue, sizeof(incValue)); - if (nWrite == sizeof(incValue)) { + if (nWrite == static_cast(sizeof(incValue))) { break; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp b/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp index 43132b5d90bd9ef4a54cdb3c1d4cc39b951d0099..92a014de32a2cf40e7c48429aee7aa9a92d332b2 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/log_print.cpp @@ -35,7 +35,11 @@ public: if (msg.empty()) { return; } +#ifdef DB_DEBUG_ENV + const std::string format = "%s"; +#else const std::string format = "%{public}s"; +#endif OHOS::HiviewDFX::HiLogLabel label = { LOG_CORE, 0xD001630, tag.c_str() }; // log module id. switch (level) { case Level::LEVEL_DEBUG: @@ -126,7 +130,11 @@ void Logger::PreparePrivateLog(const char *format, std::string &outStrFormat) outStrFormat = format; std::string::size_type pos = outStrFormat.find(PRIVATE_TAG); if (pos != std::string::npos) { +#ifdef DB_DEBUG_ENV + outStrFormat.replace(pos, PRIVATE_TAG.size(), "s"); +#else outStrFormat.replace(pos, PRIVATE_TAG.size(), ".3s"); +#endif } } } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp index 568646c384a8c04b4374e230ced3bb1dd4ad3484..b9dbb89a20295fdacb092417f62b1a207f9a4879 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/param_check_utils.cpp @@ -15,7 +15,9 @@ #include "param_check_utils.h" +#include "cloud/cloud_db_constant.h" #include "db_common.h" +#include "db_constant.h" #include "db_errno.h" #include "log_print.h" #include "platform_specific.h" @@ -202,4 +204,91 @@ bool ParamCheckUtils::CheckRelationalTableName(const std::string &tableName) } return tableName.compare(0, DBConstant::SYSTEM_TABLE_PREFIX.size(), DBConstant::SYSTEM_TABLE_PREFIX) != 0; } + +bool ParamCheckUtils::CheckTableReference(const std::vector &tableReferenceProperty) +{ + if (tableReferenceProperty.empty()) { + LOGI("[CheckTableReference] tableReferenceProperty is empty"); + return true; + } + + std::vector> dependency; + std::map tableName2Int; + int index = 0; + for (const auto &item : tableReferenceProperty) { + if (item.sourceTableName.empty() || item.targetTableName.empty() || item.columns.empty()) { + LOGE("[CheckTableReference] table name or column is empty"); + return false; + } + std::vector vec; + for (const auto &tableName : { item.sourceTableName, item.targetTableName }) { + if (tableName2Int.find(tableName) != tableName2Int.end()) { + vec.push_back(tableName2Int.at(tableName)); + } else { + vec.push_back(index); + tableName2Int[tableName] = index; + index++; + } + } + if (std::find(dependency.begin(), dependency.end(), vec) != dependency.end()) { + LOGE("[CheckTableReference] set multiple reference for two tables is not support."); + return false; + } + dependency.emplace_back(vec); + } + + if (DBCommon::IsCircularDependency(index, dependency)) { + LOGE("[CheckTableReference] circular reference is not support."); + return false; + } + return true; +} + +bool ParamCheckUtils::CheckSharedTableName(const DataBaseSchema &schema) +{ + DataBaseSchema lowerSchema = schema; + TransferSchemaToLower(lowerSchema); + std::set tableNames; + std::set sharedTableNames; + for (const auto &tableSchema : lowerSchema.tables) { + if (tableSchema.sharedTableName == tableSchema.name) { + LOGE("[CheckSharedTableName] Shared table name and table name are same."); + return false; + } + if (sharedTableNames.find(tableSchema.sharedTableName) != sharedTableNames.end() || + sharedTableNames.find(tableSchema.name) != sharedTableNames.end() || + tableNames.find(tableSchema.sharedTableName) != tableNames.end() || + tableNames.find(tableSchema.name) != tableNames.end()) { + LOGE("[CheckSharedTableName] Shared table names or table names are duplicate."); + return false; + } + if (!CheckRelationalTableName(tableSchema.sharedTableName)) { + return false; + } + tableNames.insert(tableSchema.name); + sharedTableNames.insert(tableSchema.sharedTableName); + std::set fields; + for (const auto &field : tableSchema.fields) { + if (fields.find(field.colName) != fields.end() || field.colName == CloudDbConstant::CLOUD_OWNER || + field.colName == CloudDbConstant::CLOUD_PRIVILEGE) { + LOGE("[CheckSharedTableName] fields are duplicate."); + return false; + } + fields.insert(field.colName); + } + } + return true; +} + +void ParamCheckUtils::TransferSchemaToLower(DataBaseSchema &schema) +{ + for (auto &tableSchema : schema.tables) { + std::transform(tableSchema.name.begin(), tableSchema.name.end(), tableSchema.name.begin(), tolower); + std::transform(tableSchema.sharedTableName.begin(), tableSchema.sharedTableName.end(), + tableSchema.sharedTableName.begin(), tolower); + for (auto &field : tableSchema.fields) { + std::transform(field.colName.begin(), field.colName.end(), field.colName.begin(), tolower); + } + } +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp index adc7367a50e5c696cad473a110414e53536e34fa..effa14f356e67cfdba4034bedf002dbff1bbbb08 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/platform_specific.cpp @@ -70,6 +70,9 @@ int RenameFilePath(const std::string &oldFilePath, const std::string &newFilePat int RemoveFile(const std::string &filePath) { +#ifdef DB_DEBUG_ENV + LOGD("---> remove db filePath: %s", filePath.c_str()); +#endif int errCode = remove(filePath.c_str()); if (errCode < 0) { LOGE("[RemoveFile] Remove file fail %s %d err = %d", filePath.c_str(), errCode, errno); @@ -122,6 +125,9 @@ int MakeDBDirectory(const std::string &directory) int RemoveDBDirectory(const std::string &directory) { +#ifdef DB_DEBUG_ENV + LOGD("---> remove db directory: %s", directory.c_str()); +#endif int ret = rmdir(directory.c_str()); LOGI("CheckPathExistence %s ret:%d error %d", directory.c_str(), ret, errno); return ret; @@ -164,6 +170,7 @@ int GetRealPath(const std::string &inOriPath, std::string &outRealPath) delete [] realPath; return E_OK; } +#ifndef DB_DEBUG_ENV namespace { const uint64_t MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS = 1000; const uint64_t MULTIPLES_BETWEEN_MICROSECONDS_AND_100_NANOSECONDS = 10; @@ -180,6 +187,7 @@ int GetCurrentSysTimeInMicrosecond(uint64_t &outTime) MICROSECONDS_OFFSET; return E_OK; } +#endif // DB_DEBUG_ENV int GetMonotonicRelativeTimeInMicrosecond(uint64_t &outTime) { @@ -475,7 +483,7 @@ int GetRealPath(const std::string &inOriPath, std::string &outRealPath) return E_OK; } -#ifndef RUNNING_ON_SIMULATED_ENV +#ifndef DB_DEBUG_ENV int GetCurrentSysTimeInMicrosecond(uint64_t &outTime) { struct timeval rawTime; @@ -488,7 +496,7 @@ int GetCurrentSysTimeInMicrosecond(uint64_t &outTime) static_cast(rawTime.tv_usec); return E_OK; } -#endif // RUNNING_ON_SIMULATED_ENV +#endif // DB_DEBUG_ENV namespace { const uint64_t MULTIPLES_BETWEEN_MICROSECONDS_AND_NANOSECONDS = 1000; @@ -625,7 +633,6 @@ int CloseFile(FileHandle *fileHandle) return -E_SYSTEM_API_FAIL; } delete fileHandle; - fileHandle = nullptr; return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/common/src/query.cpp b/kv_store/frameworks/libs/distributeddb/common/src/query.cpp index 17910386fa58dbbcd5cf2fb6fc58e502c7742414..9333c61e281616cede257c4f4bd5b074772c5b3c 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/query.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/query.cpp @@ -67,6 +67,12 @@ Query &Query::PrefixKey(const std::vector &key) return *this; } +Query &Query::Range(const std::vector &keyBegin, const std::vector &keyEnd) +{ + queryExpression_.QueryByKeyRange(keyBegin, keyEnd); + return *this; +} + Query &Query::SuggestIndex(const std::string &indexName) { queryExpression_.QueryBySuggestIndex(indexName); diff --git a/kv_store/frameworks/libs/distributeddb/common/src/query_expression.cpp b/kv_store/frameworks/libs/distributeddb/common/src/query_expression.cpp index 51b1c07e1615c7dbe13857b78dd524069768a489..fb74ea6dd115ba804efff3381355dec4fdcd63dc 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/query_expression.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/query_expression.cpp @@ -206,6 +206,20 @@ void QueryExpression::QueryByPrefixKey(const std::vector &key) prefixKey_ = key; } +void QueryExpression::QueryByKeyRange(const std::vector &keyBegin, const std::vector &keyEnd) +{ + if (useFromTable_) { + expressions_[fromTable_].QueryByKeyRange(keyBegin, keyEnd); + validStatus_ = -E_NOT_SUPPORT; + return; + } + SetNotSupportIfFromTables(); + queryInfo_.emplace_front(QueryObjNode{QueryObjType::KEY_RANGE, std::string(), + QueryValueType::VALUE_TYPE_NULL, std::vector()}); + beginKey_ = keyBegin; + endKey_ = keyEnd; +} + void QueryExpression::QueryBySuggestIndex(const std::string &indexName) { if (useFromTable_) { @@ -242,6 +256,16 @@ const std::list &QueryExpression::GetQueryExpression() return queryInfo_; } +std::vector QueryExpression::GetBeginKey() const +{ + return beginKey_; +} + +std::vector QueryExpression::GetEndKey() const +{ + return endKey_; +} + std::vector QueryExpression::GetPreFixKey() const { return prefixKey_; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp index 68ef8a8dc941fe7375ee6a985a684da0ebc0c601..ff4c73929242d4481a4358a28cfa6e59a6d7e486 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/relational_schema_object.cpp @@ -86,6 +86,7 @@ void RelationalSchemaObject::GenerateSchemaString() schemaString_ += it->second.ToTableInfoString(schemaVersion_); } schemaString_ += R"(])"; + schemaString_ += GetReferencePropertyString(); schemaString_ += "}"; } @@ -148,6 +149,201 @@ void RelationalSchemaObject::SetTableMode(DistributedTableMode mode) GenerateSchemaString(); } +void RelationalSchemaObject::InsertTrackerSchema(const TrackerSchema &schema) +{ + TrackerTable table; + table.Init(schema); + trackerTables_[schema.tableName].SetTrackerTable(table); + GenerateTrackerSchemaString(); +} + +void RelationalSchemaObject::RemoveTrackerSchema(const TrackerSchema &schema) +{ + trackerTables_.erase(schema.tableName); + GenerateTrackerSchemaString(); +} + +void RelationalSchemaObject::GenerateTrackerSchemaString() +{ + schemaString_ = {}; + schemaString_ += "{"; + schemaString_ += R"("SCHEMA_TYPE":"TRACKER",)"; + schemaString_ += R"("TABLES":[)"; + for (auto it = trackerTables_.begin(); it != trackerTables_.end(); it++) { + if (it != trackerTables_.begin()) { + schemaString_ += ","; + } + schemaString_ += it->second.GetTrackerTable().ToString(); + } + schemaString_ += R"(])"; + schemaString_ += "}"; +} + +std::string RelationalSchemaObject::GetReferencePropertyString() +{ + std::string res; + if (!referenceProperty_.empty()) { + res += R"(,"REFERENCE_PROPERTY":[)"; + for (const auto &reference : referenceProperty_) { + res += GetOneReferenceString(reference) + ","; + } + res.pop_back(); + res += R"(])"; + } + return res; +} + +std::string RelationalSchemaObject::GetOneReferenceString(const TableReferenceProperty &reference) +{ + std::string res = R"({"SOURCE_TABLE_NAME":")"; + res += reference.sourceTableName; + res += R"(","TARGET_TABLE_NAME":")"; + res += reference.targetTableName; + res += R"(","COLUMNS":[)"; + for (const auto &item : reference.columns) { + res += R"({"SOURCE_COL":")"; + res += item.first; + res += R"(","TARGET_COL":")"; + res += item.second; + res += R"("},)"; + } + res.pop_back(); + res += R"(]})"; + return res; +} + +static bool ColumnsCompare(const std::map &left, + const std::map &right) +{ + if (left.size() != right.size()) { + LOGE("[ColumnsCompare] column size not equal"); + return false; + } + std::map::const_iterator leftIt = left.begin(); + std::map::const_iterator rightIt = right.begin(); + for (; leftIt != left.end() && rightIt != right.end(); leftIt++, rightIt++) { + if (strcasecmp(leftIt->first.c_str(), rightIt->first.c_str()) != 0 || + strcasecmp(leftIt->second.c_str(), rightIt->second.c_str()) != 0) { + LOGE("[ColumnsCompare] column not equal"); + return false; + } + } + return true; +} + +static bool ReferenceCompare(const TableReferenceProperty &left, const TableReferenceProperty &right) +{ + if (strcasecmp(left.sourceTableName.c_str(), right.sourceTableName.c_str()) == 0 && + strcasecmp(left.targetTableName.c_str(), right.targetTableName.c_str()) == 0 && + ColumnsCompare(left.columns, right.columns)) { + return true; + } + return false; +} + +static void PropertyCompare(const std::vector &left, + const std::vector &right, std::set &changeTables) +{ + for (const auto &reference : left) { + bool found = false; + for (const auto &otherRef : right) { + if (ReferenceCompare(reference, otherRef)) { + found = true; + break; + } + } + if (!found) { + changeTables.insert(reference.sourceTableName); + changeTables.insert(reference.targetTableName); + } + } +} + +std::set RelationalSchemaObject::GetSharedTableForChangeTable(std::set &changeTables) const +{ + std::set res; + TableInfoMap tableInfos = GetTables(); + for (const auto &changeName : changeTables) { + for (const auto &item : tableInfos) { + if (item.second.GetSharedTableMark() && + (strcasecmp(item.second.GetOriginTableName().c_str(), changeName.c_str()) == 0)) { + res.insert(item.second.GetTableName()); // get shared table name + } + } + } + return res; +} + +std::set RelationalSchemaObject::CompareReferenceProperty( + const std::vector &others) const +{ + std::set changeTables; + PropertyCompare(referenceProperty_, others, changeTables); + PropertyCompare(others, referenceProperty_, changeTables); + if (!changeTables.empty()) { // get shared tables + std::set sharedTables = GetSharedTableForChangeTable(changeTables); + changeTables.insert(sharedTables.begin(), sharedTables.end()); + } + LOGI("[CompareReferenceProperty] changeTables size = %zu", changeTables.size()); + return changeTables; +} + +std::map> RelationalSchemaObject::GetReachableRef() +{ + return reachableReference_; +} + +std::map RelationalSchemaObject::GetTableWeight() +{ + return tableWeight_; +} + +TrackerTable RelationalSchemaObject::GetTrackerTable(const std::string &tableName) const +{ + auto it = trackerTables_.find(tableName); + if (it != trackerTables_.end()) { + return it->second.GetTrackerTable(); + } + return {}; +} + +int RelationalSchemaObject::ParseFromTrackerSchemaString(const std::string &inSchemaString) +{ + JsonObject schemaObj; + int errCode = schemaObj.Parse(inSchemaString); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Schema json string parse failed: %d.", errCode); + return errCode; + } + + errCode = ParseTrackerSchema(schemaObj); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Parse to relational schema failed: %d.", errCode); + return errCode; + } + + schemaString_ = schemaObj.ToString(); + return E_OK; +} + +const TableInfoMap &RelationalSchemaObject::GetTrackerTables() const +{ + return trackerTables_; +} + +void RelationalSchemaObject::SetReferenceProperty(const std::vector &referenceProperty) +{ + referenceProperty_ = referenceProperty; + GenerateSchemaString(); + GenerateReachableRef(); + GenerateTableInfoReferenced(); +} + +const std::vector &RelationalSchemaObject::GetReferenceProperty() const +{ + return referenceProperty_; +} + int RelationalSchemaObject::CompareAgainstSchemaObject(const std::string &inSchemaString, std::map &cmpRst) const { @@ -194,6 +390,117 @@ int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &f } } +int RelationalSchemaObject::ParseTrackerSchema(const JsonObject &inJsonObject) +{ + FieldType fieldType; + int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, fieldType); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get tracker schema TABLES fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::LEAF_FIELD_ARRAY != fieldType) { + LOGE("[RelationalSchema][Parse] Expect tracker TABLES fieldType ARRAY but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + std::vector tables; + errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, tables); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get tracker schema TABLES value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + for (const JsonObject &table : tables) { + errCode = ParseCheckTrackerTable(table); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Parse schema TABLES failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + } + return E_OK; +} + +int RelationalSchemaObject::ParseCheckTrackerTable(const JsonObject &inJsonObject) +{ + TrackerTable table; + int errCode = ParseCheckTrackerTableName(inJsonObject, table); + if (errCode != E_OK) { + return errCode; + } + errCode = ParseCheckTrackerExtendName(inJsonObject, table); + if (errCode != E_OK) { + return errCode; + } + errCode = ParseCheckTrackerName(inJsonObject, table); + if (errCode != E_OK) { + return errCode; + } + trackerTables_[table.GetTableName()].SetTrackerTable(table); + return E_OK; +} + +int RelationalSchemaObject::ParseCheckTrackerTableName(const JsonObject &inJsonObject, TrackerTable &resultTable) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, "NAME", FieldType::LEAF_FIELD_STRING, + true, fieldValue); + if (errCode == E_OK) { + if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in table name, err=%d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + resultTable.SetTableName(fieldValue.stringValue); + } + return errCode; +} + +int RelationalSchemaObject::ParseCheckTrackerExtendName(const JsonObject &inJsonObject, TrackerTable &resultTable) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, "EXTEND_NAME", FieldType::LEAF_FIELD_STRING, + true, fieldValue); + if (errCode == E_OK) { + if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in extend name, err=%d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + resultTable.SetExtendName(fieldValue.stringValue); + } + return errCode; +} + +int RelationalSchemaObject::ParseCheckTrackerName(const JsonObject &inJsonObject, TrackerTable &resultTable) +{ + FieldType fieldType; + int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {"TRACKER_NAMES"}, fieldType); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get tracker col names fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::LEAF_FIELD_ARRAY != fieldType) { + LOGE("[RelationalSchema][Parse] Expect tracker TABLES fieldType ARRAY but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + std::vector fieldValues; + errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{"TRACKER_NAMES"}, fieldValues); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get tracker col names value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + std::set colNames; + for (const JsonObject &value : fieldValues) { + FieldValue fieldValue; + errCode = value.GetFieldValueByFieldPath(FieldPath {}, fieldValue); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Parse tracker col name failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + colNames.insert(fieldValue.stringValue); + } + resultTable.SetTrackerNames(colNames); + return errCode; +} + int RelationalSchemaObject::ParseRelationalSchema(const JsonObject &inJsonObject) { int errCode = ParseCheckSchemaVersion(inJsonObject); @@ -208,7 +515,11 @@ int RelationalSchemaObject::ParseRelationalSchema(const JsonObject &inJsonObject if (errCode != E_OK) { return errCode; } - return ParseCheckSchemaTableDefine(inJsonObject); + errCode = ParseCheckSchemaTableDefine(inJsonObject); + if (errCode != E_OK) { + return errCode; + } + return ParseCheckReferenceProperty(inJsonObject); } namespace { @@ -301,7 +612,7 @@ int RelationalSchemaObject::ParseCheckSchemaTableDefine(const JsonObject &inJson return -E_SCHEMA_PARSE_FAIL; } std::vector tables; - errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::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; @@ -327,10 +638,18 @@ int RelationalSchemaObject::ParseCheckTableInfo(const JsonObject &inJsonObject) if (errCode != E_OK) { return errCode; } + errCode = ParseCheckOriginTableName(inJsonObject, resultTable); + if (errCode != E_OK) { + return errCode; + } errCode = ParseCheckTableAutoInc(inJsonObject, resultTable); if (errCode != E_OK) { return errCode; } + errCode = ParseCheckSharedTableMark(inJsonObject, resultTable); + if (errCode != E_OK) { + return errCode; + } errCode = ParseCheckTablePrimaryKey(inJsonObject, resultTable); if (errCode != E_OK) { return errCode; @@ -439,6 +758,24 @@ int RelationalSchemaObject::ParseCheckTableFieldInfo(const JsonObject &inJsonObj return E_OK; } +int RelationalSchemaObject::ParseCheckOriginTableName(const JsonObject &inJsonObject, TableInfo &resultTable) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, "ORIGINTABLENAME", FieldType::LEAF_FIELD_STRING, + false, fieldValue); + if (errCode == E_OK) { + if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in origin table name, err=%d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + resultTable.SetOriginTableName(fieldValue.stringValue); + } else if (errCode != -E_NOT_FOUND) { + LOGE("[RelationalSchema][Parse] Get schema orgin table name failed: %d", errCode); + return errCode; + } + return E_OK; +} + int RelationalSchemaObject::ParseCheckTableAutoInc(const JsonObject &inJsonObject, TableInfo &resultTable) { FieldValue fieldValue; @@ -451,6 +788,19 @@ int RelationalSchemaObject::ParseCheckTableAutoInc(const JsonObject &inJsonObjec return E_OK; } +int RelationalSchemaObject::ParseCheckSharedTableMark(const JsonObject &inJsonObject, TableInfo &resultTable) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, "SHAREDTABLEMARK", FieldType::LEAF_FIELD_BOOL, false, + fieldValue); + if (errCode == E_OK) { + resultTable.SetSharedTableMark(fieldValue.boolValue); + } else if (errCode != -E_NOT_FOUND) { + return errCode; + } + return E_OK; +} + int RelationalSchemaObject::ParseCheckTablePrimaryKey(const JsonObject &inJsonObject, TableInfo &resultTable) { if (!inJsonObject.IsFieldPathExist(FieldPath {"PRIMARY_KEY"})) { @@ -484,6 +834,140 @@ int RelationalSchemaObject::ParseCheckTablePrimaryKey(const JsonObject &inJsonOb return errCode; } +int RelationalSchemaObject::ParseCheckReferenceProperty(const JsonObject &inJsonObject) +{ + if (!inJsonObject.IsFieldPathExist(FieldPath {SchemaConstant::REFERENCE_PROPERTY})) { + return E_OK; + } + + FieldType fieldType; + int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::REFERENCE_PROPERTY}, fieldType); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get schema REFERENCE_PROPERTY fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::LEAF_FIELD_ARRAY != fieldType) { + LOGE("[RelationalSchema][Parse] Expect TABLES REFERENCE_PROPERTY ARRAY but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + std::vector references; + errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::REFERENCE_PROPERTY}, references); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get schema REFERENCE_PROPERTY value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + for (const JsonObject &reference : references) { + errCode = ParseCheckReference(reference); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Parse schema reference failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + } + return E_OK; +} + +int RelationalSchemaObject::ParseCheckReference(const JsonObject &inJsonObject) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::SOURCE_TABLE_NAME, FieldType::LEAF_FIELD_STRING, + true, fieldValue); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get source table name failed, errCode = %d", errCode); + return errCode; + } + if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in source table name."); + return -E_SCHEMA_PARSE_FAIL; + } + + TableReferenceProperty referenceProperty; + referenceProperty.sourceTableName = fieldValue.stringValue; + errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::TARGET_TABLE_NAME, FieldType::LEAF_FIELD_STRING, + true, fieldValue); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get target table name failed, errCode = %d", errCode); + return errCode; + } + if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in target table name."); + return -E_SCHEMA_PARSE_FAIL; + } + + referenceProperty.targetTableName = fieldValue.stringValue; + errCode = ParseCheckReferenceColumns(inJsonObject, referenceProperty); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Parse reference columns failed, errCode = %d", errCode); + return errCode; + } + referenceProperty_.emplace_back(referenceProperty); + tables_[referenceProperty.targetTableName].AddTableReferenceProperty(referenceProperty); + return E_OK; +} + +int RelationalSchemaObject::ParseCheckReferenceColumns(const JsonObject &inJsonObject, + TableReferenceProperty &tableReferenceProperty) +{ + // parse columns + FieldType fieldType; + int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::COLUMNS}, fieldType); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get schema reference COLUMNS fieldType failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + if (FieldType::LEAF_FIELD_ARRAY != fieldType) { + LOGE("[RelationalSchema][Parse] Expect reference COLUMNS ARRAY but %s.", + SchemaUtils::FieldTypeString(fieldType).c_str()); + return -E_SCHEMA_PARSE_FAIL; + } + std::vector columns; + errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::COLUMNS}, columns); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get schema reference COLUMNS value failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + + for (const JsonObject &column : columns) { + errCode = ParseCheckReferenceColumn(column, tableReferenceProperty); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Parse reference one COLUMN failed: %d.", errCode); + return -E_SCHEMA_PARSE_FAIL; + } + } + return E_OK; +} + +int RelationalSchemaObject::ParseCheckReferenceColumn(const JsonObject &inJsonObject, + TableReferenceProperty &tableReferenceProperty) +{ + FieldValue fieldValue; + int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::SOURCE_COL, FieldType::LEAF_FIELD_STRING, + true, fieldValue); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get source col failed, errCode = %d", errCode); + return errCode; + } + if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in source col name."); + return -E_SCHEMA_PARSE_FAIL; + } + + std::string sourceCol = fieldValue.stringValue; + errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::TARGET_COL, FieldType::LEAF_FIELD_STRING, + true, fieldValue); + if (errCode != E_OK) { + LOGE("[RelationalSchema][Parse] Get target col failed, errCode = %d", errCode); + return errCode; + } + if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { + LOGE("[RelationalSchema][Parse] Invalid characters in target col name."); + return -E_SCHEMA_PARSE_FAIL; + } + std::string targetCol = fieldValue.stringValue; + tableReferenceProperty.columns[sourceCol] = targetCol; + return E_OK; +} + int RelationalSchemaObject::ParseCheckTableSyncType(const JsonObject &inJsonObject, TableInfo &resultTable) { FieldValue fieldValue; @@ -541,5 +1025,93 @@ int RelationalSchemaObject::ParseCheckTableUnique(const JsonObject &inJsonObject resultTable.SetUniqueDefine(uniques); return E_OK; } + +void RelationalSchemaObject::GenerateReachableRef() +{ + reachableReference_.clear(); + tableWeight_.clear(); + std::set startNodes; // such as {a->b->c,d->e}, record {a,d} + std::map> nextNodes; // such as {a->b->c}, record {{a,{b}}, {b, {c}}} + // we need to record all table reachable reference here + for (const auto &tableRef : referenceProperty_) { + // they also can reach target + RefreshReachableRef(tableRef); + startNodes.insert(tableRef.sourceTableName); + startNodes.erase(tableRef.targetTableName); + nextNodes[tableRef.sourceTableName].insert(tableRef.targetTableName); + } + CalculateTableWeight(startNodes, nextNodes); +} + +void RelationalSchemaObject::GenerateTableInfoReferenced() +{ + for (auto &table : tables_) { + table.second.SetSourceTableReference({}); + } + for (const auto &reference : referenceProperty_) { + tables_[reference.targetTableName].AddTableReferenceProperty(reference); + } +} + +void RelationalSchemaObject::RefreshReachableRef(const TableReferenceProperty &referenceProperty) +{ + // such as source:A target:B + std::set recordSources; + // find all node which can reach source as collection recordSources + for (const auto &[start, end] : reachableReference_) { + auto node = end.find(referenceProperty.sourceTableName); + // find the node and it can reach + if (node != end.end() && node->second) { + recordSources.insert(start); + } + } + recordSources.insert(referenceProperty.sourceTableName); + // find all node which start with target as collection recordTargets + std::set recordTargets; + for (auto &[entry, reach] : reachableReference_[referenceProperty.targetTableName]) { + if (reach) { + recordTargets.insert(entry); + } + } + recordTargets.insert(referenceProperty.targetTableName); + for (const auto &source : recordSources) { + for (const auto &target : recordTargets) { + reachableReference_[source][target] = true; + } + } +} + +void RelationalSchemaObject::CalculateTableWeight(const std::set &startNodes, + const std::map> &nextNodes) +{ + // record the max long path as table weight + for (const auto &start : startNodes) { + std::map tmpTableWeight; + tmpTableWeight[start] = 1; + if (nextNodes.find(start) == nextNodes.end()) { + continue; + } + std::list queue; + for (const auto &target : nextNodes.at(start)) { + queue.push_back(target); + tmpTableWeight[target] = 2; // this path contain 2 nodes + } + // bfs all the path which start from startNodes + while (!queue.empty()) { + auto node = queue.front(); + queue.pop_front(); + if (nextNodes.find(node) == nextNodes.end()) { + continue; + } + for (const auto &item : nextNodes.at(node)) { + queue.push_back(item); + tmpTableWeight[item] = std::max(tmpTableWeight[item], tmpTableWeight[node] + 1); + } + } + for (const auto &[table, weight] : tmpTableWeight) { + tableWeight_[table] = std::max(tableWeight_[table], weight); + } + } +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp index 639dcea7aa56d2bcde7500c9b8c2993b939e1604..f55795855239796a467e026098c2bdbbeea5beed 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/table_info.cpp @@ -23,6 +23,7 @@ namespace DistributedDB { constexpr const char *ASSET = "asset"; constexpr const char *ASSETS = "assets"; +constexpr const char *ROW_ID = "rowid"; const std::string &FieldInfo::GetFieldName() const { @@ -183,7 +184,10 @@ int FieldInfo::CompareWithField(const FieldInfo &inField, bool isLite) const } if (hasDefaultValue_ && inField.HasDefaultValue()) { // lite schema only uses NULL as default value - return (isLite && defaultValue_ == "NULL") || defaultValue_ == inField.GetDefaultValue(); + return (isLite && DBCommon::CaseInsensitiveCompare(defaultValue_, "NULL")) || + (DBCommon::CaseInsensitiveCompare(defaultValue_, "NULL") && + DBCommon::CaseInsensitiveCompare(inField.GetDefaultValue(), "NULL")) || + (defaultValue_ == inField.GetDefaultValue()); } return hasDefaultValue_ == inField.HasDefaultValue(); } @@ -218,6 +222,26 @@ void TableInfo::SetTableName(const std::string &tableName) tableName_ = tableName; } +const std::string &TableInfo::GetOriginTableName() const +{ + return originTableName_; +} + +void TableInfo::SetOriginTableName(const std::string &originTableName) +{ + originTableName_ = originTableName; +} + +void TableInfo::SetSharedTableMark(bool sharedTableMark) +{ + sharedTableMark_ = sharedTableMark; +} + +bool TableInfo::GetSharedTableMark() const +{ + return sharedTableMark_; +} + void TableInfo::SetAutoIncrement(bool autoInc) { autoInc_ = autoInc; @@ -326,7 +350,7 @@ const std::map &TableInfo::GetPrimaryKey() const CompositeFields TableInfo::GetIdentifyKey() const { - if (primaryKey_.size() == 1 && primaryKey_.at(0) == "rowid") { + if (primaryKey_.size() == 1 && primaryKey_.at(0) == ROW_ID) { if (!uniqueDefines_.empty()) { return uniqueDefines_.at(0); } @@ -624,16 +648,16 @@ int TableInfo::CompareWithLiteTableFields(const FieldInfoMap &liteTableFields) c int TableInfo::CompareWithLiteSchemaTable(const TableInfo &liteTableInfo) const { - if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != "rowid") && + if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) && !CompareWithPrimaryKey(primaryKey_, liteTableInfo.GetPrimaryKey())) { LOGE("[Relational][Compare] Table primary key is not same"); return -E_RELATIONAL_TABLE_INCOMPATIBLE; } - if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) == "rowid")) { + if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) == ROW_ID)) { LOGE("[Relational][Compare] Table primary key is not same"); return -E_RELATIONAL_TABLE_INCOMPATIBLE; } - if ((liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != "rowid") && !autoInc_)) { + if ((liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) && !autoInc_)) { LOGE("[Relational][Compare] Table primary key is not same"); return -E_RELATIONAL_TABLE_INCOMPATIBLE; } @@ -647,12 +671,19 @@ std::string TableInfo::ToTableInfoString(const std::string &schemaVersion) const attrStr += "{"; attrStr += R"("NAME": ")" + tableName_ + "\","; AddFieldDefineString(attrStr); + attrStr += R"("ORIGINTABLENAME": ")" + originTableName_ + "\","; attrStr += R"("AUTOINCREMENT": )"; if (autoInc_) { attrStr += "true,"; } else { attrStr += "false,"; } + attrStr += R"("SHAREDTABLEMARK": )"; + if (sharedTableMark_) { + attrStr += "true,"; + } else { + attrStr += "false,"; + } AddUniqueDefineString(attrStr); if (primaryKey_.size() == 1 && schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) { attrStr += R"("PRIMARY_KEY": ")" + primaryKey_.at(0) + "\""; @@ -704,4 +735,64 @@ bool TableInfo::Empty() const { return tableName_.empty() || fields_.empty(); } + +void TableInfo::SetTrackerTable(const TrackerTable &table) +{ + trackerTable_ = table; +} + +int TableInfo::CheckTrackerTable() +{ + if (tableName_ != trackerTable_.GetTableName()) { + LOGE("the table name in schema is different from tracker table."); + return -E_NOT_FOUND; + } + if (trackerTable_.GetTrackerColNames().empty()) { + return E_OK; + } + for (const auto &colName: trackerTable_.GetTrackerColNames()) { + if (colName.empty()) { + LOGE("tracker col cannot be empty."); + return -E_INVALID_ARGS; + } + if (GetFields().find(colName) == GetFields().end()) { + LOGE("unable to match the tracker col from table schema."); + return -E_SCHEMA_MISMATCH; + } + } + if (trackerTable_.GetExtendName().empty()) { + return E_OK; + } + auto iter = GetFields().find(trackerTable_.GetExtendName()); + if (iter == GetFields().end()) { + LOGE("unable to match the extend col from table schema."); + return -E_SCHEMA_MISMATCH; + } else { + if (iter->second.IsAssetType() || iter->second.IsAssetsType()) { + LOGE("extend col is not allowed to be set as an asset field."); + return -E_INVALID_ARGS; + } + } + return E_OK; +} + +const TrackerTable &TableInfo::GetTrackerTable() const +{ + return trackerTable_; +} + +void TableInfo::AddTableReferenceProperty(const TableReferenceProperty &tableRefProperty) +{ + sourceTableReferenced_.push_back(tableRefProperty); +} + +void TableInfo::SetSourceTableReference(const std::vector &tableReference) +{ + sourceTableReferenced_ = tableReference; +} + +const std::vector &TableInfo::GetTableReference() const +{ + return sourceTableReferenced_; +} } // namespace DistributeDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7d50b353ef2c607516dba1e85d56273a4a94582d --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/common/src/relational/tracker_table.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef RELATIONAL_STORE +#include "tracker_table.h" +#include "schema_constant.h" + +namespace DistributedDB { +void TrackerTable::Init(const TrackerSchema &schema) +{ + tableName_ = schema.tableName; + extendColName_ = schema.extendColName; + trackerColNames_ = schema.trackerColNames; +} + +std::string TrackerTable::GetTableName() const +{ + return tableName_; +} + +const std::set &TrackerTable::GetTrackerColNames() const +{ + return trackerColNames_; +} + +const std::string TrackerTable::GetAssignValSql(bool isDelete) const +{ + if (extendColName_.empty()) { + return "''"; + } + return isDelete ? ("OLD." + extendColName_) : ("NEW." + extendColName_); +} + +const std::string TrackerTable::GetExtendAssignValSql(bool isDelete) const +{ + if (extendColName_.empty()) { + return ""; + } + return isDelete ? (", extend_field = OLD." + extendColName_) : (", extend_field = NEW." + extendColName_); +} + +const std::string TrackerTable::GetDiffTrackerValSql() const +{ + if (trackerColNames_.empty()) { + return "0"; + } + std::string sql = " case when ("; + size_t index = 0; + for (const auto &colName: trackerColNames_) { + sql += "NEW." + colName + " <> OLD." + colName; + if (index < trackerColNames_.size() - 1) { + sql += " or "; + } + index++; + } + sql += ") then 1 else 0 end"; + return sql; +} + +const std::string TrackerTable::GetExtendName() const +{ + return extendColName_; +} + +std::string TrackerTable::ToString() const +{ + std::string attrStr; + attrStr += "{"; + attrStr += R"("NAME": ")" + tableName_ + "\","; + attrStr += R"("EXTEND_NAME": ")" + extendColName_ + "\","; + attrStr += R"("TRACKER_NAMES": [)"; + for (const auto &colName: trackerColNames_) { + attrStr += "\"" + colName + "\","; + } + attrStr.pop_back(); + attrStr += "]}"; + return attrStr; +} + +const std::vector TrackerTable::GetDropTempTriggerSql() const +{ + if (IsEmpty()) { + return {}; + } + std::vector dropSql; + dropSql.push_back("DROP TRIGGER IF EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_ON_INSERT_TEMP;"); + dropSql.push_back("DROP TRIGGER IF EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_ON_UPDATE_TEMP;"); + dropSql.push_back("DROP TRIGGER IF EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_ON_DELETE_TEMP;"); + return dropSql; +} + +const std::string TrackerTable::GetTempInsertTriggerSql() const +{ + // This trigger is built on the log table + std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; + sql += "_ON_INSERT_TEMP AFTER INSERT ON " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + + " WHEN (SELECT count(1) FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; + sql += "BEGIN\n"; + sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; + sql += "cursor = (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END "; + sql += "FROM " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + ") WHERE "; + sql += " hash_key = NEW.hash_key;\n"; + if (!IsEmpty()) { + sql += "SELECT server_observer('" + tableName_ + "', 1);"; + } + sql += "\nEND;"; + return sql; +} + +const std::string TrackerTable::GetTempUpdateTriggerSql() const +{ + std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; + sql += "_ON_UPDATE_TEMP AFTER UPDATE ON " + tableName_ + + " WHEN (SELECT count(1) FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; + sql += "BEGIN\n"; + sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; + if (!IsEmpty()) { + sql += "extend_field=" + GetAssignValSql() + ","; + } + sql += " cursor = (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END "; + sql += "FROM " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + ") WHERE "; + sql += " data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; + if (!IsEmpty()) { + sql += "SELECT server_observer('" + tableName_ + "', " + GetDiffTrackerValSql() + ");"; + } + sql += "\nEND;"; + return sql; +} + +const std::string TrackerTable::GetTempDeleteTriggerSql() const +{ + std::string sql = "CREATE TEMP TRIGGER IF NOT EXISTS " + DBConstant::RELATIONAL_PREFIX + tableName_; + sql += "_ON_DELETE_TEMP AFTER DELETE ON " + tableName_ + + " WHEN (SELECT count(1) FROM " + DBConstant::RELATIONAL_PREFIX + "metadata" + + " WHERE key = 'log_trigger_switch' AND value = 'false')\n"; + sql += "BEGIN\n"; + sql += "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + " SET "; + if (!IsEmpty()) { + sql += "extend_field=" + GetAssignValSql(true) + ","; + } + sql += " cursor = (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END "; + sql += "FROM " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log" + ") WHERE "; + sql += " data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; + if (!IsEmpty()) { + sql += "SELECT server_observer('" + tableName_ + "', 1);"; + } + sql += "\nEND;"; + return sql; +} + +const std::string TrackerTable::GetUpgradedExtendValSql() const +{ + if (IsEmpty() || extendColName_.empty()) { + return "''"; + } + std::string sql = " (SELECT " + extendColName_ + " from " + tableName_ + " WHERE " + tableName_ + "." + + std::string(DBConstant::SQLITE_INNER_ROWID) + + " = " + DBConstant::RELATIONAL_PREFIX + tableName_ + "_log.data_key) "; + return sql; +} + +void TrackerTable::SetTableName(const std::string &tableName) +{ + tableName_ = tableName; +} + +void TrackerTable::SetExtendName(const std::string &colName) +{ + extendColName_ = colName; +} + +void TrackerTable::SetTrackerNames(const std::set &trackerNames) +{ + trackerColNames_ = std::move(trackerNames); +} + +bool TrackerTable::IsEmpty() const +{ + return trackerColNames_.empty(); +} + +bool TrackerTable::IsChanging(const TrackerSchema &schema) +{ + if (tableName_ != schema.tableName || extendColName_ != schema.extendColName) { + return true; + } + if (trackerColNames_.size() != schema.trackerColNames.size()) { + return true; + } + for (const auto &col: trackerColNames_) { + if (schema.trackerColNames.find(col) == schema.trackerColNames.end()) { + return true; + } + } + return false; +} +} +#endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp index 9814ca1c0b7ee427dc31398284d15a3822bf1d73..b1607155941bd2ad8b6bb9ce639cf6e6a7e6863e 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/runtime_context_impl.cpp @@ -22,6 +22,10 @@ #include "network_adapter.h" namespace DistributedDB { +#ifdef RUNNING_ON_TESTCASE +static std::atomic_uint taskID = 0; +#endif + RuntimeContextImpl::RuntimeContextImpl() : adapter_(nullptr), communicatorAggregator_(nullptr), @@ -257,7 +261,16 @@ int RuntimeContextImpl::ScheduleTask(const TaskAction &task) LOGE("Schedule task failed, fail to prepare task pool."); return errCode; } +#ifdef RUNNING_ON_TESTCASE + auto id = taskID++; + LOGI("Schedule task succeed, ID:%u", id); + return taskPool_->Schedule([task, id] { + LOGI("Execute task, ID:%u", id); + task(); + }); +#else return taskPool_->Schedule(task); +#endif } int RuntimeContextImpl::ScheduleQueuedTask(const std::string &queueTag, @@ -272,7 +285,16 @@ int RuntimeContextImpl::ScheduleQueuedTask(const std::string &queueTag, LOGE("Schedule queued task failed, fail to prepare task pool."); return errCode; } +#ifdef RUNNING_ON_TESTCASE + auto id = taskID++; + LOGI("Schedule queued task succeed, ID:%u", id); + return taskPool_->Schedule(queueTag, [task, id] { + LOGI("Execute queued task, ID:%u", id); + task(); + }); +#else return taskPool_->Schedule(queueTag, task); +#endif } void RuntimeContextImpl::ShrinkMemory(const std::string &description) diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp index 7b989f5c9baa3e488ecf26326584356569e4263f..9f1dab2a9217d43d8b116abeb6870b13dbccf2f2 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_constant.cpp @@ -34,6 +34,7 @@ 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_TYPE_BOOLEAN = "BOOLEAN"; const std::string SchemaConstant::KEYWORD_ATTR_NOT_NULL = "NOT NULL"; const std::string SchemaConstant::KEYWORD_ATTR_DEFAULT = "DEFAULT"; diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp index 489bc22128438451d7a5bcbb6a3bef54adca8be5..6e24e2f8e64e8376d2eec2bee213d2c9e4644124 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_object.cpp @@ -749,8 +749,12 @@ int SchemaObject::CompareSchemaVersionMode(const SchemaObject &newSchema) const // Only Json-Schema need to compare mode if (schemaType_ == SchemaType::JSON && schemaMode_ != newSchema.schemaMode_) { - LOGE("[Schema][CompareVerMode] OldMode=%d mismatch newMode=%d.", static_cast(schemaMode_), - static_cast(newSchema.schemaMode_)); + static std::map modeMapString = { + {SchemaMode::STRICT, "STRICT"}, + {SchemaMode::COMPATIBLE, "COMPATIBLE"}, + }; + LOGE("[Schema][CompareVerMode] OldMode=%s mismatch newMode=%s.", modeMapString[schemaMode_].c_str(), + modeMapString[newSchema.schemaMode_].c_str()); return -E_SCHEMA_UNEQUAL_INCOMPATIBLE; } // Do not return E_OK here, E_OK is ambiguous. diff --git a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp index c7899b33e3a526ba22b700c7cb15c28757204cfc..0f3293a589bdf6a4b7b1df7a99b6058af81bb942 100644 --- a/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/common/src/schema_utils.cpp @@ -501,4 +501,19 @@ std::string SchemaUtils::FieldPathString(const FieldPath &inPath) } return outString; } + +void SchemaUtils::TransTrackerSchemaToLower(const TrackerSchema &srcSchema, TrackerSchema &destSchema) +{ + std::string tableName(srcSchema.tableName.length(), ' '); + std::transform(srcSchema.tableName.begin(), srcSchema.tableName.end(), tableName.begin(), tolower); + destSchema.tableName = tableName; + std::string extendName(srcSchema.extendColName.length(), ' '); + std::transform(srcSchema.extendColName.begin(), srcSchema.extendColName.end(), extendName.begin(), tolower); + destSchema.extendColName = extendName; + for (const auto &srcName : srcSchema.trackerColNames) { + std::string colName(srcName.length(), ' '); + std::transform(srcName.begin(), srcName.end(), colName.begin(), tolower); + destSchema.trackerColNames.insert(colName); + } +} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp index 741ba34c700bcb95a11db853a1ee5f969d321680..417953843dbf34497c05aadee4fbe4ebc38c1f2a 100644 --- a/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp +++ b/kv_store/frameworks/libs/distributeddb/communicator/src/communicator_aggregator.cpp @@ -389,7 +389,7 @@ void CommunicatorAggregator::SendPacketsAndDisposeTask(const SendTask &inTask, u } } if (errCode == -E_WAIT_RETRY) { - constexpr int RETRY_INTERVAL = 1000; // 1000ms + const int RETRY_INTERVAL = 1000; // 1000ms TimerId timerId = 0u; const std::string target = inTask.dstTarget; RefObject::IncObjRef(this); diff --git a/kv_store/frameworks/libs/distributeddb/distributeddb.gni b/kv_store/frameworks/libs/distributeddb/distributeddb.gni index 3b0a403acbd6d6b1c856e347467999d9100e2a32..5b96b6d068260ada45373c58283e343eb34c54a7 100644 --- a/kv_store/frameworks/libs/distributeddb/distributeddb.gni +++ b/kv_store/frameworks/libs/distributeddb/distributeddb.gni @@ -16,6 +16,7 @@ distributeddb_path = distributeddb_src = [ "${distributeddb_path}/common/src/auto_launch.cpp", + "${distributeddb_path}/common/src/cloud/asset_operation_utils.cpp", "${distributeddb_path}/common/src/data_compression.cpp", "${distributeddb_path}/common/src/data_value.cpp", "${distributeddb_path}/common/src/db_common.cpp", @@ -46,6 +47,7 @@ distributeddb_src = [ "${distributeddb_path}/common/src/relational/relational_row_data_set.cpp", "${distributeddb_path}/common/src/relational/relational_schema_object.cpp", "${distributeddb_path}/common/src/relational/table_info.cpp", + "${distributeddb_path}/common/src/relational/tracker_table.cpp", "${distributeddb_path}/common/src/runtime_context.cpp", "${distributeddb_path}/common/src/runtime_context_impl.cpp", "${distributeddb_path}/common/src/schema_constant.cpp", @@ -93,6 +95,13 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/data_transformer.cpp", "${distributeddb_path}/storage/src/db_properties.cpp", "${distributeddb_path}/storage/src/default_factory.cpp", + "${distributeddb_path}/storage/src/single_ver_utils.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/rd_utils.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp", + "${distributeddb_path}/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp", "${distributeddb_path}/storage/src/generic_kvdb.cpp", "${distributeddb_path}/storage/src/generic_kvdb_connection.cpp", "${distributeddb_path}/storage/src/generic_single_ver_kv_entry.cpp", @@ -130,6 +139,8 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/relational_sync_data_inserter.cpp", "${distributeddb_path}/storage/src/relationaldb_properties.cpp", "${distributeddb_path}/storage/src/result_entries_window.cpp", + "${distributeddb_path}/storage/src/single_ver_natural_store.cpp", + "${distributeddb_path}/storage/src/single_ver_natural_store_connection.cpp", "${distributeddb_path}/storage/src/single_ver_natural_store_commit_notify_data.cpp", "${distributeddb_path}/storage/src/sqlite/cloud_sync_log_table_manager.cpp", "${distributeddb_path}/storage/src/sqlite/collaboration_log_table_manager.cpp", @@ -142,6 +153,7 @@ distributeddb_src = [ "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_relational_utils.cpp", "${distributeddb_path}/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp", + "${distributeddb_path}/storage/src/sqlite/simple_tracker_log_table_manager.cpp", "${distributeddb_path}/storage/src/sqlite/split_device_log_table_manager.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_local_kvdb.cpp", "${distributeddb_path}/storage/src/sqlite/sqlite_local_kvdb_connection.cpp", @@ -186,6 +198,7 @@ distributeddb_src = [ "${distributeddb_path}/syncer/src/cloud/cloud_db_proxy.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_locker.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_syncer.cpp", + "${distributeddb_path}/syncer/src/cloud/cloud_syncer_extend.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_tag_assets.cpp", "${distributeddb_path}/syncer/src/cloud/cloud_sync_utils.cpp", "${distributeddb_path}/syncer/src/cloud/process_notifier.cpp", @@ -231,3 +244,33 @@ distributeddb_src = [ "${distributeddb_path}/syncer/src/time_sync.cpp", "${distributeddb_path}/syncer/src/value_slice_sync.cpp", ] + +distributeddb_src_rd = [ + "${distributeddb_path}/gaussdb_rd/src/common/src/collection_option.cpp", + "${distributeddb_path}/gaussdb_rd/src/common/src/db_config.cpp", + "${distributeddb_path}/gaussdb_rd/src/common/src/grd_api_manager.cpp", + "${distributeddb_path}/gaussdb_rd/src/common/src/json_common.cpp", + "${distributeddb_path}/gaussdb_rd/src/common/src/rd_log_print.cpp", + "${distributeddb_path}/gaussdb_rd/src/common/src/os_api.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/base/grd_db_api.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/base/grd_db_api_inner.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/document/check_common.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/document/grd_document_api.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/document/grd_document_api_inner.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/document/grd_resultset_api.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/kv/grd_kv_api.cpp", + "${distributeddb_path}/gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/collection.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/doc_errno.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/document_key.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/document_store.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/document_store_manager.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/projection_tree.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/result_set.cpp", + "${distributeddb_path}/gaussdb_rd/src/interface/src/result_set_common.cpp", + "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp", + "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp", + "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp", + "${distributeddb_path}/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp", +] diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/BUILD.gn b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/BUILD.gn index acebb6810710f6b0d560a8e75b2472893331b199..57a2c068a7a0f9144f47878d19b91eddf29e2ad7 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/BUILD.gn @@ -38,7 +38,12 @@ config("gaussdb_rd_config") { config("gaussdb_rd_public_config") { visibility = [ "*:*" ] - include_dirs = [ "include" ] + include_dirs = [ + "include", + "include/grd_base", + "include/grd_document", + "include/grd_kv", + ] } group("build_module") { @@ -51,8 +56,8 @@ ohos_static_library("gaussdb_rd") { "src/common/src/db_config.cpp", "src/common/src/grd_api_manager.cpp", "src/common/src/json_common.cpp", - "src/common/src/log_print.cpp", "src/common/src/os_api.cpp", + "src/common/src/rd_log_print.cpp", "src/executor/base/grd_db_api.cpp", "src/executor/base/grd_db_api_inner.cpp", "src/executor/document/check_common.cpp", @@ -62,8 +67,6 @@ ohos_static_library("gaussdb_rd") { "src/executor/document/grd_resultset_api_inner.cpp", "src/executor/kv/grd_kv_api.cpp", "src/executor/kv/grd_kv_api_inner.cpp", - "src/executor/shared_obj/grd_sequence_api.cpp", - "src/executor/shared_obj/grd_sequence_api_inner.cpp", "src/interface/src/collection.cpp", "src/interface/src/doc_errno.cpp", "src/interface/src/document_key.cpp", @@ -72,10 +75,10 @@ ohos_static_library("gaussdb_rd") { "src/interface/src/projection_tree.cpp", "src/interface/src/result_set.cpp", "src/interface/src/result_set_common.cpp", - "src/oh_adapter/src/json_object.cpp", "src/oh_adapter/src/kv_store_manager.cpp", + "src/oh_adapter/src/rd_json_object.cpp", + "src/oh_adapter/src/rd_sqlite_utils.cpp", "src/oh_adapter/src/sqlite_store_executor_impl.cpp", - "src/oh_adapter/src/sqlite_utils.cpp", ] configs = [ ":gaussdb_rd_config" ] @@ -85,7 +88,10 @@ ohos_static_library("gaussdb_rd") { configs += [ "//third_party/cJSON:cJSON_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] - cflags_cc = [ "-fvisibility=hidden" ] + cflags_cc = [ + "-fvisibility=hidden", + "-std=c++17", + ] deps += [ "//third_party/cJSON:cjson" ] external_deps = [ diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/CMakeLists.txt b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/CMakeLists.txt index f935c0c5a410a0f885bd91274c0538f545711898..8fe3bca11e7ed2a15beba3a06a799dd0def2ce80 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/CMakeLists.txt +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required(VERSION 3.11.2) -project(document_ut) +project(gaussdb) set(GAUSE_SOURCE_DIR "${PROJECT_SOURCE_DIR}") -file(GLOB_RECURSE DOCUMENT_SRC ${GAUSE_SOURCE_DIR}/src/*.cpp) +#file(GLOB_RECURSE DOCUMENT_SRC ${GAUSE_SOURCE_DIR}/src/*.cpp) include_directories( ${GAUSE_SOURCE_DIR}/include ${GAUSE_SOURCE_DIR}/src/storage @@ -22,16 +22,26 @@ include_directories( ${GAUSE_SOURCE_DIR}/src/interface/src ${GAUSE_SOURCE_DIR}/third_party/third_party_cJSON ) -aux_source_directory( ${GAUSE_SOURCE_DIR}/third_party/third_party_cJSON DOCUMENT_SRC) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/common/src gaussdbSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/executor/base gaussdbSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/executor/document gaussdbSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/executor/kv gaussdbSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/interface/src gaussdbSrc) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src/oh_adapter/src gaussdbSrc) +aux_source_directory( ${GAUSE_SOURCE_DIR}/third_party/third_party_cJSON gaussdbSrc) set(MOCK_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../mock") set(KV_STORE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../kv_store") include(${MOCK_DIR}/include/CMakeLists.txt OPTIONAL) include(${KV_STORE_DIR}/interfaces/CMakeLists.txt OPTIONAL) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../utils_native/base/include) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../../../../../utils_native/safwk/native/include) -add_library(document_ut SHARED ${DOCUMENT_SRC}) -set(links mock kvdb adapter data_share secure) -target_link_libraries(document_ut ${links}) -target_include_directories(document_ut PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +add_library(gaussdb SHARED ${gaussdbSrc}) +set(links mock secure) +target_link_libraries(gaussdb ${links}) +target_include_directories(gaussdb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include) +target_include_directories(gaussdb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/common/include) +target_include_directories(gaussdb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/executor/include) +target_include_directories(gaussdb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/executor/document) +target_include_directories(gaussdb PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/oh_adapter/include) diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_db_api.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_db_api.h index c8b29240694b4a3e502d19799498ec3a1f7ada07..858484f3c0618666b531068c13a19ffd0d0c4eff 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_db_api.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_db_api.h @@ -29,6 +29,8 @@ GRD_API int32_t GRD_DBClose(GRD_DB *db, uint32_t flags); GRD_API int32_t GRD_IndexPreload(GRD_DB *db, const char *collectionName); GRD_API int32_t GRD_Flush(GRD_DB *db, uint32_t flags); + +GRD_API int32_t GRD_CrcCheck(const char *dbFile); #ifdef __cplusplus } #endif // __cplusplus diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_error.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_error.h index ecc7c705309b063cddb0232aadefe8459e4365b8..df75287b5d1becc3c8d7b76512efd7afedb10439 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_error.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_error.h @@ -32,6 +32,7 @@ extern "C" { #define GRD_SYSTEM_ERR (-4000) #define GRD_FAILED_FILE_OPERATION (-5000) #define GRD_INVALID_FILE_FORMAT (-6000) +#define GRD_INSUFFICIENT_SPACE (-7000) #define GRD_INNER_ERR (-8000) #define GRD_RESOURCE_BUSY (-9000) @@ -42,6 +43,11 @@ extern "C" { #define GRD_NOT_AVAILABLE (-19000) #define GRD_INVALID_FORMAT (-37000) #define GRD_REBUILD_DATABASE (-38000) +#define GRD_TIME_OUT (-39000) +#define GRD_DB_INSTANCE_ABNORMAL (-40000) +#define GRD_DISK_SPACE_FULL (-41000) +#define GRD_CRC_CHECK_DISABLED (-42000) +#define GRD_PERMISSION_DENIED (-43000) // not support #define GRD_JSON_OPERATION_NOT_SUPPORT (-5001001) @@ -65,7 +71,6 @@ extern "C" { // no data #define GRD_COLLECTION_NOT_FOUND (-5011001) #define GRD_RECORD_NOT_FOUND (-5011002) -#define GRD_DB_NOT_FOUND (-11003) #define GRD_FIELD_NOT_FOUND (-5011004) // data conflicted diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h index bc940e5c5c2f185c7d2c486d56cc78816c38d6b8..53b00dd368a9edf771aa62cb5945125d5d28b80d 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_base/grd_type_export.h @@ -22,6 +22,8 @@ extern "C" { #ifndef _WIN32 #define GRD_API __attribute__((visibility("default"))) +#else +#define GRD_API #endif typedef struct GRD_DB GRD_DB; @@ -35,6 +37,7 @@ typedef struct GRD_DB GRD_DB; #define GRD_DB_OPEN_CHECK_FOR_ABNORMAL 0x02 // check data in database when open database, if data is corrupted, rebuild the database. #define GRD_DB_OPEN_CHECK 0x04 +#define GRD_DB_OPEN_SHARED_READ_ONLY 0x08 /** * @brief Close database config @@ -64,7 +67,7 @@ typedef enum KvScanMode { KV_SCAN_EQUAL_OR_LESS_KEY = 1, KV_SCAN_EQUAL_OR_GREATER_KEY = 2, KV_SCAN_BUTT -} KvScanModeE; +} GRD_KvScanModeE; typedef struct GRD_ResultSet GRD_ResultSet; typedef struct GRD_DB GRD_DB; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_kv/grd_kv_api.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_kv/grd_kv_api.h index 50f33bc341a22829fed58405e7ce196b7882efa6..711027d1e14be42d56ecc44364380e0badbdf1ec 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_kv/grd_kv_api.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/include/grd_kv/grd_kv_api.h @@ -30,7 +30,7 @@ GRD_API int32_t GRD_KVGet(GRD_DB *db, const char *collectionName, const GRD_KVIt GRD_API int32_t GRD_KVDel(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key); -GRD_API int32_t GRD_KVScan(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, KvScanModeE mode, +GRD_API int32_t GRD_KVScan(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet); GRD_API int32_t GRD_KVFreeItem(GRD_KVItemT *item); @@ -40,9 +40,11 @@ GRD_API int32_t GRD_KVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch); GRD_API int32_t GRD_KVBatchPushback(const void *key, uint32_t keyLen, const void *data, uint32_t dataLen, GRD_KVBatchT *batch); +GRD_API int32_t GRD_KVBatchPut(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); + GRD_API int32_t GRD_KVBatchDel(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); -GRD_API int32_t GRD_KVBatchDestory(GRD_KVBatchT *batch); +GRD_API int32_t GRD_KVBatchDestroy(GRD_KVBatchT *batch); #ifdef __cplusplus } #endif diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h index 45a1541e949a6410b63241baab96ecc8679f22b4..8846ca22960966a9afd841888ac694f2f1a6453f 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/grd_api_manager.h @@ -42,16 +42,16 @@ typedef int32_t (*FreeResultSet)(GRD_ResultSet *resultSet); typedef int32_t (*KVPut)(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value); typedef int32_t (*KVGet)(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value); typedef int32_t (*KVDel)(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key); -typedef int32_t (*KVScan)(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, KvScanModeE mode, +typedef int32_t (*KVScan)(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet); typedef int32_t (*KVFreeItem)(GRD_KVItemT *item); typedef int32_t (*KVBatchPrepare)(uint16_t itemNum, GRD_KVBatchT **batch); -typedef int32_t ( - *KVBatchPushback)(const void *key, uint32_t keyLen, const void *data, uint32_t dataLen, GRD_KVBatchT *batch); +typedef int32_t (*KVBatchPushback)(const void *key, uint32_t keyLen, const void *data, uint32_t dataLen, + GRD_KVBatchT *batch); +typedef int32_t (*KVBatchPut)(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); typedef int32_t (*KVBatchDel)(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); typedef int32_t (*KVBatchDestory)(GRD_KVBatchT *batch); -typedef int32_t (*CreateSeq)(GRD_DB *db, const char *sequenceName, uint32_t flags); -typedef int32_t (*DropSeq)(GRD_DB *db, const char *sequenceName, uint32_t flags); +typedef int32_t (*CrcCheck)(const char *dbFile); struct GRD_APIInfo { DBOpen DBOpenApi = nullptr; @@ -78,10 +78,10 @@ struct GRD_APIInfo { KVFreeItem KVFreeItemApi = nullptr; KVBatchPrepare KVBatchPrepareApi = nullptr; KVBatchPushback KVBatchPushbackApi = nullptr; + KVBatchDel KVBatchPutApi = nullptr; KVBatchDel KVBatchDelApi = nullptr; KVBatchDestory KVBatchDestoryApi = nullptr; - CreateSeq CreateSeqApi = nullptr; - DropSeq DropSeqApi = nullptr; + CrcCheck CrcCheckApi = nullptr; }; GRD_APIInfo GetApiInfoInstance(); } // namespace DocumentDB diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h index a3a2b61d889f66a939804d262e82ccae25b2395a..e8046aed6305d9cf74a7cd5ff55b7b23eda452f8 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/json_common.h @@ -21,7 +21,7 @@ #include #include -#include "json_object.h" +#include "rd_json_object.h" namespace DocumentDB { class JsonCommon { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/db_constant.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/rd_db_constant.h similarity index 100% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/db_constant.h rename to kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/rd_db_constant.h diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/log_print.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/rd_log_print.h similarity index 95% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/log_print.h rename to kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/rd_log_print.h index f02a6a8065c4c767f87053744af4a30267b88537..d46e17d2a6530b01f025df425c02d048f5804d97 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/log_print.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/include/rd_log_print.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef LOG_PRINT_H -#define LOG_PRINT_H +#ifndef RD_LOG_PRINT_H +#define RD_LOG_PRINT_H #include diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/collection_option.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/collection_option.cpp index 06c0805efd030a5267e18bf6bc56fd95a97b33fa..851b3f20e08ca4355948532e9477ab13e9677b20 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/collection_option.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/collection_option.cpp @@ -19,18 +19,28 @@ #include #include "doc_errno.h" -#include "json_object.h" -#include "log_print.h" +#include "rd_json_object.h" +#include "rd_log_print.h" namespace DocumentDB { namespace { constexpr const char *OPT_MAX_DOC = "maxdoc"; +constexpr const char *OPT_COLLECTION_MODE = "mode"; +constexpr const char *KV_COLLECTION_MODE = "kv"; int CFG_IsValid(const JsonObject &config) { JsonObject child = config.GetChild(); while (!child.IsNull()) { std::string fieldName = child.GetItemField(); + if (strcmp(OPT_COLLECTION_MODE, fieldName.c_str()) == 0) { + if (strcmp(child.GetItemValue().GetStringValue().c_str(), KV_COLLECTION_MODE) == 0) { // The value of mode + return -E_NOT_SUPPORT; + } else { + child = child.GetNext(); + continue; + } + } if (strcmp(OPT_MAX_DOC, fieldName.c_str()) != 0) { GLOGE("Invalid collection config."); return -E_INVALID_CONFIG_VALUE; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/db_config.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/db_config.cpp index 661f55ced1557d1fdf1b8ed692f769efffe07f2a..bb97d998c8ba6404440b48365995c749ad8ed220 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/db_config.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/db_config.cpp @@ -22,8 +22,8 @@ #include "doc_errno.h" #include "doc_limit.h" -#include "json_object.h" -#include "log_print.h" +#include "rd_json_object.h" +#include "rd_log_print.h" namespace DocumentDB { namespace { @@ -40,10 +40,12 @@ constexpr const char *DB_CONFIG_REDO_PUB_BUFF_SIZE = "redopubbufsize"; constexpr const char *DB_CONFIG_MAX_CONN_NUM = "maxconnnum"; constexpr const char *DB_CONFIG_BUFFER_POOL_SIZE = "bufferpoolsize"; constexpr const char *DB_CONFIG_CRC_CHECK_ENABLE = "crccheckenable"; +constexpr const char *DB_CONFIG_BUFFPOOL_POLICY = "bufferpoolpolicy"; +constexpr const char *DB_CONFIG_SHARED_MODE = "sharedmodeenable"; -const int DB_CONFIG_SIZE = 6; // db config size -const char *dbConfig[6] = { DB_CONFIG_PAGESIZE, DB_CONFIG_REDO_FLUSH_BY_TRX, // 6 is db config size - DB_CONFIG_REDO_PUB_BUFF_SIZE, DB_CONFIG_MAX_CONN_NUM, DB_CONFIG_BUFFER_POOL_SIZE, DB_CONFIG_CRC_CHECK_ENABLE }; +const char *DB_CONFIG[] = { DB_CONFIG_PAGESIZE, DB_CONFIG_REDO_FLUSH_BY_TRX, + DB_CONFIG_REDO_PUB_BUFF_SIZE, DB_CONFIG_MAX_CONN_NUM, DB_CONFIG_BUFFER_POOL_SIZE, DB_CONFIG_CRC_CHECK_ENABLE, + DB_CONFIG_BUFFPOOL_POLICY, DB_CONFIG_SHARED_MODE}; template bool CheckAndGetDBConfig(const JsonObject &config, const std::string &name, const std::function &checkValid, @@ -125,21 +127,21 @@ bool CheckCrcCheckEnableConfig(const JsonObject &config, uint32_t &crcCheckEnabl return CheckAndGetDBConfig(config, DB_CONFIG_CRC_CHECK_ENABLE, checkFunction, crcCheckEnable); } -int CFG_IsValid(const JsonObject &config) +int IsDbconfigValid(const JsonObject &config) { JsonObject child = config.GetChild(); while (!child.IsNull()) { std::string fieldName = child.GetItemField(); bool isSupport = false; - for (int i = 0; i < DB_CONFIG_SIZE; i++) { - if (strcmp(dbConfig[i], fieldName.c_str()) == 0) { + for (uint32_t i = 0; i < sizeof(DB_CONFIG) / sizeof(char *); i++) { + if (strcmp(DB_CONFIG[i], fieldName.c_str()) == 0) { isSupport = true; break; } } if (!isSupport) { - GLOGE("Invalid db config."); + GLOGE("Invalid db config"); return -E_INVALID_CONFIG_VALUE; } @@ -157,7 +159,7 @@ DBConfig DBConfig::GetDBConfigFromJsonStr(const std::string &confStr, int &errCo return {}; } - errCode = CFG_IsValid(dbConfig); + errCode = IsDbconfigValid(dbConfig); if (errCode != E_OK) { GLOGE("Check DB config, not support config item. %d", errCode); return {}; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp index 2c75a891e1bf4868d814e24dc078bc2416faf703..9a3088501a40530a5d89d92c18670774d2eaa27c 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/grd_api_manager.cpp @@ -12,9 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "grd_api_manager.h" +#ifndef _WIN32 #include +#endif #include "check_common.h" #include "doc_errno.h" @@ -26,9 +29,12 @@ #include "grd_resultset_api_inner.h" #include "grd_sequence_api_inner.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" +#ifndef _WIN32 static void *g_library = nullptr; +#endif + namespace DocumentDB { void GRD_DBApiInitCommon(GRD_APIInfo &GRD_DBApiInfo) { @@ -56,14 +62,15 @@ void GRD_DBApiInitCommon(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.KVFreeItemApi = GRD_KVFreeItemInner; GRD_DBApiInfo.KVBatchPrepareApi = GRD_KVBatchPrepareInner; GRD_DBApiInfo.KVBatchPushbackApi = GRD_KVBatchPushbackInner; + GRD_DBApiInfo.KVBatchPutApi = GRD_KVBatchPutInner; GRD_DBApiInfo.KVBatchDelApi = GRD_KVBatchDelInner; - GRD_DBApiInfo.KVBatchDestoryApi = GRD_KVBatchDestoryInner; - GRD_DBApiInfo.CreateSeqApi = GRD_CreateSeqInner; - GRD_DBApiInfo.DropSeqApi = GRD_DropSeqInner; + GRD_DBApiInfo.KVBatchDestoryApi = GRD_KVBatchDestroyInner; + GRD_DBApiInfo.CrcCheckApi = GRD_CrcCheckInner; } void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) { +#ifndef _WIN32 GRD_DBApiInfo.DBOpenApi = (DBOpen)dlsym(g_library, "GRD_DBOpen"); GRD_DBApiInfo.DBCloseApi = (DBClose)dlsym(g_library, "GRD_DBClose"); GRD_DBApiInfo.FlushApi = (DBFlush)dlsym(g_library, "GRD_Flush"); @@ -88,21 +95,24 @@ void GRD_DBApiInitEnhance(GRD_APIInfo &GRD_DBApiInfo) GRD_DBApiInfo.KVFreeItemApi = (KVFreeItem)dlsym(g_library, "GRD_KVFreeItem"); GRD_DBApiInfo.KVBatchPrepareApi = (KVBatchPrepare)dlsym(g_library, "GRD_KVBatchPrepare"); GRD_DBApiInfo.KVBatchPushbackApi = (KVBatchPushback)dlsym(g_library, "GRD_KVBatchPushback"); + GRD_DBApiInfo.KVBatchPutApi = (KVBatchPut)dlsym(g_library, "GRD_KVBatchPut"); GRD_DBApiInfo.KVBatchDelApi = (KVBatchDel)dlsym(g_library, "GRD_KVBatchDel"); - GRD_DBApiInfo.KVBatchDestoryApi = (KVBatchDestory)dlsym(g_library, "GRD_KVBatchDestory"); - GRD_DBApiInfo.CreateSeqApi = (CreateSeq)dlsym(g_library, "GRD_CreateSeq"); - GRD_DBApiInfo.DropSeqApi = (DropSeq)dlsym(g_library, "GRD_DropSeq"); + GRD_DBApiInfo.KVBatchDestoryApi = (KVBatchDestory)dlsym(g_library, "GRD_KVBatchDestroy"); + GRD_DBApiInfo.CrcCheckApi = (CrcCheck)dlsym(g_library, "GRD_CrcCheck"); +#endif } GRD_APIInfo GetApiInfoInstance() { GRD_APIInfo GRD_TempApiStruct; +#ifndef _WIN32 g_library = dlopen("/system/lib64/libgaussdb_rd.z.so", RTLD_LAZY); if (!g_library) { GRD_DBApiInitCommon(GRD_TempApiStruct); // When calling specific function, read whether init is successful. } else { GRD_DBApiInitEnhance(GRD_TempApiStruct); } +#endif return GRD_TempApiStruct; } -} // namespace DocumentDB \ No newline at end of file +} // namespace DocumentDB diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp index 95499f9650cbb6ffbd97918107b5827735f234ca..98473caed4443ec682afc5d0e459a666b4baeda8 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/json_common.cpp @@ -17,7 +17,7 @@ #include #include "doc_errno.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { ValueObject JsonCommon::GetValueInSameLevel(JsonObject &node, const std::string &field) diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/os_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/os_api.cpp index c8a1338851d72e11836dfea7b25fab01573bd31e..246494c44d0aea6f4c24a3fbd5121f417ae25c6e 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/os_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/os_api.cpp @@ -15,11 +15,12 @@ #include "os_api.h" #include +#include #include #include #include "doc_errno.h" -#include "log_print.h" +#include "rd_log_print.h" #include "securec.h" namespace DocumentDB { @@ -53,12 +54,19 @@ int GetRealPath(const std::string &inOriPath, std::string &outRealPath) delete[] realPath; return -E_SECUREC_ERROR; } - +#ifndef _WIN32 if (realpath(inOriPath.c_str(), realPath) == nullptr) { GLOGE("[OS_API] Realpath error:%d.", errno); delete[] realPath; return -E_SYSTEM_API_FAIL; } +#else + if (_fullpath(realPath, inOriPath.c_str(), MAX_PATH_LENGTH) == nullptr) { + GLOGE("[OS] Realpath error:%d.", errno); + delete [] realPath; + return -E_SYSTEM_API_FAIL; + } +#endif outRealPath = std::string(realPath); delete[] realPath; return E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/log_print.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/rd_log_print.cpp similarity index 99% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/log_print.cpp rename to kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/rd_log_print.cpp index 398dbc33173e530a338a2170c896e14cf809eb1d..6731c1775d02ceff9344231e122d0dda5de2e400 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/log_print.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/common/src/rd_log_print.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include +#include "rd_log_print.h" #include "hilog/log.h" #include "securec.h" diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp index bc8563594e1c39565c4ab89b1bfa04a1b57abf7c..0fd91cabb36f24a1cfa21740957f23db601a569d 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api.cpp @@ -14,23 +14,21 @@ */ #include "grd_base/grd_db_api.h" -#include - #include "check_common.h" #include "doc_errno.h" #include "document_store_manager.h" #include "grd_api_manager.h" #include "grd_base/grd_error.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_DBApiInfo = GetApiInfoInstance(); +static GRD_APIInfo GRD_DBApiInfo; GRD_API int32_t GRD_DBOpen(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) { if (GRD_DBApiInfo.DBOpenApi == nullptr) { - return GRD_INNER_ERR; + GRD_DBApiInfo = GetApiInfoInstance(); } return GRD_DBApiInfo.DBOpenApi(dbPath, configStr, flags, db); } @@ -38,7 +36,7 @@ GRD_API int32_t GRD_DBOpen(const char *dbPath, const char *configStr, uint32_t f GRD_API int32_t GRD_DBClose(GRD_DB *db, uint32_t flags) { if (GRD_DBApiInfo.DBCloseApi == nullptr) { - return GRD_INNER_ERR; + GRD_DBApiInfo = GetApiInfoInstance(); } return GRD_DBApiInfo.DBCloseApi(db, flags); } @@ -46,7 +44,7 @@ GRD_API int32_t GRD_DBClose(GRD_DB *db, uint32_t flags) GRD_API int32_t GRD_Flush(GRD_DB *db, uint32_t flags) { if (GRD_DBApiInfo.FlushApi == nullptr) { - return GRD_INNER_ERR; + GRD_DBApiInfo = GetApiInfoInstance(); } return GRD_DBApiInfo.FlushApi(db, flags); } @@ -54,7 +52,15 @@ GRD_API int32_t GRD_Flush(GRD_DB *db, uint32_t flags) GRD_API int32_t GRD_IndexPreload(GRD_DB *db, const char *collectionName) { if (GRD_DBApiInfo.IndexPreloadApi == nullptr) { - return GRD_INNER_ERR; + GRD_DBApiInfo = GetApiInfoInstance(); } return GRD_DBApiInfo.IndexPreloadApi(db, collectionName); +} + +GRD_API int32_t GRD_CrcCheck(const char *dbFile) +{ + if (GRD_DBApiInfo.CrcCheckApi == nullptr) { + GRD_DBApiInfo = GetApiInfoInstance(); + } + return GRD_DBApiInfo.CrcCheckApi(dbFile); } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api_inner.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api_inner.cpp index 2aa5ba54ab06e2e22b62fc6d68c42eddc447bbdc..e80868ab2f955ceea5818e4c7c7478ae18aaeb77 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api_inner.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/base/grd_db_api_inner.cpp @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include #include "grd_db_api_inner.h" #include "check_common.h" #include "doc_errno.h" @@ -20,7 +19,7 @@ #include "grd_api_manager.h" #include "grd_base/grd_error.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { int32_t GRD_DBOpenInner(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB **db) @@ -78,4 +77,9 @@ int32_t GRD_IndexPreloadInner(GRD_DB *db, const char *collectionName) { return GRD_OK; // No support; } + +int32_t GRD_CrcCheckInner(const char *dbFile) +{ + return GRD_NOT_SUPPORT; +} } // namespace DocumentDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/check_common.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/check_common.cpp index 316e2e7e2f5654fa66d0cafae50e655f790394b5..d545c0e44def5af750a72f026028d5e3a37751e9 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/check_common.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/check_common.cpp @@ -19,7 +19,7 @@ #include "doc_errno.h" #include "grd_base/grd_db_api.h" -#include "log_print.h" +#include "rd_log_print.h" #include "securec.h" using namespace DocumentDB; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp index a30d919defd41d8f446972bcd74289df1f56eef1..ef2dd5ce7ef2d2262918c01dee3435135a49ca93 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api.cpp @@ -20,15 +20,15 @@ #include "grd_base/grd_error.h" #include "grd_resultset_inner.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_DocApiInfo = GetApiInfoInstance(); +static GRD_APIInfo GRD_DocApiInfo; GRD_API int32_t GRD_CreateCollection(GRD_DB *db, const char *collectionName, const char *optionStr, uint32_t flags) { if (GRD_DocApiInfo.CreateCollectionApi == nullptr) { - return GRD_INNER_ERR; + GRD_DocApiInfo = GetApiInfoInstance(); } return GRD_DocApiInfo.CreateCollectionApi(db, collectionName, optionStr, flags); } @@ -36,7 +36,7 @@ GRD_API int32_t GRD_CreateCollection(GRD_DB *db, const char *collectionName, con GRD_API int32_t GRD_DropCollection(GRD_DB *db, const char *collectionName, uint32_t flags) { if (GRD_DocApiInfo.DropCollectionApi == nullptr) { - return GRD_INNER_ERR; + GRD_DocApiInfo = GetApiInfoInstance(); } return GRD_DocApiInfo.DropCollectionApi(db, collectionName, flags); } @@ -45,7 +45,7 @@ GRD_API int32_t GRD_UpdateDoc(GRD_DB *db, const char *collectionName, const char uint32_t flags) { if (GRD_DocApiInfo.UpdateDocApi == nullptr) { - return GRD_INNER_ERR; + GRD_DocApiInfo = GetApiInfoInstance(); } return GRD_DocApiInfo.UpdateDocApi(db, collectionName, filter, update, flags); } @@ -54,7 +54,7 @@ GRD_API int32_t GRD_UpsertDoc(GRD_DB *db, const char *collectionName, const char uint32_t flags) { if (GRD_DocApiInfo.UpsertDocApi == nullptr) { - return GRD_INNER_ERR; + GRD_DocApiInfo = GetApiInfoInstance(); } return GRD_DocApiInfo.UpsertDocApi(db, collectionName, filter, document, flags); } @@ -62,7 +62,7 @@ GRD_API int32_t GRD_UpsertDoc(GRD_DB *db, const char *collectionName, const char GRD_API int32_t GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, uint32_t flags) { if (GRD_DocApiInfo.InsertDocApi == nullptr) { - return GRD_INNER_ERR; + GRD_DocApiInfo = GetApiInfoInstance(); } return GRD_DocApiInfo.InsertDocApi(db, collectionName, document, flags); } @@ -70,7 +70,7 @@ GRD_API int32_t GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char GRD_API int32_t GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, uint32_t flags) { if (GRD_DocApiInfo.DeleteDocApi == nullptr) { - return GRD_INNER_ERR; + GRD_DocApiInfo = GetApiInfoInstance(); } return GRD_DocApiInfo.DeleteDocApi(db, collectionName, filter, flags); } @@ -79,7 +79,7 @@ GRD_API int32_t GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, GRD_ResultSet **resultSet) { if (GRD_DocApiInfo.FindDocApi == nullptr) { - return GRD_INNER_ERR; + GRD_DocApiInfo = GetApiInfoInstance(); } return GRD_DocApiInfo.FindDocApi(db, collectionName, query, flags, resultSet); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api_inner.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api_inner.cpp index 13b50c042c467289c78f050d6ea8199185b518c9..bf076cbc14e70fb21aa402ff62a2fb96742b1dcf 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api_inner.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_document_api_inner.cpp @@ -20,7 +20,7 @@ #include "grd_document_api_inner.h" #include "grd_resultset_inner.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { int32_t GRD_CreateCollectionInner(GRD_DB *db, const char *collectionName, const char *optionStr, uint32_t flags) { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp index 837fd545dafa7327feeeecd4384337f5546675a1..cbbaccc2f5e3ee53416a851d60d03f4ea6df1497 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api.cpp @@ -18,15 +18,15 @@ #include "grd_api_manager.h" #include "grd_base/grd_error.h" #include "grd_resultset_inner.h" -#include "log_print.h" +#include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_ResultSetApiInfo = GetApiInfoInstance(); +static GRD_APIInfo GRD_ResultSetApiInfo; GRD_API int32_t GRD_Next(GRD_ResultSet *resultSet) { if (GRD_ResultSetApiInfo.NextApi == nullptr) { - return GRD_INNER_ERR; + GRD_ResultSetApiInfo = GetApiInfoInstance(); } return GRD_ResultSetApiInfo.NextApi(resultSet); } @@ -34,7 +34,7 @@ GRD_API int32_t GRD_Next(GRD_ResultSet *resultSet) GRD_API int32_t GRD_GetValue(GRD_ResultSet *resultSet, char **value) { if (GRD_ResultSetApiInfo.GetValueApi == nullptr) { - return GRD_INNER_ERR; + GRD_ResultSetApiInfo = GetApiInfoInstance(); } return GRD_ResultSetApiInfo.GetValueApi(resultSet, value); } @@ -42,7 +42,7 @@ GRD_API int32_t GRD_GetValue(GRD_ResultSet *resultSet, char **value) GRD_API int32_t GRD_FreeValue(char *value) { if (GRD_ResultSetApiInfo.FreeValueApi == nullptr) { - return GRD_INNER_ERR; + GRD_ResultSetApiInfo = GetApiInfoInstance(); } return GRD_ResultSetApiInfo.FreeValueApi(value); } @@ -50,7 +50,7 @@ GRD_API int32_t GRD_FreeValue(char *value) GRD_API int32_t GRD_FreeResultSet(GRD_ResultSet *resultSet) { if (GRD_ResultSetApiInfo.FreeResultSetApi == nullptr) { - return GRD_INNER_ERR; + GRD_ResultSetApiInfo = GetApiInfoInstance(); } return GRD_ResultSetApiInfo.FreeResultSetApi(resultSet); } @@ -58,7 +58,7 @@ GRD_API int32_t GRD_FreeResultSet(GRD_ResultSet *resultSet) GRD_API int32_t GRD_Prev(GRD_ResultSet *resultSet) { if (GRD_ResultSetApiInfo.PrevApi == nullptr) { - return GRD_INNER_ERR; + GRD_ResultSetApiInfo = GetApiInfoInstance(); } return GRD_ResultSetApiInfo.PrevApi(resultSet); } @@ -66,7 +66,7 @@ GRD_API int32_t GRD_Prev(GRD_ResultSet *resultSet) GRD_API int32_t GRD_Fetch(GRD_ResultSet *resultSet, GRD_KVItemT *key, GRD_KVItemT *value) { if (GRD_ResultSetApiInfo.FetchApi == nullptr) { - return GRD_INNER_ERR; + GRD_ResultSetApiInfo = GetApiInfoInstance(); } return GRD_ResultSetApiInfo.FetchApi(resultSet, key, value); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp index 9027d7bb77095dc6389510d87ab653c32063a43d..be9f562b249c3cb987ea6e8059bfec8610c50a45 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/document/grd_resultset_api_inner.cpp @@ -17,7 +17,7 @@ #include "grd_base/grd_error.h" #include "grd_resultset_api_inner.h" #include "grd_resultset_inner.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { int32_t GRD_NextInner(GRD_ResultSet *resultSet) @@ -67,11 +67,11 @@ int32_t GRD_FreeResultSetInner(GRD_ResultSet *resultSet) int32_t GRD_PrevInner(GRD_ResultSet *resultSet) { - return GRD_OK; // No support; + return GRD_NOT_SUPPORT; // No support; } int32_t GRD_FetchInner(GRD_ResultSet *resultSet, GRD_KVItemT *key, GRD_KVItemT *value) { - return GRD_OK; // No support; + return GRD_NOT_SUPPORT; // No support; } } // namespace DocumentDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_db_api_inner.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_db_api_inner.h index 0aafa77506d217a8262e9f3a7ce0e4d616325c3e..9ca18d1234585c1cb6de4e16069c8cae7f3b4757 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_db_api_inner.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_db_api_inner.h @@ -25,5 +25,7 @@ int32_t GRD_DBCloseInner(GRD_DB *db, uint32_t flags); int32_t GRD_IndexPreloadInner(GRD_DB *db, const char *collectionName); int32_t GRD_FlushInner(GRD_DB *db, uint32_t flags); + +int32_t GRD_CrcCheckInner(const char *dbFile); } // namespace DocumentDB #endif // GRD_DB_API_INNER_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_kv_api_inner.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_kv_api_inner.h index f4d1754801ad3c29de179dffdb5287079168c301..110a76173f7e93ccae116bdca752652a06ee27b6 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_kv_api_inner.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/include/grd_kv_api_inner.h @@ -28,7 +28,7 @@ int32_t GRD_KVGetInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT int32_t GRD_KVDelInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key); -int32_t GRD_KVScanInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, KvScanModeE mode, +int32_t GRD_KVScanInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet); int32_t GRD_KVFreeItemInner(GRD_KVItemT *item); @@ -38,8 +38,10 @@ int32_t GRD_KVBatchPrepareInner(uint16_t itemNum, GRD_KVBatchT **batch); int32_t GRD_KVBatchPushbackInner(const void *key, uint32_t keyLen, const void *data, uint32_t dataLen, GRD_KVBatchT *batch); +int32_t GRD_KVBatchPutInner(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); + int32_t GRD_KVBatchDelInner(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch); -int32_t GRD_KVBatchDestoryInner(GRD_KVBatchT *batch); +int32_t GRD_KVBatchDestroyInner(GRD_KVBatchT *batch); } // namespace DocumentDB #endif // GRD_KV_API_INNER_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp index 9b806106e781b2b857c57fe99ca163ebce06b0e4..f7a9fdbbfe44872fd01c08da1c0695b386923ff9 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api.cpp @@ -18,15 +18,15 @@ #include "grd_base/grd_error.h" #include "grd_resultset_inner.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" using namespace DocumentDB; -static GRD_APIInfo GRD_KVApiInfo = GetApiInfoInstance(); +static GRD_APIInfo GRD_KVApiInfo; GRD_API int32_t GRD_KVPut(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value) { if (GRD_KVApiInfo.KVPutApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVPutApi(db, collectionName, key, value); } @@ -34,7 +34,7 @@ GRD_API int32_t GRD_KVPut(GRD_DB *db, const char *collectionName, const GRD_KVIt GRD_API int32_t GRD_KVGet(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value) { if (GRD_KVApiInfo.KVGetApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVGetApi(db, collectionName, key, value); } @@ -42,16 +42,16 @@ GRD_API int32_t GRD_KVGet(GRD_DB *db, const char *collectionName, const GRD_KVIt GRD_API int32_t GRD_KVDel(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key) { if (GRD_KVApiInfo.KVDelApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVDelApi(db, collectionName, key); } -GRD_API int32_t GRD_KVScan(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, KvScanModeE mode, +GRD_API int32_t GRD_KVScan(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet) { if (GRD_KVApiInfo.KVScanApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVScanApi(db, collectionName, key, mode, resultSet); } @@ -59,7 +59,7 @@ GRD_API int32_t GRD_KVScan(GRD_DB *db, const char *collectionName, const GRD_KVI GRD_API int32_t GRD_KVFreeItem(GRD_KVItemT *item) { if (GRD_KVApiInfo.KVFreeItemApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVFreeItemApi(item); } @@ -67,7 +67,7 @@ GRD_API int32_t GRD_KVFreeItem(GRD_KVItemT *item) GRD_API int32_t GRD_KVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch) { if (GRD_KVApiInfo.KVBatchPrepareApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVBatchPrepareApi(itemNum, batch); } @@ -76,23 +76,31 @@ GRD_API int32_t GRD_KVBatchPushback(const void *key, uint32_t keyLen, const void GRD_KVBatchT *batch) { if (GRD_KVApiInfo.KVBatchPushbackApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVBatchPushbackApi(key, keyLen, data, dataLen, batch); } +GRD_API int32_t GRD_KVBatchPut(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) +{ + if (GRD_KVApiInfo.KVBatchPutApi == nullptr) { + GRD_KVApiInfo = GetApiInfoInstance(); + } + return GRD_KVApiInfo.KVBatchPutApi(db, collectionName, batch); +} + GRD_API int32_t GRD_KVBatchDel(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) { if (GRD_KVApiInfo.KVBatchDelApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVBatchDelApi(db, collectionName, batch); } -GRD_API int32_t GRD_KVBatchDestory(GRD_KVBatchT *batch) +GRD_API int32_t GRD_KVBatchDestroy(GRD_KVBatchT *batch) { if (GRD_KVApiInfo.KVBatchDestoryApi == nullptr) { - return GRD_INNER_ERR; + GRD_KVApiInfo = GetApiInfoInstance(); } return GRD_KVApiInfo.KVBatchDestoryApi(batch); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp index a470ef2e1dd58bb60c7a72f33382369a4a66c091..0837ae5ef7ea8c880c541f72d30d734323b2543a 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/executor/kv/grd_kv_api_inner.cpp @@ -17,7 +17,7 @@ #include "grd_base/grd_error.h" #include "grd_kv_api_inner.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { int32_t GRD_KVPutInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, const GRD_KVItemT *value) { @@ -34,7 +34,7 @@ int32_t GRD_KVDelInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT return GRD_NOT_SUPPORT; // No support. } -int32_t GRD_KVScanInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, KvScanModeE mode, +int32_t GRD_KVScanInner(GRD_DB *db, const char *collectionName, const GRD_KVItemT *key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet) { return GRD_NOT_SUPPORT; // No support. @@ -56,12 +56,17 @@ int32_t GRD_KVBatchPushbackInner(const void *key, uint32_t keyLen, const void *d return GRD_NOT_SUPPORT; // No support. } +int32_t GRD_KVBatchPutInner(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) +{ + return GRD_NOT_SUPPORT; // No support. +} + int32_t GRD_KVBatchDelInner(GRD_DB *db, const char *collectionName, GRD_KVBatchT *batch) { return GRD_NOT_SUPPORT; // No support. } -int32_t GRD_KVBatchDestoryInner(GRD_KVBatchT *batch) +int32_t GRD_KVBatchDestroyInner(GRD_KVBatchT *batch) { return GRD_NOT_SUPPORT; // No support. } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/doc_errno.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/doc_errno.h index 75f636b55da36eeec89ec0476e85807df1c99e9f..4f8d1fe7e3cbd2ee3e67f2dedc7bf6bbe8ed9e24 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/doc_errno.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/doc_errno.h @@ -41,6 +41,7 @@ constexpr int E_FAILED_MEMORY_ALLOCATE = E_BASE + 51; constexpr int E_INNER_ERROR = E_BASE + 52; constexpr int E_INVALID_FILE_FORMAT = E_BASE + 53; constexpr int E_FAILED_FILE_OPERATION = E_BASE + 54; +constexpr int E_NOT_SUPPORT = E_BASE + 55; int TransferDocErr(int err); } // namespace DocumentDB diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/document_key.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/document_key.h index 32dbd79e8b7b13ee9d8c8adc8b0d70a4def3432e..dc20f5fc846a841426a2db775978143b2a234486 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/document_key.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/document_key.h @@ -19,7 +19,7 @@ #include #include -#include "json_object.h" +#include "rd_json_object.h" #define GRD_DOC_OID_TIME_SIZE 4 #define GRD_DOC_OID_INCREMENTAL_VALUE_SIZE 2 diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/projection_tree.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/projection_tree.h index 3cdca06d33f336618a322849ce910432fb6a2aea..7d3b080b40c355b2554fe51319e3526376c45175 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/projection_tree.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/projection_tree.h @@ -21,7 +21,7 @@ #include "doc_errno.h" #include "json_common.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { struct ProjectionNode { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h index 01c42c63e52940b26a1eac9f54caf45fdb01252c..e200ed4e0499f38526ae5f8e5986c53b386c74a8 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/include/result_set.h @@ -24,7 +24,7 @@ #include "doc_errno.h" #include "document_store.h" #include "grd_base/grd_type_export.h" -#include "json_object.h" +#include "rd_json_object.h" namespace DocumentDB { class ResultSet { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/collection.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/collection.cpp index 61f6d2daac065e603bcf135c4c42c769bc8c8d1f..444910dc508a5bc886be4d4877196af36aba9e6c 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/collection.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/collection.cpp @@ -16,10 +16,10 @@ #include "collection.h" #include "check_common.h" -#include "db_constant.h" +#include "rd_db_constant.h" #include "doc_errno.h" #include "document_key.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { Collection::Collection(const std::string &name, KvStoreExecutor *executor) : executor_(executor) diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/doc_errno.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/doc_errno.cpp index bf9dca10b3fba2ae988d605ec65d609531dd49e9..3fe46256ee956983c0683154dfa244449fa4f555 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/doc_errno.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/doc_errno.cpp @@ -65,6 +65,8 @@ int TransferDocErr(int err) return GetErrorCategory(GRD_INVALID_FILE_FORMAT); case -E_FAILED_FILE_OPERATION: return GetErrorCategory(GRD_FAILED_FILE_OPERATION); + case -E_NOT_SUPPORT: + return GetErrorCategory(GRD_NOT_SUPPORT); case -E_INNER_ERROR: default: return GetErrorCategory(GRD_INNER_ERR); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp index a64932053790730da79005afe7b18b385b8d5639..7d7ddf009f2fbed3c23f866430afc99cb7051416 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_key.cpp @@ -14,9 +14,13 @@ */ #include "document_key.h" +#include +#include + #include "doc_errno.h" -#include "log_print.h" +#include "rd_log_print.h" #include "securec.h" + namespace DocumentDB { static uint16_t g_oIdIncNum = 0; constexpr uint16_t MAX_NUMBER_OF_AUTOINCREMENTS = 65535; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store.cpp index e2bb9c25206b5b4711c32a5a15fb0c08d87b00f8..9f4f9abbf160fc82e1016e1b3aeab4e9859d8e2c 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store.cpp @@ -21,7 +21,7 @@ #include "document_key.h" #include "grd_base/grd_type_export.h" #include "grd_resultset_inner.h" -#include "log_print.h" +#include "rd_log_print.h" #include "result_set.h" #include "result_set_common.h" diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store_manager.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store_manager.cpp index 5e306156c18630a11be424ec83566ce421e623fb..00a6a294f890f46177e14fc38a04ade82d4b8128 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/document_store_manager.cpp @@ -19,14 +19,15 @@ #include "doc_errno.h" #include "grd_base/grd_type_export.h" #include "kv_store_manager.h" -#include "log_print.h" #include "os_api.h" +#include "rd_log_print.h" namespace DocumentDB { namespace { bool CheckDBOpenFlag(unsigned int flag) { - unsigned int mask = ~(GRD_DB_OPEN_CREATE | GRD_DB_OPEN_CHECK_FOR_ABNORMAL | GRD_DB_OPEN_CHECK); + unsigned int mask = ~(GRD_DB_OPEN_CREATE | GRD_DB_OPEN_CHECK_FOR_ABNORMAL | GRD_DB_OPEN_CHECK | + GRD_DB_OPEN_SHARED_READ_ONLY); unsigned int invalidOpt = (GRD_DB_OPEN_CHECK_FOR_ABNORMAL | GRD_DB_OPEN_CHECK); return ((flag & mask) == 0x00) && ((flag & invalidOpt) != invalidOpt); } diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp index d537dd0ebb02b45c04ec52cacb5168bfbeeb7bbd..a9a7019535d4172f4d7921a38600a9a48a44fa4c 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/interface/src/result_set.cpp @@ -14,9 +14,9 @@ */ #include "result_set.h" -#include "db_constant.h" #include "document_key.h" -#include "log_print.h" +#include "rd_db_constant.h" +#include "rd_log_print.h" #include "securec.h" namespace DocumentDB { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/include/json_object.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/include/rd_json_object.h similarity index 96% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/include/json_object.h rename to kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/include/rd_json_object.h index bd1cba711e6efd0cd2fb5bd291fe07ff74305f0e..dad46abc339015afbdefe385718d34d4ea3f3f20 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/include/json_object.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/include/rd_json_object.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef JSON_OBJECT_H -#define JSON_OBJECT_H +#ifndef RD_JSON_OBJECT_H +#define RD_JSON_OBJECT_H #include #include @@ -22,7 +22,13 @@ #include #include +#ifndef OMIT_cJSON #include "cJSON.h" +#endif + +#ifdef OMIT_cJSON +typedef void cJSON; +#endif namespace DocumentDB { class ValueObject { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp index 79cbcc868989746ffd9ce8b7b552fd2261e90643..26fb8421780ef831154f0ea0bfc20132bdb87dde 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp @@ -16,9 +16,9 @@ #include "kv_store_manager.h" #include "doc_errno.h" -#include "log_print.h" +#include "rd_log_print.h" +#include "rd_sqlite_utils.h" #include "sqlite_store_executor_impl.h" -#include "sqlite_utils.h" namespace DocumentDB { int KvStoreManager::GetKvStore(const std::string &path, const DBConfig &config, bool isFirstOpen, diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/json_object.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp similarity index 77% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/json_object.cpp rename to kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp index 26c50fd8667a29c81e251c6fb0a3776099ea85c1..09d8847252aba0137812d2829065ec2dfe7f3db1 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/json_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_json_object.cpp @@ -13,16 +13,17 @@ * limitations under the License. */ -#include "json_object.h" +#include "rd_json_object.h" #include #include #include #include "doc_errno.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { +#ifndef OMIT_cJSON namespace { bool IsNumber(const std::string &str) { @@ -666,4 +667,280 @@ int JsonObject::DeleteItemDeeplyOnTarget(const JsonFieldPath &path) return E_OK; } +#else +ValueObject::ValueObject(bool val) +{ + valueType = ValueType::VALUE_BOOL; + boolValue = val; +} + +ValueObject::ValueObject(double val) +{ + valueType = ValueType::VALUE_NUMBER; + doubleValue = val; +} + +ValueObject::ValueObject(const char *val) +{ + valueType = ValueType::VALUE_STRING; + stringValue = val; +} + +ValueObject::ValueType ValueObject::GetValueType() const +{ + return valueType; +} + +bool ValueObject::GetBoolValue() const +{ + return boolValue; +} + +int64_t ValueObject::GetIntValue() const +{ + return static_cast(std::llround(doubleValue)); +} + +double ValueObject::GetDoubleValue() const +{ + return doubleValue; +} + +std::string ValueObject::GetStringValue() const +{ + return stringValue; +} + +JsonObject JsonObject::Parse(const std::string &jsonStr, int &errCode, bool caseSensitive, bool isFilter) +{ + (void)jsonStr; + (void)errCode; + (void)caseSensitive; + (void)isFilter; + return {}; +} + +JsonObject::JsonObject() +{ + cjson_ = nullptr; + jsonDeep_ = 0; + isOwner_ = false; + caseSensitive_ = false; +} + +JsonObject::~JsonObject() +{ +} + +bool JsonObject::operator==(const JsonObject &other) const +{ + return true; +} + + +bool JsonObject::IsNull() const +{ + return true; +} + +JsonObject::Type JsonObject::GetType() const +{ + return JsonObject::Type::JSON_LEAF; +} + +int JsonObject::GetDeep() +{ + return jsonDeep_; +} + +int JsonObject::GetDeep(cJSON *cjson) +{ + return jsonDeep_; +} + +int JsonObject::CheckNumber(cJSON *item) +{ + (void)item; + return E_OK; +} + +int JsonObject::Init(const std::string &str, bool isFilter) +{ + (void)str; + (void)isFilter; + return E_OK; +} + +int JsonObject::CheckJsonRepeatField(cJSON *object, bool isFirstFloor) +{ + (void)object; + (void)isFirstFloor; + return E_OK; +} + +bool IsFieldNameLegal(const std::string &fieldName) +{ + (void)fieldName; + return true; +} + +int JsonObject::CheckSubObj(std::set &fieldSet, cJSON *subObj, int parentType, bool isFirstFloor) +{ + (void)fieldSet; + (void)subObj; + (void)parentType; + (void)isFirstFloor; + return true; +} + +std::string JsonObject::Print() const +{ + return std::string(); +} + +JsonObject JsonObject::GetObjectItem(const std::string &field, int &errCode) +{ + (void)field; + (void)errCode; + return {}; +} + +JsonObject JsonObject::GetNext() const +{ + return {}; +} + +JsonObject JsonObject::GetChild() const +{ + return {}; +} + +int JsonObject::DeleteItemFromObject(const std::string &field) +{ + (void)field; + return E_OK; +} + +int JsonObject::AddItemToObject(const std::string &fieldName, const JsonObject &item) +{ + (void)fieldName; + (void)item; + return E_OK; +} + +int JsonObject::AddItemToObject(const std::string &fieldName) +{ + (void)fieldName; + return E_OK; +} + +ValueObject JsonObject::GetItemValue() const +{ + return {}; +} + +void JsonObject::ReplaceItemInObject(const std::string &fieldName, const JsonObject &newItem, int &errCode) +{ + (void)fieldName; + (void)newItem; + (void)errCode; +} + +void JsonObject::ReplaceItemInArray(const int &index, const JsonObject &newItem, int &errCode) +{ + (void)index; + (void)newItem; + (void)errCode; +} + +int JsonObject::InsertItemObject(int which, const JsonObject &newItem) +{ + (void)which; + (void)newItem; + return E_OK; +} + +std::string JsonObject::GetItemField() const +{ + return std::string(); +} + +std::string JsonObject::GetItemField(int &errCode) const +{ + (void)errCode; + return std::string(); +} + +cJSON *GetChild(cJSON *cjson, const std::string &field, bool caseSens) +{ + (void)cjson; + (void)field; + (void)caseSens; + return nullptr; +} + +cJSON *GetChildPowerMode(cJSON *cjson, const std::string &field, bool caseSens) +{ + (void)cjson; + (void)field; + (void)caseSens; + return nullptr; +} + +cJSON *MoveToPath(cJSON *cjson, const JsonFieldPath &jsonPath, bool caseSens) +{ + (void)cjson; + (void)jsonPath; + (void)caseSens; + return nullptr; +} + +cJSON *MoveToPathPowerMode(cJSON *cjson, const JsonFieldPath &jsonPath, bool caseSens) +{ + (void)jsonPath; + (void)caseSens; + return nullptr; +} + +bool JsonObject::IsFieldExists(const JsonFieldPath &jsonPath) const +{ + (void)jsonPath; + return true; +} + +bool JsonObject::IsFieldExistsPowerMode(const JsonFieldPath &jsonPath) const +{ + (void)jsonPath; + return true; +} + +JsonObject JsonObject::FindItem(const JsonFieldPath &jsonPath, int &errCode) const +{ + (void)jsonPath; + (void)errCode; + return {}; +} + +// Compared with the non-powerMode mode, the node found by this function is an Array, and target is an object, +// if the Array contains the same object as the target, it can match this object in this mode. +JsonObject JsonObject::FindItemPowerMode(const JsonFieldPath &jsonPath, int &errCode) const +{ + (void)jsonPath; + (void)errCode; + return {}; +} + +ValueObject JsonObject::GetObjectByPath(const JsonFieldPath &jsonPath, int &errCode) const +{ + (void)jsonPath; + (void)errCode; + return {}; +} + +int JsonObject::DeleteItemDeeplyOnTarget(const JsonFieldPath &path) +{ + (void)path; + return E_OK; +} +#endif } // namespace DocumentDB diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_utils.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp similarity index 79% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_utils.cpp rename to kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp index 2c56227d361895f44d5ae22ebcb13497b983a6c6..27bef4c14adc5eb38126bf52a30b6d4323eb7f90 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.cpp @@ -12,12 +12,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#include "sqlite_utils.h" +#include "rd_sqlite_utils.h" #include #include "doc_errno.h" -#include "log_print.h" +#include "rd_log_print.h" namespace DocumentDB { const int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit @@ -51,12 +51,12 @@ std::mutex g_logConfigMutex; bool g_configLog = false; } // namespace -void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) +void RDSQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) { GLOGD("[SQLite] err=%d sys=%d %s", err, errno, sqlite3_errstr(err)); } -int SQLiteUtils::CreateDataBase(const std::string &path, int flag, sqlite3 *&db) +int RDSQLiteUtils::CreateDataBase(const std::string &path, int flag, sqlite3 *&db) { { std::lock_guard lock(g_logConfigMutex); @@ -83,7 +83,7 @@ int SQLiteUtils::CreateDataBase(const std::string &path, int flag, sqlite3 *&db) return MapSqliteError(errCode); } -int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement) +int RDSQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement) { if (db == nullptr) { GLOGE("Invalid db for get statement"); @@ -97,7 +97,7 @@ int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr); if (errCode != SQLITE_OK) { GLOGE("Prepare SQLite statement failed:%d", errCode); - (void)SQLiteUtils::ResetStatement(statement, true); + (void)RDSQLiteUtils::ResetStatement(statement, true); return MapSqliteError(errCode); } @@ -108,7 +108,7 @@ int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt return E_OK; } -int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement) +int RDSQLiteUtils::StepWithRetry(sqlite3_stmt *statement) { if (statement == nullptr) { return -E_INVALID_ARGS; @@ -116,13 +116,13 @@ int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement) int errCode = sqlite3_step(statement); if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) { - GLOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno); + GLOGE("[RDSQLiteUtils] Step error:%d, sys:%d", errCode, errno); } return errCode; } -int SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool finalize) +int RDSQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool finalize) { if (statement == nullptr) { return -E_INVALID_ARGS; @@ -132,7 +132,7 @@ int SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool finalize) if (!finalize) { errCode = sqlite3_reset(statement); if (errCode != SQLITE_OK) { - GLOGE("[SQLiteUtils] reset statement error:%d, sys:%d", errCode, errno); + GLOGE("[RDSQLiteUtils] reset statement error:%d, sys:%d", errCode, errno); goto FINALIZE; } @@ -143,13 +143,13 @@ int SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool finalize) FINALIZE: int finalizeResult = sqlite3_finalize(statement); if (finalizeResult != SQLITE_OK) { - GLOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno); + GLOGE("[RDSQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno); } statement = nullptr; return (errCode == SQLITE_OK ? finalizeResult : errCode); } -int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector &value) +int RDSQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector &value) { if (statement == nullptr) { return -E_INVALID_ARGS; @@ -165,7 +165,7 @@ int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const s return errCode; } -int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value) +int RDSQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value) { if (statement == nullptr) { return -E_INVALID_ARGS; @@ -173,7 +173,7 @@ int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vec int keySize = sqlite3_column_bytes(statement, index); if (keySize < 0 || keySize > MAX_BLOB_READ_SIZE) { - GLOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize); + GLOGW("[RDSQLiteUtils][Column blob] size over limit:%d", keySize); value.resize(MAX_BLOB_READ_SIZE + 1); // Reset value size to invalid return E_OK; // Return OK for continue get data, but value is invalid } @@ -189,7 +189,7 @@ int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vec return E_OK; } -int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &value) +int RDSQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &value) { if (statement == nullptr) { return -E_INVALID_ARGS; @@ -204,7 +204,7 @@ int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const s return E_OK; } -int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) +int RDSQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) { if (type == TransactType::IMMEDIATE) { return ExecSql(db, BEGIN_IMMEDIATE_SQL); @@ -213,17 +213,17 @@ int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) return ExecSql(db, BEGIN_SQL); } -int SQLiteUtils::CommitTransaction(sqlite3 *db) +int RDSQLiteUtils::CommitTransaction(sqlite3 *db) { return ExecSql(db, COMMIT_SQL); } -int SQLiteUtils::RollbackTransaction(sqlite3 *db) +int RDSQLiteUtils::RollbackTransaction(sqlite3 *db) { return ExecSql(db, ROLLBACK_SQL); } -int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql) +int RDSQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql) { if (db == nullptr || sql.empty()) { return -E_INVALID_ARGS; @@ -239,7 +239,7 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql) return MapSqliteError(errCode); } -int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::function &bindCallback, +int RDSQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::function &bindCallback, const std::function &resultCallback) { if (db == nullptr || sql.empty()) { @@ -248,7 +248,7 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::functio bool bindFinish = true; sqlite3_stmt *stmt = nullptr; bool isMatchOneData = false; - int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + int errCode = RDSQLiteUtils::GetStatement(db, sql, stmt); if (errCode != E_OK) { goto END; } @@ -262,7 +262,7 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::functio } while (true) { - errCode = SQLiteUtils::StepWithRetry(stmt); + errCode = RDSQLiteUtils::StepWithRetry(stmt); if (errCode == SQLITE_DONE) { break; } else if (errCode != SQLITE_ROW) { @@ -275,11 +275,11 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::functio goto END; } } - errCode = SQLiteUtils::ResetStatement(stmt, false); + errCode = RDSQLiteUtils::ResetStatement(stmt, false); } while (!bindFinish); END: - (void)SQLiteUtils::ResetStatement(stmt, true); + (void)RDSQLiteUtils::ResetStatement(stmt, true); return MapSqliteError(errCode); } } // namespace DocumentDB diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_utils.h b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.h similarity index 95% rename from kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_utils.h rename to kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.h index 88cc77efd2f05fb8ffb991d26a0b4cb206ad6d7d..32e422c3847c4446976c42de851058f793b43b50 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_utils.h +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/rd_sqlite_utils.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef SQLITE_UTILS_H -#define SQLITE_UTILS_H +#ifndef RD_SQLITE_UTILS_H +#define RD_SQLITE_UTILS_H #include #include @@ -28,7 +28,7 @@ enum class TransactType { IMMEDIATE, }; -class SQLiteUtils { +class RDSQLiteUtils { public: static int CreateDataBase(const std::string &path, int flag, sqlite3 *&db); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp index 6750b9b5f6c2e873bf09681ee5931bed7a4ed44e..e75b4cbcc0c87c2b7be3e796471ef696ef4cdf26 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp @@ -16,11 +16,11 @@ #include "sqlite_store_executor_impl.h" #include "check_common.h" -#include "db_constant.h" +#include "rd_db_constant.h" #include "doc_errno.h" #include "document_key.h" -#include "log_print.h" -#include "sqlite_utils.h" +#include "rd_log_print.h" +#include "rd_sqlite_utils.h" namespace DocumentDB { constexpr const uint8_t KEY_TYPE = uint8_t(DocIdType::STRING); @@ -30,26 +30,26 @@ int SqliteStoreExecutorImpl::CreateDatabase(const std::string &path, const DBCon return -E_INVALID_ARGS; } - int errCode = SQLiteUtils::CreateDataBase(path, 0, db); + int errCode = RDSQLiteUtils::CreateDataBase(path, 0, db); if (errCode != E_OK || db == nullptr) { GLOGE("Open or create database failed. %d", errCode); return errCode; } std::string pageSizeSql = "PRAGMA page_size=" + std::to_string(config.GetPageSize() * 1024); - errCode = SQLiteUtils::ExecSql(db, pageSizeSql); + errCode = RDSQLiteUtils::ExecSql(db, pageSizeSql); if (errCode != E_OK) { GLOGE("Set db page size failed. %d", errCode); goto END; } - errCode = SQLiteUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"); + errCode = RDSQLiteUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"); if (errCode != E_OK) { GLOGE("Set db journal_mode failed. %d", errCode); goto END; } - errCode = SQLiteUtils::ExecSql(db, "CREATE TABLE IF NOT EXISTS grd_meta (key BLOB PRIMARY KEY, value BLOB);"); + errCode = RDSQLiteUtils::ExecSql(db, "CREATE TABLE IF NOT EXISTS grd_meta (key BLOB PRIMARY KEY, value BLOB);"); if (errCode != E_OK) { GLOGE("Create meta table failed. %d", errCode); goto END; @@ -91,17 +91,17 @@ int SqliteStoreExecutorImpl::SetDBConfig(const std::string &config) int SqliteStoreExecutorImpl::StartTransaction() { - return SQLiteUtils::BeginTransaction(dbHandle_, TransactType::IMMEDIATE); + return RDSQLiteUtils::BeginTransaction(dbHandle_, TransactType::IMMEDIATE); } int SqliteStoreExecutorImpl::Commit() { - return SQLiteUtils::CommitTransaction(dbHandle_); + return RDSQLiteUtils::CommitTransaction(dbHandle_); } int SqliteStoreExecutorImpl::Rollback() { - return SQLiteUtils::RollbackTransaction(dbHandle_); + return RDSQLiteUtils::RollbackTransaction(dbHandle_); } int SqliteStoreExecutorImpl::PutData(const std::string &collName, Key &key, const Value &value, bool isNeedAddKeyType) @@ -113,11 +113,11 @@ int SqliteStoreExecutorImpl::PutData(const std::string &collName, Key &key, cons key.push_back(KEY_TYPE); // Stitching ID type } std::string sql = "INSERT OR REPLACE INTO '" + collName + "' VALUES (?,?);"; - int errCode = SQLiteUtils::ExecSql( + int errCode = RDSQLiteUtils::ExecSql( dbHandle_, sql, [key, value](sqlite3_stmt *stmt) { - SQLiteUtils::BindBlobToStatement(stmt, 1, key); - SQLiteUtils::BindBlobToStatement(stmt, 2, value); + RDSQLiteUtils::BindBlobToStatement(stmt, 1, key); + RDSQLiteUtils::BindBlobToStatement(stmt, 2, value); return E_OK; }, nullptr); @@ -142,11 +142,11 @@ int SqliteStoreExecutorImpl::InsertData(const std::string &collName, Key &key, c key.push_back(KEY_TYPE); // Stitching ID type } std::string sql = "INSERT INTO '" + collName + "' VALUES (?,?);"; - int errCode = SQLiteUtils::ExecSql( + int errCode = RDSQLiteUtils::ExecSql( dbHandle_, sql, [key, value](sqlite3_stmt *stmt) { - SQLiteUtils::BindBlobToStatement(stmt, 1, key); - SQLiteUtils::BindBlobToStatement(stmt, 2, value); + RDSQLiteUtils::BindBlobToStatement(stmt, 1, key); + RDSQLiteUtils::BindBlobToStatement(stmt, 2, value); return E_OK; }, nullptr); @@ -169,14 +169,14 @@ int SqliteStoreExecutorImpl::GetDataByKey(const std::string &collName, Key &key, } int innerErrorCode = -E_NOT_FOUND; std::string sql = "SELECT value FROM '" + collName + "' WHERE key=?;"; - int errCode = SQLiteUtils::ExecSql( + int errCode = RDSQLiteUtils::ExecSql( dbHandle_, sql, [key](sqlite3_stmt *stmt) { - SQLiteUtils::BindBlobToStatement(stmt, 1, key); + RDSQLiteUtils::BindBlobToStatement(stmt, 1, key); return E_OK; }, [&value, &innerErrorCode](sqlite3_stmt *stmt, bool &isMatchOneData) { - SQLiteUtils::GetColumnBlobValue(stmt, 0, value); + RDSQLiteUtils::GetColumnBlobValue(stmt, 0, value); innerErrorCode = E_OK; return E_OK; }); @@ -196,14 +196,14 @@ int SqliteStoreExecutorImpl::GetDataById(const std::string &collName, Key &key, key.push_back(KEY_TYPE); // Stitching ID type int innerErrorCode = -E_NOT_FOUND; std::string sql = "SELECT value FROM '" + collName + "' WHERE key=?;"; - int errCode = SQLiteUtils::ExecSql( + int errCode = RDSQLiteUtils::ExecSql( dbHandle_, sql, [key](sqlite3_stmt *stmt) { - SQLiteUtils::BindBlobToStatement(stmt, 1, key); + RDSQLiteUtils::BindBlobToStatement(stmt, 1, key); return E_OK; }, [&value, &innerErrorCode](sqlite3_stmt *stmt, bool &isMatchOneData) { - SQLiteUtils::GetColumnBlobValue(stmt, 0, value); + RDSQLiteUtils::GetColumnBlobValue(stmt, 0, value); innerErrorCode = E_OK; return E_OK; }); @@ -250,18 +250,18 @@ int SqliteStoreExecutorImpl::GetDataByFilter(const std::string &collName, Key &k std::string sql = GeneralInsertSql(collName, key, isIdExist); key.push_back(KEY_TYPE); std::string keyStr(key.begin(), key.end()); - int errCode = SQLiteUtils::ExecSql( + int errCode = RDSQLiteUtils::ExecSql( dbHandle_, sql, [key](sqlite3_stmt *stmt) { if (!key.empty()) { - SQLiteUtils::BindBlobToStatement(stmt, 1, key); + RDSQLiteUtils::BindBlobToStatement(stmt, 1, key); } return E_OK; }, [&keyResult, &innerErrorCode, &valueResult, &filterObj, &values, &isFindMatch](sqlite3_stmt *stmt, bool &isMatchOneData) { - SQLiteUtils::GetColumnBlobValue(stmt, 0, keyResult); - SQLiteUtils::GetColumnBlobValue(stmt, 1, valueResult); + RDSQLiteUtils::GetColumnBlobValue(stmt, 0, keyResult); + RDSQLiteUtils::GetColumnBlobValue(stmt, 1, valueResult); std::string keyStr(keyResult.begin(), keyResult.end()); std::string valueStr(valueResult.begin(), valueResult.end()); JsonObject srcObj = JsonObject::Parse(valueStr, innerErrorCode, true); @@ -300,10 +300,10 @@ int SqliteStoreExecutorImpl::DelData(const std::string &collName, Key &key) return -E_NO_DATA; } std::string sql = "DELETE FROM '" + collName + "' WHERE key=?;"; - errCode = SQLiteUtils::ExecSql( + errCode = RDSQLiteUtils::ExecSql( dbHandle_, sql, [key](sqlite3_stmt *stmt) { - SQLiteUtils::BindBlobToStatement(stmt, 1, key); + RDSQLiteUtils::BindBlobToStatement(stmt, 1, key); return E_OK; }, nullptr); @@ -335,7 +335,7 @@ int SqliteStoreExecutorImpl::CreateCollection(const std::string &name, const std } std::string sql = "CREATE TABLE IF NOT EXISTS '" + collName + "' (key BLOB PRIMARY KEY, value BLOB);"; - errCode = SQLiteUtils::ExecSql(dbHandle_, sql); + errCode = RDSQLiteUtils::ExecSql(dbHandle_, sql); if (errCode != E_OK) { GLOGE("[sqlite executor] Create collection failed. err=%d", errCode); return errCode; @@ -368,7 +368,7 @@ int SqliteStoreExecutorImpl::DropCollection(const std::string &name, bool ignore } std::string sql = "DROP TABLE IF EXISTS '" + collName + "';"; - int errCode = SQLiteUtils::ExecSql(dbHandle_, sql); + int errCode = RDSQLiteUtils::ExecSql(dbHandle_, sql); if (errCode != E_OK) { GLOGE("[sqlite executor] Drop collection failed. err=%d", errCode); } @@ -379,10 +379,10 @@ bool SqliteStoreExecutorImpl::IsCollectionExists(const std::string &name, int &e { bool isExists = false; std::string sql = "SELECT tbl_name FROM sqlite_master WHERE tbl_name=?;"; - errCode = SQLiteUtils::ExecSql( + errCode = RDSQLiteUtils::ExecSql( dbHandle_, sql, [name](sqlite3_stmt *stmt) { - SQLiteUtils::BindTextToStatement(stmt, 1, name); + RDSQLiteUtils::BindTextToStatement(stmt, 1, name); return E_OK; }, [&isExists](sqlite3_stmt *stmt, bool &isMatchOneData) { diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn index 13f0f8b1d4740cd46a5cc9c86db56be9489c8149..e75938e5d6d99fc4a8b9fb22ee09b3df0965085a 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/BUILD.gn @@ -49,8 +49,8 @@ ohos_source_set("src_file") { "../../src/common/src/db_config.cpp", "../../src/common/src/grd_api_manager.cpp", "../../src/common/src/json_common.cpp", - "../../src/common/src/log_print.cpp", "../../src/common/src/os_api.cpp", + "../../src/common/src/rd_log_print.cpp", "../../src/executor/base/grd_db_api.cpp", "../../src/executor/base/grd_db_api_inner.cpp", "../../src/executor/document/check_common.cpp", @@ -60,8 +60,6 @@ ohos_source_set("src_file") { "../../src/executor/document/grd_resultset_api_inner.cpp", "../../src/executor/kv/grd_kv_api.cpp", "../../src/executor/kv/grd_kv_api_inner.cpp", - "../../src/executor/shared_obj/grd_sequence_api.cpp", - "../../src/executor/shared_obj/grd_sequence_api_inner.cpp", "../../src/interface/src/collection.cpp", "../../src/interface/src/doc_errno.cpp", "../../src/interface/src/document_key.cpp", @@ -70,10 +68,10 @@ ohos_source_set("src_file") { "../../src/interface/src/projection_tree.cpp", "../../src/interface/src/result_set.cpp", "../../src/interface/src/result_set_common.cpp", - "../../src/oh_adapter/src/json_object.cpp", "../../src/oh_adapter/src/kv_store_manager.cpp", + "../../src/oh_adapter/src/rd_json_object.cpp", + "../../src/oh_adapter/src/rd_sqlite_utils.cpp", "../../src/oh_adapter/src/sqlite_store_executor_impl.cpp", - "../../src/oh_adapter/src/sqlite_utils.cpp", "common/documentdb_test_utils.cpp", ] diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp index ee7e8dcfaec328fe4dd6dd8baf3ec910a9ac3ed3..990f82974a6534b92c15b9d8bdf4fecda44bf6ca 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_api_test.cpp @@ -21,8 +21,8 @@ #include "grd_base/grd_db_api.h" #include "grd_base/grd_error.h" #include "grd_document/grd_document_api.h" -#include "log_print.h" -#include "sqlite_utils.h" +#include "rd_log_print.h" +#include "rd_sqlite_utils.h" using namespace DocumentDB; using namespace testing::ext; @@ -60,19 +60,14 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest001, TestSize.Level0) std::string path = "./document.db"; GRD_DB *db = nullptr; int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &db); - printf("mazhao work here aaa"); EXPECT_EQ(status, GRD_OK); EXPECT_NE(db, nullptr); GLOGD("Open DB test 001: status: %d", status); EXPECT_EQ(GRD_CreateCollection(db, "student", "", 0), GRD_OK); - printf("mazhao work here bbb"); EXPECT_EQ(GRD_UpsertDoc(db, "student", R""({"_id":"10001"})"", R""({"name":"Tom", "age":23})"", 0), 1); - printf("mazhao work here ccc"); EXPECT_EQ(GRD_DropCollection(db, "student", 0), GRD_OK); - printf("mazhao work here ddd"); status = GRD_DBClose(db, GRD_DB_CLOSE); - printf("mazhao work here eee"); EXPECT_EQ(status, GRD_OK); db = nullptr; @@ -453,13 +448,13 @@ namespace { int GetDBPageSize(const std::string &path) { sqlite3 *db = nullptr; - int ret = SQLiteUtils::CreateDataBase(path, 0, db); + int ret = RDSQLiteUtils::CreateDataBase(path, 0, db); EXPECT_EQ(ret, E_OK); if (db == nullptr) { return 0; } int pageSize = 0; - SQLiteUtils::ExecSql(db, "PRAGMA page_size;", nullptr, [&pageSize](sqlite3_stmt *stmt, bool &isMatchOneData) { + RDSQLiteUtils::ExecSql(db, "PRAGMA page_size;", nullptr, [&pageSize](sqlite3_stmt *stmt, bool &isMatchOneData) { pageSize = sqlite3_column_int(stmt, 0); return E_OK; }); diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_collection_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_collection_test.cpp index 04431be400ba2e7d2c2ad9a79cc68edcf37f4695..1f9c8a67f46bd241604020c33310d58025c21178 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_collection_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_collection_test.cpp @@ -20,8 +20,8 @@ #include "grd_base/grd_db_api.h" #include "grd_base/grd_error.h" #include "grd_document/grd_document_api.h" -#include "log_print.h" -#include "sqlite_utils.h" +#include "rd_log_print.h" +#include "rd_sqlite_utils.h" using namespace DocumentDB; using namespace testing::ext; @@ -202,4 +202,16 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest007, TestSize.Level0) EXPECT_EQ(GRD_DropCollection(g_db, "student", flag), GRD_INVALID_ARGS); } } + +/** + * @tc.name: CollectionTest008 + * @tc.desc: Test create KV db collection + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest008, TestSize.Level0) +{ + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "{\"mode\" : \"kv\"}", 0), GRD_NOT_SUPPORT); +} } // namespace \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_data_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_data_test.cpp index c0fc9afd4d9c6fa22b53ffc05dbf9670971d4224..d2f49d31fa7002611af8ad9a0280b4b7cd6b7879 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_data_test.cpp @@ -21,8 +21,8 @@ #include "grd_base/grd_db_api.h" #include "grd_base/grd_error.h" #include "grd_document/grd_document_api.h" -#include "log_print.h" -#include "sqlite_utils.h" +#include "rd_log_print.h" +#include "rd_sqlite_utils.h" using namespace DocumentDB; using namespace testing::ext; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp index 654294a3c924d00700f184eecbb24f1bb28b27e5..c799a1f1f3227a4acf5e220d024f986c95bea538 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp @@ -26,7 +26,7 @@ #include "grd_document/grd_document_api.h" #include "grd_resultset_inner.h" #include "grd_type_inner.h" -#include "log_print.h" +#include "rd_log_print.h" using namespace testing::ext; using namespace DocumentDBUnitTest; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp index ff4820e9c55afd4166a3c7c835706fa5b61ddc06..4ad61a330809b8a9bb3a13353615c09b83332a91 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_json_common_test.cpp @@ -19,7 +19,7 @@ #include "doc_errno.h" #include "documentdb_test_utils.h" #include "json_common.h" -#include "log_print.h" +#include "rd_log_print.h" using namespace DocumentDB; using namespace testing::ext; diff --git a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_jsonobject_test.cpp b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_jsonobject_test.cpp index 604f2c386eeb5e9d5a9f019633c9dcc4404be2ab..45e79c8dc125de61ab58ae94d37ccd882ffa64a1 100644 --- a/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_jsonobject_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/gaussdb_rd/test/unittest/oh_adapter/documentdb_jsonobject_test.cpp @@ -17,7 +17,7 @@ #include "doc_errno.h" #include "documentdb_test_utils.h" -#include "json_object.h" +#include "rd_json_object.h" using namespace DocumentDB; using namespace testing::ext; diff --git a/kv_store/frameworks/libs/distributeddb/include/query.h b/kv_store/frameworks/libs/distributeddb/include/query.h index 25821e237db6e01573b230c4ca9ddd0336ae1585..39957c94b8ef79e3b80c538ff3d5060662c36693 100644 --- a/kv_store/frameworks/libs/distributeddb/include/query.h +++ b/kv_store/frameworks/libs/distributeddb/include/query.h @@ -149,6 +149,8 @@ public: DB_API Query &InKeys(const std::set &keys); + DB_API Query &Range(const std::vector &keyBegin, const std::vector &keyEnd); + friend class GetQueryInfo; DB_API ~Query() = default; DB_API Query() = default; diff --git a/kv_store/frameworks/libs/distributeddb/include/query_expression.h b/kv_store/frameworks/libs/distributeddb/include/query_expression.h index fffff65d1cd12d3903d97d3b654aa4a526b16a09..72b6d4536a8b1b839b6286654568fc8bdfdf6f66 100644 --- a/kv_store/frameworks/libs/distributeddb/include/query_expression.h +++ b/kv_store/frameworks/libs/distributeddb/include/query_expression.h @@ -59,6 +59,7 @@ enum class QueryObjType : uint32_t { ORDERBY, SUGGEST_INDEX = 0x0801, IN_KEYS = 0x0901, + KEY_RANGE = 0x1001, }; struct QueryObjNode { @@ -122,8 +123,14 @@ public: void QueryBySuggestIndex(const std::string &indexName); + void QueryByKeyRange(const std::vector &keyBegin, const std::vector &keyEnd); + std::vector GetPreFixKey() const; + std::vector GetBeginKey() const; + + std::vector GetEndKey() const; + void SetTableName(const std::string &tableName); const std::string &GetTableName(); bool IsTableNameSpecified() const; @@ -160,6 +167,8 @@ private: std::list queryInfo_; bool errFlag_ = true; std::vector prefixKey_; + std::vector beginKey_; + std::vector endKey_; std::string suggestIndex_; std::string tableName_; bool isTableNameSpecified_; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h index 0e12b96554a42c98e5aa907f661bdfba4b9238d3..723cfecbc17b6aac82c73b3018c9dd9647a42769 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/cloud/cloud_store_types.h @@ -35,14 +35,16 @@ enum ClearMode { DEFAULT = 0, // use for device to device sync FLAG_AND_DATA = 1, // use for device to cloud sync FLAG_ONLY = 2, - BUTT = 3, + CLEAR_SHARED_TABLE = 3, + BUTT = 4, }; enum class AssetOpType { NO_CHANGE = 0, INSERT, DELETE, - UPDATE + UPDATE, + IGNORE // mark it ignore when not handle asset in (download, batchInsert, batchUpdate) }; enum AssetStatus : uint32_t { @@ -51,7 +53,10 @@ enum AssetStatus : uint32_t { ABNORMAL, INSERT, // INSERT/DELETE/UPDATE are for client use DELETE, - UPDATE + UPDATE, + // high 16 bit USE WITH BIT MASK + DOWNLOAD_WITH_NULL = 0x40000000, + UPLOADING = 0x80000000, }; struct Asset { @@ -71,7 +76,8 @@ struct Asset { using Nil = std::monostate; using Assets = std::vector; using Bytes = std::vector; -using Type = std::variant; +using Entries = std::map; +using Type = std::variant; using VBucket = std::map; struct Field { @@ -79,10 +85,16 @@ struct Field { int32_t type; // get value from TYPE_INDEX; bool primary = false; bool nullable = true; + bool operator==(const Field &comparedField) const + { + return (colName == comparedField.colName) && (type == comparedField.type) && + (primary == comparedField.primary) && (nullable == comparedField.nullable); + } }; struct TableSchema { std::string name; + std::string sharedTableName; // if table is shared table, its sharedtablename is "" std::vector fields; }; @@ -118,5 +130,15 @@ struct QueryNode { std::string fieldName; std::vector fieldValue; }; + +struct SqlCondition { + std::string sql; // The sql statement; + std::vector bindArgs; // The bind args. +}; + +enum class RecordStatus { + MIGRATING, + MIGRATE_FINISH +}; } // namespace DistributedDB #endif // CLOUD_STORE_TYPE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h index 9f8792b39deaccb9e0b53e2e46d089d2cd939717..f3d9ae77b04d24b88e67c5e1704e54416c697d4b 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_delegate_manager.h @@ -21,7 +21,6 @@ #include #include - #include "auto_launch_export.h" #include "iprocess_communicator.h" #include "iprocess_system_api_adapter.h" diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h index 453aea705e8d1ad7343b1e2f7091a03e2f1af7ba..f33bb86655bbead36d258b5d58472ba011c22ea5 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/kv_store_nb_delegate.h @@ -55,6 +55,8 @@ public: uint8_t compressionRate = 100; // Valid in [1, 100]. bool syncDualTupleMode = false; // communicator label use dualTuple hash or not bool localOnly = false; // active sync module + std::string storageEngineType = SQLITE; // use gaussdb_rd as storage engine + Rdconfig rdconfig; }; DB_API virtual ~KvStoreNbDelegate() {} diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h index f2a57d7fcfa9592cf1a6195c7bf3d36025d268e5..5a70996a8f62c053ee09f27e2a6be420d3cdf7a1 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_client.h @@ -21,12 +21,12 @@ #include #include -#include "sqlite3.h" - #include "store_types.h" +typedef struct sqlite3 sqlite3; + struct ClientChangedData { - std::set tableNames; + std::map tableData; }; using ClientObserver = std::function; @@ -35,4 +35,6 @@ DB_API DistributedDB::DBStatus RegisterClientObserver(sqlite3 *db, const ClientO DB_API DistributedDB::DBStatus UnRegisterClientObserver(sqlite3 *db); +DB_API DistributedDB::DBStatus DropLogicDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor); + #endif // RELATIONAL_STORE_CLIENT_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h index ee0b2687f28fd22d9c4f5a0032f827af1c7ad2bb..cc386862da2c978a0aa1edb3e6a93649f048546d 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/relational/relational_store_delegate.h @@ -84,6 +84,19 @@ public: DB_API virtual DBStatus SetIAssetLoader(const std::shared_ptr &loader) = 0; DB_API virtual DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) = 0; + + DB_API virtual DBStatus SetTrackerTable(const TrackerSchema &schema) = 0; + + DB_API virtual DBStatus ExecuteSql(const SqlCondition &condition, std::vector &records) = 0; + + DB_API virtual DBStatus SetReference(const std::vector &tableReferenceProperty) = 0; + + DB_API virtual DBStatus CleanTrackerData(const std::string &tableName, int64_t cursor) = 0; + + DB_API virtual DBStatus Pragma(PragmaCmd cmd, PragmaData &pragmaData) = 0; + + DB_API virtual DBStatus UpsertData(RecordStatus status, const std::string &tableName, + const std::vector &records) = 0; protected: virtual DBStatus RemoveDeviceDataInner(const std::string &device, ClearMode mode) = 0; virtual DBStatus CreateDistributedTableInner(const std::string &tableName, TableSyncType type) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h index 6b908cec5ee73c1a818e08a1e1cb28500b3498a9..dc3676602f3d649fac411997196b603235f6ff84 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_observer.h @@ -40,6 +40,7 @@ struct ChangedData { // primaryData store row id if have no data std::vector> primaryData[OP_BUTT]; std::vector field; + ChangeProperties properties; }; enum Origin : int32_t { @@ -49,6 +50,12 @@ enum Origin : int32_t { ORIGIN_ALL, ORIGIN_BUTT }; + +enum class CallbackDetailsType : uint32_t { + DEFAULT = 0x01, + BRIEF = 0x02, + DETAILED = DEFAULT | BRIEF +}; class StoreObserver { public: virtual ~StoreObserver() {} @@ -57,6 +64,11 @@ public: virtual void OnChange(const StoreChangedData &data) {}; virtual void OnChange(Origin origin, const std::string &originalId, ChangedData &&data) {}; + + virtual uint32_t GetCallbackDetailsType() const + { + return static_cast(CallbackDetailsType::DEFAULT); + } }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h index a6ac4bccb468b7f44c5eeed3ff5ad0b33bae7136..bb04ac60a7f174b0c35fbf883487341e1ce5e41a 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/include/store_types.h @@ -18,6 +18,7 @@ #include #include +#include #include #include "types_export.h" @@ -77,6 +78,8 @@ enum DBStatus { CLOUD_FULL_RECORDS, // cloud's record is full CLOUD_LOCK_ERROR, // cloud failed to get sync lock CLOUD_ASSET_SPACE_INSUFFICIENT, // cloud failed to download asset + PROPERTY_CHANGED, // reference property changed + CLOUD_VERSION_CONFLICT, // cloud failed to update version }; struct KvStoreConfig { @@ -102,6 +105,7 @@ enum PragmaCmd { SET_SYNC_RETRY, SET_MAX_LOG_LIMIT, EXEC_CHECKPOINT, + LOGIC_DELETE_SYNC_DATA, }; enum ResolutionPolicyType { @@ -179,5 +183,27 @@ struct RemoteCondition { std::vector bindArgs; // The bind args. }; using UpdateKeyCallback = std::function; + +struct TrackerSchema { + std::string tableName; + std::string extendColName; + std::set trackerColNames; +}; + +struct TableReferenceProperty { + std::string sourceTableName; + std::string targetTableName; + std::map columns; // key is sourceTable column, value is targetTable column +}; + +static constexpr const char *GAUSSDB_RD = "gaussdb_rd"; +static constexpr const char *SQLITE = "sqlite"; +struct ChangeProperties { + bool isTrackedDataChange = false; +}; + +struct Rdconfig { + bool readOnly = false; +}; } // namespace DistributedDB #endif // KV_STORE_TYPE_H diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp index 1d68d61b07ab8c1d5d46f29c6cd6929e48b68c7f..efed701757bcd3c87ab4f2edf113f8b515f6919f 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_delegate_manager.cpp @@ -32,6 +32,7 @@ #include "kvdb_manager.h" #include "kv_store_nb_delegate_impl.h" #include "network_adapter.h" +#include "rd_utils.h" #include "runtime_config.h" #include "runtime_context.h" #include "param_check_utils.h" @@ -84,7 +85,8 @@ namespace { const SchemaObject &schema, const KvStoreNbDelegate::Option &option) { properties.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, option.createIfNecessary); - properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + properties.SetIntProp(KvDBProperties::DATABASE_TYPE, option.storageEngineType == GAUSSDB_RD ? + KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL : KvDBProperties::SINGLE_VER_TYPE_SQLITE); properties.SetBoolProp(KvDBProperties::MEMORY_MODE, option.isMemoryDb); properties.SetBoolProp(KvDBProperties::ENCRYPTED_MODE, option.isEncryptedDb); if (!option.isMemoryDb) { // memory db ignore store path @@ -110,6 +112,8 @@ namespace { } properties.SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, option.syncDualTupleMode); properties.SetBoolProp(KvDBProperties::LOCAL_ONLY, option.localOnly); + properties.SetBoolProp(KvDBProperties::READ_ONLY_MODE, option.rdconfig.readOnly); + properties.SetBoolProp(KvDBProperties::SHARED_MODE, false); } bool CheckObserverConflictParam(const KvStoreNbDelegate::Option &option) @@ -134,7 +138,7 @@ namespace { properties.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, option.createIfNecessary); properties.SetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, option.createDirByStoreIdOnly); properties.SetIntProp(KvDBProperties::DATABASE_TYPE, - ((option.localOnly == true) ? KvDBProperties::LOCAL_TYPE : KvDBProperties::MULTI_VER_TYPE)); + ((option.localOnly == true) ? KvDBProperties::LOCAL_TYPE_SQLITE : KvDBProperties::MULTI_VER_TYPE_SQLITE)); properties.SetBoolProp(KvDBProperties::MEMORY_MODE, false); properties.SetBoolProp(KvDBProperties::ENCRYPTED_MODE, option.isEncryptedDb); properties.SetStringProp(KvDBProperties::DATA_DIR, storePath); @@ -250,6 +254,10 @@ bool KvStoreDelegateManager::GetKvStoreParamCheck(const std::string &storeId, co LOGE("[KvStoreMgr] Invalid callback for kv store"); return false; } + if (!CheckRdOption(option, callback)) { + LOGE("[KvStoreMgr] Unsupport option for RD mode"); + return false; + } if (!ParamCheckUtils::CheckStoreParameter(storeId, appId_, userId_) || (GetKvStorePath().empty() && !option.isMemoryDb)) { LOGE("[KvStoreMgr] Invalid id or path info for the store"); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp index 0c5c4b61dd2fccd18f222e406f3e1a593f1d98b3..a9bdade84394bb4dfc94fa50943e36564e76ac7b 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_errno.cpp @@ -75,6 +75,8 @@ namespace { { -E_CLOUD_FULL_RECORDS, CLOUD_FULL_RECORDS }, { -E_CLOUD_LOCK_ERROR, CLOUD_LOCK_ERROR }, { -E_CLOUD_ASSET_SPACE_INSUFFICIENT, CLOUD_ASSET_SPACE_INSUFFICIENT }, + { -E_TABLE_REFERENCE_CHANGED, PROPERTY_CHANGED }, + { -E_CLOUD_VERSION_CONFLICT, CLOUD_VERSION_CONFLICT }, }; } diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp index f40f259b1c62f5dc26beb7b71beb0d9757f1ad74..ca7ebcf63d336a419bd67d7c009671d0e4a5e148 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_nb_delegate_impl.cpp @@ -506,6 +506,7 @@ DBStatus KvStoreNbDelegateImpl::Sync(const std::vector &devices, Sy } if (!DBCommon::CheckQueryWithoutMultiTable(query)) { + LOGE("not support for invalid query"); return NOT_SUPPORT; } QuerySyncObject querySyncObj(query); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_result_set_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_result_set_impl.cpp index 0e4d114148768e4e3915e4e47b70c64821d9a7f0..cdbb0f20b494b311bc79695ee36ebc35c995dab5 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_result_set_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/kv_store_result_set_impl.cpp @@ -43,15 +43,13 @@ int KvStoreResultSetImpl::GetPosition() const bool KvStoreResultSetImpl::Move(int offset) { - int64_t position = GetPosition(); - int64_t aimPos = position + offset; - if (aimPos > INT_MAX) { - return MoveToPosition(INT_MAX); + if (resultSet_ == nullptr) { + return false; } - if (aimPos < INIT_POSITION) { - return MoveToPosition(INIT_POSITION); + if (resultSet_->Move(offset) == E_OK) { + return true; } - return MoveToPosition(aimPos); + return false; } bool KvStoreResultSetImpl::MoveToPosition(int position) @@ -67,12 +65,24 @@ bool KvStoreResultSetImpl::MoveToPosition(int position) bool KvStoreResultSetImpl::MoveToFirst() { - return MoveToPosition(0); + if (resultSet_ == nullptr) { + return false; + } + if (resultSet_->MoveToFirst() == E_OK) { + return true; + } + return false; } bool KvStoreResultSetImpl::MoveToLast() { - return MoveToPosition(GetCount() - 1); + if (resultSet_ == nullptr) { + return false; + } + if (resultSet_->MoveToLast() == E_OK) { + return true; + } + return false; } bool KvStoreResultSetImpl::MoveToNext() @@ -92,14 +102,7 @@ bool KvStoreResultSetImpl::IsFirst() const if (resultSet_ == nullptr) { return false; } - int position = resultSet_->GetPosition(); - if (GetCount() == 0) { - return false; - } - if (position == 0) { - return true; - } - return false; + return resultSet_->IsFirst(); } bool KvStoreResultSetImpl::IsLast() const @@ -107,15 +110,7 @@ bool KvStoreResultSetImpl::IsLast() const if (resultSet_ == nullptr) { return false; } - int position = resultSet_->GetPosition(); - int count = GetCount(); - if (count == 0) { - return false; - } - if (position == (count - 1)) { - return true; - } - return false; + return resultSet_->IsLast(); } bool KvStoreResultSetImpl::IsBeforeFirst() const @@ -123,15 +118,7 @@ bool KvStoreResultSetImpl::IsBeforeFirst() const if (resultSet_ == nullptr) { return false; } - int position = resultSet_->GetPosition(); - - if (GetCount() == 0) { - return true; - } - if (position <= INIT_POSITION) { - return true; - } - return false; + return resultSet_->IsBeforeFirst(); } bool KvStoreResultSetImpl::IsAfterLast() const @@ -139,15 +126,7 @@ bool KvStoreResultSetImpl::IsAfterLast() const if (resultSet_ == nullptr) { return false; } - int position = resultSet_->GetPosition(); - int count = GetCount(); - if (count == 0) { - return true; - } - if (position >= count) { - return true; - } - return false; + return resultSet_->IsAfterLast(); } DBStatus KvStoreResultSetImpl::GetEntry(Entry &entry) const @@ -155,9 +134,6 @@ DBStatus KvStoreResultSetImpl::GetEntry(Entry &entry) const if (resultSet_ == nullptr) { return DB_ERROR; } - if (GetCount() == 0) { - return NOT_FOUND; - } if (resultSet_->GetEntry(entry) == E_OK) { return OK; diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp index 400049cb59621f2ceecf5425ea00d41f47e36b51..a8fb13fdea9e0c9a941c89fa91084afdf55b0ed8 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.cpp @@ -47,20 +47,20 @@ DBStatus RelationalStoreDelegateImpl::RemoveDeviceDataInner(const std::string &d LOGE("Invalid mode for Remove device data, %d.", INVALID_ARGS); return INVALID_ARGS; } - if (mode == FLAG_ONLY || mode == FLAG_AND_DATA) { - if (conn_ == nullptr) { - LOGE("[RelationalStore Delegate] Invalid connection for operation!"); - return DB_ERROR; - } + if (mode == DEFAULT) { + return RemoveDeviceData(device, ""); + } + if (conn_ == nullptr) { + LOGE("[RelationalStore Delegate] Invalid connection for operation!"); + return DB_ERROR; + } - int errCode = conn_->DoClean(mode); - if (errCode != E_OK) { - LOGE("[RelationalStore Delegate] remove device cloud data failed:%d", errCode); - return TransferDBErrno(errCode); - } - return OK; + int errCode = conn_->DoClean(mode); + if (errCode != E_OK) { + LOGE("[RelationalStore Delegate] remove device cloud data failed:%d", errCode); + return TransferDBErrno(errCode); } - return RemoveDeviceData(device, ""); + return OK; } int32_t RelationalStoreDelegateImpl::GetCloudSyncTaskCount() @@ -252,10 +252,25 @@ DBStatus RelationalStoreDelegateImpl::SetCloudDB(const std::shared_ptr DBStatus RelationalStoreDelegateImpl::SetCloudDbSchema(const DataBaseSchema &schema) { - if (conn_ == nullptr || conn_->SetCloudDbSchema(schema) != E_OK) { + DataBaseSchema cloudSchema = schema; + for (auto &tableSchema : cloudSchema.tables) { + if (tableSchema.sharedTableName.empty()) { + tableSchema.sharedTableName = tableSchema.name + CloudDbConstant::SHARED; + } + } + if (!ParamCheckUtils::CheckSharedTableName(cloudSchema)) { + LOGE("[RelationalStore Delegate] SharedTableName check failed!"); + return INVALID_ARGS; + } + if (conn_ == nullptr) { return DB_ERROR; } - return OK; + // create shared table and set cloud db schema + int errorCode = conn_->PrepareAndSetCloudDbSchema(cloudSchema); + if (errorCode != E_OK) { + LOGE("[RelationalStore Delegate] set cloud schema failed!"); + } + return TransferDBErrno(errorCode); } DBStatus RelationalStoreDelegateImpl::RegisterObserver(StoreObserver *observer) @@ -330,5 +345,108 @@ DBStatus RelationalStoreDelegateImpl::Sync(const CloudSyncOption &option, const } return OK; } + +DBStatus RelationalStoreDelegateImpl::SetTrackerTable(const TrackerSchema &schema) +{ + if (conn_ == nullptr) { + LOGE("[RelationalStore Delegate] Invalid connection for operation!"); + return DB_ERROR; + } + if (schema.tableName.empty()) { + LOGE("[RelationalStore Delegate] tracker table is empty."); + return INVALID_ARGS; + } + if (!ParamCheckUtils::CheckRelationalTableName(schema.tableName)) { + LOGE("[RelationalStore Delegate] Invalid tracker table name."); + return INVALID_ARGS; + } + int errCode = conn_->SetTrackerTable(schema); + if (errCode != E_OK) { + LOGE("[RelationalStore Delegate] Set Subscribe table failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} + +DBStatus RelationalStoreDelegateImpl::ExecuteSql(const SqlCondition &condition, std::vector &records) +{ + if (conn_ == nullptr) { + LOGE("[RelationalStore Delegate] Invalid connection for operation!"); + return DB_ERROR; + } + int errCode = conn_->ExecuteSql(condition, records); + if (errCode != E_OK) { + LOGE("[RelationalStore Delegate] execute sql failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} + +DBStatus RelationalStoreDelegateImpl::SetReference(const std::vector &tableReferenceProperty) +{ + if (conn_ == nullptr) { + LOGE("[RelationalStore SetReference] Invalid connection for operation!"); + return DB_ERROR; + } + if (!ParamCheckUtils::CheckTableReference(tableReferenceProperty)) { + return INVALID_ARGS; + } + int errCode = conn_->SetReference(tableReferenceProperty); + if (errCode != E_OK) { + if (errCode != -E_TABLE_REFERENCE_CHANGED) { + LOGE("[RelationalStore] SetReference failed:%d", errCode); + } else { + LOGI("[RelationalStore] reference changed"); + } + return TransferDBErrno(errCode); + } + return OK; +} + +DBStatus RelationalStoreDelegateImpl::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + if (conn_ == nullptr) { + LOGE("[RelationalStore Delegate] Invalid connection for operation!"); + return DB_ERROR; + } + int errCode = conn_->CleanTrackerData(tableName, cursor); + if (errCode != E_OK) { + LOGE("[RelationalStore Delegate] clean tracker data failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} + +DBStatus RelationalStoreDelegateImpl::Pragma(PragmaCmd cmd, PragmaData &pragmaData) +{ + if (cmd != PragmaCmd::LOGIC_DELETE_SYNC_DATA) { + return NOT_SUPPORT; + } + if (conn_ == nullptr) { + LOGE("[RelationalStore Delegate] Invalid connection for operation!"); + return DB_ERROR; + } + int errCode = conn_->Pragma(cmd, pragmaData); + if (errCode != E_OK) { + LOGE("[RelationalStore Delegate] Pragma failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} + +DBStatus RelationalStoreDelegateImpl::UpsertData(RecordStatus status, const std::string &tableName, + const std::vector &records) +{ + if (conn_ == nullptr) { + LOGE("[RelationalStore Delegate] Invalid connection for operation!"); + return DB_ERROR; + } + int errCode = conn_->UpsertData(status, tableName, records); + if (errCode != E_OK) { + LOGE("[RelationalStore Delegate] Upsert data failed:%d", errCode); + return TransferDBErrno(errCode); + } + return OK; +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h index 5028d9366a79d4019209aeb99721fa0bb5d3fab1..ca13d51d2346d21297f238ec63f55e6edf3ddb31 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_delegate_impl.h @@ -66,6 +66,19 @@ public: DBStatus SetIAssetLoader(const std::shared_ptr &loader) override; DBStatus Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override; + + DBStatus SetTrackerTable(const TrackerSchema &schema) override; + + DBStatus ExecuteSql(const SqlCondition &condition, std::vector &records) override; + + DBStatus SetReference(const std::vector &tableReferenceProperty) override; + + DBStatus CleanTrackerData(const std::string &tableName, int64_t cursor) override; + + DBStatus Pragma(PragmaCmd cmd, PragmaData &pragmaData) override; + + DBStatus UpsertData(RecordStatus status, const std::string &tableName, + const std::vector &records) override; private: static void OnSyncComplete(const std::map> &devicesStatus, const SyncStatusCallback &onComplete); diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp index b3886e8709f2cadf7e5cf058fc2f8aa2eeb78094..036602af378360f797bb9c153a1b22172122ef17 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_manager.cpp @@ -114,7 +114,16 @@ DB_API DBStatus RelationalStoreManager::OpenStore(const std::string &path, const conn->Close(); return DB_ERROR; } - return option.observer != nullptr ? delegate->RegisterObserver(option.observer) : OK; + + if (option.observer == nullptr) { + return OK; + } + DBStatus status = delegate->RegisterObserver(option.observer); + if (status != OK) { + LOGE("register observer failed when open store: %d", status); + conn->Close(); + } + return status; } DBStatus RelationalStoreManager::CloseStore(RelationalStoreDelegate *store) diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp index e024055aa69146e2001d0fc1ec17b9ff8e1a819f..9e222dabedadb78fb24bcd6687441bf7f88936a6 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_store_sqlite_ext.cpp @@ -20,9 +20,11 @@ #include #include "db_common.h" +#include "kv_store_errno.h" #include "platform_specific.h" #include "relational_store_client.h" #include "runtime_context.h" +#include "sqlite_utils.h" // using the "sqlite3sym.h" in OHOS #ifndef USE_SQLITE_SYMBOLS @@ -49,6 +51,10 @@ #error "PLATFORM NOT SPECIFIED!" #endif +#ifdef DB_DEBUG_ENV +#include "system_time.h" +using namespace DistributedDB::OS; +#endif using namespace DistributedDB; namespace { @@ -56,7 +62,7 @@ constexpr int E_OK = 0; constexpr int E_ERROR = 1; constexpr int STR_TO_LL_BY_DEVALUE = 10; constexpr int BUSY_TIMEOUT = 2000; // 2s. -const int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit +constexpr int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit const std::string DEVICE_TYPE = "device"; const std::string SYNC_TABLE_TYPE = "sync_table_type_"; class ValueHashCalc { @@ -130,6 +136,7 @@ public: static constexpr uint64_t MULTIPLES_BETWEEN_SECONDS_AND_MICROSECONDS = 1000000; static constexpr int64_t MAX_NOISE = 9 * 100 * 1000; // 900ms + static constexpr uint64_t MAX_INC_COUNT = 9; // last bit from 0-9 static int GetSysCurrentRawTime(uint64_t &curTime) @@ -166,13 +173,13 @@ public: if (getDbLocalTimeOffset != nullptr) { localTimeOffset_ = getDbLocalTimeOffset(); } - LOGD("First use time helper with maxTimestamp:%" PRIu64 " localTimeOffset:%" PRIu64, lastLocalTime_, - localTimeOffset_); + LOGD("Use time helper with maxTimestamp:%" PRIu64 " localTimeOffset:%" PRIu64 " first time", lastLocalTime_, + localTimeOffset_); isLoaded_ = true; } - Timestamp currentSystemTime; + Timestamp currentSystemTime = 0u; (void)GetCurrentSysTimeInMicrosecond(currentSystemTime); - Timestamp currentMonotonicTime; + Timestamp currentMonotonicTime = 0u; (void)OS::GetMonotonicRelativeTimeInMicrosecond(currentMonotonicTime); auto deltaTime = static_cast(currentMonotonicTime - lastMonotonicTime_); Timestamp currentSysTime = GetSysCurrentTime(); @@ -194,9 +201,9 @@ public: bool TimeSkew(const std::function &getLocalTimeOffsetFromDB, Timestamp timeOffset) { - Timestamp currentSystemTime; + Timestamp currentSystemTime = 0u; (void)GetCurrentSysTimeInMicrosecond(currentSystemTime); - Timestamp currentMonotonicTime; + Timestamp currentMonotonicTime = 0u; (void)OS::GetMonotonicRelativeTimeInMicrosecond(currentMonotonicTime); auto systemTimeOffset = static_cast(currentSystemTime - lastSystemTime_); @@ -213,7 +220,7 @@ public: localTimeOffset_ = static_cast(static_cast(localTimeOffset_) - (systemTimeOffset - monotonicTimeOffset) * static_cast(TO_100_NS)); LOGD("Save ext local time offset: %" PRIu64 ", changedOffset: %" PRId64, localTimeOffset_, - changedOffset); + changedOffset); } else { localTimeOffset_ = localTimeOffset; LOGD("Save ext local time offset: %" PRIu64, localTimeOffset_); @@ -252,6 +259,7 @@ public: return (curTime * TO_100_NS) + currentIncCount_; // Currently Timestamp is uint64_t } +#ifndef DB_DEBUG_ENV static int GetCurrentSysTimeInMicrosecond(uint64_t &outTime) { struct timeval rawTime; @@ -263,6 +271,7 @@ public: static_cast(rawTime.tv_usec); return E_OK; } +#endif static std::mutex systemTimeLock_; static Timestamp lastSystemTimeUs_; @@ -468,7 +477,7 @@ int GetLocalTimeOffsetFromMeta(sqlite3 *db, TimeOffset &offset) sqlite3_stmt *stmt = nullptr; int errCode = GetStatement(db, "SELECT value FROM naturalbase_rdb_aux_metadata WHERE key = ?", stmt); if (errCode != E_OK) { - LOGE("Prepare mate data stmt failed. %d", errCode); + LOGE("Prepare meta data stmt failed. %d", errCode); return -E_ERROR; } @@ -601,7 +610,7 @@ static bool GetDbFileName(sqlite3 *db, std::string &fileName) void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv) { - if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 is param counts + if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts return; } sqlite3 *db = static_cast(sqlite3_user_data(ctx)); @@ -619,6 +628,8 @@ void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **ar return; } std::string tableName = static_cast(tableNameChar); + + uint64_t isTrackerChange = static_cast(sqlite3_value_int(argv[3])); // 3 is param index bool isExistObserver = false; { std::lock_guard lock(g_clientObserverMutex); @@ -628,15 +639,21 @@ void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **ar { std::lock_guard lock(g_clientChangedDataMutex); if (isExistObserver) { - g_clientChangedDataMap[hashFileName].tableNames.insert(tableName); + auto itTable = g_clientChangedDataMap[hashFileName].tableData.find(tableName); + if (itTable != g_clientChangedDataMap[hashFileName].tableData.end()) { + itTable->second.isTrackedDataChange = + (static_cast(itTable->second.isTrackedDataChange) | isTrackerChange) > 0; + } else { + DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) }; + g_clientChangedDataMap[hashFileName].tableData.insert_or_assign(tableName, properties); + } } } sqlite3_result_int64(ctx, static_cast(1)); } -int CommitHookCallback(void *data) +int LogCommitHookCallback(void *data, sqlite3 *db, const char *zDb, int size) { - sqlite3 *db = static_cast(data); std::string fileName; if (!GetDbFileName(db, fileName)) { return 0; @@ -658,13 +675,13 @@ int CommitHookCallback(void *data) } std::lock_guard clientChangedDataLock(g_clientChangedDataMutex); auto it = g_clientChangedDataMap.find(hashFileName); - if (it != g_clientChangedDataMap.end() && !it->second.tableNames.empty()) { + if (it != g_clientChangedDataMap.end() && !it->second.tableData.empty()) { ClientChangedData clientChangedData = g_clientChangedDataMap[hashFileName]; - errCode = DistributedDB::RuntimeContext::GetInstance()->ScheduleTask([clientObserver, clientChangedData] { + (void)DistributedDB::RuntimeContext::GetInstance()->ScheduleTask([clientObserver, clientChangedData] { ClientChangedData taskClientChangedData = clientChangedData; clientObserver(taskClientChangedData); }); - g_clientChangedDataMap[hashFileName].tableNames.clear(); + g_clientChangedDataMap[hashFileName].tableData.clear(); } return 0; } @@ -683,8 +700,8 @@ void RollbackHookCallback(void* data) } std::lock_guard clientChangedDataLock(g_clientChangedDataMutex); auto it = g_clientChangedDataMap.find(hashFileName); - if (it != g_clientChangedDataMap.end() && !it->second.tableNames.empty()) { - g_clientChangedDataMap[hashFileName].tableNames.clear(); + if (it != g_clientChangedDataMap.end() && !it->second.tableData.empty()) { + g_clientChangedDataMap[hashFileName].tableData.clear(); } } @@ -713,12 +730,12 @@ int RegisterCloudDataChangeObserver(sqlite3 *db) { TransactFunc func; func.xFunc = &CloudDataChangedObserver; - return RegisterFunction(db, "client_observer", 3, db, func); // 3 is param counts + return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts } void RegisterCommitAndRollbackHook(sqlite3 *db) { - sqlite3_commit_hook(db, CommitHookCallback, db); + sqlite3_wal_hook(db, LogCommitHookCallback, db); sqlite3_rollback_hook(db, RollbackHookCallback, db); } @@ -839,13 +856,13 @@ int GetCurrentMaxTimestamp(sqlite3 *db, Timestamp &maxTimestamp) ResetStatement(checkTableStmt); return -E_ERROR; } - std::string logTablename; - GetColumnTextValue(checkTableStmt, 0, logTablename); - if (logTablename.empty()) { + std::string logTableName; + GetColumnTextValue(checkTableStmt, 0, logTableName); + if (logTableName.empty()) { continue; } - std::string getMaxTimestampSql = "SELECT MAX(timestamp) FROM " + logTablename + ";"; + std::string getMaxTimestampSql = "SELECT MAX(timestamp) FROM " + logTableName + ";"; sqlite3_stmt *getTimeStmt = nullptr; errCode = GetStatement(db, getMaxTimestampSql, getTimeStmt); if (errCode != E_OK) { @@ -878,7 +895,6 @@ bool CheckTableExists(sqlite3 *db, const std::string &tableName) isLogTblExists = true; } (void)sqlite3_finalize(stmt); - stmt = nullptr; return isLogTblExists; } @@ -942,6 +958,39 @@ void HandleDropCloudSyncTable(sqlite3 *db, const std::string &tableName) (void)sqlite3_finalize(statement); } +int HandleDropLogicDeleteData(sqlite3 *db, const std::string &tableName, uint64_t cursor) +{ + std::string logTblName = DBCommon::GetLogTableName(tableName); + std::string sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" + + " VALUES ('log_trigger_switch', 'false')"; + int errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("close log_trigger_switch failed. %d", errCode); + return errCode; + } + sql = "DELETE FROM " + tableName + " WHERE _rowid_ IN (SELECT data_key FROM " + logTblName + " WHERE " + " flag&0x08=0x08" + (cursor == 0 ? ");" : " AND cursor <= '" + std::to_string(cursor) + "');"); + errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("delete logic deletedData failed. %d", errCode); + return errCode; + } + sql = "UPDATE " + logTblName + " SET data_key = -1, flag = (flag & ~0x08) | 0x01 WHERE flag&0x08=0x08" + + (cursor == 0 ? ";" : " AND cursor <= '" + std::to_string(cursor) + "';"); + errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("update logic deletedData failed. %d", errCode); + return errCode; + } + sql = "INSERT OR REPLACE INTO " + DBConstant::RELATIONAL_PREFIX + "metadata" + + " VALUES ('log_trigger_switch', 'true')"; + errCode = sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); + if (errCode != SQLITE_OK) { + LOGE("open log_trigger_switch failed. %d", errCode); + } + return errCode; +} + int SaveDeleteFlagToDB(sqlite3 *db, const std::string &tableName) { std::string keyStr = DBConstant::TABLE_IS_DROPPED + tableName; @@ -949,12 +998,11 @@ int SaveDeleteFlagToDB(sqlite3 *db, const std::string &tableName) DBCommon::StringToVector(keyStr, key); Value value; DBCommon::StringToVector("1", value); // 1 means delete - std::string sql = "insert or replace into naturalbase_rdb_aux_metadata values(?, ?);"; + std::string sql = "INSERT OR REPLACE INTO naturalbase_rdb_aux_metadata VALUES(?, ?);"; sqlite3_stmt *statement = nullptr; int errCode = sqlite3_prepare_v2(db, sql.c_str(), -1, &statement, nullptr); if (errCode != SQLITE_OK) { LOGE("[SaveDeleteFlagToDB] prepare statement failed, %d", errCode); - (void)ResetStatement(statement); return -E_ERROR; } @@ -1005,7 +1053,7 @@ void ClearTheLogAfterDropTable(sqlite3 *db, const char *tableName, const char *s if (tableType == DEVICE_TYPE) { RegisterGetSysTime(db); RegisterGetLastTime(db); - std::string sql = "UPDATE " + logTblName + " SET flag=0x03, timestamp=get_sys_time(0) " + std::string sql = "UPDATE " + logTblName + " SET data_key=-1, flag=0x03, timestamp=get_sys_time(0) " "WHERE flag&0x03=0x02 AND timestamp<" + std::to_string(dropTimeStamp); (void)sqlite3_exec(db, sql.c_str(), nullptr, nullptr, nullptr); } else { @@ -1117,6 +1165,35 @@ DB_API DistributedDB::DBStatus UnRegisterClientObserver(sqlite3 *db) return DistributedDB::OK; } +DB_API DistributedDB::DBStatus DropLogicDeletedData(sqlite3 *db, const std::string &tableName, uint64_t cursor) +{ + std::string fileName; + if (!GetDbFileName(db, fileName)) { + return DistributedDB::INVALID_ARGS; + } + if (tableName.empty()) { + return DistributedDB::INVALID_ARGS; + } + int errCode = SQLiteUtils::BeginTransaction(db, TransactType::IMMEDIATE); + if (errCode != DistributedDB::E_OK) { + LOGE("begin transaction failed before drop logic deleted data. %d", errCode); + return DistributedDB::TransferDBErrno(errCode); + } + errCode = HandleDropLogicDeleteData(db, tableName, cursor); + if (errCode != SQLITE_OK) { + int ret = SQLiteUtils::RollbackTransaction(db); + if (ret != DistributedDB::E_OK) { + LOGE("rollback failed when drop logic deleted data. %d", ret); + } + return DistributedDB::TransferDBErrno(errCode); + } + int ret = SQLiteUtils::CommitTransaction(db); + if (ret != DistributedDB::E_OK) { + LOGE("commit failed when drop logic deleted data. %d", ret); + } + return ret == DistributedDB::E_OK ? DistributedDB::OK : DistributedDB::TransferDBErrno(ret); +} + // hw export the symbols #ifdef SQLITE_DISTRIBUTE_RELATIONAL #if defined(__GNUC__) diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h index a5a2c46a8e7ec64a91a7fd6049724b0c547c3c4c..bfa37c1542fecb91d941626a7dc96dfe14337c4b 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/relational/relational_sync_able_storage.h @@ -61,6 +61,8 @@ public: // Put meta data as a key-value entry. int PutMetaData(const Key &key, const Value &value) override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; + // Delete multiple meta data records in a transaction. int DeleteMetaData(const std::vector &keys) override; @@ -128,6 +130,9 @@ public: void ReleaseRemoteQueryContinueToken(ContinueToken &token) const override; + // recycling the write handle + void SetReusedHandle(StorageExecutor *handle); + int StartTransaction(TransactType type) override; int Commit() override; @@ -137,8 +142,6 @@ public: int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, int64_t &count) override; - int FillCloudGid(const CloudSyncData &data) override; - int GetCloudData(const TableSchema &tableSchema, const QuerySyncObject &object, const Timestamp &beginTime, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) override; @@ -153,7 +156,7 @@ public: int SetCloudDbSchema(const DataBaseSchema &schema) override; - int GetCloudDbSchema(DataBaseSchema &cloudSchema) override; + int GetCloudDbSchema(std::shared_ptr &cloudSchema) override; int GetCloudTableSchema(const TableName &tableName, TableSchema &tableSchema) override; @@ -169,7 +172,7 @@ public: int SetLogTriggerStatus(bool status) override; - int FillCloudGidAndAsset(OpType opType, const CloudSyncData &data) override; + int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) override; void SetSyncAbleEngine(std::shared_ptr syncAbleEngine); @@ -179,7 +182,34 @@ public: void ReleaseContinueToken(ContinueToken &continueStmtToken) const override; + int GetCloudDataGid(const QuerySyncObject &query, Timestamp beginTime, std::vector &gid) override; + int CheckQueryValid(const QuerySyncObject &query) override; + + int CreateTempSyncTrigger(const std::string &tableName) override; + int GetAndResetServerObserverData(const std::string &tableName, ChangeProperties &changeProperties) override; + int ClearAllTempSyncTrigger() override; + bool IsSharedTable(const std::string &tableName) override; + + std::map GetSharedTableOriginNames(); + + void SetLogicDelete(bool logicDelete); + + void SetCloudTaskConfig(const CloudTaskConfig &config) override; + + int GetAssetsByGidOrHashKey(const TableSchema &tableSchema, const std::string &gid, const Bytes &hashKey, + VBucket &assets) override; + + int SetIAssetLoader(const std::shared_ptr &loader) override; +protected: + int FillReferenceData(CloudSyncData &syncData); + + virtual int GetReferenceGid(const std::string &tableName, const CloudSyncBatch &syncBatch, + std::map &referenceGid); + + static int FillReferenceDataIntoExtend(const std::vector &rowid, + const std::map &referenceGid, std::vector &extend); + private: SQLiteSingleVerRelationalStorageExecutor *GetHandle(bool isWrite, int &errCode, OperatePerm perm = OperatePerm::NORMAL_PERM) const; @@ -193,10 +223,19 @@ private: int GetRemoteQueryData(const PreparedStmt &prepStmt, size_t packetSize, std::vector &colNames, std::vector &data) const; + int GetTableReference(const std::string &tableName, + std::map> &reference); + + std::pair GetSourceTableName(const std::string &tableName); + + std::pair GetSharedTargetTableName(const std::string &tableName); // put int PutSyncData(const QueryObject &object, std::vector &dataItems, const std::string &deviceName); int SaveSyncDataItems(const QueryObject &object, std::vector &dataItems, const std::string &deviceName); + void FilterChangeDataByDetailsType(ChangedData &changedData, uint32_t type); + StoreInfo GetStoreInfo() const; + bool IsCurrentLogicDelete() const; // data std::shared_ptr storageEngine_ = nullptr; std::function onSchemaChanged_; @@ -207,6 +246,8 @@ private: mutable std::mutex heartBeatMutex_; LruMap remoteDeviceSchema_; + StorageExecutor *reusedHandle_; + mutable std::mutex reusedHandleMutex_; // cache securityOption mutable std::mutex securityOptionMutex_; @@ -219,6 +260,9 @@ private: SchemaMgr schemaMgr_; mutable std::shared_mutex schemaMgrMutex_; std::shared_ptr syncAbleEngine_ = nullptr; + + std::atomic logicDelete_ = false; + std::atomic allowLogicDelete_ = false; }; } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp b/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp index 3c5a314585c8df79c7ffe75c835d4f8e86b2972a..092c58f9b57fb9668082b6f5dc7446136f156753 100644 --- a/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp +++ b/kv_store/frameworks/libs/distributeddb/interfaces/src/runtime_config.cpp @@ -80,14 +80,12 @@ DBStatus RuntimeConfig::SetProcessCommunicator(const std::shared_ptrSetPermissionCheckCallback(callback); - return TransferDBErrno(errCode); + return TransferDBErrno(RuntimeContext::GetInstance()->SetPermissionCheckCallback(callback)); } DBStatus RuntimeConfig::SetPermissionCheckCallback(const PermissionCheckCallbackV3 &callback) { - int errCode = RuntimeContext::GetInstance()->SetPermissionCheckCallback(callback); - return TransferDBErrno(errCode); + return TransferDBErrno(RuntimeContext::GetInstance()->SetPermissionCheckCallback(callback)); } DBStatus RuntimeConfig::SetProcessSystemAPIAdapter(const std::shared_ptr &adapter) @@ -103,15 +101,13 @@ void RuntimeConfig::Dump(int fd, const std::vector &args) DBStatus RuntimeConfig::SetSyncActivationCheckCallback(const SyncActivationCheckCallback &callback) { std::lock_guard lock(multiUserMutex_); - int errCode = RuntimeContext::GetInstance()->SetSyncActivationCheckCallback(callback); - return TransferDBErrno(errCode); + return TransferDBErrno(RuntimeContext::GetInstance()->SetSyncActivationCheckCallback(callback)); } DBStatus RuntimeConfig::NotifyUserChanged() { std::lock_guard lock(multiUserMutex_); - int errCode = RuntimeContext::GetInstance()->NotifyUserChanged(); - return TransferDBErrno(errCode); + return TransferDBErrno(RuntimeContext::GetInstance()->NotifyUserChanged()); } bool RuntimeConfig::IsProcessSystemApiAdapterValid() @@ -122,14 +118,12 @@ bool RuntimeConfig::IsProcessSystemApiAdapterValid() DBStatus RuntimeConfig::SetSyncActivationCheckCallback(const SyncActivationCheckCallbackV2 &callback) { std::lock_guard lock(multiUserMutex_); - int errCode = RuntimeContext::GetInstance()->SetSyncActivationCheckCallback(callback); - return TransferDBErrno(errCode); + return TransferDBErrno(RuntimeContext::GetInstance()->SetSyncActivationCheckCallback(callback)); } DBStatus RuntimeConfig::SetPermissionConditionCallback(const PermissionConditionCallback &callback) { - int errCode = RuntimeContext::GetInstance()->SetPermissionConditionCallback(callback); - return TransferDBErrno(errCode); + return TransferDBErrno(RuntimeContext::GetInstance()->SetPermissionConditionCallback(callback)); } void RuntimeConfig::SetTranslateToDeviceIdCallback(const DistributedDB::TranslateToDeviceIdCallback &callback) diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_meta_data.h b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_meta_data.h index 28b316e9c7847f726122b7c18ae16e38686966fe..1338082aaa3b47290b9140be1d7c553688499f31 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_meta_data.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_meta_data.h @@ -40,6 +40,7 @@ public: int CleanWaterMark(const TableName &tableName); + void CleanWaterMarkInMemory(const TableName &tableName); private: typedef struct CloudMetaValue { Timestamp localMark = 0u; @@ -48,9 +49,7 @@ private: int ReadMarkFromMeta(const TableName &tableName); int WriteMarkToMeta(const TableName &tableName, Timestamp localmark, std::string &cloudMark); - int SerializeMark(const Timestamp localMark, const std::string &cloudMark, Value &blobMeta); int DeserializeMark(Value &blobMark, CloudMetaValue &cloudMetaValue); - Key GetPrefixTableName(const TableName &tableName); mutable std::mutex cloudMetaMutex_; std::unordered_map cloudMetaVals_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h index 0f52100f1151d807ca27af27a6376d5eb2b87b1b..2fda45481f2bdac5b85a15257fb6bff368c78bce 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/cloud_storage_utils.h @@ -16,7 +16,9 @@ #ifndef CLOUD_STORAGE_UTILS_H #define CLOUD_STORAGE_UTILS_H +#include "cloud/asset_operation_utils.h" #include "cloud/cloud_store_types.h" +#include "icloud_sync_storage_interface.h" #include "sqlite_utils.h" namespace DistributedDB { @@ -46,7 +48,7 @@ public: std::vector &value); static std::set GetCloudPrimaryKey(const TableSchema &tableSchema); - static std::vector GetCloudPrimaryKeyField(const TableSchema &tableSchema); + static std::vector GetCloudPrimaryKeyField(const TableSchema &tableSchema, bool sortByName = false); static std::map GetCloudPrimaryKeyFieldMap(const TableSchema &tableSchema, bool sortByUpper = false); static bool IsContainsPrimaryKey(const TableSchema &tableSchema); @@ -59,14 +61,29 @@ public: static void ChangeAssetsOnVBucketToAsset(VBucket &vBucket, std::vector &fields); static Type GetAssetFromAssets(Type &value); static void FillAssetBeforeDownload(Asset &asset); - static void FillAssetAfterDownloadFail(Asset &asset); - static int FillAssetAfterDownload(Asset &asset); - static void FillAssetsAfterDownload(Assets &assets); - static int FillAssetForUpload(Asset &asset); - static void FillAssetsForUpload(Assets &assets); + static int FillAssetAfterDownloadFail(Asset &asset, Asset &dbAsset, AssetOperationUtils::AssetOpType assetOpType); + static void FillAssetsAfterDownloadFail(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap); + static void MergeAssetWithFillFunc(Assets &assets, Assets &dbAssets, const std::map &assetOpTypeMap, + std::function fillAsset); + static int FillAssetAfterDownload(Asset &asset, Asset &dbAsset, AssetOperationUtils::AssetOpType assetOpType); + static void FillAssetsAfterDownload(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap); + static int FillAssetBeforeUpload(Asset &asset, Asset &dbAsset, AssetOperationUtils::AssetOpType assetOpType); + static void FillAssetsBeforeUpload(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap); + static int FillAssetForUpload(Asset &asset, Asset &dbAsset, AssetOperationUtils::AssetOpType assetOpType); + static void FillAssetsForUpload(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap); + static int FillAssetForUploadFailed(Asset &asset, Asset &dbAsset, AssetOperationUtils::AssetOpType assetOpType); + static void FillAssetsForUploadFailed(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap); static void PrepareToFillAssetFromVBucket(VBucket &vBucket, std::function fillAsset); - static void FillAssetFromVBucketFinish(VBucket &vBucket, std::function fillAsset, - std::function fillAssets); + static void FillAssetFromVBucketFinish(const AssetOperationUtils::RecordAssetOpType &assetOpType, VBucket &vBucket, + VBucket &dbAssets, std::function fillAsset, + std::function &)> fillAssets); static bool IsAsset(const Type &type); static bool IsAssets(const Type &type); static bool IsAssetsContainDuplicateAsset(Assets &assets); @@ -78,6 +95,12 @@ public: static bool CheckAssetStatus(const Assets &assets); static int ConstraintsCheckForCloud(const TableInfo &table, const std::string &trimmedSql); + static std::string GetTableRefUpdateSql(const TableInfo &table, OpType opType); + static std::string GetLeftJoinLogSql(const std::string &tableName, bool logAsTableA = true); + + static bool ChkFillCloudAssetParam(const CloudSyncBatch &data, int errCode); + static void GetToBeRemoveAssets(const VBucket &vBucket, const AssetOperationUtils::RecordAssetOpType &assetOpType, + std::vector &removeAssets); template static int GetValueFromOneField(Type &cloudValue, T &outVal) @@ -95,7 +118,6 @@ public: static int GetValueFromVBucket(const std::string &fieldName, const VBucket &vBucket, T &outVal) { if (vBucket.find(fieldName) == vBucket.end()) { - LOGW("vbucket doesn't contains the field want to get"); return -E_NOT_FOUND; } Type cloudValue = vBucket.at(fieldName); diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h index c9fada101f1b89dedb673422f7591b6c38e6f2d9..b21e0b861ce45c0280a00fb70c33c8387b73fe74 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/cloud/schema_mgr.h @@ -32,6 +32,8 @@ public: std::shared_ptr GetCloudDbSchema(); int GetCloudTableSchema(const TableName &tableName, TableSchema &retSchema); int ChkSchema(const TableName &tableName, RelationalSchemaObject &localSchema); + bool IsSharedTable(const std::string &tableName); + std::map GetSharedTableOriginNames(); private: bool IsAssetPrimaryField(const Field &cloudField); @@ -41,6 +43,7 @@ private: int CompareFieldSchema(std::map &primaryKeys, FieldInfoMap &localFields, std::vector &cloudFields); std::shared_ptr cloudSchema_ = nullptr; + std::map sharedTableMap_; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h index cdd1c9593ff3ef39a3431399594496fe11a2c212..970bfd2ba918046d76a91fae0075cb3b3f798c9c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/icloud_sync_storage_interface.h @@ -17,6 +17,7 @@ #define ICLOUD_SYNC_STORAGE_INTERFACE_H #include "cloud/cloud_db_types.h" +#include "cloud/iAssetLoader.h" #include "data_transformer.h" #include "query_sync_object.h" #include "sqlite_utils.h" @@ -34,12 +35,15 @@ enum class OpType : uint8_t { SET_CLOUD_FORCE_PUSH_FLAG_ZERO, UPDATE_TIMESTAMP, CLEAR_GID, + UPDATE_VERSION, + SET_UPLOADING, NOT_HANDLE }; typedef struct DownloadData { std::vector data; std::vector opType; + std::vector existDataKey; } DownloadData; class ICloudSyncStorageInterface { @@ -55,7 +59,7 @@ public: virtual int SetCloudDbSchema(const DataBaseSchema &schema) = 0; - virtual int GetCloudDbSchema(DataBaseSchema &cloudSchema) = 0; + virtual int GetCloudDbSchema(std::shared_ptr &cloudSchema) = 0; virtual int GetCloudTableSchema(const TableName &tableName, TableSchema &tableSchema) = 0; @@ -68,8 +72,6 @@ public: virtual int GetUploadCount(const QuerySyncObject &query, const Timestamp ×tamp, bool isCloudForcePush, int64_t &count) = 0; - virtual int FillCloudGid(const CloudSyncData &data) = 0; - virtual int GetCloudData(const TableSchema &tableSchema, const QuerySyncObject &object, const Timestamp &beginTime, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) = 0; @@ -95,11 +97,46 @@ public: virtual int SetLogTriggerStatus(bool status) = 0; - virtual int FillCloudGidAndAsset(OpType opType, const CloudSyncData &data) = 0; + virtual int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid) = 0; virtual std::string GetIdentify() const = 0; + virtual int GetCloudDataGid(const QuerySyncObject &query, Timestamp beginTime, + std::vector &gid) = 0; + virtual int CheckQueryValid(const QuerySyncObject &query) = 0; + + virtual int CreateTempSyncTrigger(const std::string &tableName) + { + return E_OK; + } + + virtual int GetAndResetServerObserverData(const std::string &tableName, ChangeProperties &changeProperties) + { + return E_OK; + } + + virtual int ClearAllTempSyncTrigger() + { + return E_OK; + } + + virtual bool IsSharedTable(const std::string &tableName) = 0; + + virtual void SetCloudTaskConfig([[gnu::unused]] const CloudTaskConfig &config) + { + } + + virtual int GetAssetsByGidOrHashKey(const TableSchema &tableSchema, const std::string &gid, const Bytes &hashKey, + VBucket &assets) + { + return E_OK; + } + + virtual int SetIAssetLoader([[gnu::unused]] const std::shared_ptr &loader) + { + return E_OK; + } }; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_factory.h b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_factory.h index 66c2c619fde69bdd9e9b48b253521dc00e99e2c8..98996196ff3e1b11347c4705500c3b603f0acdf6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_factory.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_factory.h @@ -27,12 +27,13 @@ namespace DistributedDB { enum KvDBType { - LOCAL_KVDB = 0, - SINGER_VER_KVDB, + LOCAL_KVDB_SQLITE = 0, + SINGER_VER_KVDB_SQLITE, + SINGLE_VER_KVDB_RD, #ifndef OMIT_MULTI_VER - MULTI_VER_KVDB, + MULTI_VER_KVDB_SQLITE, #endif // OMIT_MULTI_VER - UNSUPPORT_KVDB_TYPE = 3, + UNSUPPORT_KVDB_TYPE = 4, }; class IKvDBFactory { diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_result_set.h b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_result_set.h index b0aa5de38b2e47e3cd182b6ee7cd4e1866237c98..92f22fba1106909a0d46fb465751ea7a9939208a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_result_set.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/ikvdb_result_set.h @@ -20,6 +20,14 @@ #include "db_types.h" namespace DistributedDB { + +enum class ResultSetType : int { + KEYPREFIX = 0, + QUERY = 1, +}; + +constexpr int INIT_POSITION = -1; + class IKvDBResultSet { public: IKvDBResultSet() = default; @@ -38,14 +46,28 @@ public: // >= 0: position, < 0: errCode virtual int GetPosition() const = 0; + virtual int Move(int offset) const = 0; + // Move the read position to an absolute position value. virtual int MoveTo(int position) const = 0; + virtual int MoveToFirst() = 0; + + virtual int MoveToLast() = 0; + + virtual bool IsFirst() const = 0; + + virtual bool IsLast() const = 0; + + virtual bool IsBeforeFirst() const = 0; + + virtual bool IsAfterLast() const = 0; + // Get the entry of current position. virtual int GetEntry(Entry &entry) const = 0; // Finalize logic - virtual void Close() = 0; + virtual int Close() = 0; }; } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h index 9bf95083e9c101c54d3c95d4480eef19f1dc4d6a..4cabb6b10131f148cb8f5616d956251f438b173c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/isync_interface.h @@ -55,7 +55,7 @@ public: virtual int GetMetaData(const Key &key, Value &value) const = 0; // Put meta data as a key-value entry. - virtual int PutMetaData(const Key &key, const Value &value) = 0; + virtual int PutMetaData(const Key &key, const Value &value, bool isInTransaction) = 0; // Delete multiple meta data records in a transaction. virtual int DeleteMetaData(const std::vector &keys) = 0; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h index 1f8749eab590579d1cc492bcecfafa1330e1587e..81381c5ec87a271644a5882adc1b3dd6ea8134f4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/kvdb_properties.h @@ -68,9 +68,13 @@ public: static const std::string COMPRESSION_RATE; static const std::string LOCAL_ONLY; - static const int LOCAL_TYPE = 1; - static const int MULTI_VER_TYPE = 2; - static const int SINGLE_VER_TYPE = 3; + static const std::string SHARED_MODE; + static const std::string READ_ONLY_MODE; + + static const int LOCAL_TYPE_SQLITE = 1; + static const int MULTI_VER_TYPE_SQLITE = 2; + static const int SINGLE_VER_TYPE_SQLITE = 3; + static const int SINGLE_VER_TYPE_RD_KERNAL = 4; private: CipherType cipherType_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h index c4b44b26bb5fc507d63ec3b2903baa136b91f4cc..fe812ae3bb2f1c2d622f460487f1e68c015f2e8b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/relational_store_connection.h @@ -64,13 +64,22 @@ public: virtual int RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, std::shared_ptr &result) = 0; virtual int SetCloudDB(const std::shared_ptr &cloudDb) = 0; - virtual int SetCloudDbSchema(const DataBaseSchema &schema) = 0; + virtual int PrepareAndSetCloudDbSchema(const DataBaseSchema &schema) = 0; virtual int SetIAssetLoader(const std::shared_ptr &loader) = 0; virtual int Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) = 0; virtual int GetStoreInfo(std::string &userId, std::string &appId, std::string &storeId) = 0; + virtual int SetTrackerTable(const TrackerSchema &schema) = 0; + virtual int ExecuteSql(const SqlCondition &condition, std::vector &records) = 0; + virtual int CleanTrackerData(const std::string &tableName, int64_t cursor) = 0; + + virtual int SetReference(const std::vector &tableReferenceProperty) = 0; + + virtual int Pragma(PragmaCmd cmd, PragmaData &pragmaData) = 0; + + virtual int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records) = 0; protected: // Get the stashed 'RelationalDB_ pointer' without ref. template diff --git a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h index 331bfff2e7da5c0b26c06e5f01d6d216419f83d1..5041875133038a42b3962d356c7b6ce05a9a1e31 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h +++ b/kv_store/frameworks/libs/distributeddb/storage/include/storage_proxy.h @@ -22,6 +22,7 @@ #include "cloud/cloud_store_types.h" #include "cloud/cloud_meta_data.h" #include "cloud/cloud_db_constant.h" +#include "cloud/iAssetLoader.h" #include "cloud/schema_mgr.h" #include "data_transformer.h" #include "icloud_sync_storage_interface.h" @@ -45,7 +46,7 @@ public: int GetCloudWaterMark(const std::string &tableName, std::string &cloudMark); int SetCloudWaterMark(const std::string &tableName, std::string &cloudMark); - + int StartTransaction(TransactType type = TransactType::DEFERRED); int Commit(); @@ -58,8 +59,6 @@ public: int GetUploadCount(const QuerySyncObject &query, const Timestamp &localMark, bool isCloudForcePush, int64_t &count); - int FillCloudGid(const CloudSyncData &data); - int GetCloudData(const std::string &tableName, const Timestamp &timeRange, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult); @@ -77,7 +76,7 @@ public: int CleanCloudData(ClearMode mode, const std::vector &tableNameList, const RelationalSchemaObject &localSchema, std::vector &assets); - + int CheckSchema(const TableName &tableName) const; int CheckSchema(std::vector &tables); @@ -93,11 +92,30 @@ public: int SetLogTriggerStatus(bool status); - int FillCloudGidAndAsset(OpType opType, const CloudSyncData &data); + int FillCloudLogAndAsset(OpType opType, const CloudSyncData &data); std::string GetIdentify() const; int CleanWaterMark(const TableName &tableName); + + int CleanWaterMarkInMemory(const TableName &tableName); + + int GetCloudDataGid(const QuerySyncObject &query, Timestamp beginTime, std::vector &gid); + + int CreateTempSyncTrigger(const std::string &tableName); + + int ClearAllTempSyncTrigger(); + + int IsSharedTable(const std::string &tableName, bool &isSharedTable); + + void FillCloudGidIfSuccess(const OpType opType, const CloudSyncData &data); + + void SetCloudTaskConfig(const CloudTaskConfig &config); + + int GetAssetsByGidOrHashKey(const std::string &tableName, const std::string &gid, const Bytes &hashKey, + VBucket &assets); + + int SetIAssetLoader(const std::shared_ptr &loader); protected: void Init(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp index 41aa74c70e759da355fb8a8192c72daf40bee0d0..63ae192ab2f6dce52ce21ae37177bef664754245 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_meta_data.cpp @@ -15,6 +15,7 @@ #include "cloud/cloud_meta_data.h" #include "cloud/cloud_db_constant.h" +#include "db_common.h" #include "db_errno.h" #include "parcel.h" @@ -25,13 +26,6 @@ CloudMetaData::CloudMetaData(ICloudSyncStorageInterface *store) { } -Key CloudMetaData::GetPrefixTableName(const TableName &tableName) -{ - TableName newName = CloudDbConstant::CLOUD_META_TABLE_PREFIX + tableName; - Key prefixedTableName(newName.begin(), newName.end()); - return prefixedTableName; -} - int CloudMetaData::GetLocalWaterMark(const TableName &tableName, Timestamp &localMark) { std::lock_guard lock(cloudMetaMutex_); @@ -108,7 +102,7 @@ int CloudMetaData::ReadMarkFromMeta(const TableName &tableName) return -E_INVALID_DB; } Value blobMetaVal; - int ret = store_->GetMetaData(GetPrefixTableName(tableName), blobMetaVal); + int ret = store_->GetMetaData(DBCommon::GetPrefixTableName(tableName), blobMetaVal); if (ret != -E_NOT_FOUND && ret != E_OK) { return ret; } @@ -124,28 +118,14 @@ int CloudMetaData::ReadMarkFromMeta(const TableName &tableName) int CloudMetaData::WriteMarkToMeta(const TableName &tableName, Timestamp localmark, std::string &cloudMark) { Value blobMetaVal; - int ret = SerializeMark(localmark, cloudMark, blobMetaVal); + int ret = DBCommon::SerializeWaterMark(localmark, cloudMark, blobMetaVal); if (ret != E_OK) { return ret; } if (store_ == nullptr) { return -E_INVALID_DB; } - return store_->PutMetaData(GetPrefixTableName(tableName), blobMetaVal); -} - -int CloudMetaData::SerializeMark(const Timestamp localMark, const std::string &cloudMark, Value &blobMeta) -{ - uint64_t length = Parcel::GetUInt64Len() + Parcel::GetStringLen(cloudMark); - blobMeta.resize(length); - Parcel parcel(blobMeta.data(), blobMeta.size()); - parcel.WriteUInt64(localMark); - parcel.WriteString(cloudMark); - if (parcel.IsError()) { - LOGE("[Meta] Parcel error while serializing cloud meta data."); - return -E_PARSE_FAIL; - } - return E_OK; + return store_->PutMetaData(DBCommon::GetPrefixTableName(tableName), blobMetaVal); } int CloudMetaData::DeserializeMark(Value &blobMark, CloudMetaValue &cloudMetaValue) @@ -177,4 +157,11 @@ int CloudMetaData::CleanWaterMark(const TableName &tableName) LOGD("[Meta] clean cloud water mark"); return E_OK; } + +void CloudMetaData::CleanWaterMarkInMemory(const TableName &tableName) +{ + std::lock_guard lock(cloudMetaMutex_); + cloudMetaVals_[tableName] = {}; + LOGD("[Meta] clean cloud water mark in memory"); +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp index d912ed9fe4b35100664de70b2c175139bc88c3d7..0dbe60c7277f7e299aa593dae794c221389dfc3e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/cloud_storage_utils.cpp @@ -300,7 +300,7 @@ std::vector CloudStorageUtils::GetCloudAsset(const TableSchema &tableSche return assetFields; } -std::vector CloudStorageUtils::GetCloudPrimaryKeyField(const TableSchema &tableSchema) +std::vector CloudStorageUtils::GetCloudPrimaryKeyField(const TableSchema &tableSchema, bool sortByName) { std::vector pkVec; for (const auto &field : tableSchema.fields) { @@ -308,6 +308,11 @@ std::vector CloudStorageUtils::GetCloudPrimaryKeyField(const TableSchema pkVec.push_back(field); } } + if (sortByName) { + std::sort(pkVec.begin(), pkVec.end(), [](const Field &a, const Field &b) { + return a.colName < b.colName; + }); + } return pkVec; } @@ -371,7 +376,7 @@ void CloudStorageUtils::ObtainAssetFromVBucket(const VBucket &vBucket, VBucket & AssetOpType CloudStorageUtils::StatusToFlag(AssetStatus status) { - switch (status) { + switch (AssetOperationUtils::EraseBitMask(status)) { case AssetStatus::INSERT: return AssetOpType::INSERT; case AssetStatus::DELETE: @@ -445,34 +450,18 @@ void CloudStorageUtils::FillAssetBeforeDownload(Asset &asset) } } -void CloudStorageUtils::FillAssetAfterDownloadFail(Asset &asset) +int CloudStorageUtils::FillAssetAfterDownload(Asset &asset, Asset &dbAsset, + AssetOperationUtils::AssetOpType assetOpType) { - AssetOpType flag = static_cast(asset.flag); - AssetStatus status = static_cast(asset.status); - switch (flag) { - case AssetOpType::INSERT: - case AssetOpType::DELETE: - case AssetOpType::UPDATE: { - if (status != AssetStatus::NORMAL) { - asset.hash = std::string(""); - asset.status = static_cast(AssetStatus::ABNORMAL); - } - break; - } - default: - break; + if (assetOpType == AssetOperationUtils::AssetOpType::NOT_HANDLE) { + return E_OK; } -} - -int CloudStorageUtils::FillAssetAfterDownload(Asset &asset) -{ + dbAsset = asset; AssetOpType flag = static_cast(asset.flag); + if (asset.status != AssetStatus::NORMAL) { + return E_OK; + } switch (flag) { - case AssetOpType::INSERT: - case AssetOpType::UPDATE: { - asset.status = static_cast(AssetStatus::NORMAL); - break; - } case AssetOpType::DELETE: { return -E_NOT_FOUND; } @@ -482,24 +471,25 @@ int CloudStorageUtils::FillAssetAfterDownload(Asset &asset) return E_OK; } -void CloudStorageUtils::FillAssetsAfterDownload(Assets &assets) +void CloudStorageUtils::FillAssetsAfterDownload(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap) { - for (auto asset = assets.begin(); asset != assets.end();) { - if (FillAssetAfterDownload(*asset) == -E_NOT_FOUND) { - asset = assets.erase(asset); - } else { - asset++; - } - } + MergeAssetWithFillFunc(assets, dbAssets, assetOpTypeMap, FillAssetAfterDownload); } -int CloudStorageUtils::FillAssetForUpload(Asset &asset) +int CloudStorageUtils::FillAssetForUpload(Asset &asset, Asset &dbAsset, AssetOperationUtils::AssetOpType assetOpType) { - AssetStatus status = static_cast(asset.status); + if (assetOpType == AssetOperationUtils::AssetOpType::NOT_HANDLE) { + // db assetId may be empty, need to be based on cache + dbAsset.assetId = asset.assetId; + return E_OK; + } + AssetStatus status = static_cast(dbAsset.status); + dbAsset = asset; switch (StatusToFlag(status)) { case AssetOpType::INSERT: case AssetOpType::UPDATE: { - asset.status = static_cast(AssetStatus::NORMAL); + dbAsset.status = static_cast(AssetStatus::NORMAL); break; } case AssetOpType::DELETE: { @@ -509,18 +499,40 @@ int CloudStorageUtils::FillAssetForUpload(Asset &asset) break; } } + dbAsset.flag = static_cast(AssetOpType::NO_CHANGE); return E_OK; } -void CloudStorageUtils::FillAssetsForUpload(Assets &assets) +void CloudStorageUtils::FillAssetsForUpload(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap) { - for (auto asset = assets.begin(); asset != assets.end();) { - if (FillAssetForUpload(*asset) == -E_NOT_FOUND) { - asset = assets.erase(asset); - } else { - asset++; - } + MergeAssetWithFillFunc(assets, dbAssets, assetOpTypeMap, FillAssetForUpload); +} + +int CloudStorageUtils::FillAssetBeforeUpload(Asset &asset, Asset &dbAsset, AssetOperationUtils::AssetOpType assetOpType) +{ + if (assetOpType == AssetOperationUtils::AssetOpType::NOT_HANDLE) { + return E_OK; + } + dbAsset = asset; + switch (static_cast(asset.flag)) { + case AssetOpType::INSERT: + case AssetOpType::UPDATE: + case AssetOpType::DELETE: + dbAsset.status |= static_cast(AssetStatus::UPLOADING); + break; + case AssetOpType::NO_CHANGE: + default: + break; } + dbAsset.flag = static_cast(AssetOpType::NO_CHANGE); + return E_OK; +} + +void CloudStorageUtils::FillAssetsBeforeUpload(Assets &assets, Assets &dbAssets, const std::map &assetOpTypeMap) +{ + MergeAssetWithFillFunc(assets, dbAssets, assetOpTypeMap, FillAssetBeforeUpload); } void CloudStorageUtils::PrepareToFillAssetFromVBucket(VBucket &vBucket, std::function fillAsset) @@ -542,29 +554,46 @@ void CloudStorageUtils::PrepareToFillAssetFromVBucket(VBucket &vBucket, std::fun } } -void CloudStorageUtils::FillAssetFromVBucketFinish(VBucket &vBucket, std::function fillAsset, - std::function fillAssets) +void CloudStorageUtils::FillAssetFromVBucketFinish(const AssetOperationUtils::RecordAssetOpType &assetOpType, + VBucket &vBucket, VBucket &dbAssets, + std::function fillAsset, + std::function &)> fillAssets) { - for (auto &item: vBucket) { + for (auto &item: dbAssets) { if (IsAsset(item.second)) { - Asset asset; - GetValueFromType(item.second, asset); - int errCode = fillAsset(asset); + Asset cacheItem; + GetValueFromType(vBucket[item.first], cacheItem); + Asset dbItem; + GetValueFromType(item.second, dbItem); + AssetOperationUtils::AssetOpType opType = AssetOperationUtils::AssetOpType::NOT_HANDLE; + auto iterCol = assetOpType.find(item.first); + if (iterCol != assetOpType.end() && iterCol->second.find(dbItem.name) != iterCol->second.end()) { + opType = iterCol->second.at(dbItem.name); + } + int errCode = fillAsset(cacheItem, dbItem, opType); if (errCode != E_OK) { - vBucket[item.first] = Nil(); + dbAssets[item.first] = Nil(); } else { - vBucket[item.first] = asset; + dbAssets[item.first] = dbItem; } continue; } if (IsAssets(item.second)) { - Assets assets; - GetValueFromType(item.second, assets); - fillAssets(assets); - if (assets.empty()) { - vBucket[item.first] = Nil(); + Assets cacheItems; + GetValueFromType(vBucket[item.first], cacheItems); + Assets dbItems; + GetValueFromType(item.second, dbItems); + auto iterCol = assetOpType.find(item.first); + if (iterCol == assetOpType.end()) { + fillAssets(cacheItems, dbItems, {}); + } else { + fillAssets(cacheItems, dbItems, iterCol->second); + } + if (dbItems.empty()) { + dbAssets[item.first] = Nil(); } else { - vBucket[item.first] = assets; + dbAssets[item.first] = dbItems; } } } @@ -722,11 +751,194 @@ int CloudStorageUtils::ConstraintsCheckForCloud(const TableInfo &table, const st bool CloudStorageUtils::CheckAssetStatus(const Assets &assets) { for (const Asset &asset: assets) { - if (asset.status > static_cast(AssetStatus::UPDATE)) { + if (AssetOperationUtils::EraseBitMask(asset.status) > static_cast(AssetStatus::UPDATE)) { LOGE("assets contain invalid status:[%u]", asset.status); return false; } } return true; } + +std::string CloudStorageUtils::GetTableRefUpdateSql(const TableInfo &table, OpType opType) +{ + std::string sql; + std::string rowid = std::string(DBConstant::SQLITE_INNER_ROWID); + for (const auto &reference : table.GetTableReference()) { + if (reference.columns.empty()) { + return ""; + } + std::string sourceLogName = DBCommon::GetLogTableName(reference.sourceTableName); + sql += " UPDATE " + sourceLogName + " SET timestamp=get_raw_sys_time(), flag=flag|0x02 WHERE "; + int index = 0; + for (const auto &itCol : reference.columns) { + if (opType != OpType::UPDATE) { + continue; + } + if (index++ != 0) { + sql += " OR "; + } + sql += " OLD." + itCol.second + " <> " + " NEW." + itCol.second; + } + if (opType == OpType::UPDATE) { + sql += " AND "; + } + sql += " (flag&0x08=0x00) AND data_key IN (SELECT " + sourceLogName + ".data_key FROM " + sourceLogName + + " LEFT JOIN " + reference.sourceTableName + " ON " + sourceLogName + ".data_key = " + + reference.sourceTableName + "." + rowid + " WHERE "; + index = 0; + for (const auto &itCol : reference.columns) { + if (index++ != 0) { + sql += " OR "; + } + if (opType == OpType::UPDATE) { + sql += itCol.first + "=OLD." + itCol.second + " OR " + itCol.first + "=NEW." + itCol.second; + } else if (opType == OpType::INSERT) { + sql += itCol.first + "=NEW." + itCol.second; + } else if (opType == OpType::DELETE) { + sql += itCol.first + "=OLD." + itCol.second; + } + } + sql += ");"; + } + return sql; +} + +std::string CloudStorageUtils::GetLeftJoinLogSql(const std::string &tableName, bool logAsTableA) +{ + std::string sql; + if (logAsTableA) { + sql += " FROM '" + DBCommon::GetLogTableName(tableName) + "' AS a LEFT JOIN '" + tableName + "' AS b " + + " ON (a.data_key = b." + std::string(DBConstant::SQLITE_INNER_ROWID) + ")"; + } else { + sql += " FROM '" + DBCommon::GetLogTableName(tableName) + "' AS b LEFT JOIN '" + tableName + "' AS a " + + " ON (b.data_key = a." + std::string(DBConstant::SQLITE_INNER_ROWID) + ")"; + } + return sql; +} + +bool CloudStorageUtils::ChkFillCloudAssetParam(const CloudSyncBatch &data, int errCode) +{ + if (data.assets.empty()) { + errCode = E_OK; + return true; + } + if (data.rowid.empty() || data.timestamp.empty()) { + errCode = -E_INVALID_ARGS; + LOGE("param is empty when fill cloud Asset. rowidN:%u, timeN:%u", errCode, data.rowid.size(), + data.timestamp.size()); + return true; + } + if (data.assets.size() != data.rowid.size() || data.assets.size() != data.timestamp.size() || + data.assets.size() != data.hashKey.size() || data.assets.size() != data.extend.size()) { + errCode = -E_INVALID_ARGS; + LOGE("the num of param is invalid when fill cloud Asset. assetsN:%u, rowidN:%u, timeN:%u, " + "hashKeyN:%u, extendN:%u", data.assets.size(), data.rowid.size(), data.timestamp.size(), + data.hashKey.size(), data.extend.size()); + return true; + } + return false; +} + +void CloudStorageUtils::GetToBeRemoveAssets(const VBucket &vBucket, + const AssetOperationUtils::RecordAssetOpType &assetOpType, std::vector &removeAssets) +{ + for (const auto &col: assetOpType) { + auto itCol = vBucket.find(col.first); + if (itCol == vBucket.end()) { + continue; + } + auto itItem = itCol->second; + if (!CloudStorageUtils::IsAsset(itItem) && !CloudStorageUtils::IsAssets(itItem)) { + continue; + } + if (CloudStorageUtils::IsAsset(itItem)) { + Asset delAsset; + GetValueFromType(itItem, delAsset); + auto itOp = col.second.find(delAsset.name); + if (itOp != col.second.end() && itOp->second == AssetOperationUtils::AssetOpType::NOT_HANDLE) { + removeAssets.push_back(delAsset); + } + continue; + } + Assets assets; + GetValueFromType(itItem, assets); + for (const auto &asset: assets) { + auto itOp = col.second.find(asset.name); + if (itOp == col.second.end() || itOp->second == AssetOperationUtils::AssetOpType::HANDLE) { + continue; + } + removeAssets.push_back(asset); + } + } +} + +int CloudStorageUtils::FillAssetForUploadFailed(Asset &asset, Asset &dbAsset, + AssetOperationUtils::AssetOpType assetOpType) +{ + dbAsset.assetId = asset.assetId; + dbAsset.status &= ~AssetStatus::UPLOADING; + return E_OK; +} + +void CloudStorageUtils::FillAssetsForUploadFailed(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap) +{ + MergeAssetWithFillFunc(assets, dbAssets, assetOpTypeMap, FillAssetForUploadFailed); +} + +int CloudStorageUtils::FillAssetAfterDownloadFail(Asset &asset, Asset &dbAsset, + AssetOperationUtils::AssetOpType assetOpType) +{ + AssetStatus status = static_cast(asset.status); + if (assetOpType == AssetOperationUtils::AssetOpType::NOT_HANDLE) { + return E_OK; + } + if (status != AssetStatus::ABNORMAL) { + return FillAssetAfterDownload(asset, dbAsset, assetOpType); + } + AssetOpType flag = static_cast(asset.flag); + dbAsset = asset; + switch (flag) { + case AssetOpType::INSERT: + case AssetOpType::DELETE: + case AssetOpType::UPDATE: { + dbAsset.hash = std::string(""); + break; + } + default: + // other flag type do not need to clear hash + break; + } + return E_OK; +} + +void CloudStorageUtils::FillAssetsAfterDownloadFail(Assets &assets, Assets &dbAssets, + const std::map &assetOpTypeMap) +{ + MergeAssetWithFillFunc(assets, dbAssets, assetOpTypeMap, FillAssetAfterDownloadFail); +} + +void CloudStorageUtils::MergeAssetWithFillFunc(Assets &assets, Assets &dbAssets, const std::map &assetOpTypeMap, + std::function fillAsset) +{ + std::map indexMap = GenAssetsIndexMap(assets); + for (auto dbAsset = dbAssets.begin(); dbAsset != dbAssets.end();) { + Asset cacheAsset; + auto it = indexMap.find(dbAsset->name); + if (it != indexMap.end()) { + cacheAsset = assets[it->second]; + } + AssetOperationUtils::AssetOpType opType = AssetOperationUtils::AssetOpType::NOT_HANDLE; + auto iterOp = assetOpTypeMap.find(dbAsset->name); + if (iterOp != assetOpTypeMap.end()) { + opType = iterOp->second; + } + if (fillAsset(cacheAsset, *dbAsset, opType) == -E_NOT_FOUND) { + dbAsset = dbAssets.erase(dbAsset); + } else { + dbAsset++; + } + } +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp index 7587cf2352b6652e553f43b6452cc46ea1948ba7..7e3268d87214d22b83dd14251851c187ae5204ca 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/cloud/schema_mgr.cpp @@ -145,23 +145,23 @@ bool SchemaMgr::ComparePrimaryField(std::map &localPrimaryKeys, void SchemaMgr::SetCloudDbSchema(const DataBaseSchema &schema) { - DataBaseSchema cloudSchema; - for (const auto &table : schema.tables) { - TableSchema tableSchema; - std::string name(table.name.length(), ' '); - std::transform(table.name.begin(), table.name.end(), name.begin(), tolower); - tableSchema.name = name; - for (const auto &field : table.fields) { - Field tableField; - std::string colName(field.colName.length(), ' '); - std::transform(field.colName.begin(), field.colName.end(), colName.begin(), tolower); - tableField.colName = colName; - tableField.type = field.type; - tableField.primary = field.primary; - tableField.nullable = field.nullable; - tableSchema.fields.emplace_back(tableField); + DataBaseSchema cloudSchema = schema; + DataBaseSchema cloudSharedSchema; + for (const auto &tableSchema : cloudSchema.tables) { + if (tableSchema.name.empty()) { + continue; } - cloudSchema.tables.emplace_back(tableSchema); + bool hasPrimaryKey = DBCommon::HasPrimaryKey(tableSchema.fields); + auto sharedTableFields = tableSchema.fields; + Field ownerField = { CloudDbConstant::CLOUD_OWNER, TYPE_INDEX, hasPrimaryKey, true }; + Field privilegeField = { CloudDbConstant::CLOUD_PRIVILEGE, TYPE_INDEX, false, true }; + sharedTableFields.push_back(ownerField); + sharedTableFields.push_back(privilegeField); + TableSchema sharedTableSchema = { tableSchema.sharedTableName, "", sharedTableFields }; + cloudSharedSchema.tables.push_back(sharedTableSchema); + } + for (const auto &sharedTableSchema : cloudSharedSchema.tables) { + cloudSchema.tables.push_back(sharedTableSchema); } cloudSchema_ = std::make_shared(cloudSchema); } @@ -185,4 +185,37 @@ int SchemaMgr::GetCloudTableSchema(const TableName &tableName, TableSchema &retS return -E_NOT_FOUND; } +bool SchemaMgr::IsSharedTable(const std::string &tableName) +{ + if (cloudSchema_ == nullptr) { + return false; + } + if (sharedTableMap_.find(tableName) != sharedTableMap_.end()) { + return sharedTableMap_[tableName]; + } + for (const auto &tableSchema : (*cloudSchema_).tables) { + if (DBCommon::CaseInsensitiveCompare(tableName, tableSchema.sharedTableName)) { + sharedTableMap_[tableName] = true; + return true; + } + } + sharedTableMap_[tableName] = false; + return false; +} + +std::map SchemaMgr::GetSharedTableOriginNames() +{ + if (cloudSchema_ == nullptr) { + LOGW("[SchemaMgr] Not found cloud schema!"); + return {}; + } + std::map res; + for (const auto &item : cloudSchema_->tables) { + if (item.sharedTableName.empty()) { + continue; + } + res[item.name] = item.sharedTableName; + } + return res; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h index 6498006fc030e2f9c7275c64e26eb38645b3d48f..e9d34dbf7962b09fe994c614006b83c5601044e0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/data_transformer.h @@ -37,6 +37,11 @@ struct LogInfo { std::string cloudGid; // use for sync with cloud }; +enum class LogInfoFlag : uint32_t { + FLAG_DELETE = 0x1, + FLAG_LOGIC_DELETE = 0x8 +}; + struct RowDataWithLog { LogInfo logInfo; RowData rowData; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/db_properties.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/db_properties.cpp index a1292eac225c5adb38cb78d0aae64fd524797f29..5e7e6daca906bcd4987d39e402bddc3a82131f03 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/db_properties.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/db_properties.cpp @@ -18,7 +18,6 @@ namespace DistributedDB { const std::string DBProperties::CREATE_IF_NECESSARY = "createIfNecessary"; -const std::string DBProperties::DATABASE_TYPE = "databaseType"; const std::string DBProperties::DATA_DIR = "dataDir"; const std::string DBProperties::USER_ID = "userId"; const std::string DBProperties::APP_ID = "appId"; @@ -30,6 +29,8 @@ const std::string DBProperties::DUAL_TUPLE_IDENTIFIER_DATA = "dualTupleIdentifie const std::string DBProperties::SYNC_DUAL_TUPLE_MODE = "syncDualTuple"; const std::string DBProperties::AUTO_LAUNCH_ID = "autoLaunchID"; +const std::string DBProperties::DATABASE_TYPE = "databaseType"; + std::string DBProperties::GetStringProp(const std::string &name, const std::string &defaultValue) const { auto iter = stringProperties_.find(name); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.cpp index 8c57e89fb3cb68ab7b394b1468e825e62b88c576..e2ecd61db76db8e4bd332cb7d72b04e788e65355 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.cpp @@ -23,6 +23,7 @@ #include "multi_ver_natural_store.h" #include "multi_ver_natural_store_commit_storage.h" #endif +#include "rd_single_ver_natural_store.h" #include "sqlite_single_ver_natural_store.h" #ifndef OMIT_MULTI_VER #include "sqlite_multi_ver_data_storage.h" @@ -33,13 +34,15 @@ IKvDB *DefaultFactory::CreateKvDb(KvDBType kvDbType, int &errCode) { switch (kvDbType) { #ifndef OMIT_MULTI_VER - case LOCAL_KVDB: + case LOCAL_KVDB_SQLITE: return CreateLocalKvDB(errCode); #endif - case SINGER_VER_KVDB: + case SINGER_VER_KVDB_SQLITE: return CreateSingleVerNaturalStore(errCode); + case SINGLE_VER_KVDB_RD: + return CreateRdSingleVerNaturalStore(errCode); #ifndef OMIT_MULTI_VER - case MULTI_VER_KVDB: + case MULTI_VER_KVDB_SQLITE: return CreateMultiVerNaturalStore(errCode); #endif default: @@ -73,6 +76,14 @@ IKvDB *DefaultFactory::CreateSingleVerNaturalStore(int &errCode) return kvDb; } +// Create the single version natural store with gaussdb_rd +IKvDB *DefaultFactory::CreateRdSingleVerNaturalStore(int &errCode) +{ + IKvDB *kvDb = new (std::nothrow) RdSingleVerNaturalStore(); + errCode = ((kvDb == nullptr) ? -E_OUT_OF_MEMORY : E_OK); + return kvDb; +} + #ifndef OMIT_MULTI_VER // Create a key-value database for commit storage module. IKvDB *DefaultFactory::CreateCommitStorageDB(int &errCode) diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.h b/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.h index 86a0b7482ede9bbe6d5ed155f0bb5b0b83336c74..26bb7d713c8d0f49f09197fd2fab766a1fae8ad1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/default_factory.h @@ -48,6 +48,8 @@ private: #endif IKvDB *CreateSingleVerNaturalStore(int &errCode); + + IKvDB *CreateRdSingleVerNaturalStore(int &errCode); }; } // namespace DistributedDB #endif // DEFAULT_FACTORY_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a1ce9d27138a3b037961ffa86e282935f950e5eb --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.cpp @@ -0,0 +1,429 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rd_single_ver_natural_store.h" + +#include "rd_single_ver_natural_store_connection.h" +#include "rd_utils.h" +#include "sqlite_single_ver_storage_engine.h" + +namespace DistributedDB { + +RdSingleVerNaturalStore::RdSingleVerNaturalStore() +{ + LOGD("RdSingleVerNaturalStore Created"); +} + +RdSingleVerNaturalStore::~RdSingleVerNaturalStore() +{ +} + +GenericKvDBConnection *RdSingleVerNaturalStore::NewConnection(int &errCode) +{ + RdSingleVerNaturalStoreConnection *connection = new (std::nothrow) RdSingleVerNaturalStoreConnection(this); + if (connection == nullptr) { + errCode = -E_OUT_OF_MEMORY; + return nullptr; + } + errCode = E_OK; + return connection; +} + +int RdSingleVerNaturalStore::GetAndInitStorageEngine(const KvDBProperties &kvDBProp) +{ + int errCode = E_OK; + { + std::unique_lock lock(engineMutex_); + storageEngine_ = + static_cast(StorageEngineManager::GetStorageEngine(kvDBProp, errCode)); + if (storageEngine_ == nullptr) { + return errCode; + } + } + + errCode = InitDatabaseContext(kvDBProp); + if (errCode != E_OK) { + LOGE("[RdSinStore][GetAndInitStorageEngine] Init database context fail! errCode = [%d]", errCode); + } + return errCode; +} + +int RdSingleVerNaturalStore::RegisterNotification() +{ + static const std::vector events { + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT), + }; + for (auto event = events.begin(); event != events.end(); ++event) { + int errCode = RegisterNotificationEventType(*event); + if (errCode == E_OK) { + continue; + } + LOGE("Register rd single version event %d failed:%d!", *event, errCode); + for (auto iter = events.begin(); iter != event; ++iter) { + UnRegisterNotificationEventType(*iter); + } + return errCode; + } + notificationEventsRegistered_ = true; + return E_OK; +} + +void RdSingleVerNaturalStore::ReleaseHandle(RdSingleVerStorageExecutor *&handle) const +{ + if (handle == nullptr) { + return; + } + if (storageEngine_ != nullptr) { + StorageExecutor *databaseHandle = handle; + storageEngine_->Recycle(databaseHandle); + handle = nullptr; + } + engineMutex_.unlock_shared(); // unlock after handle used up +} + +int RdSingleVerNaturalStore::TransObserverTypeToRegisterFunctionType(int observerType, RegisterFuncType &type) const +{ + static constexpr TransPair transMap[] = { + { static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT), + RegisterFuncType::OBSERVER_SINGLE_VERSION_NS_PUT_EVENT }, + }; + auto funcType = GetFuncType(observerType, transMap, sizeof(transMap) / sizeof(TransPair)); + if (funcType == RegisterFuncType::REGISTER_FUNC_TYPE_MAX) { + return -E_NOT_SUPPORT; + } + type = funcType; + return E_OK; +} + +int RdSingleVerNaturalStore::Open(const KvDBProperties &kvDBProp) +{ + // Currently, Design for the consistency of directory and file setting secOption + int errCode = ClearIncompleteDatabase(kvDBProp); + if (errCode != E_OK) { + LOGE("Clear incomplete database failed in single version:%d", errCode); + return errCode; + } + const std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, ""); + const std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, ""); + bool isCreate = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); + errCode = DBCommon::CreateStoreDirectory(dataDir, identifierDir, DBConstant::SINGLE_SUB_DIR, isCreate); + if (errCode != E_OK) { + LOGE("Create single version natural store directory failed:%d", errCode); + return errCode; + } + LOGD("[RdSingleVerNaturalStore] Open RdSingleVerNaturalStore"); + errCode = GetAndInitStorageEngine(kvDBProp); + if (errCode != E_OK) { + ReleaseResources(); + return errCode; + } + errCode = RegisterNotification(); + if (errCode != E_OK) { + LOGE("register notification failed:%d", errCode); + ReleaseResources(); + return errCode; + } + MyProp() = kvDBProp; + OnKill([this]() { ReleaseResources(); }); + return errCode; +} + +void RdSingleVerNaturalStore::ReleaseResources() +{ + if (notificationEventsRegistered_) { + UnRegisterNotificationEventType( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); + notificationEventsRegistered_ = false; + } + { + std::unique_lock lock(engineMutex_); + if (storageEngine_ != nullptr) { + (void)StorageEngineManager::ReleaseStorageEngine(storageEngine_); + storageEngine_ = nullptr; + } + } +} + +// Invoked automatically when connection count is zero +void RdSingleVerNaturalStore::Close() +{ + ReleaseResources(); +} + +// Get interface type of this kvdb. +int RdSingleVerNaturalStore::GetInterfaceType() const +{ + return -E_NOT_SUPPORT; +} + +// Get the interface ref-count, in order to access asynchronously. +void RdSingleVerNaturalStore::IncRefCount() +{ + return; +} + +// Drop the interface ref-count. +void RdSingleVerNaturalStore::DecRefCount() +{ + return; +} + +// Get the identifier of this kvdb. +std::vector RdSingleVerNaturalStore::GetIdentifier() const +{ + return {}; +} + +// Get interface for syncer. +IKvDBSyncInterface *RdSingleVerNaturalStore::GetSyncInterface() +{ + return nullptr; +} + +int RdSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction) +{ + return -E_NOT_SUPPORT; +} + +// Delete multiple meta data records in a transaction. +int RdSingleVerNaturalStore::DeleteMetaData(const std::vector &keys) +{ + return -E_NOT_SUPPORT; +} + +// Delete multiple meta data records with key prefix in a transaction. +int RdSingleVerNaturalStore::DeleteMetaDataByPrefixKey(const Key &keyPrefix) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStore::GetAllMetaKeys(std::vector &keys) const +{ + return -E_NOT_SUPPORT; +} + +void RdSingleVerNaturalStore::GetMaxTimestamp(Timestamp &stamp) const +{ + return; +} + +void RdSingleVerNaturalStore::SetMaxTimestamp(Timestamp timestamp) +{ + return; +} + +int RdSingleVerNaturalStore::Rekey(const CipherPassword &passwd) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStore::Export(const std::string &filePath, const CipherPassword &passwd) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStore::Import(const std::string &filePath, const CipherPassword &passwd) +{ + return -E_NOT_SUPPORT; +} + +RdSingleVerStorageExecutor *RdSingleVerNaturalStore::GetHandle(bool isWrite, int &errCode, + OperatePerm perm) const +{ + engineMutex_.lock_shared(); + if (storageEngine_ == nullptr) { + errCode = -E_INVALID_DB; + engineMutex_.unlock_shared(); // unlock when get handle failed. + return nullptr; + } + auto handle = storageEngine_->FindExecutor(isWrite, perm, errCode); + if (handle == nullptr) { + LOGD("Find null storage engine"); + engineMutex_.unlock_shared(); // unlock when get handle failed. + } + return static_cast(handle); +} + +SchemaObject RdSingleVerNaturalStore::GetSchemaInfo() const +{ + return MyProp().GetSchema(); +} + +bool RdSingleVerNaturalStore::CheckCompatible(const std::string &schema, uint8_t type) const +{ + return true; +} + +Timestamp RdSingleVerNaturalStore::GetCurrentTimestamp() +{ + return 0; +} + +SchemaObject RdSingleVerNaturalStore::GetSchemaObject() const +{ + return MyProp().GetSchema(); +} + +const SchemaObject &RdSingleVerNaturalStore::GetSchemaObjectConstRef() const +{ + return MyProp().GetSchemaConstRef(); +} + +const KvDBProperties &RdSingleVerNaturalStore::GetDbProperties() const +{ + return GetMyProperties(); +} + +int RdSingleVerNaturalStore::GetKvDBSize(const KvDBProperties &properties, uint64_t &size) const +{ + return -E_NOT_SUPPORT; +} + +KvDBProperties &RdSingleVerNaturalStore::GetDbPropertyForUpdate() +{ + return MyProp(); +} + +int RdSingleVerNaturalStore::InitDatabaseContext(const KvDBProperties &kvDBProp) +{ + OpenDbProperties option; + InitDataBaseOption(kvDBProp, option); + + StorageEngineAttr poolSize = {1, 1, 1, 16}; // at most 1 write 16 read. + + storageEngine_->SetNotifiedCallback( + [&](int eventType, KvDBCommitNotifyFilterAbleData *committedData) { + auto commitData = static_cast(committedData); + this->CommitAndReleaseNotifyData(commitData, true, eventType); + } + ); + + std::string identifier = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DATA, ""); + int errCode = storageEngine_->InitRdStorageEngine(poolSize, option, identifier); + if (errCode != E_OK) { + LOGE("Init the rd storage engine failed:%d", errCode); + } + return errCode; +} + +int RdSingleVerNaturalStore::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStore::SetAutoLifeCycleTime(uint32_t time) +{ + return -E_NOT_SUPPORT; +} + +bool RdSingleVerNaturalStore::IsDataMigrating() const +{ + return false; +} + +int RdSingleVerNaturalStore::TriggerToMigrateData() const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStore::CheckReadDataControlled() const +{ + return E_OK; +} + +bool RdSingleVerNaturalStore::IsCacheDBMode() const +{ + return false; +} + +void RdSingleVerNaturalStore::IncreaseCacheRecordVersion() const +{ + return; +} + +uint64_t RdSingleVerNaturalStore::GetCacheRecordVersion() const +{ + return 0; +} + +uint64_t RdSingleVerNaturalStore::GetAndIncreaseCacheRecordVersion() const +{ + return 0; +} + +int RdSingleVerNaturalStore::CheckIntegrity() const +{ + KvDBProperties dbProp = GetDbProperties(); + std::string uri = GetDatabasePath(dbProp); + return RdCrcCheck(uri.c_str()); +} + +int RdSingleVerNaturalStore::GetCompressionAlgo(std::set &algorithmSet) const +{ + return -E_NOT_SUPPORT; +} + +void RdSingleVerNaturalStore::SetDataInterceptor(const PushDataInterceptor &interceptor) +{ + return; +} + +int RdSingleVerNaturalStore::SetMaxLogSize(uint64_t limit) +{ + return -E_NOT_SUPPORT; +} + +uint64_t RdSingleVerNaturalStore::GetMaxLogSize() const +{ + return 0; +} + +void RdSingleVerNaturalStore::Dump(int fd) +{ + return; +} + +void RdSingleVerNaturalStore::WakeUpSyncer() +{ + LOGD("Not support syncer yet"); + return; +} + +void RdSingleVerNaturalStore::InitDataBaseOption(const KvDBProperties &kvDBProp, OpenDbProperties &option) +{ + option.uri = GetDatabasePath(kvDBProp); + option.subdir = GetSubDirPath(kvDBProp); + SecurityOption securityOpt; + if (RuntimeContext::GetInstance()->IsProcessSystemApiAdapterValid()) { + securityOpt.securityLabel = kvDBProp.GetSecLabel(); + securityOpt.securityFlag = kvDBProp.GetSecFlag(); + } + option.createIfNecessary = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); + option.createDirByStoreIdOnly = kvDBProp.GetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, false); + option.readOnly = kvDBProp.GetBoolProp(KvDBProperties::READ_ONLY_MODE, false); + option.isNeedIntegrityCheck = kvDBProp.GetBoolProp(KvDBProperties::CHECK_INTEGRITY, false); + option.isNeedRmCorruptedDb = kvDBProp.GetBoolProp(KvDBProperties::RM_CORRUPTED_DB, false); + bool isSharedMode = kvDBProp.GetBoolProp(KvDBProperties::SHARED_MODE, false); + std::string config = "{" + InitRdConfig(); + config += isSharedMode ? R"(, "sharedModeEnable": 1)" : R"(, "sharedModeEnable": 0)"; + config += "}"; + option.rdConfig = config; +} + +} // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h new file mode 100644 index 0000000000000000000000000000000000000000..dd7f94da0c861c3d70138a1800328f2179e724e2 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RD_SINGLE_VER_NATURAL_STORE_H +#define RD_SINGLE_VER_NATURAL_STORE_H +#include +#include + +#include "db_common.h" +#include "grd_kv_api.h" +#include "kvdb_utils.h" +#include "rd_single_ver_storage_engine.h" +#include "rd_single_ver_storage_executor.h" +#include "single_ver_natural_store.h" +#include "storage_engine_manager.h" + +namespace DistributedDB { +class RdSingleVerNaturalStore : public SingleVerNaturalStore { +public: + RdSingleVerNaturalStore(); + ~RdSingleVerNaturalStore() override; + + // Delete the copy and assign constructors + DISABLE_COPY_ASSIGN_MOVE(RdSingleVerNaturalStore); + + // Open the database + int Open(const KvDBProperties &kvDBProp) override; + + // Invoked automatically when connection count is zero + void Close() override; + + // Create a connection object. + GenericKvDBConnection *NewConnection(int &errCode) override; + + // Get interface type of this kvdb. + int GetInterfaceType() const override; + + // Get the interface ref-count, in order to access asynchronously. + void IncRefCount() override; + + // Drop the interface ref-count. + void DecRefCount() override; + + // Get the identifier of this kvdb. + std::vector GetIdentifier() const override; + + // Get interface for syncer. + IKvDBSyncInterface *GetSyncInterface() override; + + int GetMetaData(const Key &key, Value &value) const override; + + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; + + // Delete multiple meta data records in a transaction. + int DeleteMetaData(const std::vector &keys) override; + + // Delete multiple meta data records with key prefix in a transaction. + int DeleteMetaDataByPrefixKey(const Key &keyPrefix) const override; + + int GetAllMetaKeys(std::vector &keys) const override; + + void GetMaxTimestamp(Timestamp &stamp) const override; + + void SetMaxTimestamp(Timestamp timestamp); + + int Rekey(const CipherPassword &passwd) override; + + int Export(const std::string &filePath, const CipherPassword &passwd) override; + + int Import(const std::string &filePath, const CipherPassword &passwd) override; + + RdSingleVerStorageExecutor *GetHandle(bool isWrite, int &errCode, + OperatePerm perm = OperatePerm::NORMAL_PERM) const; + + void ReleaseHandle(RdSingleVerStorageExecutor *&handle) const; + + int TransObserverTypeToRegisterFunctionType(int observerType, RegisterFuncType &type) const override; + + SchemaObject GetSchemaInfo() const override; + + bool CheckCompatible(const std::string &schema, uint8_t type) const override; + + Timestamp GetCurrentTimestamp(); + + SchemaObject GetSchemaObject() const; + + const SchemaObject &GetSchemaObjectConstRef() const; + + const KvDBProperties &GetDbProperties() const override; + + int GetKvDBSize(const KvDBProperties &properties, uint64_t &size) const override; + + KvDBProperties &GetDbPropertyForUpdate(); + + int InitDatabaseContext(const KvDBProperties &kvDBProp); + + int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier); + + int SetAutoLifeCycleTime(uint32_t time); + + bool IsDataMigrating() const override; + + int TriggerToMigrateData() const; + + int CheckReadDataControlled() const; + + bool IsCacheDBMode() const; + + bool IsExtendedCacheDBMode() const; + + void IncreaseCacheRecordVersion() const; + + uint64_t GetCacheRecordVersion() const; + + uint64_t GetAndIncreaseCacheRecordVersion() const; + + int CheckIntegrity() const override; + + int GetCompressionAlgo(std::set &algorithmSet) const override; + + void SetDataInterceptor(const PushDataInterceptor &interceptor) override; + + int SetMaxLogSize(uint64_t limit); + + uint64_t GetMaxLogSize() const; + + void Dump(int fd) override; + + void WakeUpSyncer() override; + +private: + + int GetAndInitStorageEngine(const KvDBProperties &kvDBProp); + + int RegisterNotification(); + + void ReleaseResources(); + + void InitDataBaseOption(const KvDBProperties &kvDBProp, OpenDbProperties &option); + mutable std::shared_mutex engineMutex_; + RdSingleVerStorageEngine *storageEngine_; + bool notificationEventsRegistered_; +}; +} // namespace DistributedDB +#endif // RD_SINGLE_VER_NATURAL_STORE_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1e27b1f34735684cfbbab3b760084633aec9234d --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.cpp @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rd_single_ver_natural_store_connection.h" +#include "rd_single_ver_result_set.h" + +#include + +#include "db_common.h" +#include "db_constant.h" +#include "db_dfx_adapter.h" +#include "db_errno.h" +#include "kvdb_observer_handle.h" +#include "kvdb_pragma.h" +#include "log_print.h" +#include "store_types.h" +#include "sqlite_single_ver_storage_engine.h" + +namespace DistributedDB { + +RdSingleVerNaturalStoreConnection::RdSingleVerNaturalStoreConnection(RdSingleVerNaturalStore *kvDB) + : SingleVerNaturalStoreConnection(kvDB), committedData_(nullptr), writeHandle_(nullptr) +{ + LOGD("RdSingleVerNaturalStoreConnection Created"); +} + +RdSingleVerNaturalStoreConnection::~RdSingleVerNaturalStoreConnection() +{ +} + +int RdSingleVerNaturalStoreConnection::GetEntries(const IOption &option, const Key &keyPrefix, + std::vector &entries) const +{ + return GetEntriesInner(true, option, keyPrefix, entries); +} + +int RdSingleVerNaturalStoreConnection::CheckOption(const IOption &option, SingleVerDataType &type) +{ + if (option.dataType == IOption::SYNC_DATA) { + type = SingleVerDataType::SYNC_TYPE; + } else { + LOGE("IOption only support SYNC_DATA type."); + return -E_NOT_SUPPORT; + } + return E_OK; +} + +int RdSingleVerNaturalStoreConnection::GetEntriesInner(bool isGetValue, const IOption &option, + const Key &keyPrefix, std::vector &entries) const +{ + if (keyPrefix.size() > DBConstant::MAX_KEY_SIZE) { + return -E_INVALID_ARGS; + } + + SingleVerDataType type; + int errCode = CheckOption(option, type); + if (errCode != E_OK) { + return errCode; + } + + DBDfxAdapter::StartTracing(); + { + std::lock_guard lock(transactionMutex_); + if (writeHandle_ != nullptr) { + LOGD("[RdSingleVerNaturalStoreConnection] Transaction started already."); + errCode = writeHandle_->GetEntries(isGetValue, type, keyPrefix, entries); + DBDfxAdapter::FinishTraceSQL(); + return errCode; + } + } + RdSingleVerStorageExecutor *handle = GetExecutor(false, errCode); + if (handle == nullptr) { + LOGE("[RdSingleVerNaturalStoreConnection]::[GetEntries] Get executor failed, errCode = [%d]", errCode); + DBDfxAdapter::FinishTraceSQL(); + return errCode; + } + + errCode = handle->GetEntries(isGetValue, type, keyPrefix, entries); + ReleaseExecutor(handle); + DBDfxAdapter::FinishTraceSQL(); + return errCode; +} + +int RdSingleVerNaturalStoreConnection::GetResultSet(const IOption &option, const Key &keyPrefix, + IKvDBResultSet *&resultSet) const +{ + // maximum of result set size is 4 + std::lock_guard lock(kvDbResultSetsMutex_); + if (kvDbResultSets_.size() >= maxResultSetSize) { + LOGE("Over max result set size"); + return -E_MAX_LIMITS; + } + + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + + RdSingleVerResultSet *tmpResultSet = new (std::nothrow) RdSingleVerResultSet(naturalStore, keyPrefix); + if (tmpResultSet == nullptr) { + LOGE("Create single version result set failed."); + return -E_OUT_OF_MEMORY; + } + int errCode = tmpResultSet->Open(false); + if (errCode != E_OK) { + delete tmpResultSet; + resultSet = nullptr; + tmpResultSet = nullptr; + LOGE("Open result set failed."); + return errCode; + } + resultSet = (IKvDBResultSet *)tmpResultSet; + kvDbResultSets_.insert(resultSet); + return E_OK; +} + +int RdSingleVerNaturalStoreConnection::GetResultSet(const IOption &option, + const Query &query, IKvDBResultSet *&resultSet) const +{ + // maximum of result set size is 4 + std::lock_guard lock(kvDbResultSetsMutex_); + if (kvDbResultSets_.size() >= maxResultSetSize) { + LOGE("Over max result set size"); + return -E_MAX_LIMITS; + } + + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + QueryParam queryParam; + int errCode = GetQueryParam(query, queryParam); + if (errCode != E_OK) { + LOGE("[RdSingleVerNaturalStoreConnection] GetQueryParam faild"); + return errCode; + } + RdSingleVerResultSet *tmpResultSet = new (std::nothrow) RdSingleVerResultSet(naturalStore, + queryParam.beginKey_, queryParam.endKey_, queryParam.kvScanMode_, ResultSetType::QUERY); + if (tmpResultSet == nullptr) { + LOGE("Create single version result set failed."); + return -E_OUT_OF_MEMORY; + } + errCode = tmpResultSet->Open(false); + if (errCode != E_OK) { + delete tmpResultSet; + resultSet = nullptr; + tmpResultSet = nullptr; + LOGE("Open result set failed."); + return errCode; + } + resultSet = (IKvDBResultSet *)tmpResultSet; + kvDbResultSets_.insert(resultSet); + return E_OK; +} + + +void RdSingleVerNaturalStoreConnection::ReleaseResultSet(IKvDBResultSet *&resultSet) +{ + if (resultSet == nullptr) { + return; + } + RdSingleVerResultSet *tmpResultSet = (RdSingleVerResultSet *)resultSet; + int errCode = tmpResultSet->Close(); + if (errCode != E_OK) { + LOGE("Open result set failed."); + return; + } + std::lock_guard lock(kvDbResultSetsMutex_); + kvDbResultSets_.erase(resultSet); + delete resultSet; + resultSet = nullptr; + return; +} + +int RdSingleVerNaturalStoreConnection::Pragma(int cmd, void *parameter) +{ + switch (cmd) { + case PRAGMA_EXEC_CHECKPOINT: + return ForceCheckPoint(); + default: + break; + } + LOGD("Rd Pragma only support check point for now:%d", cmd); + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStoreConnection::TranslateObserverModeToEventTypes( + unsigned mode, std::list &eventTypes) const +{ + int errCode = E_OK; + switch (mode) { + case static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT): + eventTypes.push_back(static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); + break; + default: + errCode = -E_NOT_SUPPORT; + break; + } + return errCode; +} + +int RdSingleVerNaturalStoreConnection::ForceCheckPoint() const +{ + int errCode = E_OK; + RdSingleVerStorageExecutor *handle = GetExecutor(false, errCode); + if (handle == nullptr) { + LOGE("[Connection]::[GetEntries] Get executor failed, errCode = [%d]", errCode); + return errCode; + } + + errCode = handle->ForceCheckPoint(); + ReleaseExecutor(handle); + return errCode; +} + +void RdSingleVerNaturalStoreConnection::CommitAndReleaseNotifyData( + SingleVerNaturalStoreCommitNotifyData *&committedData, bool isNeedCommit, int eventType) +{ + RdSingleVerNaturalStore *naturalStore = GetDB(); + if ((naturalStore != nullptr) && (committedData != nullptr)) { + if (isNeedCommit) { + if (!committedData->IsChangedDataEmpty()) { + naturalStore->CommitNotify(eventType, committedData); + } + } + } + ReleaseCommitData(committedData); +} + +int RdSingleVerNaturalStoreConnection::Get(const IOption &option, const Key &key, Value &value) const +{ + SingleVerDataType dataType; + int errCode = CheckOption(option, dataType); + if (errCode != E_OK) { + return errCode; + } + + if (key.size() > DBConstant::MAX_KEY_SIZE || key.empty()) { + return -E_INVALID_ARGS; + } + + errCode = CheckReadDataControlled(); + if (errCode != E_OK) { + LOGE("[Get] Do not allowed to read data with errCode = [%d]!", errCode); + return errCode; + } + + DBDfxAdapter::StartTracing(); + { + // need to check if the transaction started + std::lock_guard lock(transactionMutex_); + if (writeHandle_ != nullptr) { + Timestamp recordTimestamp; + errCode = writeHandle_->GetKvData(dataType, key, value, recordTimestamp); + DBDfxAdapter::FinishTraceSQL(); + return errCode; + } + } + RdSingleVerStorageExecutor *handle = GetExecutor(false, errCode); + if (handle == nullptr) { + DBDfxAdapter::FinishTraceSQL(); + return errCode; + } + + Timestamp timestamp; + errCode = handle->GetKvData(dataType, key, value, timestamp); + ReleaseExecutor(handle); + DBDfxAdapter::FinishTraceSQL(); + return errCode; +} + +// Clear all the data from the database +int RdSingleVerNaturalStoreConnection::Clear(const IOption &option) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStoreConnection::GetEntriesInner(const IOption &option, const Query &query, + std::vector &entries) const +{ + QueryParam queryParam; + int errCode = GetQueryParam(query, queryParam); + if (errCode != E_OK) { + LOGE("[RdSingleVerNaturalStoreConnection] GetQueryParam faild"); + return errCode; + } + SingleVerDataType type; + errCode = CheckOption(option, type); + if (errCode != E_OK) { + return errCode; + } + + DBDfxAdapter::StartTracing(); + { + std::lock_guard lock(transactionMutex_); + if (writeHandle_ != nullptr) { + LOGD("[RdSingleVerNaturalStoreConnection] Transaction started already."); + errCode = writeHandle_->GetEntries(queryParam, type, entries); + DBDfxAdapter::FinishTraceSQL(); + return errCode; + } + } + RdSingleVerStorageExecutor *handle = GetExecutor(false, errCode); + if (handle == nullptr) { + LOGE("[RdSingleVerNaturalStoreConnection]::[GetEntries] Get executor failed, errCode = [%d]", errCode); + DBDfxAdapter::FinishTraceSQL(); + return errCode; + } + + errCode = handle->GetEntries(queryParam, type, entries); + ReleaseExecutor(handle); + DBDfxAdapter::FinishTraceSQL(); + return errCode; +} +int RdSingleVerNaturalStoreConnection::GetEntries(const IOption &option, const Query &query, + std::vector &entries) const +{ + return GetEntriesInner(option, query, entries); +} + +int RdSingleVerNaturalStoreConnection::GetCount(const IOption &option, const Query &query, int &count) const +{ + return -E_NOT_SUPPORT; +} + +// Get the snapshot +int RdSingleVerNaturalStoreConnection::GetSnapshot(IKvDBSnapshot *&snapshot) const +{ + return -E_NOT_SUPPORT; +} + +// Release the created snapshot +void RdSingleVerNaturalStoreConnection::ReleaseSnapshot(IKvDBSnapshot *&snapshot) +{ + return; +} + +// Start the transaction +int RdSingleVerNaturalStoreConnection::StartTransaction() +{ + return -E_NOT_SUPPORT; +} + +// Commit the transaction +int RdSingleVerNaturalStoreConnection::Commit() +{ + return -E_NOT_SUPPORT; +} + +// Roll back the transaction +int RdSingleVerNaturalStoreConnection::RollBack() +{ + return -E_NOT_SUPPORT; +} + +// Check if the transaction already started manually +bool RdSingleVerNaturalStoreConnection::IsTransactionStarted() const +{ + return false; +} + +int RdSingleVerNaturalStoreConnection::Rekey(const CipherPassword &passwd) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStoreConnection::Export(const std::string &filePath, const CipherPassword &passwd) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStoreConnection::Import(const std::string &filePath, const CipherPassword &passwd) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStoreConnection::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) +{ + return -E_NOT_SUPPORT; +} + +// Called when Close and delete the connection. +int RdSingleVerNaturalStoreConnection::PreClose() +{ + // check if result set closed + std::lock_guard lock(kvDbResultSetsMutex_); + if (kvDbResultSets_.size() > 0) { + LOGE("The rd connection have [%zu] active result set, can not close.", kvDbResultSets_.size()); + return -E_BUSY; + } + // check if transaction closed + { + std::lock_guard transactionLock(transactionMutex_); + if (writeHandle_ != nullptr) { + LOGW("Transaction started, rollback before close."); + int errCode = RollbackInner(); + if (errCode != E_OK) { + LOGE("cannot rollback %d.", errCode); + } + ReleaseExecutor(writeHandle_); + } + } + return E_OK; +} + +int RdSingleVerNaturalStoreConnection::CheckIntegrity() const +{ + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + LOGE("[SingleVerConnection] the store is null"); + return -E_NOT_INIT; + } + return naturalStore->CheckIntegrity(); +} + +int RdSingleVerNaturalStoreConnection::GetKeys(const IOption &option, const Key &keyPrefix, + std::vector &keys) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStoreConnection::UpdateKey(const UpdateKeyCallback &callback) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerNaturalStoreConnection::CheckSyncEntriesValid(const std::vector &entries) const +{ + if (entries.size() > DBConstant::MAX_BATCH_SIZE) { + return -E_INVALID_ARGS; + } + + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + + for (const auto &entry : entries) { + int errCode = naturalStore->CheckDataStatus(entry.key, entry.value, false); + if (errCode != E_OK) { + return errCode; + } + } + return E_OK; +} + +int RdSingleVerNaturalStoreConnection::PutBatchInner(const IOption &option, const std::vector &entries) +{ + LOGD("PutBatchInner"); + std::lock_guard lock(transactionMutex_); + bool isAuto = false; + int errCode = E_OK; + if (option.dataType != IOption::SYNC_DATA) { + LOGE("LOCAL_DATA TYPE NOT SUPPORT in RD executor"); + return -E_NOT_SUPPORT; + } + if (writeHandle_ == nullptr) { + isAuto = true; + errCode = StartTransactionInner(TransactType::IMMEDIATE); + if (errCode != E_OK) { + return errCode; + } + } + + errCode = SaveSyncEntries(entries, false); + + if (isAuto) { + if (errCode == E_OK) { + errCode = CommitInner(); + } else { + int innerCode = RollbackInner(); + errCode = (innerCode != E_OK) ? innerCode : errCode; + } + } + return errCode; +} + +int RdSingleVerNaturalStoreConnection::SaveSyncEntries(const std::vector &entries, bool isDelete) +{ + if (IsSinglePutOrDelete(entries)) { + return SaveEntry(entries[0], isDelete); + } + return writeHandle_->BatchSaveEntries(entries, isDelete, committedData_); +} + +// This function currently only be called in local procedure to change sync_data table, do not use in sync procedure. +// It will check and amend value when need if it is a schema database. return error if some value disagree with the +// schema. But in sync procedure, we just neglect the value that disagree with schema. +int RdSingleVerNaturalStoreConnection::SaveEntry(const Entry &entry, bool isDelete, Timestamp timestamp) +{ + LOGD("Saving Entry"); + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + LOGE("[RdSingleVerNaturalStoreConnection][SaveEntry] the store is null"); + return -E_INVALID_DB; + } + + if (IsExtendedCacheDBMode()) { + return -E_NOT_SUPPORT; + } else { + return SaveEntryNormally(entry, isDelete); + } +} + +int RdSingleVerNaturalStoreConnection::SaveEntryNormally(const Entry &entry, bool isDelete) +{ + int errCode = writeHandle_->SaveSyncDataItem(entry, committedData_, isDelete); + if (errCode != E_OK) { + LOGE("Save entry failed, err:%d", errCode); + } + return errCode; +} + +RdSingleVerStorageExecutor *RdSingleVerNaturalStoreConnection::GetExecutor(bool isWrite, int &errCode) const +{ + LOGD("[RdSingleVerNaturalStoreConnection] Getting Executor "); + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + errCode = -E_NOT_INIT; + LOGE("[SingleVerConnection] the store is null"); + return nullptr; + } + return naturalStore->GetHandle(isWrite, errCode); +} + +void RdSingleVerNaturalStoreConnection::ReleaseExecutor(RdSingleVerStorageExecutor *&executor) const +{ + kvDB_->ReEnableConnection(OperatePerm::NORMAL_WRITE); + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore != nullptr) { + naturalStore->ReleaseHandle(executor); + } +} + +void RdSingleVerNaturalStoreConnection::ReleaseCommitData(SingleVerNaturalStoreCommitNotifyData *&committedData) +{ + if (committedData != nullptr) { + committedData->DecObjRef(committedData); + committedData = nullptr; + } +} + +int RdSingleVerNaturalStoreConnection::StartTransactionInner(TransactType transType) +{ + if (IsExtendedCacheDBMode()) { + return -E_NOT_SUPPORT; + } else { + return StartTransactionNormally(transType); + } +} + +int RdSingleVerNaturalStoreConnection::StartTransactionNormally(TransactType transType) +{ + int errCode = E_OK; + RdSingleVerStorageExecutor *handle = GetExecutor(true, errCode); + if (handle == nullptr) { + return errCode; + } + + errCode = kvDB_->TryToDisableConnection(OperatePerm::NORMAL_WRITE); + if (errCode != E_OK) { + ReleaseExecutor(handle); + LOGE("Start transaction failed, %d", errCode); + return errCode; + } + + if (committedData_ == nullptr) { + committedData_ = new (std::nothrow) SingleVerNaturalStoreCommitNotifyData; + if (committedData_ == nullptr) { + ReleaseExecutor(handle); + return -E_OUT_OF_MEMORY; + } + } + + errCode = handle->StartTransaction(transType); + if (errCode != E_OK) { + ReleaseExecutor(handle); + ReleaseCommitData(committedData_); + return errCode; + } + + writeHandle_ = handle; + return E_OK; +} + +int RdSingleVerNaturalStoreConnection::CommitInner() +{ + int errCode = writeHandle_->Commit(); + ReleaseExecutor(writeHandle_); + writeHandle_ = nullptr; + + CommitAndReleaseNotifyData(committedData_, true, + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT)); + return errCode; +} + +int RdSingleVerNaturalStoreConnection::RollbackInner() +{ + int errCode = writeHandle_->Rollback(); + ReleaseCommitData(committedData_); + ReleaseExecutor(writeHandle_); + writeHandle_ = nullptr; + return errCode; +} + +int RdSingleVerNaturalStoreConnection::CheckReadDataControlled() const +{ + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + LOGE("[SingleVerConnection] natural store is nullptr in CheckReadDataControlled."); + return E_OK; + } + return naturalStore->CheckReadDataControlled(); +} + +int RdSingleVerNaturalStoreConnection::CheckSyncKeysValid(const std::vector &keys) const +{ + if (keys.size() > DBConstant::MAX_BATCH_SIZE) { + return -E_INVALID_ARGS; + } + + RdSingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + + for (const auto &key : keys) { + int errCode = naturalStore->CheckDataStatus(key, {}, true); + if (errCode != E_OK) { + return errCode; + } + } + return E_OK; +} + +int RdSingleVerNaturalStoreConnection::DeleteBatchInner(const IOption &option, const std::vector &keys) +{ + DBDfxAdapter::StartTracing(); + bool isAuto = false; + int errCode = E_OK; + if (option.dataType != IOption::SYNC_DATA) { + LOGE("LOCAL_DATA TYPE NOT SUPPORT in RD executor"); + DBDfxAdapter::FinishTraceSQL(); + return -E_NOT_SUPPORT; + } + std::lock_guard lock(transactionMutex_); + if (writeHandle_ == nullptr) { + isAuto = true; + errCode = StartTransactionInner(TransactType::IMMEDIATE); + if (errCode != E_OK) { + DBDfxAdapter::FinishTraceSQL(); + return errCode; + } + } + + errCode = DeleteSyncEntries(keys); + + if (isAuto) { + if (errCode == E_OK) { + errCode = CommitInner(); + } else { + int innerCode = RollbackInner(); + errCode = (innerCode != E_OK) ? innerCode : errCode; + } + } + DBDfxAdapter::FinishTraceSQL(); + return errCode; +} + +int RdSingleVerNaturalStoreConnection::DeleteSyncEntries(const std::vector &keys) +{ + std::vector entries; + for (const auto &key : keys) { + Entry entry; + entry.key = std::move(key); + entries.emplace_back(std::move(entry)); + } + + int errCode = SaveSyncEntries(entries, true); + if ((errCode != E_OK) && (errCode != -E_NOT_FOUND)) { + LOGE("[DeleteSyncEntries] Delete data err:%d", errCode); + } + return (errCode == -E_NOT_FOUND) ? E_OK : errCode; +} + +int RdSingleVerNaturalStoreConnection::GetSyncDataSize(const std::string &device, size_t &size) const +{ + return -E_NOT_SUPPORT; +} +} +// namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h new file mode 100644 index 0000000000000000000000000000000000000000..39680da2f03cbcb4d71b9f4b7879e97c44096626 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_natural_store_connection.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RD_SINGLE_VER_NATURAL_STORE_CONNECTION_H +#define RD_SINGLE_VER_NATURAL_STORE_CONNECTION_H +#include + +#include "db_common.h" +#include "db_types.h" +#include "rd_single_ver_natural_store.h" +#include "rd_single_ver_storage_executor.h" +#include "runtime_context.h" +#include "sync_able_kvdb_connection.h" +#include "single_ver_natural_store_connection.h" + +namespace DistributedDB { +class SQLiteSingleVerNaturalStore; + +class RdSingleVerNaturalStoreConnection : public SingleVerNaturalStoreConnection { +public: + explicit RdSingleVerNaturalStoreConnection(RdSingleVerNaturalStore *kvDB); + ~RdSingleVerNaturalStoreConnection() override; + + // Delete the copy and assign constructors + DISABLE_COPY_ASSIGN_MOVE(RdSingleVerNaturalStoreConnection); + + // Get the value from the database + int Get(const IOption &option, const Key &key, Value &value) const override; + + // Clear all the data from the database + int Clear(const IOption &option) override; + + // Get all the data from the database + int GetEntries(const IOption &option, const Key &keyPrefix, std::vector &entries) const override; + + int GetEntries(const IOption &option, const Query &query, std::vector &entries) const override; + + int GetCount(const IOption &option, const Query &query, int &count) const override; + + // Get the snapshot + int GetSnapshot(IKvDBSnapshot *&snapshot) const override; + + // Release the created snapshot + void ReleaseSnapshot(IKvDBSnapshot *&snapshot) override; + + // Start the transaction + int StartTransaction() override; + + // Commit the transaction + int Commit() override; + + // Roll back the transaction + int RollBack() override; + + // Check if the transaction already started manually + bool IsTransactionStarted() const override; + + // Pragma interface. + int Pragma(int cmd, void *parameter) override; + + // Parse event types(from observer mode). + int TranslateObserverModeToEventTypes(unsigned mode, std::list &eventTypes) const override; + + int Rekey(const CipherPassword &passwd) override; + + int Export(const std::string &filePath, const CipherPassword &passwd) override; + + int Import(const std::string &filePath, const CipherPassword &passwd) override; + + // Get the result set + int GetResultSet(const IOption &option, const Key &keyPrefix, IKvDBResultSet *&resultSet) const override; + + int GetResultSet(const IOption &option, const Query &query, IKvDBResultSet *&resultSet) const override; + + // Release the result set + void ReleaseResultSet(IKvDBResultSet *&resultSet) override; + + int RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier) override; + + // Called when Close and delete the connection. + int PreClose() override; + + int CheckIntegrity() const override; + + int GetKeys(const IOption &option, const Key &keyPrefix, std::vector &keys) const override; + + int UpdateKey(const UpdateKeyCallback &callback) override; + + int GetSyncDataSize(const std::string &device, size_t &size) const override; + +private: + int GetEntriesInner(bool isGetValue, const IOption &option, + const Key &keyPrefix, std::vector &entries) const; + + int GetEntriesInner(const IOption &option, const Query &query, + std::vector &entries) const; + + static int CheckOption(const IOption &option, SingleVerDataType &type); + int ForceCheckPoint() const; + mutable std::mutex kvDbResultSetsMutex_; + mutable std::set kvDbResultSets_; + + // ResultSet Related Info + static constexpr std::size_t maxResultSetSize = 8; // Max 8 ResultSet At The Same Time + + int CheckSyncEntriesValid(const std::vector &entries) const override; + + int PutBatchInner(const IOption &option, const std::vector &entries) override; + + int SaveSyncEntries(const std::vector &entries, bool isDelete); + + // This func currently only be called in local procedure to change sync_data table, do not use in sync procedure. + // It will check and amend value when need if it is a schema database. return error if some value disagree with the + // schema. But in sync procedure, we just neglect the value that disagree with schema. + int SaveEntry(const Entry &entry, bool isDelete, Timestamp timestamp = 0); + + int SaveEntryNormally(const Entry &entry, bool isDelete); + + RdSingleVerStorageExecutor *GetExecutor(bool isWrite, int &errCode) const; + + void ReleaseExecutor(RdSingleVerStorageExecutor *&executor) const; + + void ReleaseCommitData(SingleVerNaturalStoreCommitNotifyData *&committedData); + + int StartTransactionInner(TransactType transType = TransactType::DEFERRED); + + int StartTransactionNormally(TransactType transType = TransactType::DEFERRED); + + int CommitInner(); + + int RollbackInner(); + + void CommitAndReleaseNotifyData(SingleVerNaturalStoreCommitNotifyData *&committedData, + bool isNeedCommit, int eventType); + + int CheckReadDataControlled() const; + + int CheckSyncKeysValid(const std::vector &keys) const override; + + int DeleteBatchInner(const IOption &option, const std::vector &keys) override; + + int DeleteSyncEntries(const std::vector &keys); + + bool IsSinglePutOrDelete(const std::vector &entries) + { + return entries.size() == 1; + } + + SingleVerNaturalStoreCommitNotifyData *committedData_; // used for transaction + + mutable std::mutex transactionMutex_; + RdSingleVerStorageExecutor *writeHandle_; // only existed while in transaction. +}; +} +#endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp new file mode 100644 index 0000000000000000000000000000000000000000..25971f5ba8151451dd952b207597f09e912e6024 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.cpp @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rd_single_ver_result_set.h" +#include "db_errno.h" +#include "grd_db_api.h" +#include "grd_resultset_api.h" +#include "log_print.h" +#include "rd_utils.h" +#include "sqlite_single_ver_storage_executor_sql.h" + +namespace DistributedDB { +RdSingleVerResultSet::RdSingleVerResultSet(RdSingleVerNaturalStore *kvDB, const Key &key) + : type_(ResultSetType::KEYPREFIX), key_(key), kvDB_(kvDB) +{ + kvScanMode_ = KV_SCAN_PREFIX; +} + +RdSingleVerResultSet::RdSingleVerResultSet(RdSingleVerNaturalStore *kvDB, const Key &beginKey, + const Key &endKey, GRD_KvScanModeE kvScanMode, const ResultSetType &ResultSetType) + : type_(ResultSetType), beginKey_(beginKey), endKey_(endKey), kvScanMode_(kvScanMode), kvDB_(kvDB) +{ + if (!endKey.empty() && !beginKey.empty()) { + isGetValueFromEntry_ = true; + } // Get data from entry_ that stored in resultSet; +} + +RdSingleVerResultSet::~RdSingleVerResultSet() +{ + isOpen_ = false; + position_ = INIT_POSITION; + kvDB_ = nullptr; + handle_ = nullptr; +} + +int RdSingleVerResultSet::Open(bool isMemDb) +{ + (void)isMemDb; + std::lock_guard lockGuard(mutex_); + if (isOpen_) { + LOGW("[RdSinResSet] Not need to open result set again!"); + return E_OK; + } + if (kvDB_ == nullptr) { // Unlikely + return -E_INVALID_ARGS; + } + if (type_ != ResultSetType::KEYPREFIX && type_ != ResultSetType::QUERY) { + LOGE("[RdSinResSet] Open result set only support prefix and query mode for now."); + return -E_INVALID_ARGS; + } + int errCode = E_OK; + handle_ = kvDB_->GetHandle(false, errCode); + if (handle_ == nullptr) { + LOGE("[RdSinResSet] Get handle failed, errCode=%d.", errCode); + return errCode; + } + switch (kvScanMode_) { + case KV_SCAN_PREFIX: { + errCode = handle_->OpenResultSet(key_, kvScanMode_, &resultSet_); + break; + } + case KV_SCAN_EQUAL_OR_GREATER_KEY: { + errCode = handle_->OpenResultSet(beginKey_, kvScanMode_, &resultSet_); + break; + } + case KV_SCAN_EQUAL_OR_LESS_KEY: { + errCode = handle_->OpenResultSet(endKey_, kvScanMode_, &resultSet_); + break; + } + default: + return -E_INVALID_ARGS; + } + if (errCode != E_OK) { + LOGE("[RdSinResSet] open result set failed, %d.", errCode); + kvDB_->ReleaseHandle(handle_); + return errCode; + } + isOpen_ = true; + return E_OK; +} + +int RdSingleVerResultSet::Close() +{ + std::lock_guard lockGuard(mutex_); + int errCode = PreCheckResultSet(); + if (errCode != E_OK) { + return errCode; + } + + errCode = handle_->CloseResultSet(resultSet_); + if (errCode != E_OK) { + LOGE("[RdSinResSet] close rd result set failed, errCode=%d.", errCode); + kvDB_->ReleaseHandle(handle_); + return errCode; + } + kvDB_->ReleaseHandle(handle_); + isOpen_ = false; + position_ = INIT_POSITION; + return E_OK; +} + +int RdSingleVerResultSet::PreCheckResultSet() const +{ + if (!isOpen_) { + LOGE("[RdSinResSet] Result set not open yet."); + return -E_RESULT_SET_STATUS_INVALID; + } + if (kvDB_ == nullptr) { // Unlikely + LOGE("[RdSinResSet] KvDB not set yet."); + return -E_INVALID_ARGS; + } + + if (handle_ == nullptr) { + LOGE("[RdSinResSet] Handle not set yet."); + return -E_INVALID_ARGS; + } + return E_OK; +} + +int RdSingleVerResultSet::GetCount() const +{ + int errCode = PreCheckResultSet(); + if (errCode != E_OK) { + return errCode; + } + int count = 0; + switch (kvScanMode_) { + case KV_SCAN_PREFIX: { + errCode = handle_->GetCount(key_, count, kvScanMode_, endKey_); + break; + } + case KV_SCAN_EQUAL_OR_GREATER_KEY: { + errCode = handle_->GetCount(beginKey_, count, kvScanMode_, endKey_); + break; + } + case KV_SCAN_EQUAL_OR_LESS_KEY: { + errCode = handle_->GetCount(endKey_, count, kvScanMode_, endKey_); + break; + } + default: + return -E_INVALID_ARGS; + } + if (errCode != E_OK && errCode != -E_RESULT_SET_EMPTY) { + return errCode; + } + return count; +} + +int RdSingleVerResultSet::GetPosition() const +{ + std::lock_guard lockGuard(mutex_); + return position_; +} + +int RdSingleVerResultSet::Move(int offset) const +{ + std::lock_guard lockGuard(mutex_); + int errCode = E_OK; + if (offset == 0) { + return errCode; + } + offset = offset > INT_MAX ? INT_MAX : offset; + offset = offset < INT_MIN ? INT_MIN : offset; + + while (offset > 0) { + errCode = MoveToNext(); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet] move by offset failed, errCode=%d, offset=%d", errCode, offset); + return errCode; + } + --offset; + if (errCode == -E_NOT_FOUND && offset >= 0) { + LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds, position: %d", offset, position_); + return -E_INVALID_ARGS; + } + } + while (offset < 0) { + errCode = MoveToPrev(); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet] move by offset failed, errCode=%d, offset=%d", errCode, offset); + return errCode; + } + ++offset; + if (errCode == -E_NOT_FOUND && offset <= 0) { + LOGE("[RdSingleVerStorageExecutor] move offset: %d, out of bounds, position: %d", offset, position_); + return -E_INVALID_ARGS; + } + } + return errCode; +} + +int RdSingleVerResultSet::MoveToNext() const +{ + int errCode = PreCheckResultSet(); + if (errCode != E_OK) { + LOGE("[RdSinResSet] PreCheckResultSet failed"); + return errCode; + } + + if (position_ == INIT_POSITION && isMovedBefore_) { + ++position_; + return E_OK; + } + errCode = handle_->MoveToNext(resultSet_); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet] move next failed, errCode=%d.", errCode); + return errCode; + } else if (errCode == -E_NOT_FOUND) { + if (!isMovedBefore_) { + LOGE("[RdSinResSet] move next failed, result set is empty"); + return -E_RESULT_SET_EMPTY; + } + // nothing to do when position_ equal with endposition_ which isn't equal with INIT_POSITION + if (endPosition_ == INIT_POSITION || position_ != endPosition_) { + ++position_; + endPosition_ = position_; + } + return errCode; + } else { + // E_OK + ++position_; + isMovedBefore_ = true; + if (position_ == endPosition_ && endPosition_ != INIT_POSITION) { + // incase we have chosen an end, but new data put in after that + endPosition_ = position_ + 1; + } + } + + if (isGetValueFromEntry_) { + errCode = CmpKeyAndStoreEntry(true); + if (errCode != E_OK) { + endPosition_ = position_; + LOGE("[RdSinResSet] CmpKeyAndStoreEntry failed"); + return errCode; + } + } + return errCode; +} + +int RdSingleVerResultSet::MoveToPrev() const +{ + int errCode = PreCheckResultSet(); + if (errCode != E_OK) { + LOGE("[RdSinResSet] PreCheckResultSet failed"); + return errCode; + } + + if (position_ == endPosition_ && endPosition_ != INIT_POSITION) { + --position_; + return E_OK; + } + + errCode = handle_->MoveToPrev(resultSet_); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet] move prev failed, errCode=%d.", errCode); + return errCode; + } + + if (errCode == -E_NOT_FOUND) { + position_ = INIT_POSITION; + } else { + if (position_ <= 0) { + position_ = 0; + } else { + --position_; + } + + if (isGetValueFromEntry_) { + errCode = CmpKeyAndStoreEntry(false); + if (errCode != E_OK) { + LOGE("[RdSinResSet] store entry faild"); + return errCode; + } + } + } + return errCode; +} + +int RdSingleVerResultSet::CmpKeyAndStoreEntry(bool isCmpKey) const +{ + Entry tmpEntry; + int ret = GetEntry(tmpEntry, false); + if (ret != E_OK) { + return -E_NOT_FOUND; + } + if (isCmpKey && RdSingleVerStorageExecutor::CompareKeyWithEndKey(tmpEntry.key, endKey_)) { + (void)MoveToPrev(); // whether MoveToPrev successfully or not,return NOT_FOUND. + return -E_NOT_FOUND; + } + entry_ = tmpEntry; + return E_OK; +} + +int RdSingleVerResultSet::MoveTo(int position) const +{ + int errCode = PreCheckResultSet(); + if (errCode != E_OK) { + return errCode; + } + + if (position < 0) { + LOGW("[RdSinResSet][MoveTo] Target Position=%d invalid.", position); + } + + return Move(position - position_); +} + +int RdSingleVerResultSet::MoveToFirst() +{ + if (!isMovedBefore_) { + return MoveToNext(); + } + if (position_ == INIT_POSITION) { + ++position_; + return E_OK; + } + + int errCode = E_OK; + do { + errCode = MoveToPrev(); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet] move to first failed, errCode=%d, position=%d", errCode, position_); + return errCode; + } + if (errCode == -E_NOT_FOUND) { + ++position_; + break; + } + } while (errCode == E_OK); + + return E_OK; +} + +int RdSingleVerResultSet::MoveToLast() +{ + int errCode = E_OK; + do { + errCode = MoveToNext(); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet] move to last failed, errCode=%d, position=%d", errCode, position_); + return errCode; + } + if (errCode == -E_NOT_FOUND) { + --position_; + break; + } + } while (errCode == E_OK); + + return E_OK; +} + +bool RdSingleVerResultSet::IsFirst() const +{ + int position = GetPosition(); + if (GetCount() == 0) { + return false; + } + if (position == 0) { + return true; + } + return false; +} + +bool RdSingleVerResultSet::IsLast() const +{ + int position = GetPosition(); + int count = GetCount(); + if (count == 0) { + return false; + } + if (position == (count - 1)) { + return true; + } + return false; +} + +bool RdSingleVerResultSet::IsBeforeFirst() const +{ + int position = GetPosition(); + + if (GetCount() == 0) { + return true; + } + if (position <= INIT_POSITION) { + return true; + } + return false; +} + +bool RdSingleVerResultSet::IsAfterLast() const +{ + int position = GetPosition(); + int count = GetCount(); + if (count == 0) { + return true; + } + if (position >= count) { + return true; + } + return false; +} + +int RdSingleVerResultSet::GetEntry(Entry &entry) const +{ + std::lock_guard lockGuard(mutex_); + int errCode = PreCheckResultSet(); + if (errCode != E_OK) { + return errCode; + } + + if (position_ == INIT_POSITION || (position_ == endPosition_ && endPosition_ != INIT_POSITION)) { + return -E_NO_SUCH_ENTRY; + } + + if (!isGetValueFromEntry_) { + errCode = handle_->GetEntry(resultSet_, entry); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet][GetEntry] failed to get entry form result set."); + } + } else { + if (position_ >= endPosition_ && endPosition_ != INIT_POSITION) { + return -E_NOT_FOUND; + } + entry = entry_; + } + return errCode == -E_NOT_FOUND ? -E_NO_SUCH_ENTRY : errCode; +} + +int RdSingleVerResultSet::GetEntry(Entry &entry, bool isGetValueFromEntry) const +{ + int errCode = PreCheckResultSet(); + if (errCode != E_OK) { + return errCode; + } + if (!isGetValueFromEntry) { + errCode = handle_->GetEntry(resultSet_, entry); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSinResSet][GetEntry] failed to get entry form result set."); + } + } else { + entry = entry_; + } + return errCode == -E_NOT_FOUND ? -E_NO_SUCH_ENTRY : errCode; +} + +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.h new file mode 100644 index 0000000000000000000000000000000000000000..81e637b8dd3e2b09fc71b04c7a0bc4e22145b585 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_result_set.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RD_SINGLE_VER_RESULT_SET_H +#define RD_SINGLE_VER_RESULT_SET_H +#include "ikvdb_result_set.h" +#include "grd_resultset_api.h" +#include "rd_single_ver_natural_store.h" +#include "rd_single_ver_storage_executor.h" + +namespace DistributedDB { +class RdSingleVerResultSet : public IKvDBResultSet { +public: + RdSingleVerResultSet(RdSingleVerNaturalStore *kvDB, const Key &key); + RdSingleVerResultSet(RdSingleVerNaturalStore *kvDB, const Key &beginKey, + const Key &endKey, GRD_KvScanModeE kvScanMode, const ResultSetType &ResultSetType); + ~RdSingleVerResultSet() override; + + // Initialize logic + int Open(bool isMemDb) override; + + // Finalize logic + int Close() override; + + // Get total entries count. + // >= 0: count, < 0: errCode. + int GetCount() const override; + + // Get current read position. + // >= 0: position, < 0: errCode + int GetPosition() const override; + + int Move(int offset) const override; + + // Move the read position to an absolute position value. + int MoveTo(int position) const override; + + int MoveToFirst() override; + + int MoveToLast() override; + + bool IsFirst() const override; + + bool IsLast() const override; + + bool IsBeforeFirst() const override; + + bool IsAfterLast() const override; + + // Get the entry of current position. + int GetEntry(Entry &entry) const override; + + int GetEntry(Entry &entry, bool isGetValueFromEntry) const; + +private: + int PreCheckResultSet() const; + + int MoveToNext() const; + + int MoveToPrev() const; + + int CmpKeyAndStoreEntry(bool isCmpKey = true) const; + + mutable std::mutex mutex_; + + mutable bool isOpen_ = false; + + mutable int position_ = INIT_POSITION; // The position in the overall result + + mutable int endPosition_ = INIT_POSITION; // the position after the last position, if find + + mutable bool isMovedBefore_ = false; + + // For KeyPrefix Type Or Query Type. + ResultSetType type_ = ResultSetType::KEYPREFIX; + + Key key_; + + Key beginKey_; + + Key endKey_; + + GRD_KvScanModeE kvScanMode_ = KV_SCAN_PREFIX; + + mutable bool isGetValueFromEntry_ = false; + + mutable Entry entry_; + + // Common Pointer For Use, Not Own it, Not Responsible To Release It. + RdSingleVerNaturalStore *kvDB_ = nullptr; + + // Cache EntryId Mode Using StorageExecutor, Own It, Responsible To Release It. + RdSingleVerStorageExecutor *handle_ = nullptr; + + GRD_ResultSet *resultSet_ = nullptr; +}; +} // namespace DistributedDB +#endif // RD_SINGLE_VER_RESULT_SET_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aaefb67a07146e64f16c210ed54de6a7e0a8bf90 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.cpp @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rd_single_ver_storage_engine.h" + +#include "grd_error.h" +#include "grd_type_export.h" +#include "rd_single_ver_storage_executor.h" +#include "rd_utils.h" +#include "single_ver_utils.h" +#include "sqlite_single_ver_storage_executor_sql.h" + +namespace DistributedDB { + +RdSingleVerStorageEngine::RdSingleVerStorageEngine() +{ + LOGD("[RdSingleVerStorageEngine] RdSingleVerStorageEngine Created"); +} + +RdSingleVerStorageEngine::~RdSingleVerStorageEngine() +{ +} + +int RdSingleVerStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handle) +{ + int ret = PreCreateExecutor(isWrite); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageEngine][CreateNewExecutor] PreCreateExecutor unscuccess"); + return ret; + } + GRD_DB *db = nullptr; + ret = TryToOpenMainDatabase(isWrite, db); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageEngine] GRD_DBOPEN FAILED:%d", ret); + return ret; + } + if (!option_.readOnly) { + ret = TransferGrdErrno(GRD_CreateCollection(db, SYNC_COLLECTION_NAME.c_str(), + DBConstant::RD_KV_COLLECTION_MODE.c_str(), 0)); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageEngine] GRD_CreateCollection SYNC_COLLECTION_NAME FAILED %d", ret); + return ret; + } + } + ret = TransferGrdErrno(IndexPreLoad(db, SYNC_COLLECTION_NAME.c_str())); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageEngine] GRD_IndexPreload FAILED %d", ret); + return ret; + } + handle = new (std::nothrow) RdSingleVerStorageExecutor(db, isWrite); + if (handle == nullptr) { + return -E_OUT_OF_MEMORY; + } + if (OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && + OS::RemoveFile(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { + LOGE("Finish to create the complete database, but delete token fail! errCode = [E_SYSTEM_API_FAIL]"); + return -E_SYSTEM_API_FAIL; + } + return E_OK; +} + +int RdSingleVerStorageEngine::InitRdStorageEngine(const StorageEngineAttr &poolSize, const OpenDbProperties &option, + const std::string &identifier) +{ + if (StorageEngine::CheckEngineAttr(poolSize)) { + LOGE("Invalid storage engine attributes!"); + return -E_INVALID_ARGS; + } + engineAttr_ = poolSize; + option_ = option; + identifier_ = identifier; + int errCode = Init(); + if (errCode != E_OK) { + LOGI("Storage engine init fail! errCode = [%d]", errCode); + } + return errCode; +} + +int RdSingleVerStorageEngine::GetExistedSecOption(SecurityOption &secOption) const +{ + LOGD("[RdSingleVerStorageEngine] Try to get existed sec option"); + return GetExistedSecOpt(option_, secOption); +} + +int RdSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secOption) const +{ + if (!(secOption == option_.securityOpt) && + secOption.securityLabel != SecurityLabel::NOT_SET && + option_.securityOpt.securityLabel != SecurityLabel::NOT_SET) { + LOGE("[RdSingleVerStorageEngine] SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]", + secOption.securityLabel, secOption.securityFlag, option_.securityOpt.securityLabel, + option_.securityOpt.securityFlag); + return -E_SECURITY_OPTION_CHECK_ERROR; + } + return E_OK; +} + +int RdSingleVerStorageEngine::CreateNewDirsAndSetSecOpt() const +{ + LOGD("[RdSingleVerStorageEngine] Begin to create new dirs and set security option"); + return CreateNewDirsAndSetSecOption(option_); +} + +int RdSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, GRD_DB *&db) +{ + // Only could get the main database handle in the uninitialized and the main status. + if (GetEngineState() != EngineState::INVALID && GetEngineState() != EngineState::MAINDB) { + LOGE("[RdSinStoreEng][GetMainHandle] Can only create new handle for state[%d]", GetEngineState()); + return -E_EKEYREVOKED; + } + + option_.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + + DBConstant::DB_EXTENSION; + + OpenDbProperties optionTemp = option_; + if (!isWrite) { + optionTemp.createIfNecessary = false; + } + int errCode = E_OK; + bool isNeedUpdateCrcCheck = true; + if (OS::CheckPathExistence(optionTemp.uri)) { + errCode = CrcCheckIfNeed(optionTemp); + if (errCode != E_OK) { + LOGE("crc check failed [%d]", errCode); + return errCode; + } + isNeedUpdateCrcCheck = false; + } + errCode = OpenGrdDb(optionTemp, db); + if (errCode != E_OK) { + LOGE("Failed to open the main database [%d]", errCode); + return errCode; + } + if (isNeedUpdateCrcCheck) { + crcCheck_ = true; + } + + // Set the engine state to main status for that the main database is valid. + SetEngineState(EngineState::MAINDB); + return errCode; +} + +int RdSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption &secOpt, GRD_DB *&dbHandle) +{ + int errCode = TryToOpenMainDatabase(isWrite, dbHandle); + LOGD("Finish to open the main database, write[%d], label[%d], flag[%d], id[%.6s], errCode[%d]", isWrite, + secOpt.securityLabel, secOpt.securityFlag, DBCommon::TransferStringToHex(identifier_).c_str(), errCode); + if (!(ParamCheckUtils::IsS3SECEOpt(secOpt) && errCode == -E_EKEYREVOKED)) { + return errCode; + } + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageEngine::PreCreateExecutor(bool isWrite) +{ + if (!isWrite) { + return E_OK; + } + // Get the existed database secure option. + SecurityOption existedSecOpt; + int ret = GetExistedSecOption(existedSecOpt); + if (ret != E_OK) { + LOGD("[RdSingleVerStorageEngine][PreCreateExecutor]Something unexpected happened"); + return ret; + } + ret = CheckDatabaseSecOpt(existedSecOpt); + if (ret != E_OK) { + LOGD("[RdSingleVerStorageEngine][CheckDatabaseSecOpt]Something unexpected happened"); + return ret; + } + ret = CreateNewDirsAndSetSecOpt(); + if (ret != E_OK) { + LOGD("[RdSingleVerStorageEngine][CreateNewDirsAndSetSecOpt]Something unexpected happened"); + } + return ret; +} + +int RdSingleVerStorageEngine::OpenGrdDb(const OpenDbProperties &option, GRD_DB *&db) +{ + uint32_t flag = GRD_DB_OPEN_ONLY; + if (option.createIfNecessary && !option.readOnly) { + flag |= GRD_DB_OPEN_CREATE; + } + if (!option.readOnly && (option.isNeedIntegrityCheck || option.isNeedRmCorruptedDb)) { + flag |= GRD_DB_OPEN_CHECK; + } + if (option.readOnly) { + flag |= GRD_DB_OPEN_SHARED_READ_ONLY; + } + int errCode = RdDbOpen(option.uri.c_str(), option.rdConfig.c_str(), flag, db); + if (errCode == -E_REBUILD_DATABASE) { + if (option.isNeedRmCorruptedDb) { + LOGD("[RdSingleVerStorageEngine] rebuild database successfully"); + return E_OK; + } else { + LOGE("[RdSingleVerStorageEngine] database is corrupted"); + return -E_INVALID_PASSWD_OR_CORRUPTED_DB; + } + } + return errCode; +} + +int RdSingleVerStorageEngine::IndexPreLoad(GRD_DB *&db, const char *collectionName) +{ + return RdIndexPreload(db, collectionName); +} + +int RdSingleVerStorageEngine::CrcCheckIfNeed(const OpenDbProperties &option) +{ + if (!option.isNeedIntegrityCheck || crcCheck_) { + return E_OK; + } + int errCode = RdCrcCheck(option.uri.c_str()); + if (errCode != E_OK && errCode != -E_INVALID_PASSWD_OR_CORRUPTED_DB) { + return errCode; + } + if (option.readOnly && errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) { + LOGE("crc check failed [%d], read process can not open", errCode); + return errCode; + } + if (errCode != E_OK && !option.readOnly && !option.isNeedRmCorruptedDb) { + LOGE("crc check failed [%d], write process can not open", errCode); + return errCode; + } + crcCheck_ = true; + return E_OK; +} + +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h new file mode 100644 index 0000000000000000000000000000000000000000..81d39b33af8e4f87c99cc5957b77a5e838731cfc --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_engine.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RD_SINGLE_VER_STORAGE_ENGINE_H +#define RD_SINGLE_VER_STORAGE_ENGINE_H + +#include "db_common.h" +#include "grd_db_api.h" +#include "param_check_utils.h" +#include "platform_specific.h" +#include "runtime_context.h" +#include "single_ver_utils.h" +#include "sqlite_utils.h" +#include "storage_engine.h" + +namespace DistributedDB { +class RdSingleVerStorageEngine : public StorageEngine { +public: + RdSingleVerStorageEngine(); + ~RdSingleVerStorageEngine() override; + + int InitRdStorageEngine(const StorageEngineAttr &poolSize, const OpenDbProperties &option, + const std::string &identifier = std::string()); + +protected: + int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) override; + +private: + int PreCreateExecutor(bool isWrite); + + int GetExistedSecOption(SecurityOption &secOption) const; + + int CheckDatabaseSecOpt(const SecurityOption &secOption) const; + + int CreateNewDirsAndSetSecOpt() const; + + int TryToOpenMainDatabase(bool isWrite, GRD_DB *&db); + + int GetDbHandle(bool isWrite, const SecurityOption &secOpt, GRD_DB *&dbHandle); + + int OpenGrdDb(const OpenDbProperties &option, GRD_DB *&db); + + int IndexPreLoad(GRD_DB *&db, const char *collectionName); + + int CrcCheckIfNeed(const OpenDbProperties &dbFile); + + std::atomic crcCheck_ = false; +}; +} // namespace DistributedDB +#endif // RD_SINGLE_VER_STORAGE_ENGINE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3632cd34e02e8b03bc6bc6f2a22db887c847d367 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.cpp @@ -0,0 +1,890 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rd_single_ver_storage_executor.h" + +#include +#include + +#include "db_common.h" +#include "grd_db_api.h" +#include "grd_document_api.h" +#include "grd_error.h" +#include "grd_resultset_api.h" +#include "ikvdb_result_set.h" +#include "rd_utils.h" +#include "sqlite_single_ver_storage_executor_sql.h" +#include "get_query_info.h" +#include "grd_type_export.h" + +namespace DistributedDB { +int GetQueryParam(const Query &query, QueryParam &queryParam) +{ + QueryExpression queryExpression = GetQueryInfo::GetQueryExpression(query); + std::list queryObjNodes_ = queryExpression.GetQueryExpression(); + if (queryObjNodes_.size() > 1) { // Only Support one query filter. + return -E_INVALID_ARGS; + } + for (const auto &queryObjNode : queryObjNodes_) { + if (queryObjNode.operFlag != QueryObjType::KEY_RANGE) { + return -E_INVALID_ARGS; + } + } + queryParam.beginKey_ = queryExpression.GetBeginKey(); + queryParam.endKey_ = queryExpression.GetEndKey(); + if (queryParam.beginKey_.size() > DBConstant::MAX_KEY_SIZE || + queryParam.endKey_.size() > DBConstant::MAX_KEY_SIZE) { + return -E_INVALID_ARGS; + } + if (!queryParam.beginKey_.empty() || queryParam.endKey_.empty()) { + queryParam.kvScanMode_ = KV_SCAN_EQUAL_OR_GREATER_KEY; + } else { + queryParam.kvScanMode_ = KV_SCAN_EQUAL_OR_LESS_KEY; + } + return E_OK; +} + +int GetQueryParam(const Key &keyPrefix, QueryParam &queryParam) +{ + queryParam.kvScanMode_ = KV_SCAN_PREFIX; + queryParam.keyPrefix_ = keyPrefix; + return E_OK; +} + +RDStorageExecutor::RDStorageExecutor(GRD_DB *db, bool isWrite) : StorageExecutor(isWrite), db_(db) +{ +} + +RDStorageExecutor::~RDStorageExecutor() +{ +} + +int RDStorageExecutor::Reset() +{ + LOGW("[RdSingleVerStorageExecutor] Not support Reset rd single ver storage executor"); + return -E_NOT_SUPPORT; +} + +int RDStorageExecutor::GetDbHandle(GRD_DB *&dbHandle) const +{ + dbHandle = db_; + return E_OK; +} + +RdSingleVerStorageExecutor::RdSingleVerStorageExecutor(GRD_DB *db, bool isWrite) : RDStorageExecutor(db, isWrite) +{ + LOGD("[RdSingleVerStorageExecutor] RdSingleVerStorageExecutor Created"); +} + +RdSingleVerStorageExecutor::~RdSingleVerStorageExecutor() +{ + int ret = GRD_OK; + if (db_ != nullptr) { + ret = RdDBClose(db_, 0); + LOGD("[RdSingleVerStorageExecutor] rd has been closed"); + } + if (ret != GRD_OK) { + LOGE("Can not close db %d", ret); + } + db_ = nullptr; + LOGD("[RdSingleVerStorageExecutor] RdSingleVerStorageExecutor has been deconstructed"); +} + +int RdSingleVerStorageExecutor::OpenResultSet(const Key &key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet) +{ + int errCode = RdKVScan(db_, SYNC_COLLECTION_NAME.c_str(), key, mode, resultSet); + if (errCode != E_OK) { + LOGE("Can not open rd result set."); + } + return errCode; +} + +int RdSingleVerStorageExecutor::CloseResultSet(GRD_ResultSet *resultSet) +{ + int errCode = RdFreeResultSet(resultSet); + if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to free result set."); + } + return errCode; +} + +int RdSingleVerStorageExecutor::InnerMoveToHead(const int position, GRD_ResultSet *resultSet, int &currPosition) +{ + int errCode = E_OK; + while (true) { + errCode = TransferGrdErrno(GRD_Prev(resultSet)); + if (errCode == -E_NOT_FOUND) { + currPosition = 0; + int ret = TransferGrdErrno(GRD_Next(resultSet)); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to move next for result set."); + currPosition = position <= INIT_POSITION ? INIT_POSITION : currPosition; + return ret; + } + ret = TransferGrdErrno(GRD_Prev(resultSet)); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to move prev for result set."); + return ret; + } + break; + } else if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to move prev for result set."); + return errCode; + } + currPosition--; + } + return E_OK; +} + +bool RdSingleVerStorageExecutor::CompareKeyWithEndKey(const Key &key, const Key &keyEnd) +{ + return key > keyEnd; +} + +int RdSingleVerStorageExecutor::CompareKeyAndStoreEntry(GRD_ResultSet *resultSet, const Key &keyEnd, + bool isNeedStore, Entry &entry_) +{ + if (!keyEnd.empty()) { + Entry tmpEntry; + int errCode = RdKvFetch(resultSet, tmpEntry.key, tmpEntry.value); + if (errCode != E_OK || CompareKeyWithEndKey(tmpEntry.key, keyEnd)) { + return -E_NOT_FOUND; + } else { + if (isNeedStore) { + entry_ = tmpEntry; // store the entry. + } + } + } + return E_OK; +} + +int RdSingleVerStorageExecutor::MoveTo(const int position, GRD_ResultSet *resultSet, int &currPosition, + Entry &entry_, const Key &keyEnd) +{ + int errCode = E_OK; // incase it never been move before + if (currPosition == INIT_POSITION) { + errCode = TransferGrdErrno(GRD_Next(resultSet)); // but when we have only 1 element ? + if (errCode == -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor] result set is empty when move to"); + return -E_RESULT_SET_EMPTY; + } + if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to move next for result set."); + return errCode; + } + currPosition++; + } + errCode = InnerMoveToHead(position, resultSet, currPosition); + if (errCode != E_OK) { + return errCode; + } + if (position <= INIT_POSITION) { + LOGE("[RdSingleVerStorageExecutor] current position must > -1 when move to."); + int ret = TransferGrdErrno(GRD_Prev(resultSet)); + if (ret != E_OK && ret != -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor] failed to move prev for result set."); + return ret; + } + currPosition = -1; + return -E_INVALID_ARGS; + } + currPosition = 0; + while (currPosition < position) { + errCode = TransferGrdErrno(GRD_Next(resultSet)); + if (errCode == -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor] move to position: %d, out of bounds", position); + currPosition++; + return -E_INVALID_ARGS; + } else if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to move next for result set."); + return errCode; + } + errCode = CompareKeyAndStoreEntry(resultSet, keyEnd, true, entry_); + if (errCode != E_OK) { + return -E_NOT_FOUND; // Current Key is bigger than End Key, return no found. + } + currPosition++; + } + return E_OK; +} + +int RdSingleVerStorageExecutor::MoveToNext(GRD_ResultSet *resultSet) +{ + int errCode = TransferGrdErrno(GRD_Next(resultSet)); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor] failed to move next for result set."); + } + return errCode; +} + +int RdSingleVerStorageExecutor::MoveToPrev(GRD_ResultSet *resultSet) +{ + int errCode = TransferGrdErrno(GRD_Prev(resultSet)); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor] failed to move prev for result set."); + } + return errCode; +} + +int RdSingleVerStorageExecutor::GetEntry(GRD_ResultSet *resultSet, Entry &entry) +{ + int errCode = RdKvFetch(resultSet, entry.key, entry.value); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor] failed to get entry form result set."); + } + return errCode; +} + +int RdSingleVerStorageExecutor::GetCount(const Key &key, int &count, GRD_KvScanModeE kvScanMode, const Key &keyEnd) +{ + count = 0; + GRD_ResultSet *tmpResultSet = nullptr; + int errCode = RdKVScan(db_, SYNC_COLLECTION_NAME.c_str(), key, kvScanMode, &tmpResultSet); + if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to get count for current key."); + return errCode; + } + bool isFirstMove = true; + int ret = E_OK; + while (errCode == E_OK) { + errCode = TransferGrdErrno(GRD_Next(tmpResultSet)); + if (isFirstMove && errCode == -E_NOT_FOUND) { + ret = CloseResultSet(tmpResultSet); + if (ret != E_OK) { + return ret; + } + return -E_RESULT_SET_EMPTY; + } else if (errCode == -E_NOT_FOUND) { + break; + } else if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to get count when move next."); + ret = CloseResultSet(tmpResultSet); + if (ret != E_OK) { + return ret; + } + return errCode; + } + Entry entryTmp; + errCode = CompareKeyAndStoreEntry(tmpResultSet, keyEnd, false, entryTmp); + if (errCode != E_OK) { + break; // No need to return errCode when GetCount. + } + ++count; + isFirstMove = false; + } + ret = CloseResultSet(tmpResultSet); + if (ret != E_OK) { + return ret; + } + return E_OK; +} + +int RdSingleVerStorageExecutor::PrepareNotifyForEntries(const std::vector &entries, + SingleVerNaturalStoreCommitNotifyData *committedData, std::vector ¬ifys, + bool isDelete) +{ + for (const auto &entry : entries) { + NotifyConflictAndObserverData notify = { + .committedData = committedData + }; + int errCode = PrepareForNotifyConflictAndObserver(entry, notify, isDelete); + if (errCode != E_OK) { + return errCode; + } + notifys.push_back(notify); + } + return E_OK; +} + +int RdSingleVerStorageExecutor::GetKvData(SingleVerDataType type, const Key &key, Value &value, + Timestamp ×tamp) const +{ + if (key.empty()) { + LOGE("[RdSingleVerStorageExecutor][GetKvData] empty key."); + return -E_INVALID_ARGS; + } + + return RdKVGet(db_, SYNC_COLLECTION_NAME.c_str(), key, value); +} + +int RdSingleVerStorageExecutor::ClearEntriesAndFreeResultSet(std::vector &entries, GRD_ResultSet *resultSet) +{ + entries.clear(); + entries.shrink_to_fit(); + int errCode = RdFreeResultSet(resultSet); + if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to free result set."); + } + return errCode; +} + +int RdSingleVerStorageExecutor::GetEntriesPrepare(GRD_DB *db, SingleVerDataType type, const QueryParam &queryParam, + std::vector &entries, GRD_ResultSet **resultSet) +{ + if (type != SingleVerDataType::SYNC_TYPE) { + LOGE("[RdSingleVerStorageExecutor][GetEntries]unsupported data type"); + return -E_INVALID_ARGS; + } + int ret = E_OK; + switch (queryParam.kvScanMode_) { + case KV_SCAN_PREFIX: + ret = RdKVScan(db, SYNC_COLLECTION_NAME.c_str(), queryParam.keyPrefix_, KV_SCAN_PREFIX, resultSet); + break; + case KV_SCAN_EQUAL_OR_GREATER_KEY: + ret = RdKVScan(db, SYNC_COLLECTION_NAME.c_str(), queryParam.beginKey_, + KV_SCAN_EQUAL_OR_GREATER_KEY, resultSet); + break; + case KV_SCAN_EQUAL_OR_LESS_KEY: + ret = RdKVScan(db, SYNC_COLLECTION_NAME.c_str(), queryParam.endKey_, KV_SCAN_EQUAL_OR_LESS_KEY, resultSet); + break; + default: + break; + } + if (ret != E_OK) { + LOGE("[RdSingleVerStorageExecutor][GetEntries]ERROR %d", ret); + return ret; + } + entries.clear(); + entries.shrink_to_fit(); + return E_OK; +} + +int RdSingleVerStorageExecutor::GetEntries(bool isGetValue, SingleVerDataType type, const Key &keyPrefix, + std::vector &entries) const +{ + (void)isGetValue; + GRD_ResultSet *resultSet = nullptr; + QueryParam queryParam; + int ret = GetQueryParam(keyPrefix, queryParam); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageExecutor] Init rd QueryObject fail"); + return ret; + } + ret = GetEntriesPrepare(db_, type, queryParam, entries, &resultSet); + if (ret != E_OK) { + return ret; + } + int innerCode = E_OK; + ret = TransferGrdErrno(GRD_Next(resultSet)); + if (ret == -E_NOT_FOUND) { + innerCode = ClearEntriesAndFreeResultSet(entries, resultSet); + if (innerCode != E_OK) { + return innerCode; + } + return ret; + } + while (ret == E_OK) { + Entry tmpEntry; + ret = RdKvFetch(resultSet, tmpEntry.key, tmpEntry.value); + if (ret != E_OK && ret != -E_NOT_FOUND) { + LOGE("RdSingleVerStorageExecutor][GetEntries]fail to fetch, %d", ret); + innerCode = ClearEntriesAndFreeResultSet(entries, resultSet); + if (innerCode != E_OK) { + return innerCode; + } + return ret; + } + entries.push_back(std::move(tmpEntry)); + ret = TransferGrdErrno(GRD_Next(resultSet)); + } + if (ret != -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor][GetEntries]fail to move, %d", ret); + innerCode = ClearEntriesAndFreeResultSet(entries, resultSet); + if (innerCode != E_OK) { + return innerCode; + } + return ret; + } + ret = RdFreeResultSet(resultSet); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to free result set."); + return ret; + } + return E_OK; +} + +int RdSingleVerStorageExecutor::GetEntries(QueryParam &queryParam, SingleVerDataType type, + std::vector &entries) const +{ + GRD_ResultSet *resultSet = nullptr; + int ret = GetEntriesPrepare(db_, type, queryParam, entries, &resultSet); + if (ret != E_OK) { + return ret; + } + + int innerCode = E_OK; + ret = TransferGrdErrno(GRD_Next(resultSet)); + if (ret == -E_NOT_FOUND) { + innerCode = ClearEntriesAndFreeResultSet(entries, resultSet); + if (innerCode != E_OK) { + return innerCode; + } + return ret; + } + while (ret == E_OK) { + Entry tmpEntry; + ret = RdKvFetch(resultSet, tmpEntry.key, tmpEntry.value); + if (ret != E_OK && ret != -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor][GetEntries]fail to fetch, %d", ret); + innerCode = ClearEntriesAndFreeResultSet(entries, resultSet); + if (innerCode != E_OK) { + return innerCode; + } + return ret; + } + if (!queryParam.endKey_.empty() && !queryParam.beginKey_.empty()) { + if (CompareKeyWithEndKey(tmpEntry.key, queryParam.endKey_)) { + ret = -E_NOT_FOUND; + break; + } + } + entries.push_back(std::move(tmpEntry)); + ret = TransferGrdErrno(GRD_Next(resultSet)); + } + if (ret != -E_NOT_FOUND) { + LOGE("[RdSingleVerStorageExecutor][GetEntries]fail to move, %d", ret); + innerCode = ClearEntriesAndFreeResultSet(entries, resultSet); + if (innerCode != E_OK) { + return innerCode; + } + return ret; + } + + ret = RdFreeResultSet(resultSet); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageExecutor] failed to free result set."); + return ret; + } + return E_OK; +} + +int RdSingleVerStorageExecutor::ForceCheckPoint() const +{ + return RdFlush(db_, 0); +} + +int RdSingleVerStorageExecutor::SaveKvData(SingleVerDataType type, const Key &key, const Value &value) +{ + std::string collectionName; + int ret = GetCollNameFromType(type, collectionName); + if (ret != E_OK) { + LOGE("Can not GetCollNameFromType"); + return ret; + } + return RdKVPut(db_, collectionName.c_str(), key, value); +} + +int RdSingleVerStorageExecutor::DelKvData(const Key &key) +{ + return RdKVDel(db_, SYNC_COLLECTION_NAME.c_str(), key); +} + +int RdSingleVerStorageExecutor::BatchSaveEntries(const std::vector &entries, bool isDelete, + SingleVerNaturalStoreCommitNotifyData *committedData) +{ + GRD_KVBatchT *batch = nullptr; + int ret = RdKVBatchPrepare(entries.size(), &batch); + if (ret != E_OK) { + LOGE("[RdSingleVerStorageExecutor][BatchSaveEntries] Can not prepare KVBatch structure"); + return ret; + } + for (const auto &entry : entries) { + ret = RdKVBatchPushback(batch, entry.key, entry.value); + if (ret != E_OK) { + (void)RdKVBatchDestroy(batch); + LOGE("[RdSingleVerStorageExecutor][BatchSaveEntries] Can not push back entries to KVBatch structure"); + return ret; + } + } + std::vector notifys; + ret = PrepareNotifyForEntries(entries, committedData, notifys, isDelete); + if (ret != E_OK) { + (void)RdKVBatchDestroy(batch); + return ret; + } + if (isDelete) { + ret = RdKVBatchDel(db_, SYNC_COLLECTION_NAME.c_str(), batch); + } else { + ret = RdKVBatchPut(db_, SYNC_COLLECTION_NAME.c_str(), batch); + } + if (ret != E_OK) { + (void)RdKVBatchDestroy(batch); + LOGE("[RdSingleVerStorageExecutor][BatchSaveEntries] Can not put or delete batchly with mode %d", isDelete); + return ret; + } else { + for (size_t i = 0; i < entries.size(); i++) { + PutIntoCommittedData(entries[i].key, entries[i].value, notifys[i]); + } + } + int errCode = RdKVBatchDestroy(batch); + if (errCode != E_OK) { + LOGE("[RdSingleVerStorageExecutor][BatchSaveEntries] Can not destroy batch %d", isDelete); + } + return ret; +} + +int RdSingleVerStorageExecutor::GetKvDataByHashKey(const Key &hashKey, SingleVerRecord &result) const +{ + return -E_NOT_SUPPORT; +} + +// Put the Kv data according the type(meta and the local data). +int RdSingleVerStorageExecutor::PutKvData(SingleVerDataType type, const Key &key, const Value &value, + Timestamp timestamp, SingleVerNaturalStoreCommitNotifyData *committedData) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetEntries(QueryObject &queryObj, std::vector &entries) const +{ + return -E_NOT_SUPPORT; +} + +// Get all the meta keys. +int RdSingleVerStorageExecutor::GetAllMetaKeys(std::vector &keys) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetAllSyncedEntries(const std::string &hashDev, std::vector &entries) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::SaveSyncDataItem(const Entry &entry, + SingleVerNaturalStoreCommitNotifyData *committedData, bool isDelete) +{ + NotifyConflictAndObserverData notify = { + .committedData = committedData + }; + + int errCode = PrepareForNotifyConflictAndObserver(entry, notify, isDelete); + if (errCode != E_OK) { + return errCode; + } + + errCode = SaveSyncDataToDatabase(entry, isDelete); + if (errCode == E_OK) { + PutIntoCommittedData(entry.key, entry.value, notify); + } else { + LOGE("Save sync data to db failed:%d", errCode); + } + return errCode; +} + +int RdSingleVerStorageExecutor::EraseSyncData(const Key &hashKey) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::RemoveDeviceData(const std::string &deviceName) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::RemoveDeviceDataInCacheMode(const std::string &hashDev, bool isNeedNotify, + uint64_t recordVersion) const +{ + return -E_NOT_SUPPORT; +} + +void RdSingleVerStorageExecutor::InitCurrentMaxStamp(Timestamp &maxStamp) +{ + return; +} + +void RdSingleVerStorageExecutor::ReleaseContinueStatement() +{ + return; +} + +int RdSingleVerStorageExecutor::GetSyncDataByTimestamp(std::vector &dataItems, size_t appendLength, + Timestamp begin, Timestamp end, const DataSizeSpecInfo &dataSizeInfo) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetDeletedSyncDataByTimestamp(std::vector &dataItems, size_t appendLength, + Timestamp begin, Timestamp end, const DataSizeSpecInfo &dataSizeInfo) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetDeviceIdentifier(PragmaEntryDeviceIdentifier *identifier) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::OpenResultSet(QueryObject &queryObj, int &count) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::StartTransaction(TransactType type) +{ + return E_OK; +} + +int RdSingleVerStorageExecutor::Commit() +{ + return E_OK; +} + +int RdSingleVerStorageExecutor::Rollback() +{ + return E_OK; +} + +bool RdSingleVerStorageExecutor::CheckIfKeyExisted(const Key &key, bool isLocal, Value &value, + Timestamp ×tamp) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::ResetForSavingData(SingleVerDataType type) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::UpdateLocalDataTimestamp(Timestamp timestamp) +{ + return -E_NOT_SUPPORT; +} + +void RdSingleVerStorageExecutor::SetAttachMetaMode(bool attachMetaMode) +{ + return; +} + +int RdSingleVerStorageExecutor::PutLocalDataToCacheDB(const LocalDataItem &dataItem) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::SaveSyncDataItemInCacheMode(DataItem &dataItem, const DeviceInfo &deviceInfo, + Timestamp &maxStamp, uint64_t recordVersion, const QueryObject &query) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::PrepareForSavingCacheData(SingleVerDataType type) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::ResetForSavingCacheData(SingleVerDataType type) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::MigrateLocalData() +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::MigrateSyncDataByVersion(uint64_t recordVer, NotifyMigrateSyncData &syncData, + std::vector &dataItems) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetMinVersionCacheData(std::vector &dataItems, + uint64_t &minVerIncurCacheDb) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetMaxVersionInCacheDb(uint64_t &maxVersion) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::AttachMainDbAndCacheDb(CipherType type, const CipherPassword &passwd, + const std::string &attachDbAbsPath, EngineState engineState) +{ + return -E_NOT_SUPPORT; +} + +// Clear migrating data. +void RdSingleVerStorageExecutor::ClearMigrateData() +{ + return; +} + +// Get current max timestamp. +int RdSingleVerStorageExecutor::GetMaxTimestampDuringMigrating(Timestamp &maxTimestamp) const +{ + return -E_NOT_SUPPORT; +} + +void RdSingleVerStorageExecutor::SetConflictResolvePolicy(int policy) +{ + return; +} + +// Delete multiple meta data records in a transaction. +int RdSingleVerStorageExecutor::DeleteMetaData(const std::vector &keys) +{ + return -E_NOT_SUPPORT; +} + +// Delete multiple meta data records with key prefix in a transaction. +int RdSingleVerStorageExecutor::DeleteMetaDataByPrefixKey(const Key &keyPrefix) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::CheckIntegrity() const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::CheckQueryObjectLegal(QueryObject &queryObj) const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::CheckDataWithQuery(QueryObject query, std::vector &dataItems, + const DeviceInfo &deviceInfo) +{ + return -E_NOT_SUPPORT; +} + +size_t RdSingleVerStorageExecutor::GetDataItemSerialSize(const DataItem &item, size_t appendLen) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::AddSubscribeTrigger(QueryObject &query, const std::string &subscribeId) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::RemoveSubscribeTrigger(const std::vector &subscribeIds) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::RemoveSubscribeTriggerWaterMark(const std::vector &subscribeIds) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetTriggers(const std::string &namePreFix, std::vector &triggerNames) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::RemoveTrigger(const std::vector &triggers) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetSyncDataWithQuery(const QueryObject &query, size_t appendLength, + const DataSizeSpecInfo &dataSizeInfo, const std::pair &timeRange, + std::vector &dataItems) const +{ + return -E_NOT_SUPPORT; +} + +uint64_t RdSingleVerStorageExecutor::GetLogFileSize() const +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::GetExistsDevicesFromMeta(std::set &devices) +{ + return -E_NOT_SUPPORT; +} + +int RdSingleVerStorageExecutor::UpdateKey(const UpdateKeyCallback &callback) +{ + return -E_NOT_SUPPORT; +} + +void RdSingleVerStorageExecutor::PutIntoCommittedData(const Key &key, const Value &value, + NotifyConflictAndObserverData &data) +{ + if (data.committedData == nullptr) { + return; + } + + Entry entry; + int errCode = E_OK; + if (!data.dataStatus.isDeleted) { + entry.key = key; + entry.value = value; + DataType dataType = (data.dataStatus.preStatus == DataStatus::EXISTED) ? DataType::UPDATE : DataType::INSERT; + errCode = data.committedData->InsertCommittedData(std::move(entry), dataType, true); + } else { + if (data.dataStatus.preStatus == DataStatus::NOEXISTED) { + return; + } + entry.key = data.getData.key; + entry.value = data.getData.value; + errCode = data.committedData->InsertCommittedData(std::move(entry), DataType::DELETE, true); + } + + if (errCode != E_OK) { + LOGE("[SingleVerExe][PutCommitData] Rd Insert failed:%d", errCode); + } +} + +int RdSingleVerStorageExecutor::GetSyncDataPreByKey(const Key &key, DataItem &itemGet) const +{ + Timestamp recordTimestamp; + Value value; + int errCode = GetKvData(SingleVerDataType::SYNC_TYPE, key, value, recordTimestamp); + if (errCode == E_OK) { + itemGet.key = key; + itemGet.value = value; + } + return errCode; +} + +int RdSingleVerStorageExecutor::PrepareForNotifyConflictAndObserver(const Entry &entry, + NotifyConflictAndObserverData ¬ify, bool isDelete) +{ + // Check sava data existed info + int errCode = DBCommon::CalcValueHash(entry.key, notify.hashKey); + if (errCode != E_OK) { + return errCode; + } + errCode = GetSyncDataPreByKey(entry.key, notify.getData); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGD("[SingleVerExe][PrepareForNotifyConflictAndObserver] failed:%d", errCode); + return errCode; + } + + bool isHashKeyExisted = (errCode != -E_NOT_FOUND); + + LOGD("Preparing for notify conflict and observer"); + notify.dataStatus.isDeleted = isDelete; + if (isHashKeyExisted) { + notify.dataStatus.preStatus = DataStatus::EXISTED; + } else { + notify.dataStatus.preStatus = DataStatus::NOEXISTED; + } + InitCommitNotifyDataKeyStatus(notify.committedData, notify.hashKey, notify.dataStatus); + return E_OK; +} + +int RdSingleVerStorageExecutor::SaveSyncDataToDatabase(const Entry &entry, bool isDelete) +{ + if (isDelete) { + return DelKvData(entry.key); + } + return SaveKvData(SingleVerDataType::SYNC_TYPE, entry.key, entry.value); +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.h new file mode 100644 index 0000000000000000000000000000000000000000..abe96a13bde58cdaf54d334f5fbef78c2f2b4298 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_single_ver_storage_executor.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the spRdSingleVerStorageExecutorecific language governing permissions and + * limitations under the License. + */ + +#ifndef RD_SINGLE_VER_STORAGE_EXECUTOR_H +#define RD_SINGLE_VER_STORAGE_EXECUTOR_H +#include "macro_utils.h" +#include "db_types.h" +#include "grd_kv_api.h" +#include "grd_resultset_api.h" +#include "query_object.h" +#include "sqlite_utils.h" +#include "sqlite_single_ver_storage_executor.h" +#include "single_ver_natural_store_commit_notify_data.h" + +namespace DistributedDB { +struct QueryParam { + GRD_KvScanModeE kvScanMode_; + std::vector beginKey_; + std::vector endKey_; + Key keyPrefix_; +}; + +int GetQueryParam(const Query &query, QueryParam &queryParam); + +int GetQueryParam(const Key &keyPrefix, QueryParam &queryParam); + +class RDStorageExecutor : public StorageExecutor { +public: + RDStorageExecutor(GRD_DB *db, bool isWrite); + ~RDStorageExecutor() override; + + // Delete the copy and assign constructors + DISABLE_COPY_ASSIGN_MOVE(RDStorageExecutor); + + int Reset() override; + + int GetDbHandle(GRD_DB *&dbHandle) const; + +protected: + GRD_DB *db_; +}; + +class RdSingleVerStorageExecutor : public RDStorageExecutor { +public: + RdSingleVerStorageExecutor(GRD_DB *db, bool isWrite); + ~RdSingleVerStorageExecutor() override; + + // Delete the copy and assign constructors + DISABLE_COPY_ASSIGN_MOVE(RdSingleVerStorageExecutor); + + // Get the Kv data according the type(sync, meta, local data). + int GetKvData(SingleVerDataType type, const Key &key, Value &value, Timestamp ×tamp) const; + + // Get the sync data record by hash key. + int GetKvDataByHashKey(const Key &hashKey, SingleVerRecord &result) const; + + // Put the Kv data according the type(meta and the local data). + virtual int PutKvData(SingleVerDataType type, const Key &key, const Value &value, + Timestamp timestamp, SingleVerNaturalStoreCommitNotifyData *committedData); + + virtual int GetEntries(bool isGetValue, SingleVerDataType type, const Key &keyPrefix, + std::vector &entries) const; + + int GetEntries(QueryObject &queryObj, std::vector &entries) const; + + int GetEntries(QueryParam &queryParam, SingleVerDataType type, std::vector &entries) const; + + int GetCount(const Key &key, int &count, GRD_KvScanModeE kvScanMode, const Key &keyEnd); + + // Get all the meta keys. + int GetAllMetaKeys(std::vector &keys) const; + + int GetAllSyncedEntries(const std::string &hashDev, std::vector &entries) const; + + int BatchSaveEntries(const std::vector &entries, bool isDelete, + SingleVerNaturalStoreCommitNotifyData *committedData); + + int SaveSyncDataItem(const Entry &entry, SingleVerNaturalStoreCommitNotifyData *committedData, bool isDelete); + + int PrepareNotifyForEntries(const std::vector &entries, + SingleVerNaturalStoreCommitNotifyData *committedData, std::vector ¬ifys, + bool isDelete); + + int DeleteLocalKvData(const Key &key, SingleVerNaturalStoreCommitNotifyData *committedData, Value &value, + Timestamp ×tamp); + + int EraseSyncData(const Key &hashKey); + + int RemoveDeviceData(const std::string &deviceName); + int RemoveDeviceDataInCacheMode(const std::string &hashDev, bool isNeedNotify, uint64_t recordVersion) const; + + void InitCurrentMaxStamp(Timestamp &maxStamp); + + void ReleaseContinueStatement(); + + int GetSyncDataByTimestamp(std::vector &dataItems, size_t appendLength, Timestamp begin, + Timestamp end, const DataSizeSpecInfo &dataSizeInfo) const; + + int GetDeletedSyncDataByTimestamp(std::vector &dataItems, size_t appendLength, Timestamp begin, + Timestamp end, const DataSizeSpecInfo &dataSizeInfo) const; + + int GetDeviceIdentifier(PragmaEntryDeviceIdentifier *identifier); + + int OpenResultSet(const Key &key, GRD_KvScanModeE mode, GRD_ResultSet **resultSet); + + int CloseResultSet(GRD_ResultSet *resultSet); + + int MoveTo(const int position, GRD_ResultSet *resultSet, int &currPosition, + Entry &entry_, const Key &keyEnd); + + int MoveToNext(GRD_ResultSet *resultSet); + + int MoveToPrev(GRD_ResultSet *resultSet); + + int GetEntry(GRD_ResultSet *resultSet, Entry &entry); + + int OpenResultSet(QueryObject &queryObj, int &count); + + int StartTransaction(TransactType type); + + int Commit(); + + int Rollback(); + + bool CheckIfKeyExisted(const Key &key, bool isLocal, Value &value, Timestamp ×tamp) const; + + int ResetForSavingData(SingleVerDataType type); + + int UpdateLocalDataTimestamp(Timestamp timestamp); + + void SetAttachMetaMode(bool attachMetaMode); + + int PutLocalDataToCacheDB(const LocalDataItem &dataItem) const; + + int SaveSyncDataItemInCacheMode(DataItem &dataItem, const DeviceInfo &deviceInfo, Timestamp &maxStamp, + uint64_t recordVersion, const QueryObject &query); + + int PrepareForSavingCacheData(SingleVerDataType type); + + int ResetForSavingCacheData(SingleVerDataType type); + + int MigrateLocalData(); + + int MigrateSyncDataByVersion(uint64_t recordVer, NotifyMigrateSyncData &syncData, + std::vector &dataItems); + + int GetMinVersionCacheData(std::vector &dataItems, uint64_t &minVerIncurCacheDb) const; + + int GetMaxVersionInCacheDb(uint64_t &maxVersion) const; + + int AttachMainDbAndCacheDb(CipherType type, const CipherPassword &passwd, + const std::string &attachDbAbsPath, EngineState engineState); + + // Clear migrating data. + void ClearMigrateData(); + + // Get current max timestamp. + int GetMaxTimestampDuringMigrating(Timestamp &maxTimestamp) const; + + void SetConflictResolvePolicy(int policy); + + // Delete multiple meta data records in a transaction. + int DeleteMetaData(const std::vector &keys); + + // Delete multiple meta data records with key prefix in a transaction. + int DeleteMetaDataByPrefixKey(const Key &keyPrefix); + + int CheckIntegrity() const; + + int CheckQueryObjectLegal(QueryObject &queryObj) const; + + int CheckDataWithQuery(QueryObject query, std::vector &dataItems, const DeviceInfo &deviceInfo); + + static size_t GetDataItemSerialSize(const DataItem &item, size_t appendLen); + + int AddSubscribeTrigger(QueryObject &query, const std::string &subscribeId); + + int RemoveSubscribeTrigger(const std::vector &subscribeIds); + + int RemoveSubscribeTriggerWaterMark(const std::vector &subscribeIds); + + int GetTriggers(const std::string &namePreFix, std::vector &triggerNames); + + int RemoveTrigger(const std::vector &triggers); + + int GetSyncDataWithQuery(const QueryObject &query, size_t appendLength, const DataSizeSpecInfo &dataSizeInfo, + const std::pair &timeRange, std::vector &dataItems) const; + + int ForceCheckPoint() const; + + uint64_t GetLogFileSize() const; + + int GetExistsDevicesFromMeta(std::set &devices); + + int UpdateKey(const UpdateKeyCallback &callback); + + static bool CompareKeyWithEndKey(const Key &key, const Key &keyEnd); + +protected: + int SaveKvData(SingleVerDataType type, const Key &key, const Value &value); + + int DeleteLocalDataInner(SingleVerNaturalStoreCommitNotifyData *committedData, const Key &key, const Value &value); + +private: + void PutIntoCommittedData(const Key &key, const Value &value, NotifyConflictAndObserverData &data); + + int GetSyncDataPreByKey(const Key &key, DataItem &itemGet) const; + + int PrepareForNotifyConflictAndObserver(const Entry &entry, + NotifyConflictAndObserverData ¬ify, bool isDelete = false); + + int DelKvData(const Key &key); + + int SaveSyncDataToDatabase(const Entry &entry, bool isDelete); + + int InnerMoveToHead(const int position, GRD_ResultSet *resultSet, int &currPosition); + + static int ClearEntriesAndFreeResultSet(std::vector &entries, GRD_ResultSet *resultSet); + + static int GetEntriesPrepare(GRD_DB *db, SingleVerDataType type, const Key &keyPrefix, std::vector &entries, + GRD_ResultSet **resultSet); + + static int GetEntriesPrepare(GRD_DB *db, SingleVerDataType type, const QueryParam &queryParam, + std::vector &entries, GRD_ResultSet **resultSet); + + int CompareKeyAndStoreEntry(GRD_ResultSet *resultSet, const Key &keyEnd, + bool isNeedStore, Entry &entry_); +}; +} // namespace DistributedDB +#endif // RD_SINGLE_VER_STORAGE_EXECUTOR_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..dc5d30e3721abffeaf4a46496b253a8b81486983 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.cpp @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "rd_utils.h" +#include "db_errno.h" +#include "log_print.h" +#include "sqlite_single_ver_storage_executor_sql.h" + +namespace { + using namespace DistributedDB; + + bool CheckRdOptionMode(const KvStoreNbDelegate::Option &option) + { + return (option.mode != 0 && option.mode != 1) || option.syncDualTupleMode; + } + + bool CheckOption(const KvStoreNbDelegate::Option &option) + { + if (option.storageEngineType == GAUSSDB_RD && + (CheckRdOptionMode(option) || + option.isMemoryDb || + option.isEncryptedDb || + option.cipher != CipherType::DEFAULT || + option.passwd != CipherPassword() || + !option.schema.empty() || + option.conflictType != 0 || + option.notifier != nullptr || + option.conflictResolvePolicy != LAST_WIN || + option.isNeedCompressOnSync || + option.compressionRate != 100 || // Valid in [1, 100]. + option.localOnly)) { + return false; + } + return true; + } +} + +namespace DistributedDB { + +std::string InitRdConfig() +{ + return R"("pageSize": 32, "redoFlushByTrx": 1, "redoPubBufSize": 2048, "maxConnNum": 100, + "bufferPoolSize": 2048, "crcCheckEnable": 1, "bufferPoolPolicy": "BUF_PRIORITY_INDEX")"; +} + +struct GrdErrnoPair { + int32_t grdCode; + int kvDbCode; +}; + +const GrdErrnoPair GRD_ERRNO_MAP[] = { + { GRD_OK, E_OK }, + { GRD_NOT_SUPPORT, -E_NOT_SUPPORT }, + { GRD_OVER_LIMIT, -E_MAX_LIMITS }, + { GRD_INVALID_ARGS, -E_INVALID_ARGS }, + { GRD_FAILED_FILE_OPERATION, -E_SYSTEM_API_FAIL }, + { GRD_INVALID_FILE_FORMAT, -E_INVALID_PASSWD_OR_CORRUPTED_DB }, + { GRD_INSUFFICIENT_SPACE, -E_INTERNAL_ERROR }, + { GRD_INNER_ERR, -E_INTERNAL_ERROR }, + { GRD_RESOURCE_BUSY, -E_BUSY }, + { GRD_NO_DATA, -E_NOT_FOUND }, + { GRD_FAILED_MEMORY_ALLOCATE, -E_OUT_OF_MEMORY }, + { GRD_FAILED_MEMORY_RELEASE, -E_OUT_OF_MEMORY }, + { GRD_DATA_CONFLICT, -E_INVALID_DATA }, + { GRD_NOT_AVAILABLE, -E_NOT_FOUND }, + { GRD_INVALID_FORMAT, -E_INVALID_FORMAT }, + { GRD_TIME_OUT, -E_TIMEOUT }, + { GRD_DB_INSTANCE_ABNORMAL, -E_INTERNAL_ERROR }, + { GRD_DISK_SPACE_FULL, -E_INTERNAL_ERROR }, + { GRD_CRC_CHECK_DISABLED, -E_INVALID_ARGS }, + { GRD_PERMISSION_DENIED, -E_DENIED_SQL }, + { GRD_REBUILD_DATABASE, -E_REBUILD_DATABASE}, // rebuild database means ok +}; + +GRD_KVItemT BlobToKvItem(const std::vector &blob) +{ + return { + .data = (void *)&blob[0], + .dataLen = (uint32_t)blob.size() + }; +} + +int TransferGrdErrno(int err) +{ + if (err > 0) { + return err; + } + for (const auto &item : GRD_ERRNO_MAP) { + if (item.grdCode == err) { + return item.kvDbCode; + } + } + return -E_INTERNAL_ERROR; +} + +std::vector KvItemToBlob(GRD_KVItemT &item) +{ + return std::vector((uint8_t *)item.data, (uint8_t *)item.data + item.dataLen); +} + +int GetCollNameFromType(SingleVerDataType type, std::string &collName) +{ + switch (type) { + case SingleVerDataType::SYNC_TYPE: + collName = SYNC_COLLECTION_NAME; + break; + default: + LOGE("data type not support"); + return -E_INVALID_ARGS; + } + return E_OK; +} + +int RdKVPut(GRD_DB *db, const char *collectionName, const Key &key, const Value &value) +{ + if (db == nullptr) { + LOGE("[rdUtils][RdKvPut] invalid db"); + return -E_INVALID_DB; + } + GRD_KVItemT innerKey = BlobToKvItem(key); + GRD_KVItemT innerVal = BlobToKvItem(value); + int ret = TransferGrdErrno(GRD_KVPut(db, collectionName, &innerKey, &innerVal)); + if (ret != E_OK) { + LOGE("[rdUtils][RdKvPut] ERROR:%d", ret); + } + return ret; +} + +int RdKVGet(GRD_DB *db, const char *collectionName, const Key &key, Value &value) +{ + if (db == nullptr) { + LOGE("[rdUtils][RdKvGet] invalid db"); + return -E_INVALID_DB; + } + GRD_KVItemT innerKey = BlobToKvItem(key); + GRD_KVItemT innerVal = { 0 }; + int ret = TransferGrdErrno(GRD_KVGet(db, collectionName, &innerKey, &innerVal)); + if (ret != E_OK) { + LOGI("[rdUtils][GetKvData] Cannot get the data %d", ret); + return ret; + } + value = KvItemToBlob(innerVal); + (void)GRD_KVFreeItem(&innerVal); + return E_OK; +} + +int RdKVDel(GRD_DB *db, const char *collectionName, const Key &key) +{ + if (db == nullptr) { + LOGE("[rdUtils][RdKvDel] invalid db"); + return -E_INVALID_DB; + } + GRD_KVItemT innerKey = BlobToKvItem(key); + int ret = TransferGrdErrno(GRD_KVDel(db, collectionName, &innerKey)); + if (ret < 0) { + LOGE("[rdUtils][RdKvDel] failed:%d", ret); + } + return ret; +} + +int RdKVScan(GRD_DB *db, const char *collectionName, const Key &key, GRD_KvScanModeE mode, + GRD_ResultSet **resultSet) +{ + if (db == nullptr) { + LOGE("[rdUtils][RdKVScan] invalid db"); + return -E_INVALID_DB; + } + if (key.empty()) { + return TransferGrdErrno(GRD_KVScan(db, collectionName, NULL, mode, resultSet)); + } + GRD_KVItemT innerKey = BlobToKvItem(key); + return TransferGrdErrno(GRD_KVScan(db, collectionName, &innerKey, mode, resultSet)); +} + +int RdKvFetch(GRD_ResultSet *resultSet, Key &key, Value &value) +{ + GRD_KVItemT innerKey = { nullptr, 0 }; + GRD_KVItemT innerValue = { nullptr, 0 }; + int errCode = TransferGrdErrno(GRD_Fetch(resultSet, &innerKey, &innerValue)); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + return errCode; + } + key = KvItemToBlob(innerKey); + value = KvItemToBlob(innerValue); + (void)GRD_KVFreeItem(&innerKey); + (void)GRD_KVFreeItem(&innerValue); + return errCode; +} + +int RdDBClose(GRD_DB *db, uint32_t flags) +{ + return TransferGrdErrno(GRD_DBClose(db, flags)); +} + +int RdFreeResultSet(GRD_ResultSet *resultSet) +{ + return TransferGrdErrno(GRD_FreeResultSet(resultSet)); +} + +int RdKVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch) +{ + return TransferGrdErrno(GRD_KVBatchPrepare(itemNum, batch)); +} + +int RdKVBatchPushback(GRD_KVBatchT *batch, const Key &key, const Value &value) +{ + GRD_KVItemT innerKey = BlobToKvItem(key); + GRD_KVItemT innerVal = BlobToKvItem(value); + int ret = TransferGrdErrno( + GRD_KVBatchPushback(innerKey.data, innerKey.dataLen, innerVal.data, innerVal.dataLen, batch)); + if (ret != E_OK) { + LOGE("[rdUtils][BatchSaveEntries] Can not push back entries to KVBatch structure"); + } + return ret; +} + +int RdKVBatchPut(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch) +{ + if (db == nullptr) { + LOGE("[rdUtils][RdKVBatchPut] invalid db"); + return -E_INVALID_DB; + } + return TransferGrdErrno(GRD_KVBatchPut(db, kvTableName, batch)); +} + +int RdFlush(GRD_DB *db, uint32_t flags) +{ + if (db == nullptr) { + LOGE("[rdUtils][ForceCheckPoint] invalid db"); + return -E_INVALID_DB; + } + // flags means options, input 0 in current version. + return TransferGrdErrno(GRD_Flush(db, flags)); +} + +int RdKVBatchDel(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch) +{ + if (db == nullptr) { + LOGE("[rdUtils][RdKVBatchDel] invalid db"); + return -E_INVALID_DB; + } + return TransferGrdErrno(GRD_KVBatchDel(db, kvTableName, batch)); +} + +int RdKVBatchDestroy(GRD_KVBatchT *batch) +{ + return TransferGrdErrno(GRD_KVBatchDestroy(batch)); +} + +int RdDbOpen(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB *&db) +{ + return TransferGrdErrno(GRD_DBOpen(dbPath, configStr, flags, &db)); +} + +int RdIndexPreload(GRD_DB *&db, const char *collectionName) +{ + if (db == nullptr) { + LOGE("[rdUtils][RdIndexPreload] db is null"); + return -E_INVALID_DB; + } + return TransferGrdErrno(GRD_IndexPreload(db, collectionName)); +} + +bool CheckRdOption(const KvStoreNbDelegate::Option &option, + const std::function &callback) +{ + if (option.storageEngineType != GAUSSDB_RD && option.storageEngineType != SQLITE) { + callback(INVALID_ARGS, nullptr); + return false; + } + if (option.rdconfig.readOnly && option.isNeedRmCorruptedDb) { + callback(INVALID_ARGS, nullptr); + return false; + } + if (!CheckOption(option)) { + callback(NOT_SUPPORT, nullptr); + return false; + } + return true; +} + +int RdCrcCheck(const char *dbFile) +{ + return TransferGrdErrno(GRD_CrcCheck(dbFile)); +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..938094aa4a636377776e1f9d265d55b1774bbc79 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/gaussdb_rd/rd_utils.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RD_UTILS_H +#define RD_UTILS_H +#include +#include "db_errno.h" +#include "grd_db_api.h" +#include "grd_error.h" +#include "grd_kv_api.h" +#include "grd_type_export.h" +#include "kv_store_nb_delegate.h" +#include "sqlite_single_ver_storage_executor.h" +#include "grd_document_api.h" + +namespace DistributedDB { + +const std::string SYNC_COLLECTION_NAME = + "naturalbase_kv_sync_data"; + +std::string InitRdConfig(); + +GRD_KVItemT BlobToKvItem(const std::vector &blob); + +int TransferGrdErrno(int err); + +std::vector KvItemToBlob(GRD_KVItemT &item); + +int GetCollNameFromType(SingleVerDataType type, std::string &collName); + +int RdKVPut(GRD_DB *db, const char *collectionName, const Key &key, const Value &value); + +int RdKVGet(GRD_DB *db, const char *collectionName, const Key &key, Value &value); + +int RdKVDel(GRD_DB *db, const char *collectionName, const Key &key); + +int RdKVScan(GRD_DB *db, const char *collectionName, const Key &key, GRD_KvScanModeE mode, + GRD_ResultSet **resultSet); + +int RdKvFetch(GRD_ResultSet *resultSet, Key &key, Value &value); + +int RdFreeResultSet(GRD_ResultSet *resultSet); + +int RdDBClose(GRD_DB *db, uint32_t flags); + +int RdKVBatchPrepare(uint16_t itemNum, GRD_KVBatchT **batch); + +int RdKVBatchPushback(GRD_KVBatchT *batch, const Key &key, const Value &value); + +int RdKVBatchPut(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch); + +int RdFlush(GRD_DB *db, uint32_t flags); + +int RdKVBatchDel(GRD_DB *db, const char *kvTableName, GRD_KVBatchT *batch); + +int RdKVBatchDestroy(GRD_KVBatchT *batch); + +int RdDbOpen(const char *dbPath, const char *configStr, uint32_t flags, GRD_DB *&db); + +int RdIndexPreload(GRD_DB *&db, const char *collectionName); + +bool CheckRdOption(const KvStoreNbDelegate::Option &option, + const std::function &callback); + +int RdCrcCheck(const char *dbFile); +} // namespace DistributedDB +#endif // RD_UTILS_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp index d87b4b693a35322c610c575364b0943e6be5c992..6d8e198538e44dea38fe40967c9d73220ac8d9ae 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/generic_kvdb_connection.cpp @@ -88,6 +88,7 @@ KvDBObserverHandle *GenericKvDBConnection::RegisterObserver(unsigned mode, } if (isExclusive_.load()) { errCode = -E_BUSY; + LOGE("Observer is exclusived %d", errCode); return nullptr; } auto observerHandle = new (std::nothrow) KvDBObserverHandle(mode); @@ -180,9 +181,11 @@ int GenericKvDBConnection::Close() } if (isExclusive_.load()) { + LOGE("Current connection is occupied by other connection"); return -E_BUSY; } if (kvDB_->IsDataMigrating()) { + LOGE("Data is migrating"); return -E_BUSY; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp index 95bbc0d2674b0bb18742931a74dbf74fabc284fe..2049b4b8bbcb4c0b488d23e8e0be725dca7479fc 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_manager.cpp @@ -36,12 +36,13 @@ namespace { static const KvDBType g_dbTypeArr[] = { #ifndef OMIT_MULTI_VER - LOCAL_KVDB, + LOCAL_KVDB_SQLITE, #endif // OMIT_MULTI_VER - SINGER_VER_KVDB, + SINGER_VER_KVDB_SQLITE, #ifndef OMIT_MULTI_VER - MULTI_VER_KVDB + MULTI_VER_KVDB_SQLITE, #endif // OMIT_MULTI_VER + SINGLE_VER_KVDB_RD }; int CreateDataBaseInstance(const KvDBProperties &property, IKvDB *&kvDB) @@ -51,21 +52,23 @@ namespace { return -E_OUT_OF_MEMORY; } int errCode = E_OK; - int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); - if (databaseType == KvDBProperties::LOCAL_TYPE) { + int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); + if (databaseType == KvDBProperties::LOCAL_TYPE_SQLITE) { #ifndef OMIT_MULTI_VER - kvDB = factory->CreateKvDb(LOCAL_KVDB, errCode); + kvDB = factory->CreateKvDb(LOCAL_KVDB_SQLITE, errCode); if (kvDB != nullptr) { kvDB->EnableAutonomicUpgrade(); } #else return -E_NOT_SUPPORT; #endif // OMIT_MULTI_VER - } else if (databaseType == KvDBProperties::SINGLE_VER_TYPE) { - kvDB = factory->CreateKvDb(SINGER_VER_KVDB, errCode); + } else if (databaseType == KvDBProperties::SINGLE_VER_TYPE_SQLITE) { + kvDB = factory->CreateKvDb(SINGER_VER_KVDB_SQLITE, errCode); + } else if (databaseType == KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL) { + kvDB = factory->CreateKvDb(SINGLE_VER_KVDB_RD, errCode); } else { #ifndef OMIT_MULTI_VER - kvDB = factory->CreateKvDb(MULTI_VER_KVDB, errCode); + kvDB = factory->CreateKvDb(MULTI_VER_KVDB_SQLITE, errCode); #else return -E_NOT_SUPPORT; #endif // OMIT_MULTI_VER @@ -379,8 +382,15 @@ int KvDBManager::ReleaseDatabaseConnection(IKvDBConnection *connection) IKvDB *KvDBManager::CreateDataBase(const KvDBProperties &property, int &errCode) { IKvDB *kvDB = OpenNewDatabase(property, errCode); + int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); if (kvDB == nullptr) { LOGE("Failed to open the new database."); + bool isReadOnly = property.GetBoolProp(KvDBProperties::READ_ONLY_MODE, false); + if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB && + databaseType == KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL && isReadOnly) { + LOGI("readOnly process can not remove database"); + return kvDB; + } if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB && property.GetBoolProp(KvDBProperties::RM_CORRUPTED_DB, false)) { LOGI("Remove the corrupted database while open"); @@ -389,8 +399,8 @@ IKvDB *KvDBManager::CreateDataBase(const KvDBProperties &property, int &errCode) } return kvDB; } - - if (property.GetBoolProp(KvDBProperties::CHECK_INTEGRITY, false)) { + if (property.GetBoolProp(KvDBProperties::CHECK_INTEGRITY, false) && + databaseType != KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL) { int integrityStatus = kvDB->CheckIntegrity(); if (integrityStatus == -E_INVALID_PASSWD_OR_CORRUPTED_DB) { RemoveKvDBFromCache(kvDB); @@ -492,6 +502,9 @@ int KvDBManager::CalculateKvStoreSize(const KvDBProperties &properties, uint64_t uint64_t totalSize = 0; for (KvDBType kvDbType : g_dbTypeArr) { + if (kvDbType == SINGLE_VER_KVDB_RD) { + continue; + } int innerErrCode = E_OK; IKvDB *kvDB = factory->CreateKvDb(kvDbType, innerErrCode); if (innerErrCode != E_OK) { @@ -671,17 +684,17 @@ IKvDB *KvDBManager::SaveKvDBToCache(IKvDB *kvDB) { KvDBProperties properties = kvDB->GetMyProperties(); std::string identifier = GenerateKvDBIdentifier(properties); - int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::lock_guard lockGuard(kvDBLock_); int errCode = E_OK; - if (databaseType == KvDBProperties::LOCAL_TYPE) { + if (databaseType == KvDBProperties::LOCAL_TYPE_SQLITE) { IKvDB *kvDBTmp = FindKvDBFromCache(properties, localKvDBs_, true, errCode); if (kvDBTmp != nullptr) { kvDBTmp->IncObjRef(kvDBTmp); return kvDBTmp; } localKvDBs_.insert(std::pair(identifier, kvDB)); - } else if (databaseType == KvDBProperties::MULTI_VER_TYPE) { + } else if (databaseType == KvDBProperties::MULTI_VER_TYPE_SQLITE) { IKvDB *kvDBTmp = FindKvDBFromCache(properties, multiVerNaturalStores_, true, errCode); if (kvDBTmp != nullptr) { kvDBTmp->IncObjRef(kvDBTmp); @@ -713,11 +726,11 @@ void KvDBManager::RemoveKvDBFromCache(const IKvDB *kvDB) { const KvDBProperties &properties = kvDB->GetMyProperties(); std::string identifier = GenerateKvDBIdentifier(properties); - int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::lock_guard lockGuard(kvDBLock_); - if (databaseType == KvDBProperties::LOCAL_TYPE) { + if (databaseType == KvDBProperties::LOCAL_TYPE_SQLITE) { localKvDBs_.erase(identifier); - } else if (databaseType == KvDBProperties::MULTI_VER_TYPE) { + } else if (databaseType == KvDBProperties::MULTI_VER_TYPE_SQLITE) { multiVerNaturalStores_.erase(identifier); } else { singleVerNaturalStores_.erase(identifier); @@ -768,8 +781,9 @@ IKvDB *KvDBManager::FindKvDBFromCache(const KvDBProperties &properties, const st errCode = -E_INTERNAL_ERROR; return nullptr; } - int newType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); - int oldType = kvDB->GetMyProperties().GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int newType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); + int oldType = kvDB->GetMyProperties().GetIntProp(KvDBProperties::DATABASE_TYPE, + KvDBProperties::LOCAL_TYPE_SQLITE); if (oldType == newType) { errCode = CheckKvDBProperties(kvDB, properties, isNeedCheckPasswd); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_properties.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_properties.cpp index bf07aba2f189116938f2ffdbc61875e6d60f26c3..ea3f3800bbfb6ed2c9a3d9bf7c1d424c07e2d84d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_properties.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_properties.cpp @@ -32,6 +32,9 @@ const std::string KvDBProperties::COMPRESS_ON_SYNC = "needCompressOnSync"; const std::string KvDBProperties::COMPRESSION_RATE = "compressionRate"; const std::string KvDBProperties::LOCAL_ONLY = "localOnly"; +const std::string KvDBProperties::SHARED_MODE = "sharedMode"; +const std::string KvDBProperties::READ_ONLY_MODE = "read_only"; + KvDBProperties::KvDBProperties() : cipherType_(CipherType::AES_256_GCM) {} @@ -41,11 +44,11 @@ KvDBProperties::~KvDBProperties() {} std::string KvDBProperties::GetStoreSubDirectory(int type) { switch (type) { - case LOCAL_TYPE: + case LOCAL_TYPE_SQLITE: return DBConstant::LOCAL_SUB_DIR; - case MULTI_VER_TYPE: + case MULTI_VER_TYPE_SQLITE: return DBConstant::MULTI_SUB_DIR; - case SINGLE_VER_TYPE: + case SINGLE_VER_TYPE_SQLITE: return DBConstant::SINGLE_SUB_DIR; default: return "unknown"; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_utils.cpp index b947542a22b95eaf544ef678436b40e136669d57..4fb6451b004a61f9ea905b63aa73bee778dbe2e6 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_utils.cpp @@ -50,7 +50,7 @@ int KvDBUtils::RemoveKvDB(const std::string &dir, const std::string &dbName) { std::string dbFileName = dir; GetStoreDirectory(dbFileName, dbName); - dbFileName += DBConstant::SQLITE_DB_EXTENSION; + dbFileName += DBConstant::DB_EXTENSION; int errCode = E_OK; if (OS::CheckPathExistence(dbFileName)) { errCode = DBCommon::RemoveAllFilesOfDirectory(dir, true); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.cpp index ca269bf6cf41eefd4a427813284b8e32b28117a8..4f4787157cdc1bd9f6df27850e2126c4ce240d4f 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.cpp @@ -42,17 +42,53 @@ int KvDBWindowedResultSet::GetPosition() const return -1; // return invalid position } +int KvDBWindowedResultSet::Move(int offset) const +{ + return -E_NOT_SUPPORT; +} + int KvDBWindowedResultSet::MoveTo(int position) const { return -E_NOT_SUPPORT; } +int KvDBWindowedResultSet::MoveToFirst() +{ + return -E_NOT_SUPPORT; +} + +int KvDBWindowedResultSet::MoveToLast() +{ + return -E_NOT_SUPPORT; +} + +bool KvDBWindowedResultSet::IsFirst() const +{ + return -E_NOT_SUPPORT; +} + +bool KvDBWindowedResultSet::IsLast() const +{ + return -E_NOT_SUPPORT; +} + +bool KvDBWindowedResultSet::IsBeforeFirst() const +{ + return -E_NOT_SUPPORT; +} + +bool KvDBWindowedResultSet::IsAfterLast() const +{ + return -E_NOT_SUPPORT; +} + int KvDBWindowedResultSet::GetEntry(Entry &entry) const { return -E_NOT_SUPPORT; } -void KvDBWindowedResultSet::Close() +int KvDBWindowedResultSet::Close() { + return E_OK; } } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.h b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.h index 2c5fe3b7d7eece7188b54bf1559a454a52f0cff9..d8bc7991bc9e1a4f6ca4229449d504661afa086e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/kvdb_windowed_result_set.h @@ -37,14 +37,28 @@ public: // >= 0: position, < 0: errCode int GetPosition() const override; + int Move(int offset) const override; + // Move the read position to an absolute position value. int MoveTo(int position) const override; + int MoveToFirst() override; + + int MoveToLast() override; + + bool IsFirst() const override; + + bool IsLast() const override; + + bool IsBeforeFirst() const override; + + bool IsAfterLast() const override; + // Get the entry of current position. int GetEntry(Entry &entry) const override; // Finalize logic - void Close() override; + int Close() override; private: ResultEntriesWindow *window_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_kvdata_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_kvdata_storage.cpp index 25857f603edd5f37fb6c7b964e4de0bfdcb0fec9..5a1657435ebf06713c27ddafb27933db298bdf0c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_kvdata_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_kvdata_storage.cpp @@ -42,7 +42,7 @@ static IKvDB *OpenKvDB(const DatabaseIdentifierCfg &config, CipherType type, con return nullptr; } - IKvDB *kvDB = factory->CreateKvDb(LOCAL_KVDB, errCode); + IKvDB *kvDB = factory->CreateKvDb(LOCAL_KVDB_SQLITE, errCode); if (kvDB == nullptr) { LOGE("Create local kvdb failed:%d", errCode); return nullptr; @@ -53,7 +53,7 @@ static IKvDB *OpenKvDB(const DatabaseIdentifierCfg &config, CipherType type, con dbProperties.SetStringProp(KvDBProperties::DATA_DIR, config.databaseDir); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, config.fileName); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, config.identifier); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(type, passwd); errCode = kvDB->Open(dbProperties); @@ -302,7 +302,7 @@ int MultiVerKvDataStorage::GetVersion(const Property &property, int &metaVer, bo dbProperties.SetStringProp(KvDBProperties::DATA_DIR, property.dataDir); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, DBConstant::MULTI_VER_VALUE_STORE); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, property.identifierName); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(property.cipherType, property.passwd); int errCode = localKvdb->GetVersion(dbProperties, sliceVer, isSliceDbExist); if (errCode != E_OK) { @@ -438,7 +438,7 @@ int MultiVerKvDataStorage::BackupCurrentDatabase(const Property &property, const dbProperties.SetStringProp(KvDBProperties::DATA_DIR, property.dataDir); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, DBConstant::MULTI_VER_META_STORE); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, property.identifierName); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(property.cipherType, property.passwd); int errCode = SQLiteLocalKvDB::BackupCurrentDatabase(dbProperties, dir); if (errCode != E_OK) { @@ -457,7 +457,7 @@ int MultiVerKvDataStorage::ImportDatabase(const Property &property, const std::s dbProperties.SetStringProp(KvDBProperties::DATA_DIR, property.dataDir); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, DBConstant::MULTI_VER_META_STORE); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, property.identifierName); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(property.cipherType, property.passwd); int errCode = SQLiteLocalKvDB::ImportDatabase(dbProperties, dir, passwd); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp index 623f506e73af39a1767d3e14cc016953fead3ac4..8437cc75c11d668402a375c1c46b1613844a814b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.cpp @@ -533,8 +533,9 @@ int MultiVerNaturalStore::GetMetaData(const Key &key, Value &value) const } // Put meta data as a key-value entry. -int MultiVerNaturalStore::PutMetaData(const Key &key, const Value &value) +int MultiVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { + (void)isInTransaction; int errCode = E_OK; auto handle = GetHandle(true, errCode); if (handle == nullptr) { @@ -1059,7 +1060,7 @@ int MultiVerNaturalStore::RemoveKvDB(const KvDBProperties &properties) { std::string storeOnlyDir; std::string storeDir; - GenericKvDB::GetStoreDirectory(properties, KvDBProperties::MULTI_VER_TYPE, storeDir, storeOnlyDir); + GenericKvDB::GetStoreDirectory(properties, KvDBProperties::MULTI_VER_TYPE_SQLITE, storeDir, storeOnlyDir); int errCodeVersion = KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, DBConstant::MULTI_VER_DATA_STORE); int errCodeCommit = KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, DBConstant::MULTI_VER_COMMIT_STORE); int errCodeValue = KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, DBConstant::MULTI_VER_VALUE_STORE); @@ -1087,7 +1088,7 @@ int MultiVerNaturalStore::GetKvDBSize(const KvDBProperties &properties, uint64_t { std::string storeOnlyDir; std::string storeDir; - GenericKvDB::GetStoreDirectory(properties, KvDBProperties::MULTI_VER_TYPE, storeDir, storeOnlyDir); + GenericKvDB::GetStoreDirectory(properties, KvDBProperties::MULTI_VER_TYPE_SQLITE, storeDir, storeOnlyDir); std::vector storageNames = { DBConstant::MULTI_VER_DATA_STORE, diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h index 28145b1d85607651079a88ae8d674439354997e3..e2f005d941727776f77c47c2dd35108637d3bac9 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store.h @@ -72,7 +72,7 @@ public: int GetMetaData(const Key &key, Value &value) const override; // Put meta data as a key-value entry. - int PutMetaData(const Key &key, const Value &value) override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; // Delete multiple meta data records in a transaction. int DeleteMetaData(const std::vector &keys) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store_commit_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store_commit_storage.cpp index c32c7aa554196ea7074c76a66622ebe7c915d26a..b4ecd4987a76a626b0aa568ed124cf3228116419 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store_commit_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/multiver/multi_ver_natural_store_commit_storage.cpp @@ -86,7 +86,7 @@ int MultiVerNaturalStoreCommitStorage::GetVersion(const IKvDBCommitStorage::Prop dbProperties.SetStringProp(KvDBProperties::DATA_DIR, property.path); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, DBConstant::MULTI_VER_COMMIT_STORE); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, property.identifierName); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(property.cipherType, property.passwd); int errCode = localKvdb->GetVersion(dbProperties, version, isDbExisted); @@ -117,7 +117,7 @@ int MultiVerNaturalStoreCommitStorage::Open(const IKvDBCommitStorage::Property & dbProperties.SetStringProp(KvDBProperties::DATA_DIR, property.path); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, DBConstant::MULTI_VER_COMMIT_STORE); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, property.identifierName); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(property.cipherType, property.passwd); errCode = commitStorageDatabase_->Open(dbProperties); @@ -891,7 +891,7 @@ int MultiVerNaturalStoreCommitStorage::BackupCurrentDatabase(const Property &pro dbProperties.SetStringProp(KvDBProperties::DATA_DIR, property.path); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, DBConstant::MULTI_VER_COMMIT_STORE); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, property.identifierName); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(property.cipherType, property.passwd); int errCode = SQLiteLocalKvDB::BackupCurrentDatabase(dbProperties, dir); return errCode; @@ -905,7 +905,7 @@ int MultiVerNaturalStoreCommitStorage::ImportDatabase(const Property &property, dbProperties.SetStringProp(KvDBProperties::DATA_DIR, property.path); dbProperties.SetStringProp(KvDBProperties::FILE_NAME, DBConstant::MULTI_VER_COMMIT_STORE); dbProperties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, property.identifierName); - dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + dbProperties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); dbProperties.SetPassword(property.cipherType, property.passwd); int errCode = SQLiteLocalKvDB::ImportDatabase(dbProperties, dir, passwd); return errCode; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp index e832f58e481e0c2b223cbde5de72ebd57a5ee655..9d8528f91a604b118580f6498db239de156c4376 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/database_oper.cpp @@ -81,7 +81,7 @@ int DatabaseOper::GetCtrlFilePrefix(const KvDBProperties &property, std::string return errCode; } - int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::string dbSubDir = KvDBProperties::GetStoreSubDirectory(dbType); filePrefix = baseDir + "/" + dbSubDir; return E_OK; @@ -95,7 +95,7 @@ int DatabaseOper::RekeyRecover(const KvDBProperties &property) return errCode; } - int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::string dbSubDir = KvDBProperties::GetStoreSubDirectory(dbType); std::string preCtrlFileName = workDir + "/" + dbSubDir + DBConstant::REKEY_FILENAME_POSTFIX_PRE; @@ -230,7 +230,7 @@ int DatabaseOper::CreateBackupDirForExport(const KvDBProperties &property, std:: return errCode; } - int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType); currentDir = baseDir + "/" + subDir; @@ -419,7 +419,7 @@ void DatabaseOper::InitImportFileInfo(ImportFileInfo &info, const KvDBProperties { std::string dataDir = property.GetStringProp(KvDBProperties::DATA_DIR, ""); std::string identifierDir = property.GetStringProp(KvDBProperties::IDENTIFIER_DIR, ""); - int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType); std::string baseDir = dataDir + "/" + identifierDir + "/" + subDir; @@ -445,7 +445,7 @@ int DatabaseOper::UnpackAndCheckImportedFile(const std::string &srcFile, const I LOGE("Failed to unpack the imported file:%d", errCode); return errCode; } - int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); if (fileInfo.dbType != static_cast(dbType)) { DBCommon::RemoveAllFilesOfDirectory(info.unpackedDir); LOGE("Check db type [%u] vs [%u] or devicesId fail!", fileInfo.dbType, static_cast(dbType)); @@ -504,7 +504,7 @@ int DatabaseOper::ClearImportTempFile(const KvDBProperties &property) const return errCode; } - int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::string dbSubDir = KvDBProperties::GetStoreSubDirectory(dbType); std::string oriKeepFile = workDir + "/" + dbSubDir + DBConstant::PATH_POSTFIX_IMPORT_ORIGIN; @@ -552,7 +552,7 @@ int DatabaseOper::ClearExportedTempFiles(const KvDBProperties &property) const return errCode; } - int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int dbType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::string dbSubDir = KvDBProperties::GetStoreSubDirectory(dbType); std::string backupDir = workDir + "/" + dbSubDir + DBConstant::PATH_POSTFIX_EXPORT_BACKUP; errCode = DBCommon::RemoveAllFilesOfDirectory(backupDir); @@ -568,7 +568,7 @@ int DatabaseOper::PackExportedDatabase(const std::string &fileDir, const std::st const KvDBProperties &property) const { LOGI("Pack the exported database."); - int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + int databaseType = property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); FileInfo fileInfo = {static_cast(databaseType), deviceId_}; int errCode = PackageFile::PackageFiles(fileDir, packedFile, fileInfo); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/local_database_oper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/operation/local_database_oper.cpp index 373b26e657ef33373e0d51fc8db4013a6d6f3baa..7456167822f8fef85692b43c7026132c3cf037b0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/local_database_oper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/local_database_oper.cpp @@ -91,7 +91,7 @@ int LocalDatabaseOper::BackupDb(const CipherPassword &passwd) const CipherType cipherType; CipherPassword oldPasswd; localKvDb_->GetDbProperties().GetPassword(cipherType, oldPasswd); - std::string backupDbName = backupDir + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::SQLITE_DB_EXTENSION; + std::string backupDbName = backupDir + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION; return localKvDb_->RunExportLogic(cipherType, passwd, backupDbName); } @@ -122,8 +122,8 @@ int LocalDatabaseOper::RekeyPostHandle(const CipherPassword &passwd) int LocalDatabaseOper::ExportAllDatabases(const std::string ¤tDir, const CipherPassword &passwd, const std::string &dbDir) const { - std::string backupDbName = dbDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::SQLITE_DB_EXTENSION; - std::string currentDb = currentDir + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::SQLITE_DB_EXTENSION; + std::string backupDbName = dbDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION; + std::string currentDb = currentDir + "/" + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION; CipherType cipherType; CipherPassword currPasswd; @@ -154,9 +154,9 @@ int LocalDatabaseOper::BackupCurrentDatabase(const ImportFileInfo &info) const } std::string currentFile = info.currentDir + DBConstant::LOCAL_DATABASE_NAME + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; std::string backupFile = info.backupDir + DBConstant::LOCAL_DATABASE_NAME + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; errCode = DBCommon::CopyFile(currentFile, backupFile); if (errCode != E_OK) { LOGE("Backup the current database error:%d", errCode); @@ -178,8 +178,8 @@ int LocalDatabaseOper::ImportUnpackedDatabase(const ImportFileInfo &info, const return errCode; } - std::string unpackedFile = info.unpackedDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::SQLITE_DB_EXTENSION; - std::string currentFile = info.currentDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::SQLITE_DB_EXTENSION; + std::string unpackedFile = info.unpackedDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION; + std::string currentFile = info.currentDir + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION; CipherType cipherType; CipherPassword passwd; localKvDb_->GetDbProperties().GetPassword(cipherType, passwd); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp index c47b082c6ddb00cb98b19bfc378d17b761e2beb4..a822d2e418bf1a2f297b209dd7d2c683d95cc0ff 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/operation/single_ver_database_oper.cpp @@ -33,8 +33,8 @@ int SingleVerDatabaseOper::SetSecOpt(const std::string &path, bool isDir) const std::string currentMetaPath = path + "/" + DBConstant::METADB_DIR; std::string currentMainPath = path + "/" + DBConstant::MAINDB_DIR; if (!isDir) { - currentMetaPath = currentMetaPath + "/" + DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; - currentMainPath = currentMainPath + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + currentMetaPath = currentMetaPath + "/" + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; + currentMainPath = currentMainPath + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; } SecurityOption option; int mainSecLabel = singleVerNaturalStore_->GetDbProperties().GetSecLabel(); @@ -174,9 +174,9 @@ int SingleVerDatabaseOper::ExportMainDB(const std::string ¤tDir, const Cip const std::string &dbDir) const { std::string backupDbName = dbDir + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; std::string currentDb = currentDir + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; CipherType cipherType; CipherPassword currPasswd; @@ -194,9 +194,9 @@ int SingleVerDatabaseOper::ExportMetaDB(const std::string ¤tDir, const Cip const std::string &dbDir) const { std::string backupDbName = dbDir + DBConstant::METADB_DIR + "/" + DBConstant::SINGLE_VER_META_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; std::string currentDb = currentDir + "/" + DBConstant::METADB_DIR + "/" + DBConstant::SINGLE_VER_META_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; if (!OS::CheckPathExistence(currentDb)) { // Is S2 label, can access LOGD("No metaDB, no need Export metaDB."); return E_OK; @@ -233,9 +233,9 @@ int SingleVerDatabaseOper::ExportAllDatabases(const std::string ¤tDir, con int SingleVerDatabaseOper::BackupDatabase(const ImportFileInfo &info) const { std::string currentMainFile = info.currentDir + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; std::string backupMainFile = info.backupDir + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; int errCode = DBCommon::CopyFile(currentMainFile, backupMainFile); if (errCode != E_OK) { LOGE("Backup the current database error:%d", errCode); @@ -243,10 +243,10 @@ int SingleVerDatabaseOper::BackupDatabase(const ImportFileInfo &info) const } std::string currentMetaFile = info.currentDir + DBConstant::METADB_DIR + "/" + DBConstant::SINGLE_VER_META_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; if (OS::CheckPathExistence(currentMetaFile)) { std::string backupMetaFile = info.backupDir + DBConstant::METADB_DIR + "/" + DBConstant::SINGLE_VER_META_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; errCode = DBCommon::CopyFile(currentMetaFile, backupMetaFile); if (errCode != E_OK) { LOGE("Backup the current database error:%d", errCode); @@ -328,15 +328,15 @@ int SingleVerDatabaseOper::ImportUnpackedMainDatabase(const ImportFileInfo &info const CipherPassword &srcPasswd) const { std::string unpackedMainFile = info.unpackedDir + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; std::string currentMainFile = info.currentDir + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; CipherType cipherType; CipherPassword passwd; singleVerNaturalStore_->GetDbProperties().GetPassword(cipherType, passwd); std::string unpackedOldMainFile = info.unpackedDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; bool isMainDbExisted = OS::CheckPathExistence(unpackedMainFile); bool isOldMainDbExisted = OS::CheckPathExistence(unpackedOldMainFile); // version < 3, mainDb in singer_ver/ if (isMainDbExisted && isOldMainDbExisted) { @@ -367,9 +367,9 @@ int SingleVerDatabaseOper::ImportUnpackedMetaDatabase(const ImportFileInfo &info { LOGI("MetaDB existed, need import, no need upgrade!"); std::string unpackedMetaFile = info.unpackedDir + DBConstant::METADB_DIR + "/" + - DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; std::string currentMetaFile = info.currentDir + DBConstant::METADB_DIR + "/" + - DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; int errCode = SQLiteUtils::ExportDatabase(unpackedMetaFile, CipherType::DEFAULT, CipherPassword(), currentMetaFile, CipherPassword()); if (errCode != E_OK) { @@ -382,7 +382,7 @@ int SingleVerDatabaseOper::ImportUnpackedMetaDatabase(const ImportFileInfo &info int SingleVerDatabaseOper::ImportUnpackedDatabase(const ImportFileInfo &info, const CipherPassword &srcPasswd) const { std::string unpackedMetaFile = info.unpackedDir + DBConstant::METADB_DIR + "/" + - DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; bool metaDbExisted = OS::CheckPathExistence(unpackedMetaFile); int errCode = ClearCurrentDatabase(info); if (errCode != E_OK) { @@ -430,14 +430,14 @@ int SingleVerDatabaseOper::ImportPostHandle() const int SingleVerDatabaseOper::RunExportLogic(const CipherPassword &passwd, const std::string &filePrefix) const { std::string currentMainDb = filePrefix + "/" + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; CipherType cipherType; CipherPassword currPasswd; singleVerNaturalStore_->GetDbProperties().GetPassword(cipherType, currPasswd); // get backup db name std::string backupMainDbName = filePrefix + DBConstant::PATH_BACKUP_POSTFIX + "/" + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; int errCode = SQLiteUtils::ExportDatabase(currentMainDb, cipherType, currPasswd, backupMainDbName, passwd); if (errCode != E_OK) { @@ -446,7 +446,7 @@ int SingleVerDatabaseOper::RunExportLogic(const CipherPassword &passwd, const st } std::string currentMetaDb = filePrefix + "/" + DBConstant::METADB_DIR + "/" + - DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; if (!OS::CheckPathExistence(currentMetaDb)) { LOGD("No metaDB, no need Export metaDB."); return E_OK; @@ -454,7 +454,7 @@ int SingleVerDatabaseOper::RunExportLogic(const CipherPassword &passwd, const st LOGI("Begin export metaDB to back up!"); std::string backupMetaDbName = filePrefix + DBConstant::PATH_BACKUP_POSTFIX + "/" + DBConstant::METADB_DIR + "/" + - DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; // Set metaDB db passwd same as mainDB temp, may be not need errCode = SQLiteUtils::ExportDatabase(currentMetaDb, CipherType::DEFAULT, CipherPassword(), backupMetaDbName, CipherPassword()); @@ -490,7 +490,7 @@ void SingleVerDatabaseOper::InitDataBaseOption(OpenDbProperties &option) const const std::string dataDir = properties.GetStringProp(KvDBProperties::DATA_DIR, ""); const std::string identifierDir = properties.GetStringProp(KvDBProperties::IDENTIFIER_DIR, ""); std::string uri = dataDir + "/" + identifierDir + "/" + DBConstant::SINGLE_SUB_DIR + "/" + - DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; bool isMemoryDb = properties.GetBoolProp(KvDBProperties::MEMORY_MODE, false); if (isMemoryDb) { uri = identifierDir + DBConstant::SQLITE_MEMDB_IDENTIFY; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp index c4f868e43cd20d6ae5d6010aaa4214fc97531980..8e8ca9bdec01b0338a9653b482951af38606a48a 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/relational_sync_able_storage.cpp @@ -185,7 +185,7 @@ int RelationalSyncAbleStorage::GetMetaData(const Key &key, Value &value) const return -E_INVALID_ARGS; } int errCode = E_OK; - auto *handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); + auto handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); if (handle == nullptr) { return errCode; } @@ -216,6 +216,42 @@ int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value) return errCode; } +int RelationalSyncAbleStorage::PutMetaData(const Key &key, const Value &value, bool isInTransaction) +{ + CHECK_STORAGE_ENGINE; + int errCode = E_OK; + SQLiteSingleVerRelationalStorageExecutor *handle = nullptr; + std::unique_lock handLock(reusedHandleMutex_, std::defer_lock); + + // try to recycle using the handle + if (isInTransaction) { + handLock.lock(); + if (reusedHandle_ != nullptr) { + handle = static_cast(reusedHandle_); + } else { + isInTransaction = false; + handLock.unlock(); + } + } + + if (handle == nullptr) { + handle = GetHandle(true, errCode, OperatePerm::NORMAL_PERM); + if (handle == nullptr) { + return errCode; + } + } + + errCode = handle->PutKvData(key, value); + if (errCode != E_OK) { + LOGE("Put kv data err:%d", errCode); + TriggerCloseAutoLaunchConn(storageEngine_->GetProperties()); + } + if (!isInTransaction) { + ReleaseHandle(handle); + } + return errCode; +} + // Delete multiple meta data records in a transaction. int RelationalSyncAbleStorage::DeleteMetaData(const std::vector &keys) { @@ -499,11 +535,7 @@ int RelationalSyncAbleStorage::SaveSyncDataItems(const QueryObject &object, std: return errCode; } - StoreInfo info = { - storageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") - }; + StoreInfo info = GetStoreInfo(); auto inserter = RelationalSyncDataInserter::CreateInserter(deviceName, query, storageEngine_->GetSchema(), remoteSchema.GetTable(query.GetTableName()).GetFieldInfos(), info); inserter.SetEntries(dataItems); @@ -513,7 +545,7 @@ int RelationalSyncAbleStorage::SaveSyncDataItems(const QueryObject &object, std: return errCode; } - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); errCode = handle->SaveSyncItems(inserter); @@ -632,11 +664,7 @@ int RelationalSyncAbleStorage::CreateDistributedDeviceTable(const std::string &d return errCode; } - StoreInfo info = { - storageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), - storageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") - }; + StoreInfo info = GetStoreInfo(); for (const auto &[table, strategy] : syncStrategy) { if (!strategy.permitSync) { continue; @@ -736,12 +764,16 @@ void RelationalSyncAbleStorage::TriggerObserverAction(const std::string &deviceN int observerCnt = 0; std::lock_guard lock(dataChangeDeviceMutex_); for (const auto &item : dataChangeCallbackMap_) { - for (const auto &action : item.second) { - if (action.second != nullptr) { - observerCnt++; - ChangedData observerChangeData = changedData; - action.second(deviceName, std::move(observerChangeData), isChangedData); + for (auto &action : item.second) { + if (action.second == nullptr) { + continue; } + observerCnt++; + ChangedData observerChangeData = changedData; + if (action.first != nullptr) { + FilterChangeDataByDetailsType(observerChangeData, action.first->GetCallbackDetailsType()); + } + action.second(deviceName, std::move(observerChangeData), isChangedData); } } LOGD("relational observer size = %d", observerCnt); @@ -924,6 +956,12 @@ int RelationalSyncAbleStorage::GetRemoteDeviceSchema(const std::string &deviceId return errCode; } +void RelationalSyncAbleStorage::SetReusedHandle(StorageExecutor *handle) +{ + std::lock_guard autoLock(reusedHandleMutex_); + reusedHandle_ = handle; +} + void RelationalSyncAbleStorage::ReleaseRemoteQueryContinueToken(ContinueToken &token) const { auto remoteToken = static_cast(token); @@ -932,6 +970,16 @@ void RelationalSyncAbleStorage::ReleaseRemoteQueryContinueToken(ContinueToken &t token = nullptr; } +StoreInfo RelationalSyncAbleStorage::GetStoreInfo() const +{ + StoreInfo info = { + storageEngine_->GetProperties().GetStringProp(DBProperties::USER_ID, ""), + storageEngine_->GetProperties().GetStringProp(DBProperties::APP_ID, ""), + storageEngine_->GetProperties().GetStringProp(DBProperties::STORE_ID, "") + }; + return info; +} + int RelationalSyncAbleStorage::StartTransaction(TransactType type) { CHECK_STORAGE_ENGINE; @@ -1002,38 +1050,11 @@ int RelationalSyncAbleStorage::GetUploadCount(const QuerySyncObject &query, cons return errCode; } -int RelationalSyncAbleStorage::FillCloudGid(const CloudSyncData &data) -{ - if (storageEngine_ == nullptr) { - return -E_INVALID_DB; - } - int errCode = E_OK; - auto writeHandle = static_cast( - storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); - if (writeHandle == nullptr) { - return errCode; - } - errCode = writeHandle->StartTransaction(TransactType::IMMEDIATE); - if (errCode != E_OK) { - ReleaseHandle(writeHandle); - return errCode; - } - errCode = writeHandle->UpdateCloudLogGid(data); - if (errCode != E_OK) { - writeHandle->Rollback(); - ReleaseHandle(writeHandle); - return errCode; - } - errCode = writeHandle->Commit(); - ReleaseHandle(writeHandle); - return errCode; -} - int RelationalSyncAbleStorage::GetCloudData(const TableSchema &tableSchema, const QuerySyncObject &querySyncObject, const Timestamp &beginTime, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { if (transactionHandle_ == nullptr) { - LOGE(" the transaction has not been started"); + LOGE("the transaction has not been started"); return -E_INVALID_DB; } SyncTimeRange syncTimeRange = { .beginTime = beginTime }; @@ -1064,13 +1085,18 @@ int RelationalSyncAbleStorage::GetCloudDataNext(ContinueToken &continueStmtToken ReleaseCloudDataToken(continueStmtToken); return -E_INVALID_DB; } + cloudDataResult.isShared = IsSharedTable(cloudDataResult.tableName); int errCode = transactionHandle_->GetSyncCloudData(cloudDataResult, CloudDbConstant::MAX_UPLOAD_SIZE, *token); if (errCode != -E_UNFINISHED) { delete token; token = nullptr; } continueStmtToken = static_cast(token); - return errCode; + if (errCode != E_OK && errCode != -E_UNFINISHED) { + return errCode; + } + int fillRefGidCode = FillReferenceData(cloudDataResult); + return fillRefGidCode == E_OK ? errCode : fillRefGidCode; } int RelationalSyncAbleStorage::GetCloudGid(const TableSchema &tableSchema, const QuerySyncObject &querySyncObject, @@ -1122,13 +1148,6 @@ int RelationalSyncAbleStorage::SetCloudDbSchema(const DataBaseSchema &schema) return E_OK; } -int RelationalSyncAbleStorage::GetCloudDbSchema(DataBaseSchema &cloudSchema) -{ - std::shared_lock readLock(schemaMgrMutex_); - cloudSchema = *(schemaMgr_.GetCloudDbSchema()); - return E_OK; -} - int RelationalSyncAbleStorage::GetInfoByPrimaryKeyOrGid(const std::string &tableName, const VBucket &vBucket, DataInfoWithLog &dataInfoWithLog, VBucket &assetInfo) { @@ -1163,7 +1182,18 @@ int RelationalSyncAbleStorage::PutCloudSyncData(const std::string &tableName, Do } RelationalSchemaObject localSchema = GetSchemaInfo(); transactionHandle_->SetLocalSchema(localSchema); - return transactionHandle_->PutCloudSyncData(tableName, tableSchema, downloadData); + TrackerTable trackerTable = storageEngine_->GetTrackerSchema().GetTrackerTable(tableName); + transactionHandle_->SetLogicDelete(IsCurrentLogicDelete()); + errCode = transactionHandle_->PutCloudSyncData(tableName, tableSchema, trackerTable, downloadData); + transactionHandle_->SetLogicDelete(false); + return errCode; +} + +int RelationalSyncAbleStorage::GetCloudDbSchema(std::shared_ptr &cloudSchema) +{ + std::shared_lock readLock(schemaMgrMutex_); + cloudSchema = schemaMgr_.GetCloudDbSchema(); + return E_OK; } int RelationalSyncAbleStorage::CleanCloudData(ClearMode mode, const std::vector &tableNameList, @@ -1173,7 +1203,6 @@ int RelationalSyncAbleStorage::CleanCloudData(ClearMode mode, const std::vector< LOGE("the transaction has not been started"); return -E_INVALID_DB; } - return transactionHandle_->DoCleanInner(mode, tableNameList, localSchema, assets); } @@ -1220,13 +1249,19 @@ int RelationalSyncAbleStorage::SetLogTriggerStatus(bool status) return errCode; } -int RelationalSyncAbleStorage::FillCloudGidAndAsset(const OpType opType, const CloudSyncData &data) +int RelationalSyncAbleStorage::FillCloudLogAndAsset(const OpType opType, const CloudSyncData &data, bool fillAsset, + bool ignoreEmptyGid) { CHECK_STORAGE_ENGINE; if (opType == OpType::UPDATE && data.updData.assets.empty()) { return E_OK; } - int errCode = E_OK; + TableSchema tableSchema; + int errCode = GetCloudTableSchema(data.tableName, tableSchema); + if (errCode != E_OK) { + LOGE("get table schema failed when fill log and asset. %d", errCode); + return errCode; + } auto writeHandle = static_cast( storageEngine_->FindExecutor(true, OperatePerm::NORMAL_PERM, errCode)); if (writeHandle == nullptr) { @@ -1237,22 +1272,9 @@ int RelationalSyncAbleStorage::FillCloudGidAndAsset(const OpType opType, const C ReleaseHandle(writeHandle); return errCode; } - if (opType == OpType::INSERT) { - errCode = writeHandle->UpdateCloudLogGid(data); - if (errCode != E_OK) { - LOGE("Failed to fill cloud log gid, %d.", errCode); - writeHandle->Rollback(); - ReleaseHandle(writeHandle); - return errCode; - } - if (!data.insData.assets.empty()) { - errCode = writeHandle->FillCloudAssetForUpload(data.tableName, data.insData); - } - } else { - errCode = writeHandle->FillCloudAssetForUpload(data.tableName, data.updData); - } + errCode = writeHandle->FillHandleWithOpType(opType, data, fillAsset, ignoreEmptyGid, tableSchema); if (errCode != E_OK) { - LOGE("Failed to fill cloud asset, %d.", errCode); + LOGE("Failed to fill version or cloud asset, opType:%d ret:%d.", opType, errCode); writeHandle->Rollback(); ReleaseHandle(writeHandle); return errCode; @@ -1297,6 +1319,12 @@ void RelationalSyncAbleStorage::ReleaseContinueToken(ContinueToken &continueStmt continueStmtToken = nullptr; } +int RelationalSyncAbleStorage::GetCloudDataGid(const QuerySyncObject &query, Timestamp beginTime, + std::vector &gid) +{ + return E_OK; +} + int RelationalSyncAbleStorage::CheckQueryValid(const QuerySyncObject &query) { int errCode = E_OK; @@ -1320,5 +1348,282 @@ int RelationalSyncAbleStorage::CheckQueryValid(const QuerySyncObject &query) } return errCode; } + +int RelationalSyncAbleStorage::CreateTempSyncTrigger(const std::string &tableName) +{ + int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + return errCode; + } + TrackerTable trackerTable = storageEngine_->GetTrackerSchema().GetTrackerTable(tableName); + if (trackerTable.IsEmpty()) { + trackerTable.SetTableName(tableName); + } + errCode = handle->CreateTempSyncTrigger(trackerTable); + ReleaseHandle(handle); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] Create temp sync trigger failed %d", errCode); + } + return errCode; +} + +int RelationalSyncAbleStorage::GetAndResetServerObserverData(const std::string &tableName, + ChangeProperties &changeProperties) +{ + int errCode = E_OK; + auto *handle = GetHandle(false, errCode); + if (handle == nullptr) { + return errCode; + } + errCode = handle->GetAndResetServerObserverData(tableName, changeProperties); + ReleaseHandle(handle); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] get server observer data failed %d", errCode); + } + return errCode; +} + +void RelationalSyncAbleStorage::FilterChangeDataByDetailsType(ChangedData &changedData, uint32_t type) +{ + if ((type & static_cast(CallbackDetailsType::DEFAULT)) == 0) { + changedData.field = {}; + for (size_t i = ChangeType::OP_INSERT; i < ChangeType::OP_BUTT; ++i) { + changedData.primaryData[i].clear(); + } + } + if ((type & static_cast(CallbackDetailsType::BRIEF)) == 0) { + changedData.properties = {}; + } +} + +int RelationalSyncAbleStorage::ClearAllTempSyncTrigger() +{ + int errCode = E_OK; + auto *handle = GetHandle(true, errCode); + if (handle == nullptr) { + return errCode; + } + errCode = handle->ClearAllTempSyncTrigger(); + ReleaseHandle(handle); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] clear all temp sync trigger failed %d", errCode); + } + return errCode; +} + +int RelationalSyncAbleStorage::FillReferenceData(CloudSyncData &syncData) +{ + std::map referenceGid; + int errCode = GetReferenceGid(syncData.tableName, syncData.insData, referenceGid); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] get insert reference data failed %d", errCode); + return errCode; + } + errCode = FillReferenceDataIntoExtend(syncData.insData.rowid, referenceGid, syncData.insData.extend); + if (errCode != E_OK) { + return errCode; + } + referenceGid.clear(); + errCode = GetReferenceGid(syncData.tableName, syncData.updData, referenceGid); + if (errCode != E_OK) { + LOGE("[RelationalSyncAbleStorage] get update reference data failed %d", errCode); + return errCode; + } + return FillReferenceDataIntoExtend(syncData.updData.rowid, referenceGid, syncData.updData.extend); +} + +int RelationalSyncAbleStorage::FillReferenceDataIntoExtend(const std::vector &rowid, + const std::map &referenceGid, std::vector &extend) +{ + if (referenceGid.empty()) { + return E_OK; + } + int ignoredCount = 0; + for (size_t index = 0u; index < rowid.size(); index++) { + if (index >= extend.size()) { + LOGE("[RelationalSyncAbleStorage] index out of range when fill reference gid into extend!"); + return -E_UNEXPECTED_DATA; + } + int64_t rowId = rowid[index]; + if (referenceGid.find(rowId) == referenceGid.end()) { + // current data miss match reference data, we ignored it + ignoredCount++; + continue; + } + extend[index].insert({ CloudDbConstant::REFERENCE_FIELD, referenceGid.at(rowId) }); + } + if (ignoredCount != 0) { + LOGD("[RelationalSyncAbleStorage] ignored %d data when fill reference data", ignoredCount); + } + return E_OK; +} + +bool RelationalSyncAbleStorage::IsSharedTable(const std::string &tableName) +{ + std::unique_lock writeLock(schemaMgrMutex_); + return schemaMgr_.IsSharedTable(tableName); +} + +std::map RelationalSyncAbleStorage::GetSharedTableOriginNames() +{ + std::unique_lock writeLock(schemaMgrMutex_); + return schemaMgr_.GetSharedTableOriginNames(); +} + +int RelationalSyncAbleStorage::GetReferenceGid(const std::string &tableName, const CloudSyncBatch &syncBatch, + std::map &referenceGid) +{ + std::map> tableReference; + int errCode = GetTableReference(tableName, tableReference); + if (errCode != E_OK) { + return errCode; + } + if (tableReference.empty()) { + LOGD("[RelationalSyncAbleStorage] currentTable not exist reference property"); + return E_OK; + } + auto *handle = GetHandle(false, errCode); + if (handle == nullptr) { + return errCode; + } + errCode = handle->GetReferenceGid(tableName, syncBatch, tableReference, referenceGid); + ReleaseHandle(handle); + return errCode; +} + +int RelationalSyncAbleStorage::GetTableReference(const std::string &tableName, + std::map> &reference) +{ + if (storageEngine_ == nullptr) { + LOGE("[RelationalSyncAbleStorage] storage is null when get reference gid"); + return -E_INVALID_DB; + } + RelationalSchemaObject schema = storageEngine_->GetSchema(); + auto referenceProperty = schema.GetReferenceProperty(); + if (referenceProperty.empty()) { + return E_OK; + } + auto [sourceTableName, errCode] = GetSourceTableName(tableName); + if (errCode != E_OK) { + return errCode; + } + for (const auto &property : referenceProperty) { + if (DBCommon::CaseInsensitiveCompare(property.sourceTableName, sourceTableName)) { + if (!IsSharedTable(tableName)) { + reference[property.targetTableName].push_back(property); + continue; + } + TableReferenceProperty tableReference; + tableReference.sourceTableName = tableName; + tableReference.columns = property.columns; + auto [sharedTargetTable, ret] = GetSharedTargetTableName(property.targetTableName); + if (ret != E_OK) { + return ret; + } + tableReference.targetTableName = sharedTargetTable; + reference[tableReference.targetTableName].push_back(tableReference); + } + } + return E_OK; +} + +std::pair RelationalSyncAbleStorage::GetSourceTableName(const std::string &tableName) +{ + std::pair res = { "", E_OK }; + std::shared_ptr cloudSchema; + (void) GetCloudDbSchema(cloudSchema); + if (cloudSchema == nullptr) { + LOGE("[RelationalSyncAbleStorage] cloud schema is null when get source table"); + return { "", -E_INTERNAL_ERROR }; + } + for (const auto &table : cloudSchema->tables) { + if (table.sharedTableName.empty()) { + continue; + } + if (DBCommon::CaseInsensitiveCompare(table.name, tableName) || + DBCommon::CaseInsensitiveCompare(table.sharedTableName, tableName)) { + res.first = table.name; + break; + } + } + if (res.first.empty()) { + LOGE("[RelationalSyncAbleStorage] not found table in cloud schema"); + res.second = -E_SCHEMA_MISMATCH; + } + return res; +} + +std::pair RelationalSyncAbleStorage::GetSharedTargetTableName(const std::string &tableName) +{ + std::pair res = { "", E_OK }; + std::shared_ptr cloudSchema; + (void) GetCloudDbSchema(cloudSchema); + if (cloudSchema == nullptr) { + LOGE("[RelationalSyncAbleStorage] cloud schema is null when get shared target table"); + return { "", -E_INTERNAL_ERROR }; + } + for (const auto &table : cloudSchema->tables) { + if (table.sharedTableName.empty()) { + continue; + } + if (DBCommon::CaseInsensitiveCompare(table.name, tableName)) { + res.first = table.sharedTableName; + break; + } + } + if (res.first.empty()) { + LOGE("[RelationalSyncAbleStorage] not found table in cloud schema"); + res.second = -E_SCHEMA_MISMATCH; + } + return res; +} + +void RelationalSyncAbleStorage::SetLogicDelete(bool logicDelete) +{ + logicDelete_ = logicDelete; + LOGI("[RelationalSyncAbleStorage] set logic delete %d", static_cast(logicDelete)); +} + +void RelationalSyncAbleStorage::SetCloudTaskConfig(const CloudTaskConfig &config) +{ + allowLogicDelete_ = config.allowLogicDelete; + LOGD("[RelationalSyncAbleStorage] allow logic delete %d", static_cast(config.allowLogicDelete)); +} + +bool RelationalSyncAbleStorage::IsCurrentLogicDelete() const +{ + return allowLogicDelete_ && logicDelete_; +} + +int RelationalSyncAbleStorage::GetAssetsByGidOrHashKey(const TableSchema &tableSchema, const std::string &gid, + const Bytes &hashKey, VBucket &assets) +{ + if (gid.empty() && hashKey.empty()) { + LOGE("both gid and hashKey are empty."); + return -E_INVALID_ARGS; + } + if (transactionHandle_ == nullptr) { + LOGE("the transaction has not been started"); + return -E_INVALID_DB; + } + int errCode = transactionHandle_->GetAssetsByGidOrHashKey(tableSchema, gid, hashKey, assets); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("get assets by gid or hashKey failed. %d", errCode); + } + return errCode; +} + +int RelationalSyncAbleStorage::SetIAssetLoader(const std::shared_ptr &loader) +{ + int errCode = E_OK; + auto *wHandle = GetHandle(true, errCode); + if (wHandle == nullptr) { + return errCode; + } + wHandle->SetIAssetLoader(loader); + ReleaseHandle(wHandle); + return errCode; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0f9028b3fc9e1727424f2b6a446abd4fce313eef --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "single_ver_natural_store.h" + +#include "db_common.h" +#include "db_errno.h" +#include "kvdb_utils.h" +#include "log_print.h" +#include "sqlite_single_ver_storage_engine.h" +#include "storage_engine_manager.h" + +namespace DistributedDB { +SingleVerNaturalStore::SingleVerNaturalStore() +{ +} + +SingleVerNaturalStore::~SingleVerNaturalStore() +{ +} + +void SingleVerNaturalStore::EnableHandle() +{ + return; +} + +void SingleVerNaturalStore::AbortHandle() +{ + return; +} + +int SingleVerNaturalStore::RemoveKvDB(const KvDBProperties &properties) +{ + // To avoid leakage, the engine resources are forced to be released + const std::string identifier = properties.GetStringProp(KvDBProperties::IDENTIFIER_DATA, ""); + (void)StorageEngineManager::ForceReleaseStorageEngine(identifier); + + // Only care the data directory and the db name. + std::string storeOnlyDir; + std::string storeDir; + GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE_SQLITE, storeDir, storeOnlyDir); + + const std::vector> dbDir { + { DBConstant::MAINDB_DIR, DBConstant::SINGLE_VER_DATA_STORE }, + { DBConstant::METADB_DIR, DBConstant::SINGLE_VER_META_STORE }, + { DBConstant::CACHEDB_DIR, DBConstant::SINGLE_VER_CACHE_STORE } + }; + + bool isAllNotFound = true; + for (const auto &item : dbDir) { + std::string currentDir = storeDir + item.first + "/"; + std::string currentOnlyDir = storeOnlyDir + item.first + "/"; + int errCode = KvDBUtils::RemoveKvDB(currentDir, currentOnlyDir, item.second); + if (errCode != -E_NOT_FOUND) { + if (errCode != E_OK) { + return errCode; + } + isAllNotFound = false; + } + }; + if (isAllNotFound) { + return -E_NOT_FOUND; + } + + int errCode = DBCommon::RemoveAllFilesOfDirectory(storeDir, true); + if (errCode != E_OK) { + return errCode; + } + return DBCommon::RemoveAllFilesOfDirectory(storeOnlyDir, true); +} + +RegisterFuncType SingleVerNaturalStore::GetFuncType(int index, const TransPair *transMap, int32_t len) +{ + int32_t head = 0; + int32_t end = len - 1; + while (head <= end) { + int32_t mid = head + (end - head) / 2; + if (transMap[mid].index < index) { + head = mid + 1; + continue; + } + if (transMap[mid].index > index) { + end = mid - 1; + continue; + } + return transMap[mid].funcType; + } + return RegisterFuncType::REGISTER_FUNC_TYPE_MAX; +} + +void SingleVerNaturalStore::CommitAndReleaseNotifyData(SingleVerNaturalStoreCommitNotifyData *&committedData, + bool isNeedCommit, int eventType) +{ + if (isNeedCommit) { + if (committedData != nullptr) { + if (!committedData->IsChangedDataEmpty()) { + CommitNotify(eventType, committedData); + } + if (!committedData->IsConflictedDataEmpty()) { + CommitNotify(static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_CONFLICT_EVENT), + committedData); + } + } + } + + if (committedData != nullptr) { + committedData->DecObjRef(committedData); + committedData = nullptr; + } +} + +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.h new file mode 100644 index 0000000000000000000000000000000000000000..e523b03b54c5b3180135c6fbf37033f173fbbadb --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SINGLE_VER_NATURAL_STORE_H +#define SINGLE_VER_NATURAL_STORE_H +#include "single_ver_kvdb_sync_interface.h" +#include "single_ver_natural_store_commit_notify_data.h" +#include "sync_able_kvdb.h" + +namespace DistributedDB { +class SingleVerNaturalStore : public SyncAbleKvDB, public SingleVerKvDBSyncInterface { +public: + SingleVerNaturalStore(); + ~SingleVerNaturalStore() override; + + virtual void EnableHandle(); + + virtual void AbortHandle(); + + int RemoveKvDB(const KvDBProperties &properties) override; + +protected: + struct TransPair { + int index; + RegisterFuncType funcType; + }; + static RegisterFuncType GetFuncType(int index, const TransPair *transMap, int32_t len); + + void CommitAndReleaseNotifyData(SingleVerNaturalStoreCommitNotifyData *&committedData, + bool isNeedCommit, int eventType); +}; +} // namespace DistributedDB + +#endif // SINGLE_VER_NATURAL_STORE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store_connection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c7fd1dc028753ca18d6507433dda4985450875f0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store_connection.cpp @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "single_ver_natural_store_connection.h" + +#include "db_errno.h" +#include "log_print.h" +#include "single_ver_natural_store.h" + +namespace DistributedDB { +SingleVerNaturalStoreConnection::SingleVerNaturalStoreConnection(SyncAbleKvDB *kvDB) : SyncAbleKvDBConnection(kvDB) +{ +} + +SingleVerNaturalStoreConnection::~SingleVerNaturalStoreConnection() +{ +} + +int SingleVerNaturalStoreConnection::Put(const IOption &option, const Key &key, const Value &value) +{ + std::vector entries; + Entry entry{key, value}; + entries.emplace_back(std::move(entry)); + + return PutBatch(option, entries); +} + +int SingleVerNaturalStoreConnection::PutBatch(const IOption &option, const std::vector &entries) +{ + LOGD("[PutBatch] entries size is : %zu, dataType : %d", entries.size(), option.dataType); + if (option.dataType != IOption::SYNC_DATA) { + return -E_NOT_SUPPORT; + } + int errCode = CheckSyncEntriesValid(entries); + if (errCode != E_OK) { + return errCode; + } + return PutBatchInner(option, entries); +} + +bool SingleVerNaturalStoreConnection::IsExtendedCacheDBMode() const +{ + return false; +} + +int SingleVerNaturalStoreConnection::CheckSyncEntriesValid(const std::vector &entries) const +{ + if (entries.size() > DBConstant::MAX_BATCH_SIZE) { + return -E_INVALID_ARGS; + } + + SingleVerNaturalStore *naturalStore = GetDB(); + if (naturalStore == nullptr) { + return -E_INVALID_DB; + } + + int errCode = CheckWritePermission(); + if (errCode != E_OK) { + return errCode; + } + + for (const auto &entry : entries) { + errCode = naturalStore->CheckDataStatus(entry.key, entry.value, false); + if (errCode != E_OK) { + return errCode; + } + } + return E_OK; +} + +int SingleVerNaturalStoreConnection::CheckWritePermission() const +{ + return E_OK; +} + +int SingleVerNaturalStoreConnection::Get(const IOption &option, const Key &key, Value &value) const +{ + return E_OK; +} + +int SingleVerNaturalStoreConnection::Delete(const IOption &option, const Key &key) +{ + std::vector keys; + keys.push_back(key); + + return DeleteBatch(option, keys); +} + +int SingleVerNaturalStoreConnection::DeleteBatch(const IOption &option, const std::vector &keys) +{ + LOGD("[DeleteBatch] keys size is : %zu, dataType : %d", keys.size(), option.dataType); + if (option.dataType != IOption::SYNC_DATA) { + return -E_NOT_SUPPORT; + } + int errCode = CheckSyncKeysValid(keys); + if (errCode != E_OK) { + return errCode; + } + return DeleteBatchInner(option, keys); +} + +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store_connection.h new file mode 100644 index 0000000000000000000000000000000000000000..6c0f72f3f4fbab518199345261e62cfa4e178bc1 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_natural_store_connection.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SINGLE_VER_NATURAL_STORE_CONNECTION_H +#define SINGLE_VER_NATURAL_STORE_CONNECTION_H +#include "sync_able_kvdb_connection.h" + +namespace DistributedDB { +class SingleVerNaturalStoreConnection : public SyncAbleKvDBConnection { +public: + explicit SingleVerNaturalStoreConnection(SyncAbleKvDB *kvDB); + + virtual ~SingleVerNaturalStoreConnection(); + + int Put(const IOption &option, const Key &key, const Value &value) override; + + int PutBatch(const IOption &option, const std::vector &entries) override; + + virtual bool IsExtendedCacheDBMode() const; + + int Get(const IOption &option, const Key &key, Value &value) const override; + + // Delete the value from the database + int Delete(const IOption &option, const Key &key) override; + + // Delete the batch values from the database. + int DeleteBatch(const IOption &option, const std::vector &keys) override; + +protected: + virtual int CheckSyncEntriesValid(const std::vector &entries) const; + + virtual int CheckWritePermission() const; + + virtual int PutBatchInner(const IOption &option, const std::vector &entries) = 0; + + virtual int CheckSyncKeysValid(const std::vector &keys) const = 0; + + virtual int DeleteBatchInner(const IOption &option, const std::vector &keys) = 0; +}; +} // namespace DistributedDB + +#endif // SINGLE_VER_NATURAL_STORE_CONNECTION_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..21750611d28ba5b760845611c641322537bff861 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "single_ver_utils.h" + +#include "db_common.h" +#include "platform_specific.h" +#include "runtime_context.h" + +namespace DistributedDB { + +int GetPathSecurityOption(const std::string &filePath, SecurityOption &secOpt) +{ + return RuntimeContext::GetInstance()->GetSecurityOption(filePath, secOpt); +} + +std::string GetDbDir(const std::string &subDir, DbType type) +{ + switch (type) { + case DbType::MAIN: + return subDir + "/" + DBConstant::MAINDB_DIR; + case DbType::META: + return subDir + "/" + DBConstant::METADB_DIR; + case DbType::CACHE: + return subDir + "/" + DBConstant::CACHEDB_DIR; + default: + break; + } + return ""; +} + +std::string GetDatabasePath(const KvDBProperties &kvDBProp) +{ + return GetSubDirPath(kvDBProp) + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + + DBConstant::DB_EXTENSION; +} + +std::string GetSubDirPath(const KvDBProperties &kvDBProp) +{ + std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, ""); + std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, ""); + return dataDir + "/" + identifierDir + "/" + DBConstant::SINGLE_SUB_DIR; +} + +int ClearIncompleteDatabase(const KvDBProperties &kvDBPro) +{ + std::string dbSubDir = GetSubDirPath(kvDBPro); + if (OS::CheckPathExistence(dbSubDir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE)) { + int errCode = DBCommon::RemoveAllFilesOfDirectory(dbSubDir); + if (errCode != E_OK) { + LOGE("Remove the incomplete database dir failed!"); + return -E_REMOVE_FILE; + } + } + return E_OK; +} + +int CreateNewDirsAndSetSecOption(const OpenDbProperties &option) +{ + std::vector dbDir { DBConstant::MAINDB_DIR, DBConstant::METADB_DIR, DBConstant::CACHEDB_DIR }; + for (const auto &item : dbDir) { + if (OS::CheckPathExistence(option.subdir + "/" + item)) { + continue; + } + + // Dir and old db file not existed, it means that the database is newly created + // need create flag of database not incomplete + if (!OS::CheckPathExistence(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && + !OS::CheckPathExistence(option.subdir + "/" + DBConstant::SINGLE_VER_DATA_STORE + + DBConstant::DB_EXTENSION) && + OS::CreateFileByFileName(option.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { + LOGE("Fail to create the token of database incompleted! errCode = [E_SYSTEM_API_FAIL]"); + return -E_SYSTEM_API_FAIL; + } + + if (DBCommon::CreateDirectory(option.subdir + "/" + item) != E_OK) { + LOGE("Create sub-directory for single ver failed, errno:%d", errno); + return -E_SYSTEM_API_FAIL; + } + + if (option.securityOpt.securityLabel == NOT_SET) { + continue; + } + + SecurityOption secOption = option.securityOpt; + if (item == DBConstant::METADB_DIR) { + secOption.securityLabel = ((option.securityOpt.securityLabel >= SecurityLabel::S2) ? + SecurityLabel::S2 : option.securityOpt.securityLabel); + secOption.securityFlag = SecurityFlag::ECE; + } + + int errCode = RuntimeContext::GetInstance()->SetSecurityOption(option.subdir + "/" + item, secOption); + if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { + LOGE("Set the security option of sub-directory failed[%d]", errCode); + return errCode; + } + } + return E_OK; +} + +int GetExistedSecOpt(const OpenDbProperties &opt, SecurityOption &secOption) +{ + // Check the existence of the database, include the origin database and the database in the 'main' directory. + auto mainDbDir = GetDbDir(opt.subdir, DbType::MAIN); + auto mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + auto origDbFilePath = opt.subdir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + if (!OS::CheckPathExistence(origDbFilePath) && !OS::CheckPathExistence(mainDbFilePath)) { + secOption = opt.securityOpt; + return E_OK; + } + + // the main database file has high priority of the security option. + int errCode; + if (OS::CheckPathExistence(mainDbFilePath)) { + errCode = GetPathSecurityOption(mainDbFilePath, secOption); + } else { + errCode = GetPathSecurityOption(origDbFilePath, secOption); + } + if (errCode == E_OK) { + return E_OK; + } + secOption = SecurityOption(); + if (errCode == -E_NOT_SUPPORT) { + return E_OK; + } + LOGE("Get the security option of the existed database failed."); + return errCode; +} + +void InitCommitNotifyDataKeyStatus(SingleVerNaturalStoreCommitNotifyData *committedData, const Key &hashKey, + const DataOperStatus &dataStatus) +{ + if (committedData == nullptr) { + return; + } + + ExistStatus existedStatus = ExistStatus::NONE; + if (dataStatus.preStatus == DataStatus::DELETED) { + existedStatus = ExistStatus::DELETED; + } else if (dataStatus.preStatus == DataStatus::EXISTED) { + existedStatus = ExistStatus::EXIST; + } + + committedData->InitKeyPropRecord(hashKey, existedStatus); +} +} // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..c01d14b44d16bce667f6e62ff05bda8c23956edc --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/single_ver_utils.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SINGLE_VER_UTILS_H +#define SINGLE_VER_UTILS_H + +#include "kvdb_properties.h" +#include "storage_executor.h" +#include "types_export.h" + +namespace DistributedDB { + +const uint64_t CACHE_RECORD_DEFAULT_VERSION = 1; + +enum class DbType : int32_t { + MAIN, + META, + CACHE +}; + +struct OpenDbProperties { + std::string uri {}; + bool createIfNecessary = true; + bool isMemDb = false; + std::vector sqls {}; + CipherType cipherType = CipherType::AES_256_GCM; + CipherPassword passwd {}; + std::string schema {}; + std::string subdir {}; + SecurityOption securityOpt {}; + int conflictReslovePolicy = DEFAULT_LAST_WIN; + bool createDirByStoreIdOnly = false; + uint32_t iterTimes = DBConstant::DEFAULT_ITER_TIMES; + // newly added RD properties + std::string rdConfig {}; + bool isNeedIntegrityCheck = false; + bool isNeedRmCorruptedDb = false; + bool readOnly = false; +}; + +int GetPathSecurityOption(const std::string &filePath, SecurityOption &secOpt); + +std::string GetDbDir(const std::string &subDir, DbType type); + +std::string GetDatabasePath(const KvDBProperties &kvDBProp); + +std::string GetSubDirPath(const KvDBProperties &kvDBProp); + +int ClearIncompleteDatabase(const KvDBProperties &kvDBPro); + +int CreateNewDirsAndSetSecOption(const OpenDbProperties &option); + +int GetExistedSecOpt(const OpenDbProperties &option, SecurityOption &secOption); + +void InitCommitNotifyDataKeyStatus(SingleVerNaturalStoreCommitNotifyData *committedData, const Key &hashKey, + const DataOperStatus &dataStatus); +} // namespace DistributedDB + +#endif // SINGLE_VER_UTILS_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp index c485bdd57c003efa67cc45a147aac39c58a6857d..df4a8380c61849cbb410b98e1297cac2fa6df980 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.cpp @@ -15,6 +15,7 @@ #include "cloud_sync_log_table_manager.h" #include "cloud/cloud_db_constant.h" +#include "cloud/cloud_storage_utils.h" #include "db_common.h" namespace DistributedDB { @@ -69,9 +70,12 @@ void CloudSyncLogTableManager::GetIndexSql(const TableInfo &table, std::vector0 FROM "; insertTrigger += logTblName + " WHERE hash_key = " + CalcPrimaryKeyHash("NEW.", table, identity); insertTrigger += ") THEN (SELECT cloud_gid FROM " + logTblName + " WHERE hash_key = "; - insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ") ELSE '' END);\n"; + insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ") ELSE '' END, "; + insertTrigger += table.GetTrackerTable().GetAssignValSql(); + insertTrigger += ", case when (SELECT count(1)<>0 FROM " + logTblName + ") then "; + insertTrigger += " (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END"; + insertTrigger += " FROM " + logTblName + ")"; + insertTrigger += " ELSE new." + std::string(DBConstant::SQLITE_INNER_ROWID) + " end, '');\n"; + insertTrigger += CloudStorageUtils::GetTableRefUpdateSql(table, OpType::INSERT); insertTrigger += "SELECT client_observer('" + tableName + "', NEW." + std::string(DBConstant::SQLITE_INNER_ROWID); - insertTrigger += ", 0);\n"; + insertTrigger += ", 0, "; + insertTrigger += (table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1"); + insertTrigger += ");\n"; insertTrigger += "END;"; return insertTrigger; } @@ -121,9 +134,18 @@ std::string CloudSyncLogTableManager::GetUpdateTrigger(const TableInfo &table, c updateTrigger += "BEGIN\n"; // if user change the primary key, we can still use gid to identify which one is updated updateTrigger += "\t UPDATE " + logTblName; updateTrigger += " SET timestamp=get_raw_sys_time(), device='', flag=0x02"; - updateTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; - updateTrigger += "SELECT client_observer('" + tableName + "', OLD." + std::string(DBConstant::SQLITE_INNER_ROWID); - updateTrigger += ", 1);\n"; + if (!table.GetTrackerTable().GetTrackerColNames().empty()) { + updateTrigger += table.GetTrackerTable().GetExtendAssignValSql(); + } + updateTrigger += ", cursor = (SELECT case when (MAX(cursor) is null) then 1 else (MAX(cursor) + 1) END "; + updateTrigger += " from " + logTblName; + updateTrigger += ") WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";\n"; + updateTrigger += CloudStorageUtils::GetTableRefUpdateSql(table, OpType::UPDATE); + updateTrigger += "select client_observer('" + tableName + "', OLD."; + updateTrigger += std::string(DBConstant::SQLITE_INNER_ROWID); + updateTrigger += ", 1, "; + updateTrigger += table.GetTrackerTable().GetDiffTrackerValSql(); + updateTrigger += ");"; updateTrigger += "END;"; return updateTrigger; } @@ -131,6 +153,7 @@ std::string CloudSyncLogTableManager::GetUpdateTrigger(const TableInfo &table, c std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity) { (void)identity; + std::string logTblName = GetLogTableName(table); std::string tableName = table.GetTableName(); std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS "; deleteTrigger += "naturalbase_rdb_" + tableName + "_ON_DELETE BEFORE DELETE \n"; @@ -140,10 +163,35 @@ std::string CloudSyncLogTableManager::GetDeleteTrigger(const TableInfo &table, c deleteTrigger += "BEGIN\n"; deleteTrigger += "\t UPDATE " + GetLogTableName(table); deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_raw_sys_time()"; + if (!table.GetTrackerTable().GetTrackerColNames().empty()) { + deleteTrigger += table.GetTrackerTable().GetExtendAssignValSql(true); + } + deleteTrigger += ", cursor = (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END "; + deleteTrigger += " FROM " + logTblName + ")"; deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";"; + deleteTrigger += CloudStorageUtils::GetTableRefUpdateSql(table, OpType::DELETE); // -1 is rowid when data is deleted, 2 means change type is delete(ClientChangeType) - deleteTrigger += "SELECT client_observer('" + tableName + "', -1, 2);\n"; + deleteTrigger += "SELECT client_observer('" + tableName + "', -1, 2, "; + deleteTrigger += table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1"; + deleteTrigger += ");\n"; deleteTrigger += "END;"; return deleteTrigger; } + +std::vector CloudSyncLogTableManager::GetDropTriggers(const TableInfo &table) +{ + std::vector dropTriggers; + std::string tableName = table.GetTableName(); + std::string insertTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_INSERT; "; + std::string updateTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_UPDATE; "; + std::string deleteTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_DELETE; "; + dropTriggers.emplace_back(insertTrigger); + dropTriggers.emplace_back(updateTrigger); + dropTriggers.emplace_back(deleteTrigger); + if (table.GetTrackerTable().GetTrackerColNames().empty()) { + std::string clearExtendSql = "UPDATE " + GetLogTableName(table) + " SET extend_field = '';"; + dropTriggers.emplace_back(clearExtendSql); + } + return dropTriggers; +} } // DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h index 137c36ca0950151cfcec0aa7efa8966862f45cbb..6a8e837ccef45a909da774e64adeda6255ac6ef3 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/cloud_sync_log_table_manager.h @@ -36,6 +36,7 @@ private: std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) override; std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) override; std::string GetDeleteTrigger(const TableInfo &table, const std::string &identity) override; + std::vector GetDropTriggers(const TableInfo &table) override; }; } // DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp index 64d79568352789ccbaefb1ffbd79bbe0261c854d..4c97b628280691137c628f98bb7c34636b882003 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.cpp @@ -90,7 +90,7 @@ std::string CollaborationLogTableManager::GetUpdateTrigger(const TableInfo &tabl std::string(DBConstant::SQLITE_INNER_ROWID) + ", '', '', get_sys_time(0), " "get_last_time(), CASE WHEN (" + CalcPrimaryKeyHash("NEW.", table, identity) + " != " + CalcPrimaryKeyHash("NEW.", table, identity) + ") THEN 0x02 ELSE 0x22 END, " + - CalcPrimaryKeyHash("NEW.", table, identity) + ", '');\n"; + CalcPrimaryKeyHash("NEW.", table, identity) + ", '', '', '', '');\n"; } updateTrigger += "END;"; return updateTrigger; @@ -107,7 +107,7 @@ std::string CollaborationLogTableManager::GetDeleteTrigger(const TableInfo &tabl deleteTrigger += "BEGIN\n"; deleteTrigger += "\t UPDATE " + DBConstant::RELATIONAL_PREFIX + table.GetTableName() + "_log"; deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_sys_time(0)"; - deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";"; + deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";"; deleteTrigger += "END;"; return deleteTrigger; } @@ -124,4 +124,17 @@ void CollaborationLogTableManager::GetIndexSql(const TableInfo &table, std::vect GetLogTableName(table) + "(data_key);"; schema.emplace_back(dataKeyIndex); } + +std::vector CollaborationLogTableManager::GetDropTriggers(const TableInfo &table) +{ + std::vector dropTriggers; + std::string tableName = table.GetTableName(); + std::string insertTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_INSERT; "; + std::string updateTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_UPDATE; "; + std::string deleteTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_DELETE; "; + dropTriggers.emplace_back(insertTrigger); + dropTriggers.emplace_back(updateTrigger); + dropTriggers.emplace_back(deleteTrigger); + return dropTriggers; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.h index c5bea74f1a4a26140934ff79f36819daecbd066f..b7e2091af6975a37d8e9f5cc5f60cc758e67cde5 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/collaboration_log_table_manager.h @@ -35,6 +35,7 @@ private: std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) override; std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) override; std::string GetDeleteTrigger(const TableInfo &table, const std::string &identity) override; + std::vector GetDropTriggers(const TableInfo &table) override; }; } #endif // COLLABORATION_LOG_TABLE_MANAGER_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.cpp index 2e0baaf4530c77f7453ff6e6ec103ccd896ee8c5..297fe24c7b907045226674f5d218b4c5ac354751 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.cpp @@ -416,6 +416,13 @@ bool QueryObject::IsQueryOnlyByKey() const }); } +bool QueryObject::IsQueryByRange() const +{ + return std::any_of(queryObjNodes_.begin(), queryObjNodes_.end(), [&](const QueryObjNode &node) { + return node.operFlag == QueryObjType::KEY_RANGE; + }); +} + bool QueryObject::IsQueryForRelationalDB() const { return isTableNameSpecified_ && @@ -511,6 +518,7 @@ SortType QueryObject::GetSortType() const int QueryObject::CheckPrimaryKey(const std::map &primaryKeyMap) const { + // 1 primary key and name is "rowid" means no user-defined rowid if (primaryKeyMap.size() == 1 && primaryKeyMap.begin()->second == "rowid") { return -E_NOT_SUPPORT; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.h index 4d1b663c2bb4d1cfd765b40648aa8b4d0b41ff9e..47681cf042df2be45e90a0e887dc4a38b12d8167 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_object.h @@ -45,6 +45,7 @@ public: void SetSchema(const SchemaObject &schema); bool IsQueryOnlyByKey() const; + bool IsQueryByRange() const; bool IsQueryForRelationalDB() const; void SetTableName(const std::string &tableName); @@ -63,7 +64,7 @@ public: SortType GetSortType() const; - int CheckPrimaryKey(const std::map &primaryMap) const; + int CheckPrimaryKey(const std::map &primaryKeyMap) const; #ifdef RELATIONAL_STORE int SetSchema(const RelationalSchemaObject &schemaObj); // The interface can only be used in relational query. diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp index 44666396df9dddfccbe115f89a82c12b2e6179af..bd6a27f0bd5e309a4eacb79b199ded4df1975d73 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/query_sync_object.cpp @@ -472,7 +472,6 @@ int QuerySyncObject::TransformValueToType(const QueryObjNode &objNode, std::vect types.emplace_back(value.doubleValue); break; case QueryValueType::VALUE_TYPE_INVALID: - default: return -E_INVALID_ARGS; } } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp index 5f4ae1d9ed5f62c00eb49876ad6030fa53da9b1a..2af779f56286e95334056579aea53fcbe5ac3c41 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp @@ -133,7 +133,7 @@ int SqliteRelationalDatabaseUpgrader::UpgradeTrigger(const std::string &logTable static bool inline NeedUpdateLogTable(const std::string &logTableVersion) { - return logTableVersion < DBConstant::LOG_TABLE_VERSION_3; + return logTableVersion < DBConstant::LOG_TABLE_VERSION_CURRENT; } int SqliteRelationalDatabaseUpgrader::UpgradeLogTable(const std::string &logTableVersion) @@ -159,8 +159,19 @@ int SqliteRelationalDatabaseUpgrader::UpgradeLogTable(const std::string &logTabl } for (const auto &item : schemaObject.GetTables()) { - std::string addColumnSql = "alter table " + DBConstant::RELATIONAL_PREFIX + item.first + - "_log add cloud_gid text after hash_key;"; + std::string addColumnSql; + if (logTableVersion < DBConstant::LOG_TABLE_VERSION_3) { + addColumnSql += "alter table " + DBConstant::RELATIONAL_PREFIX + item.first + + "_log add cloud_gid text after hash_key;"; + } + if (logTableVersion < DBConstant::LOG_TABLE_VERSION_5) { + addColumnSql += "alter table " + DBConstant::RELATIONAL_PREFIX + item.first + + "_log add extend_field blob after cloud_gid;"; + addColumnSql += "alter table " + DBConstant::RELATIONAL_PREFIX + item.first + + "_log add cursor int after extend_field;"; + addColumnSql += "alter table " + DBConstant::RELATIONAL_PREFIX + item.first + + "_log add version int after cursor;"; + } errCode = SQLiteUtils::ExecuteRawSQL(db_, addColumnSql); if (errCode != E_OK) { LOGE("[Relational][UpgradeLogTable] add column failed.", errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp index 777f4310b0fe7cf41d9e4ce8f55f19c02af8bdde..ad145273026598f6f4815b4d10efd30206048bc3 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.cpp @@ -171,6 +171,11 @@ int SQLiteRelationalStore::CheckProperties(RelationalDBProperties properties) LOGE("Get relational schema from meta failed. errcode=%d", errCode); return errCode; } + int ret = InitTrackerSchemaFromMeta(); + if (ret != E_OK) { + LOGE("Init tracker schema from meta failed. errcode=%d", ret); + return ret; + } properties.SetSchema(schema); // Empty schema means no distributed table has been used, we may set DB to any table mode @@ -469,6 +474,10 @@ int SQLiteRelationalStore::CleanCloudData(ClearMode mode) TableInfoMap tables = localSchema.GetTables(); std::vector cloudTableNameList; for (const auto &tableInfo : tables) { + bool isSharedTable = tableInfo.second.GetSharedTableMark(); + if ((mode == CLEAR_SHARED_TABLE && !isSharedTable) || (mode != CLEAR_SHARED_TABLE && isSharedTable)) { + continue; + } if (tableInfo.second.GetTableSyncType() == CLOUD_COOPERATION) { cloudTableNameList.push_back(tableInfo.first); } @@ -477,7 +486,6 @@ int SQLiteRelationalStore::CleanCloudData(ClearMode mode) LOGI("[RelationalStore] device doesn't has cloud table, clean cloud data finished."); return E_OK; } - if (cloudSyncer_ == nullptr) { LOGE("[RelationalStore] cloudSyncer was not initialized when clean cloud data"); return -E_INVALID_DB; @@ -557,7 +565,7 @@ int SQLiteRelationalStore::RemoveDeviceData(const std::string &device, const std return -E_DISTRIBUTED_SCHEMA_NOT_FOUND; } // cloud mode is not permit - if (iter->second.GetTableSyncType() == CLOUD_COOPERATION) { + if (iter != tables.end() && iter->second.GetTableSyncType() == CLOUD_COOPERATION) { LOGE("Remove device data with cloud sync table name."); return -E_NOT_SUPPORT; } @@ -826,7 +834,6 @@ int SQLiteRelationalStore::GetHandleAndStartTransaction(SQLiteSingleVerRelationa if (errCode != E_OK) { LOGE("start transaction failed %d", errCode); ReleaseHandle(handle); - return errCode; } return errCode; } @@ -909,6 +916,9 @@ std::vector SQLiteRelationalStore::GetAllDistributedTableName() TableInfoMap tables = sqliteStorageEngine_->GetSchema().GetTables(); // TableInfoMap std::vector tableNames; for (const auto &table: tables) { + if (table.second.GetTableSyncType() == TableSyncType::CLOUD_COOPERATION) { + continue; + } tableNames.push_back(table.second.GetTableName()); } return tableNames; @@ -924,12 +934,97 @@ int SQLiteRelationalStore::SetCloudDB(const std::shared_ptr &cloudDb) return E_OK; } -int SQLiteRelationalStore::SetCloudDbSchema(const DataBaseSchema &schema) +bool SQLiteRelationalStore::CheckFields(const std::vector &newFields, const TableInfo &tableInfo, + std::vector &addFields) +{ + std::vector oldFields = tableInfo.GetFieldInfos(); + if (newFields.size() < oldFields.size()) { + return false; + } + for (size_t index = 0; index < newFields.size(); index++) { + if (index >= oldFields.size()) { + addFields.push_back(newFields[index]); + continue; + } + int32_t type = newFields[index].type; + // Field type need to match storage type + if (type >= TYPE_INDEX && type <= TYPE_INDEX) { + type++; // storage type - field type = 1 + } else if (type == TYPE_INDEX) { + type = 1; // storage type is STORAGE_TYPE_NULL + } else if (type >= TYPE_INDEX && type <= TYPE_INDEX) { + type = TYPE_INDEX; // storage type is STORAGE_TYPE_BLOB + } + auto primaryKeyMap = tableInfo.GetPrimaryKey(); + auto it = std::find_if(primaryKeyMap.begin(), primaryKeyMap.end(), + [&](const std::map::value_type &pair) { + return pair.second == newFields[index].colName; + }); + if (newFields[index].colName != oldFields[index].GetFieldName() || + type != static_cast(oldFields[index].GetStorageType()) || + newFields[index].primary != (it != primaryKeyMap.end()) || + newFields[index].nullable == oldFields[index].IsNotNull()) { + return false; + } + } + return true; +} + +bool SQLiteRelationalStore::PrepareSharedTable(const DataBaseSchema &schema, std::vector &deleteTableNames, + std::map> &updateTableNames, std::map &alterTableNames) +{ + std::set tableNames; + std::map sharedTableNamesMap; + std::map> fieldsMap; + for (const auto &table : schema.tables) { + tableNames.insert(table.name); + sharedTableNamesMap[table.name] = table.sharedTableName; + std::vector fields = table.fields; + bool hasPrimaryKey = DBCommon::HasPrimaryKey(fields); + Field ownerField = {CloudDbConstant::CLOUD_OWNER, TYPE_INDEX, hasPrimaryKey}; + Field privilegeField = {CloudDbConstant::CLOUD_PRIVILEGE, TYPE_INDEX}; + fields.insert(fields.begin(), privilegeField); + fields.insert(fields.begin(), ownerField); + fieldsMap[table.name] = fields; + } + + RelationalSchemaObject localSchema = sqliteStorageEngine_->GetSchema(); + TableInfoMap tableList = localSchema.GetTables(); + for (const auto &tableInfo : tableList) { + if (!tableInfo.second.GetSharedTableMark()) { + continue; + } + std::string oldSharedTableName = tableInfo.second.GetTableName(); + std::string oldOriginTableName = tableInfo.second.GetOriginTableName(); + std::vector addFields; + if (tableNames.find(oldOriginTableName) == tableNames.end()) { + deleteTableNames.push_back(oldSharedTableName); + } else if (CheckFields(fieldsMap[oldOriginTableName], tableInfo.second, addFields)) { + if (!addFields.empty()) { + updateTableNames[oldSharedTableName] = addFields; + } + if (oldSharedTableName != sharedTableNamesMap[oldOriginTableName]) { + alterTableNames[oldSharedTableName] = sharedTableNamesMap[oldOriginTableName]; + } + } else { + return false; + } + } + return true; +} + +int SQLiteRelationalStore::PrepareAndSetCloudDbSchema(const DataBaseSchema &schema) { if (storageEngine_ == nullptr) { - LOGE("[RelationalStore][SetCloudDbSchema] storageEngine was not initialized"); + LOGE("[RelationalStore][PrepareAndSetCloudDbSchema] storageEngine was not initialized"); return -E_INVALID_DB; } + // delete, update and create shared table and its distributed table + int errCode = ExecuteCreateSharedTable(schema); + if (errCode != E_OK) { + LOGE("[RelationalStore] prepare shared table failed:%d", errCode); + return errCode; + } return storageEngine_->SetCloudDbSchema(schema); } @@ -954,12 +1049,24 @@ int SQLiteRelationalStore::ChkSchema(const TableName &tableName) int SQLiteRelationalStore::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) { + if (storageEngine_ == nullptr) { + LOGE("[RelationalStore][Sync] storageEngine was not initialized"); + return -E_INVALID_DB; + } int errCode = CheckBeforeSync(option); if (errCode != E_OK) { return errCode; } CloudSyncer::CloudTaskInfo info; FillSyncInfo(option, onProcess, info); + auto [table, ret] = sqliteStorageEngine_->CalTableRef(info.table, storageEngine_->GetSharedTableOriginNames()); + if (ret != E_OK) { + return ret; + } + ret = ReFillSyncInfoTable(table, info); + if (ret != E_OK) { + return ret; + } return cloudSyncer_->Sync(info); } @@ -1019,20 +1126,18 @@ int SQLiteRelationalStore::CheckQueryValid(bool priorityTask, const Query &query if (errCode != E_OK) { return errCode; } - errCode = CheckObjectValid(priorityTask, object); - return errCode; + return CheckObjectValid(priorityTask, object); } int SQLiteRelationalStore::CheckObjectValid(bool priorityTask, const std::vector &object) { - int errCode = E_OK; RelationalSchemaObject localSchema = sqliteStorageEngine_->GetSchema(); for (const auto &item : object) { if (priorityTask && !item.IsContainQueryNodes()) { LOGE("[RelationalStore] not support priority sync with full table"); return -E_INVALID_ARGS; } - errCode = storageEngine_->CheckQueryValid(item); + int errCode = storageEngine_->CheckQueryValid(item); if (errCode != E_OK) { return errCode; } @@ -1053,7 +1158,7 @@ int SQLiteRelationalStore::CheckObjectValid(bool priorityTask, const std::vector } } } - return errCode; + return E_OK; } int SQLiteRelationalStore::CheckTableName(const std::vector &tableNames) @@ -1096,5 +1201,185 @@ void SQLiteRelationalStore::FillSyncInfo(const CloudSyncOption &option, const Sy info.timeout = option.waitTime; info.priorityTask = option.priorityTask; } + +int SQLiteRelationalStore::SetTrackerTable(const TrackerSchema &trackerSchema) +{ + RelationalSchemaObject localSchema = sqliteStorageEngine_->GetSchema(); + TableInfo tableInfo = localSchema.GetTable(trackerSchema.tableName); + if (tableInfo.Empty()) { + return sqliteStorageEngine_->SetTrackerTable(trackerSchema); + } + int errCode = sqliteStorageEngine_->CheckAndCacheTrackerSchema(trackerSchema, tableInfo); + if (errCode != E_OK) { + return errCode == -E_IGNORE_DATA ? E_OK : errCode; + } + errCode = CreateDistributedTable(trackerSchema.tableName, tableInfo.GetTableSyncType()); + if (errCode != E_OK) { + return errCode; + } + return sqliteStorageEngine_->SaveTrackerSchema(); +} + +int SQLiteRelationalStore::ExecuteSql(const SqlCondition &condition, std::vector &records) +{ + if (condition.sql.empty()) { + LOGE("[RelationalStore] execute sql is empty."); + return -E_INVALID_ARGS; + } + return sqliteStorageEngine_->ExecuteSql(condition, records); +} + +int SQLiteRelationalStore::CleanWaterMark(std::set &clearWaterMarkTable) +{ + int errCode = E_OK; + for (const auto &tableName : clearWaterMarkTable) { + std::string cloudWaterMark; + Value blobMetaVal; + errCode = DBCommon::SerializeWaterMark(0, cloudWaterMark, blobMetaVal); + if (errCode != E_OK) { + LOGE("[SQLiteRelationalStore] SerializeWaterMark failed, errCode = %d", errCode); + return errCode; + } + errCode = storageEngine_->PutMetaData(DBCommon::GetPrefixTableName(tableName), blobMetaVal, true); + if (errCode != E_OK) { + LOGE("[SQLiteRelationalStore] put meta data failed, errCode = %d", errCode); + return errCode; + } + } + errCode = cloudSyncer_->CleanWaterMarkInMemory(clearWaterMarkTable); + if (errCode != E_OK) { + LOGE("[SQLiteRelationalStore] CleanWaterMarkInMemory failed, errCode = %d", errCode); + } + return errCode; +} + +int SQLiteRelationalStore::SetReference(const std::vector &tableReferenceProperty) +{ + SQLiteSingleVerRelationalStorageExecutor *handle = nullptr; + int errCode = GetHandleAndStartTransaction(handle); + if (errCode != E_OK) { + LOGE("[SQLiteRelationalStore] SetReference start transaction failed, errCode = %d", errCode); + return errCode; + } + std::set clearWaterMarkTables; + RelationalSchemaObject schema; + errCode = sqliteStorageEngine_->SetReference(tableReferenceProperty, handle, clearWaterMarkTables, schema); + if (errCode != E_OK && errCode != -E_TABLE_REFERENCE_CHANGED) { + LOGE("[SQLiteRelationalStore] SetReference failed, errCode = %d", errCode); + (void)handle->Rollback(); + ReleaseHandle(handle); + return errCode; + } + + if (!clearWaterMarkTables.empty()) { + storageEngine_->SetReusedHandle(handle); + int ret = CleanWaterMark(clearWaterMarkTables); + if (ret != E_OK) { + LOGE("[SQLiteRelationalStore] SetReference failed, errCode = %d", ret); + storageEngine_->SetReusedHandle(nullptr); + (void)handle->Rollback(); + ReleaseHandle(handle); + return ret; + } + storageEngine_->SetReusedHandle(nullptr); + LOGI("[SQLiteRelationalStore] SetReference clear water mark success"); + } + + int ret = handle->Commit(); + ReleaseHandle(handle); + if (ret == E_OK) { + sqliteStorageEngine_->SetSchema(schema); + return errCode; + } + LOGE("[SQLiteRelationalStore] SetReference commit transaction failed, errCode = %d", ret); + return ret; +} + +int SQLiteRelationalStore::InitTrackerSchemaFromMeta() +{ + int errCode = sqliteStorageEngine_->GetOrInitTrackerSchemaFromMeta(); + return errCode == -E_NOT_FOUND ? E_OK : errCode; +} + +int SQLiteRelationalStore::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + if (tableName.empty()) { + return -E_INVALID_ARGS; + } + return sqliteStorageEngine_->CleanTrackerData(tableName, cursor); +} + +int SQLiteRelationalStore::ExecuteCreateSharedTable(const DataBaseSchema &schema) +{ + if (sqliteStorageEngine_ == nullptr) { + LOGE("[RelationalStore][ExecuteCreateSharedTable] sqliteStorageEngine was not initialized"); + return -E_INVALID_DB; + } + std::vector deleteTableNames; + std::map> updateTableNames; + std::map alterTableNames; + if (!PrepareSharedTable(schema, deleteTableNames, updateTableNames, alterTableNames)) { + LOGE("[RelationalStore][ExecuteCreateSharedTable] table fields are invalid."); + return -E_INVALID_ARGS; + } + LOGI("[RelationalStore][ExecuteCreateSharedTable] upgrade shared table start"); + // upgrade contains delete, alter, update and create + int errCode = sqliteStorageEngine_->UpgradeSharedTable(schema, deleteTableNames, updateTableNames, + alterTableNames); + if (errCode != E_OK) { + LOGE("[RelationalStore][ExecuteCreateSharedTable] upgrade shared table failed. %d", errCode); + } else { + LOGI("[RelationalStore][ExecuteCreateSharedTable] upgrade shared table end"); + } + return errCode; +} + +int SQLiteRelationalStore::ReFillSyncInfoTable(const std::vector &actualTable, + CloudSyncer::CloudTaskInfo &info) +{ + if (info.priorityTask && actualTable.size() != info.table.size()) { + LOGE("[RelationalStore] Not support regenerate table with priority task"); + return -E_NOT_SUPPORT; + } + if (actualTable.size() == info.table.size()) { + return E_OK; + } + LOGD("[RelationalStore] Fill tables from %zu to %zu", info.table.size(), actualTable.size()); + info.table = actualTable; + info.queryList.clear(); + for (const auto &item: info.table) { + QuerySyncObject object(Query::Select()); + object.SetTableName(item); + info.queryList.push_back(object); + } + return E_OK; +} + +int SQLiteRelationalStore::Pragma(PragmaCmd cmd, PragmaData &pragmaData) +{ + if (cmd != LOGIC_DELETE_SYNC_DATA) { + return -E_NOT_SUPPORT; + } + if (pragmaData == nullptr) { + return -E_INVALID_ARGS; + } + auto logicDelete = *(static_cast(pragmaData)); + if (storageEngine_ == nullptr) { + LOGE("[RelationalStore][ChkSchema] storageEngine was not initialized"); + return -E_INVALID_DB; + } + storageEngine_->SetLogicDelete(logicDelete); + return E_OK; +} + +int SQLiteRelationalStore::UpsertData(RecordStatus status, const std::string &tableName, + const std::vector &records) +{ + if (sqliteStorageEngine_ == nullptr) { + LOGE("[RelationalStore][UpsertData] sqliteStorageEngine was not initialized"); + return -E_INVALID_DB; + } + return sqliteStorageEngine_ ->UpsertData(status, tableName, records); +} } #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h index cb7e3086404e6270667e1435a7299beea4c1caf4..e10e8a4b599677dd579edf1bab6db8d4a2467415 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store.h @@ -85,7 +85,7 @@ public: int SetCloudDB(const std::shared_ptr &cloudDb); - int SetCloudDbSchema(const DataBaseSchema &schema); + int PrepareAndSetCloudDbSchema(const DataBaseSchema &schema); int SetIAssetLoader(const std::shared_ptr &loader); @@ -93,6 +93,17 @@ public: int Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess); + int SetTrackerTable(const TrackerSchema &trackerSchema); + + int ExecuteSql(const SqlCondition &condition, std::vector &records); + + int CleanTrackerData(const std::string &tableName, int64_t cursor); + + int SetReference(const std::vector &tableReferenceProperty); + + int Pragma(PragmaCmd cmd, PragmaData &pragmaData); + + int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records); private: void ReleaseResources(); @@ -141,6 +152,20 @@ private: void FillSyncInfo(const CloudSyncOption &option, const SyncProcessCallback &onProcess, CloudSyncer::CloudTaskInfo &info); + int CleanWaterMark(std::set &clearWaterMarkTable); + + int InitTrackerSchemaFromMeta(); + + bool CheckFields(const std::vector &newFields, const TableInfo &tableInfo, std::vector &addFields); + + bool PrepareSharedTable(const DataBaseSchema &schema, std::vector &deleteTableNames, + std::map> &updateTableNames, + std::map &alterTableNames); + + int ExecuteCreateSharedTable(const DataBaseSchema &schema); + + static int ReFillSyncInfoTable(const std::vector &actualTable, CloudSyncer::CloudTaskInfo &info); + // use for sync Interactive std::shared_ptr syncAbleEngine_ = nullptr; // For storage operate sync function // use ref obj same as kv diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp index fd7273dd60f40c97917e1db967cd93d967b72449..2042f04f89824c4575953352db871545ca11f80c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.cpp @@ -311,7 +311,7 @@ int SQLiteRelationalStoreConnection::SetCloudDB(const std::shared_ptr return store->SetCloudDB(cloudDb); } -int SQLiteRelationalStoreConnection::SetCloudDbSchema(const DataBaseSchema &schema) +int SQLiteRelationalStoreConnection::PrepareAndSetCloudDbSchema(const DataBaseSchema &schema) { auto *store = GetDB(); if (store == nullptr) { @@ -319,9 +319,9 @@ int SQLiteRelationalStoreConnection::SetCloudDbSchema(const DataBaseSchema &sche return -E_INVALID_CONNECTION; } - int ret = store->SetCloudDbSchema(schema); + int ret = store->PrepareAndSetCloudDbSchema(schema); if (ret != E_OK) { - LOGE("[RelationalConnection] SetCloudDbSchema failed. %d", ret); + LOGE("[RelationalConnection] PrepareAndSetCloudDbSchema failed. %d", ret); } return ret; } @@ -375,5 +375,70 @@ int SQLiteRelationalStoreConnection::GetStoreInfo(std::string &userId, std::stri storeId = properties.GetStringProp(RelationalDBProperties::STORE_ID, ""); return E_OK; } + +int SQLiteRelationalStoreConnection::SetTrackerTable(const TrackerSchema &schema) + { + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, get DB failed!"); + return -E_INVALID_CONNECTION; + } + int errCode = store->SetTrackerTable(schema); + if (errCode != E_OK) { + LOGE("[RelationalConnection] set tracker table failed. %d", errCode); + } + return errCode; +} + +int SQLiteRelationalStoreConnection::ExecuteSql(const SqlCondition &condition, std::vector &records) +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, get executor failed!"); + return -E_INVALID_CONNECTION; + } + return store->ExecuteSql(condition, records); +} + +int SQLiteRelationalStoreConnection::SetReference(const std::vector &tableReferenceProperty) +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[SetReference] store is null, get DB failed!"); + return -E_INVALID_CONNECTION; + } + return store->SetReference(tableReferenceProperty); +} + +int SQLiteRelationalStoreConnection::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, get executor failed!"); + return -E_INVALID_CONNECTION; + } + return store->CleanTrackerData(tableName, cursor); +} + +int SQLiteRelationalStoreConnection::Pragma(PragmaCmd cmd, PragmaData &pragmaData) +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, get executor failed!"); + return -E_INVALID_CONNECTION; + } + return store->Pragma(cmd, pragmaData); +} + +int SQLiteRelationalStoreConnection::UpsertData(RecordStatus status, const std::string &tableName, + const std::vector &records) +{ + auto *store = GetDB(); + if (store == nullptr) { + LOGE("[RelationalConnection] store is null, upsert dara failed!"); + return -E_INVALID_CONNECTION; + } + return store->UpsertData(status, tableName, records); +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h index ea773ad9e85c0bd394f0266b9a58b74705ac8d5a..5445aab5179019c8a66d31fe6fbea1eb50515318 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_store_connection.h @@ -48,13 +48,22 @@ public: int RemoteQuery(const std::string &device, const RemoteCondition &condition, uint64_t timeout, std::shared_ptr &result) override; int SetCloudDB(const std::shared_ptr &cloudDb) override; - int SetCloudDbSchema(const DataBaseSchema &schema) override; + int PrepareAndSetCloudDbSchema(const DataBaseSchema &schema) override; int SetIAssetLoader(const std::shared_ptr &loader) override; int Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess) override; int GetStoreInfo(std::string &userId, std::string &appId, std::string &storeId) override; + int SetTrackerTable(const TrackerSchema &schema) override; + int ExecuteSql(const SqlCondition &condition, std::vector &records) override; + int CleanTrackerData(const std::string &tableName, int64_t cursor) override; + + int SetReference(const std::vector &tableReferenceProperty) override; + + int Pragma(PragmaCmd cmd, PragmaData &pragmaData) override; + + int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records) override; protected: int Pragma(int cmd, void *parameter) override; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp index 92d436afbe24275ccecfc4eddd96b695e93e16d8..aeb81b6af01b29189766a962c1df7990e0c7da7b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.cpp @@ -17,6 +17,9 @@ #include "db_errno.h" #include "cloud/cloud_db_types.h" #include "sqlite_utils.h" +#include "cloud/cloud_storage_utils.h" +#include "runtime_context.h" +#include "cloud/cloud_db_constant.h" namespace DistributedDB { int SQLiteRelationalUtils::GetDataValueByType(sqlite3_stmt *statement, int cid, DataValue &value) @@ -125,6 +128,7 @@ int SQLiteRelationalUtils::GetCloudValueByType(sqlite3_stmt *statement, int type } default: { cloudValue = Nil(); + break; } } return E_OK; @@ -155,4 +159,244 @@ void SQLiteRelationalUtils::CalCloudValueLen(Type &cloudValue, uint32_t &totalSi } } } + +int SQLiteRelationalUtils::BindStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal) +{ + int errCode = E_OK; + switch (typeVal.index()) { + case TYPE_INDEX: { + int64_t value = 0; + (void)CloudStorageUtils::GetValueFromType(typeVal, value); + errCode = SQLiteUtils::BindInt64ToStatement(statement, cid, value); + break; + } + case TYPE_INDEX: { + bool value = false; + (void)CloudStorageUtils::GetValueFromType(typeVal, value); + errCode = SQLiteUtils::BindInt64ToStatement(statement, cid, value); + break; + } + case TYPE_INDEX: { + double value = 0.0; + (void)CloudStorageUtils::GetValueFromType(typeVal, value); + errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_double(statement, cid, value)); + break; + } + case TYPE_INDEX: { + std::string value; + (void)CloudStorageUtils::GetValueFromType(typeVal, value); + errCode = SQLiteUtils::BindTextToStatement(statement, cid, value); + break; + } + default: { + errCode = BindExtendStatementByType(statement, cid, typeVal); + break; + } + } + return errCode; +} + +int SQLiteRelationalUtils::BindExtendStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal) +{ + int errCode = E_OK; + switch (typeVal.index()) { + case TYPE_INDEX: { + Bytes value; + (void)CloudStorageUtils::GetValueFromType(typeVal, value); + errCode = SQLiteUtils::BindBlobToStatement(statement, cid, value); + break; + } + case TYPE_INDEX: { + Asset value; + (void)CloudStorageUtils::GetValueFromType(typeVal, value); + Bytes val; + errCode = RuntimeContext::GetInstance()->AssetToBlob(value, val); + if (errCode != E_OK) { + break; + } + errCode = SQLiteUtils::BindBlobToStatement(statement, cid, val); + break; + } + case TYPE_INDEX: { + Assets value; + (void)CloudStorageUtils::GetValueFromType(typeVal, value); + Bytes val; + errCode = RuntimeContext::GetInstance()->AssetsToBlob(value, val); + if (errCode != E_OK) { + break; + } + errCode = SQLiteUtils::BindBlobToStatement(statement, cid, val); + break; + } + default: { + errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(statement, cid)); + break; + } + } + return errCode; +} + +int SQLiteRelationalUtils::StepNext(bool isMemDB, sqlite3_stmt *stmt) +{ + if (stmt == nullptr) { + return -E_INVALID_ARGS; + } + int errCode = SQLiteUtils::StepWithRetry(stmt, isMemDB); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = -E_FINISHED; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + errCode = E_OK; + } + return errCode; +} + +int SQLiteRelationalUtils::GetSelectVBucket(sqlite3_stmt *stmt, VBucket &bucket) +{ + if (stmt == nullptr) { + return -E_INVALID_ARGS; + } + for (int cid = 0, colCount = sqlite3_column_count(stmt); cid < colCount; ++cid) { + Type typeVal; + int errCode = GetTypeValByStatement(stmt, cid, typeVal); + if (errCode != E_OK) { + LOGE("get typeVal from stmt failed"); + return errCode; + } + const char *colName = sqlite3_column_name(stmt, cid); + bucket.insert_or_assign(colName, std::move(typeVal)); + } + return E_OK; +} + +bool SQLiteRelationalUtils::GetDbFileName(sqlite3 *db, std::string &fileName) +{ + if (db == nullptr) { + return false; + } + + auto dbFilePath = sqlite3_db_filename(db, nullptr); + if (dbFilePath == nullptr) { + return false; + } + fileName = std::string(dbFilePath); + return true; +} + +int SQLiteRelationalUtils::GetTypeValByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal) +{ + if (stmt == nullptr || cid < 0 || cid >= sqlite3_column_count(stmt)) { + return -E_INVALID_ARGS; + } + int errCode = E_OK; + switch (sqlite3_column_type(stmt, cid)) { + case SQLITE_INTEGER: { + const char *declType = sqlite3_column_decltype(stmt, cid); + if (declType == nullptr) { + typeVal = static_cast(sqlite3_column_int64(stmt, cid)); + break; + } + if (strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOL.c_str()) == 0 || + strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOLEAN.c_str()) == 0) { + typeVal = static_cast(sqlite3_column_int(stmt, cid)); + break; + } + typeVal = static_cast(sqlite3_column_int64(stmt, cid)); + break; + } + case SQLITE_FLOAT: { + typeVal = sqlite3_column_double(stmt, cid); + break; + } + case SQLITE_BLOB: { + errCode = GetBlobByStatement(stmt, cid, typeVal); + if (errCode != E_OK) { + break; + } + } + case SQLITE3_TEXT: { + errCode = GetBlobByStatement(stmt, cid, typeVal); + if (errCode != E_OK) { + break; + } + if (typeVal.index() != TYPE_INDEX) { + break; + } + std::string str; + (void)SQLiteUtils::GetColumnTextValue(stmt, cid, str); + typeVal = str; + break; + } + default: { + typeVal = Nil(); + break; + } + } + return errCode; +} + +int SQLiteRelationalUtils::GetBlobByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal) +{ + const char *declType = sqlite3_column_decltype(stmt, cid); + int errCode = E_OK; + if (declType != nullptr && strcasecmp(declType, CloudDbConstant::ASSET) == 0) { + std::vector blobValue; + errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue); + if (errCode != E_OK) { + return errCode; + } + Asset asset; + errCode = RuntimeContext::GetInstance()->BlobToAsset(blobValue, asset); + if (errCode != E_OK) { + return errCode; + } + typeVal = asset; + } else if (declType != nullptr && strcasecmp(declType, CloudDbConstant::ASSETS) == 0) { + std::vector blobValue; + errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue); + if (errCode != E_OK) { + return errCode; + } + Assets assets; + errCode = RuntimeContext::GetInstance()->BlobToAssets(blobValue, assets); + if (errCode != E_OK) { + return errCode; + } + typeVal = assets; + } else if (sqlite3_column_type(stmt, cid) == SQLITE_BLOB) { + std::vector blobValue; + errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue); + if (errCode != E_OK) { + return errCode; + } + typeVal = blobValue; + } + return E_OK; +} + +int SQLiteRelationalUtils::SelectServerObserver(sqlite3 *db, const std::string &tableName, bool isChanged) +{ + if (db == nullptr || tableName.empty()) { + return -E_INVALID_ARGS; + } + std::string sql; + if (isChanged) { + sql = "SELECT server_observer('" + tableName + "', 1);"; + } else { + sql = "SELECT server_observer('" + tableName + "', 0);"; + } + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(db, sql, stmt); + if (errCode != E_OK) { + LOGE("get select server observer stmt failed. %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("select server observer failed. %d", errCode); + return SQLiteUtils::MapSQLiteErrno(errCode); + } + return ret == E_OK ? E_OK : ret; +} } // namespace DistributedDB \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h index 53984e119f6a4ef3b39f7423ee078ad067cbbf41..ba1463892e7f41d7fca64dc713ae708aa7be04b0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_relational_utils.h @@ -31,6 +31,21 @@ public: static int GetCloudValueByType(sqlite3_stmt *statement, int type, int cid, Type &cloudValue); static void CalCloudValueLen(Type &cloudValue, uint32_t &totalSize); + + static int BindStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal); + + static int StepNext(bool isMemDB, sqlite3_stmt *stmt); + + static int GetSelectVBucket(sqlite3_stmt *stmt, VBucket &bucket); + + static bool GetDbFileName(sqlite3 *db, std::string &fileName); + + static int SelectServerObserver(sqlite3 *db, const std::string &tableName, bool isChanged); +private: + static int BindExtendStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal); + + static int GetTypeValByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal); + static int GetBlobByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal); }; } // namespace DistributedDB #endif // SQLITE_RELATIONAL_UTILS_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp index 5d29e74b95d1ee47efd89702b6ba5f819fb03bce..9da2faf44bfa4b2cd2c8c601763e0a49d78e6e4b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp @@ -81,6 +81,11 @@ int SQLiteSingleRelationalStorageEngine::RegisterFunction(sqlite3 *db) const LOGE("[engine] register cloud observer failed!"); } + errCode = SQLiteUtils::RegisterCloudDataChangeServerObserver(db); + if (errCode != E_OK) { + LOGE("[engine] register cloud server observer failed!"); + } + return errCode; } @@ -156,6 +161,20 @@ int SaveSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, cons return errCode; } +int SaveTrackerSchemaToMetaTable(SQLiteSingleVerRelationalStorageExecutor *handle, + const RelationalSchemaObject &schema) +{ + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + 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 SaveSyncTableTypeAndDropFlagToMeta(SQLiteSingleVerRelationalStorageExecutor *handle, const std::string &tableName, TableSyncType syncType) { @@ -203,7 +222,40 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::strin schemaChanged = true; } - return CreateDistributedTable(tableName, isUpgraded, identity, schema, syncType); + int errCode = CreateDistributedTable(tableName, isUpgraded, identity, schema, syncType); + if (errCode != E_OK) { + return errCode; + } + if (isUpgraded && schemaChanged) { + // Used for upgrading the stock data of the trackerTable + errCode = UpgradeTrackerTableLog(tableName, schema); + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::CreateDistributedSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::string &tableName, const std::string &sharedTableName, TableSyncType tableSyncType, + RelationalSchemaObject &schema) +{ + TableInfo table; + table.SetTableName(sharedTableName); + table.SetOriginTableName(tableName); + table.SetSharedTableMark(true); + table.SetTableSyncType(tableSyncType); + table.SetTrackerTable(trackerSchema_.GetTrackerTable(sharedTableName)); + if (!table.GetTrackerTable().IsEmpty() && tableSyncType == TableSyncType::DEVICE_COOPERATION) { + LOGE("current is trackerTable, not support creating device distributed table."); + return -E_NOT_SUPPORT; + } + bool isUpgraded = schema.GetTable(sharedTableName).GetTableName() == sharedTableName; + int errCode = CreateDistributedTable(handle, isUpgraded, "", table, schema); + if (errCode != E_OK) { + LOGE("create distributed table failed. %d", errCode); + return errCode; + } + std::lock_guard lock(schemaMutex_); + schema_ = schema; + return errCode; } int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::string &tableName, bool isUpgraded, @@ -223,36 +275,55 @@ int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(const std::strin return errCode; } - auto mode = static_cast(properties_.GetIntProp( - RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE)); TableInfo table; table.SetTableName(tableName); table.SetTableSyncType(tableSyncType); - errCode = handle->CreateDistributedTable(mode, isUpgraded, identity, table, tableSyncType); + table.SetTrackerTable(trackerSchema_.GetTrackerTable(tableName)); + if (isUpgraded) { + table.SetSourceTableReference(schema.GetTable(tableName).GetTableReference()); + } + if (!table.GetTrackerTable().IsEmpty() && tableSyncType == TableSyncType::DEVICE_COOPERATION) { + LOGE("current is trackerTable, not support creating device distributed table. %d", errCode); + (void)handle->Rollback(); + return -E_NOT_SUPPORT; + } + errCode = CreateDistributedTable(handle, isUpgraded, identity, table, schema); if (errCode != E_OK) { LOGE("create distributed table failed. %d", errCode); (void)handle->Rollback(); return errCode; } + errCode = handle->Commit(); + if (errCode == E_OK) { + schema_ = schema; + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::CreateDistributedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + bool isUpgraded, const std::string &identity, TableInfo &table, RelationalSchemaObject &schema) +{ + auto mode = static_cast(properties_.GetIntProp( + RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE)); + TableSyncType tableSyncType = table.GetTableSyncType(); + int errCode = handle->CreateDistributedTable(mode, isUpgraded, identity, table, tableSyncType); + if (errCode != E_OK) { + LOGE("create distributed table failed. %d", errCode); + return errCode; + } schema.SetTableMode(mode); schema.AddRelationalTable(table); errCode = SaveSchemaToMetaTable(handle, schema); if (errCode != E_OK) { LOGE("Save schema to meta table for create distributed table failed. %d", errCode); - (void)handle->Rollback(); return errCode; } + std::string tableName = table.GetTableName(); errCode = SaveSyncTableTypeAndDropFlagToMeta(handle, tableName, tableSyncType); if (errCode != E_OK) { - (void)handle->Rollback(); - return errCode; - } - - errCode = handle->Commit(); - if (errCode == E_OK) { - schema_ = schema; + LOGE("Save sync table type or drop flag to meta table failed. %d", errCode); } return errCode; } @@ -319,19 +390,21 @@ int SQLiteSingleRelationalStorageEngine::CleanDistributedDeviceTable(std::vector 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 + // Remove non-existent tables from the schema + for (const auto &tableName : missingTables) { + schema_.RemoveRelationalTable(tableName); + } + errCode = SaveSchemaToMetaTable(handle, schema_); // save schema to meta_data + if (errCode != E_OK) { + LOGE("Save schema to metaTable failed. %d", errCode); + (void)handle->Rollback(); + } else { + errCode = handle->Commit(); } } else { LOGE("Check distributed table failed. %d", errCode); (void)handle->Rollback(); } - ReleaseExecutor(handle); return errCode; } @@ -358,5 +431,595 @@ int SQLiteSingleRelationalStorageEngine::CreateRelationalMetaTable(sqlite3 *db) } return errCode; } + +int SQLiteSingleRelationalStorageEngine::SetTrackerTable(const TrackerSchema &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; + } + RelationalSchemaObject tracker = trackerSchema_; + if (!tracker.GetTrackerTable(schema.tableName).IsChanging(schema)) { + (void)handle->Rollback(); + ReleaseExecutor(handle); + LOGW("tracker schema is no change."); + return E_OK; + } + bool isUpgrade = !tracker.GetTrackerTable(schema.tableName).IsEmpty(); + tracker.InsertTrackerSchema(schema); + errCode = handle->CreateTrackerTable(tracker.GetTrackerTable(schema.tableName), isUpgrade); + if (errCode != E_OK) { + (void)handle->Rollback(); + ReleaseExecutor(handle); + return errCode; + } + + if (schema.trackerColNames.empty()) { + tracker.RemoveTrackerSchema(schema); + } + errCode = SaveTrackerSchemaToMetaTable(handle, tracker); + if (errCode != E_OK) { + (void)handle->Rollback(); + ReleaseExecutor(handle); + return errCode; + } + + errCode = handle->Commit(); + if (errCode != E_OK) { + ReleaseExecutor(handle); + return errCode; + } + + trackerSchema_ = tracker; + ReleaseExecutor(handle); + return E_OK; +} + +int SQLiteSingleRelationalStorageEngine::CheckAndCacheTrackerSchema(const TrackerSchema &schema, TableInfo &tableInfo) +{ + if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { + return -E_NOT_SUPPORT; + } + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, + OperatePerm::NORMAL_PERM, errCode)); + if (handle == nullptr) { + return errCode; + } + RelationalSchemaObject tracker = trackerSchema_; + if (!tracker.GetTrackerTable(schema.tableName).IsChanging(schema)) { + ReleaseExecutor(handle); + LOGW("tracker schema is no change for distributed table."); + return -E_IGNORE_DATA; + } + tracker.InsertTrackerSchema(schema); + tableInfo.SetTrackerTable(tracker.GetTrackerTable(schema.tableName)); + errCode = tableInfo.CheckTrackerTable(); + if (errCode != E_OK) { + LOGE("check tracker table schema failed. %d", errCode); + ReleaseExecutor(handle); + return errCode; + } + + if (schema.trackerColNames.empty()) { + tracker.RemoveTrackerSchema(schema); + } + + trackerSchema_ = tracker; + ReleaseExecutor(handle); + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::GetOrInitTrackerSchemaFromMeta() +{ + RelationalSchemaObject trackerSchema; + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, + errCode)); + if (handle == nullptr) { + return errCode; + } + errCode = handle->GetOrInitTrackerSchemaFromMeta(trackerSchema); + if (errCode != E_OK) { + ReleaseExecutor(handle); + return errCode; + } + const TableInfoMap tableInfoMap = trackerSchema.GetTrackerTables(); + for (const auto &iter: tableInfoMap) { + TableInfo tableInfo; + errCode = handle->AnalysisTrackerTable(iter.second.GetTrackerTable(), tableInfo); + if (errCode == -E_NOT_FOUND) { + const std::string trackerTableName = iter.second.GetTrackerTable().GetTableName(); + errCode = CleanTrackerDeviceTable({ trackerTableName }, trackerSchema, handle); + if (errCode != E_OK) { + LOGE("cancel tracker table failed during db opening. %d", errCode); + ReleaseExecutor(handle); + return errCode; + } + } else if (errCode != E_OK) { + LOGE("the tracker schema does not match the tracker schema. %d", errCode); + ReleaseExecutor(handle); + return errCode; + } + } + trackerSchema_ = trackerSchema; + ReleaseExecutor(handle); + return E_OK; +} + +int SQLiteSingleRelationalStorageEngine::SaveTrackerSchema() +{ + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, + errCode)); + if (handle == nullptr) { + return errCode; + } + RelationalSchemaObject tracker = trackerSchema_; + errCode = SaveTrackerSchemaToMetaTable(handle, tracker); + ReleaseExecutor(handle); + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::ExecuteSql(const SqlCondition &condition, std::vector &records) +{ + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, + errCode)); + if (handle == nullptr) { + return errCode; + } + errCode = handle->ExecuteSql(condition, records); + if (errCode != E_OK) { + ReleaseExecutor(handle); + return errCode; + } + ReleaseExecutor(handle); + return errCode; +} + +static int CheckReference(const std::vector &tableReferenceProperty, + const RelationalSchemaObject &schema) +{ + for (const auto &reference : tableReferenceProperty) { + TableInfo sourceTableInfo = schema.GetTable(reference.sourceTableName); + TableInfo targetTableInfo = schema.GetTable(reference.targetTableName); + if (strcasecmp(sourceTableInfo.GetTableName().c_str(), reference.sourceTableName.c_str()) != 0 || + strcasecmp(targetTableInfo.GetTableName().c_str(), reference.targetTableName.c_str()) != 0) { + LOGE("can't set reference for table which doesn't create distributed table."); + return -E_DISTRIBUTED_SCHEMA_NOT_FOUND; + } + if (sourceTableInfo.GetTableSyncType() != CLOUD_COOPERATION || + targetTableInfo.GetTableSyncType() != CLOUD_COOPERATION) { + LOGE("can't set reference for table which doesn't create distributed table with cloud mode."); + return -E_DISTRIBUTED_SCHEMA_NOT_FOUND; + } + if (sourceTableInfo.GetSharedTableMark() || targetTableInfo.GetSharedTableMark()) { + LOGE("can't set reference for shared table."); + return -E_NOT_SUPPORT; + } + + FieldInfoMap sourceFieldMap = sourceTableInfo.GetFields(); + FieldInfoMap targetFieldMap = targetTableInfo.GetFields(); + for (const auto &[sourceFieldName, targetFieldName] : reference.columns) { + if (sourceFieldMap.find(sourceFieldName) == sourceFieldMap.end() || + targetFieldMap.find(targetFieldName) == targetFieldMap.end()) { + LOGE("reference field doesn't exists in table."); + return -E_INVALID_ARGS; + } + } + } + return E_OK; +} + +int SQLiteSingleRelationalStorageEngine::SetReference(const std::vector &tableReferenceProperty, + SQLiteSingleVerRelationalStorageExecutor *handle, std::set &clearWaterMarkTables, + RelationalSchemaObject &schema) +{ + std::lock_guard lock(schemaMutex_); + schema = schema_; + int errCode = CheckReference(tableReferenceProperty, schema); + if (errCode != E_OK) { + LOGE("check reference failed, errCode = %d.", errCode); + return errCode; + } + + errCode = handle->GetClearWaterMarkTables(tableReferenceProperty, schema, clearWaterMarkTables); + if (errCode != E_OK) { + return errCode; + } + schema.SetReferenceProperty(tableReferenceProperty); + errCode = SaveSchemaToMetaTable(handle, schema); + if (errCode != E_OK) { + LOGE("Save schema to meta table for reference failed. %d", errCode); + return errCode; + } + auto mode = static_cast(properties_.GetIntProp( + RelationalDBProperties::DISTRIBUTED_TABLE_MODE, DistributedTableMode::SPLIT_BY_DEVICE)); + for (auto &table : schema.GetTables()) { + if (table.second.GetTableReference().empty()) { + continue; + } + TableInfo tableInfo = table.second; + errCode = handle->RenewTableTrigger(mode, tableInfo, TableSyncType::CLOUD_COOPERATION); + if (errCode != E_OK) { + LOGE("renew table trigger for reference failed. %d", errCode); + return errCode; + } + } + return clearWaterMarkTables.empty() ? E_OK : -E_TABLE_REFERENCE_CHANGED; +} + +RelationalSchemaObject SQLiteSingleRelationalStorageEngine::GetTrackerSchema() const +{ + return trackerSchema_; +} + +int SQLiteSingleRelationalStorageEngine::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, OperatePerm::NORMAL_PERM, + errCode)); + if (handle == nullptr) { + return errCode; + } + errCode = handle->CleanTrackerData(tableName, cursor); + ReleaseExecutor(handle); + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::UpgradeSharedTable(const DataBaseSchema &cloudSchema, + const std::vector &deleteTableNames, const std::map> &updateTableNames, + const std::map &alterTableNames) +{ + 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; + } + RelationalSchemaObject schema = GetSchema(); + errCode = UpgradeSharedTableInner(handle, cloudSchema, deleteTableNames, updateTableNames, alterTableNames); + if (errCode != E_OK) { + handle->Rollback(); + ReleaseExecutor(handle); + return errCode; + } + errCode = handle->Commit(); + if (errCode != E_OK) { + std::lock_guard lock(schemaMutex_); + schema_ = schema; // revert schema to the initial state + } + ReleaseExecutor(handle); + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::UpgradeSharedTableInner(SQLiteSingleVerRelationalStorageExecutor *&handle, + const DataBaseSchema &cloudSchema, const std::vector &deleteTableNames, + const std::map> &updateTableNames, + const std::map &alterTableNames) +{ + RelationalSchemaObject schema = GetSchema(); + int errCode = DoDeleteSharedTable(handle, deleteTableNames, schema); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] delete shared table or distributed table failed. %d", errCode); + return errCode; + } + errCode = DoUpdateSharedTable(handle, updateTableNames); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] update shared table or distributed table failed. %d", errCode); + return errCode; + } + errCode = CheckIfExistUserTable(handle, cloudSchema, alterTableNames, schema); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] check local user table failed. %d", errCode); + return errCode; + } + errCode = DoAlterSharedTableName(handle, alterTableNames, schema); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] alter shared table or distributed table failed. %d", errCode); + return errCode; + } + errCode = DoCreateSharedTable(handle, cloudSchema, schema); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] create shared table or distributed table failed. %d", errCode); + return errCode; + } + std::lock_guard lock(schemaMutex_); + schema_ = schema; + return E_OK; +} + +int SQLiteSingleRelationalStorageEngine::DoDeleteSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::vector &deleteTableNames, RelationalSchemaObject &schema) +{ + if (deleteTableNames.empty()) { + return E_OK; + } + int errCode = handle->DeleteTable(deleteTableNames); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] delete shared table failed. %d", errCode); + return errCode; + } + std::vector keys; + for (const auto &tableName : deleteTableNames) { + errCode = handle->CleanResourceForDroppedTable(tableName); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] delete shared distributed table failed. %d", errCode); + return errCode; + } + Key sharedTableKey = DBCommon::GetPrefixTableName(tableName); + if (sharedTableKey.empty() || sharedTableKey.size() > DBConstant::MAX_KEY_SIZE) { + LOGE("[RelationalStorageEngine] shared table key is invalid."); + return -E_INVALID_ARGS; + } + keys.push_back(sharedTableKey); + schema.RemoveRelationalTable(tableName); + } + errCode = handle->DeleteMetaData(keys); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] delete meta data failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::DoUpdateSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::map> &updateTableNames) +{ + if (updateTableNames.empty()) { + return E_OK; + } + int errCode = handle->UpdateSharedTable(updateTableNames); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] update shared table failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::DoAlterSharedTableName(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::map &alterTableNames, RelationalSchemaObject &schema) +{ + if (alterTableNames.empty()) { + return E_OK; + } + int errCode = handle->AlterTableName(alterTableNames); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] alter shared table failed. %d", errCode); + return errCode; + } + std::map distributedSharedTableNames; + for (const auto &tableName : alterTableNames) { + errCode = handle->DeleteTableTrigger(tableName.first); + if (errCode != E_OK) { + return errCode; + } + std::string oldDistributedName = DBCommon::GetLogTableName(tableName.first); + std::string newDistributedName = DBCommon::GetLogTableName(tableName.second); + distributedSharedTableNames[oldDistributedName] = newDistributedName; + } + errCode = handle->AlterTableName(distributedSharedTableNames); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] alter distributed shared table failed. %d", errCode); + return errCode; + } + for (const auto &[oldTableName, newTableName] : alterTableNames) { + schema.GetTable(oldTableName).SetTableName(newTableName); + } + errCode = UpdateKvData(handle, alterTableNames); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] update kv data failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::DoCreateSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + const DataBaseSchema &cloudSchema, RelationalSchemaObject &schema) +{ + int errCode = handle->CreateSharedTable(cloudSchema); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] create shared table failed. %d", errCode); + return errCode; + } + for (auto const &tableSchema : cloudSchema.tables) { + errCode = CreateDistributedSharedTable(handle, tableSchema.name, tableSchema.sharedTableName, + TableSyncType::CLOUD_COOPERATION, schema); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] create distributed shared table failed. %d", errCode); + return errCode; + } + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::UpdateKvData(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::map &alterTableNames) +{ + std::vector keys; + for (const auto &tableName : alterTableNames) { + Key oldKey = DBCommon::GetPrefixTableName(tableName.first); + Value value; + int ret = handle->GetKvData(oldKey, value); + if (ret == -E_NOT_FOUND) { + continue; + } + if (ret != E_OK) { + LOGE("[RelationalStorageEngine] get meta data failed. %d", ret); + return ret; + } + keys.push_back(oldKey); + Key newKey = DBCommon::GetPrefixTableName(tableName.second); + ret = handle->PutKvData(newKey, value); + if (ret != E_OK) { + LOGE("[RelationalStorageEngine] put meta data failed. %d", ret); + return ret; + } + } + int errCode = handle->DeleteMetaData(keys); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] delete meta data failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::CheckIfExistUserTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + const DataBaseSchema &cloudSchema, const std::map &alterTableNames, + const RelationalSchemaObject &schema) +{ + for (const auto &tableSchema : cloudSchema.tables) { + if (alterTableNames.find(tableSchema.sharedTableName) != alterTableNames.end()) { + continue; + } + TableInfo tableInfo = schema.GetTable(tableSchema.sharedTableName); + if (tableInfo.GetSharedTableMark()) { + continue; + } + int errCode = handle->CheckIfExistUserTable(tableSchema.sharedTableName); + if (errCode != E_OK) { + LOGE("[RelationalStorageEngine] local exists table. %d", errCode); + return errCode; + } + } + return E_OK; +} + +std::pair, int> SQLiteSingleRelationalStorageEngine::CalTableRef( + const std::vector &tableNames, const std::map &sharedTableOriginNames) +{ + std::pair, int> res = { tableNames, E_OK }; + std::map> reachableReference; + std::map tableWeight; + { + std::lock_guard lock(schemaMutex_); + reachableReference = schema_.GetReachableRef(); + tableWeight = schema_.GetTableWeight(); + } + if (reachableReference.empty()) { + return res; + } + auto reachableWithShared = GetReachableWithShared(reachableReference, sharedTableOriginNames); + // check dependency conflict + for (size_t i = 0; i < tableNames.size(); ++i) { + for (size_t j = i + 1; j < tableNames.size(); ++j) { + // such as table A B, if dependency is A->B + // sync should not be A->B, it should be B->A + // so if A can reach B, it's wrong + if (reachableWithShared[tableNames[i]][tableNames[j]]) { + LOGE("[RDBStorageEngine] table %zu reach table %zu", i, j); + res.second = -E_INVALID_ARGS; + return res; + } + } + } + tableWeight = GetTableWeightWithShared(tableWeight, sharedTableOriginNames); + auto actualTable = DBCommon::GenerateNodesByNodeWeight(tableNames, reachableWithShared, tableWeight); + res.first.assign(actualTable.begin(), actualTable.end()); + return res; +} + +int SQLiteSingleRelationalStorageEngine::CleanTrackerDeviceTable(const std::vector &tableNames, + RelationalSchemaObject &trackerSchemaObj, SQLiteSingleVerRelationalStorageExecutor *&handle) +{ + std::vector missingTrackerTables; + int errCode = handle->CheckAndCleanDistributedTable(tableNames, missingTrackerTables); + if (errCode != E_OK) { + LOGE("Check tracker table failed. %d", errCode); + return errCode; + } + if (missingTrackerTables.empty()) { + return E_OK; + } + for (const auto &tableName : missingTrackerTables) { + TrackerSchema schema; + schema.tableName = tableName; + trackerSchemaObj.RemoveTrackerSchema(schema); + } + errCode = SaveTrackerSchemaToMetaTable(handle, trackerSchemaObj); // save schema to meta_data + if (errCode != E_OK) { + LOGE("Save tracker schema to metaTable failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleRelationalStorageEngine::UpgradeTrackerTableLog(const std::string &tableName, + RelationalSchemaObject &schema) +{ + LOGD("Upgrade tracker table log."); + int errCode = E_OK; + auto *handle = static_cast(FindExecutor(true, + OperatePerm::NORMAL_PERM, errCode)); + if (handle == nullptr) { + return errCode; + } + ResFinalizer finalizer([&handle, this] { this->ReleaseExecutor(handle); }); + + errCode = handle->StartTransaction(TransactType::IMMEDIATE); + if (errCode != E_OK) { + return errCode; + } + + TableInfo table = schema_.GetTable(tableName); + errCode = handle->UpgradedLogForExistedData(table); + if (errCode != E_OK) { + LOGE("Upgrade tracker table log failed. %d", errCode); + (void)handle->Rollback(); + return errCode; + } + return handle->Commit(); +} + +std::map> SQLiteSingleRelationalStorageEngine::GetReachableWithShared( + const std::map> &reachableReference, + const std::map &tableToShared) +{ + // we translate all origin table to shared table + std::map> reachableWithShared; + for (const auto &[source, reach] : reachableReference) { + bool sourceHasNoShared = tableToShared.find(source) == tableToShared.end(); + const std::string &sourceSharedName = tableToShared.at(source); + for (const auto &[target, isReach] : reach) { + // merge two reachable reference + reachableWithShared[source][target] = isReach; + if (sourceHasNoShared || tableToShared.find(target) == tableToShared.end()) { + continue; + } + // record shared reachable reference + reachableWithShared[sourceSharedName][tableToShared.at(target)] = isReach; + } + } + return reachableWithShared; +} + +std::map SQLiteSingleRelationalStorageEngine::GetTableWeightWithShared( + const std::map &tableWeight, const std::map &tableToShared) +{ + std::map res; + for (const auto &[table, weight] : tableWeight) { + res[table] = weight; + if (tableToShared.find(table) == tableToShared.end()) { + continue; + } + res[tableToShared.at(table)] = weight; + } + return res; +} + +int SQLiteSingleRelationalStorageEngine::UpsertData([[gnu::unused]] RecordStatus status, + [[gnu::unused]] const std::string &tableName, [[gnu::unused]] const std::vector &records) +{ + return E_OK; +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h index 91bbd82f027af7c18358f65b25eabca1ca1b9a23..92dbc08a8a28dcd0daa396c87e9fa352a9c5e5be 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/relational/sqlite_single_relational_storage_engine.h @@ -20,6 +20,7 @@ #include "relationaldb_properties.h" #include "sqlite_storage_engine.h" #include "sqlite_single_ver_relational_storage_executor.h" +#include "tracker_table.h" namespace DistributedDB { class SQLiteSingleRelationalStorageEngine : public SQLiteStorageEngine { @@ -42,11 +43,29 @@ public: const RelationalDBProperties &GetProperties() const; void SetProperties(const RelationalDBProperties &properties); + int SetTrackerTable(const TrackerSchema &schema); + int CheckAndCacheTrackerSchema(const TrackerSchema &schema, TableInfo &tableInfo); + int GetOrInitTrackerSchemaFromMeta(); + int SaveTrackerSchema(); + + int ExecuteSql(const SqlCondition &condition, std::vector &records); + RelationalSchemaObject GetTrackerSchema() const; + int CleanTrackerData(const std::string &tableName, int64_t cursor); + + int SetReference(const std::vector &tableReferenceProperty, + SQLiteSingleVerRelationalStorageExecutor *handle, std::set &clearWaterMarkTables, + RelationalSchemaObject &schema); + int UpgradeSharedTable(const DataBaseSchema &cloudSchema, const std::vector &deleteTableNames, + const std::map> &updateTableNames, + const std::map &alterTableNames); + std::pair, int> CalTableRef(const std::vector &tableNames, + const std::map &sharedTableOriginNames); + + int UpsertData(RecordStatus status, const std::string &tableName, const std::vector &records); protected: StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) override; int Upgrade(sqlite3 *db) override; int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) override; - private: // For executor. int ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor *&handle); @@ -55,12 +74,55 @@ private: int RegisterFunction(sqlite3 *db) const; int UpgradeDistributedTable(const std::string &tableName, bool &schemaChanged, TableSyncType syncType); + + int CreateDistributedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, bool isUpgraded, + const std::string &identity, TableInfo &table, RelationalSchemaObject &schema); + int CreateDistributedTable(const std::string &tableName, bool isUpgraded, const std::string &identity, RelationalSchemaObject &schema, TableSyncType tableSyncType); + int CreateDistributedSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, const std::string &tableName, + const std::string &sharedTableName, TableSyncType syncType, RelationalSchemaObject &schema); + int CreateRelationalMetaTable(sqlite3 *db); + int CleanTrackerDeviceTable(const std::vector &tableNames, RelationalSchemaObject &trackerSchemaObj, + SQLiteSingleVerRelationalStorageExecutor *&handle); + + int UpgradeTrackerTableLog(const std::string &tableName, RelationalSchemaObject &schema); + + static std::map> GetReachableWithShared( + const std::map> &reachableReference, + const std::map &tableToShared); + + static std::map GetTableWeightWithShared(const std::map &tableWeight, + const std::map &tableToShared); + + int UpgradeSharedTableInner(SQLiteSingleVerRelationalStorageExecutor *&handle, + const DataBaseSchema &cloudSchema, const std::vector &deleteTableNames, + const std::map> &updateTableNames, + const std::map &alterTableNames); + + int DoDeleteSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::vector &deleteTableNames, RelationalSchemaObject &schema); + + int DoUpdateSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::map> &updateTableNames); + + int DoAlterSharedTableName(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::map &alterTableNames, RelationalSchemaObject &schema); + + int DoCreateSharedTable(SQLiteSingleVerRelationalStorageExecutor *&handle, const DataBaseSchema &cloudSchema, + RelationalSchemaObject &schema); + + int UpdateKvData(SQLiteSingleVerRelationalStorageExecutor *&handle, + const std::map &alterTableNames); + + int CheckIfExistUserTable(SQLiteSingleVerRelationalStorageExecutor *&handle, const DataBaseSchema &cloudSchema, + const std::map &alterTableNames, const RelationalSchemaObject &schema); + RelationalSchemaObject schema_; + RelationalSchemaObject trackerSchema_; mutable std::mutex schemaMutex_; RelationalDBProperties properties_; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/simple_tracker_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/simple_tracker_log_table_manager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a47c331c1fbc8445160c068bb8fc55faada1932 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/simple_tracker_log_table_manager.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "simple_tracker_log_table_manager.h" + +namespace DistributedDB { + +std::string SimpleTrackerLogTableManager::CalcPrimaryKeyHash(const std::string &references, const TableInfo &table, + const std::string &identity) +{ + (void)identity; + std::string sql; + if (table.GetPrimaryKey().size() == 1) { + sql = "calc_hash(" + references + "'" + table.GetPrimaryKey().at(0) + "', 0)"; + } else { + sql = "calc_hash("; + for (const auto &it : table.GetPrimaryKey()) { + sql += "calc_hash(" + references + "'" + it.second + "', 0)||"; + } + sql.pop_back(); + sql.pop_back(); + sql += ", 0)"; + } + return sql; +} + +void SimpleTrackerLogTableManager::GetIndexSql(const TableInfo &table, std::vector &schema) +{ + const std::string tableName = GetLogTableName(table); + + std::string indexCursor = "CREATE INDEX IF NOT EXISTS " + tableName + + "_cursor_index ON " + tableName + "(cursor);"; + schema.emplace_back(indexCursor); +} + +std::string SimpleTrackerLogTableManager::GetPrimaryKeySql(const TableInfo &table) +{ + return "PRIMARY KEY(hash_key)"; +} + +// The parameter "identity" is a hash string that identifies a device. The same for the next two functions. +std::string SimpleTrackerLogTableManager::GetInsertTrigger(const TableInfo &table, const std::string &identity) +{ + if (table.GetTrackerTable().GetTrackerColNames().empty()) { + return ""; + } + std::string logTblName = GetLogTableName(table); + std::string tableName = table.GetTableName(); + std::string insertTrigger = "CREATE TRIGGER IF NOT EXISTS "; + insertTrigger += "naturalbase_rdb_" + tableName + "_ON_INSERT AFTER INSERT \n"; + insertTrigger += "ON '" + tableName + "'\n"; + insertTrigger += " FOR EACH ROW \n"; + insertTrigger += "BEGIN\n"; + insertTrigger += "\t INSERT OR REPLACE INTO " + logTblName; + insertTrigger += " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key, cloud_gid"; + insertTrigger += ", extend_field, cursor, version)"; + insertTrigger += " VALUES (new." + std::string(DBConstant::SQLITE_INNER_ROWID) + ", '', '',"; + insertTrigger += " get_raw_sys_time(), get_raw_sys_time(), 0x02, "; + insertTrigger += CalcPrimaryKeyHash("NEW.", table, identity) + ", '', "; + insertTrigger += table.GetTrackerTable().GetAssignValSql(); + insertTrigger += ", case when (SELECT count(1)<>0 FROM " + logTblName + ") then "; + insertTrigger += " (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END"; + insertTrigger += " FROM " + logTblName + ")"; + insertTrigger += " ELSE new." + std::string(DBConstant::SQLITE_INNER_ROWID) + " end, '');\n"; + insertTrigger += "SELECT client_observer('" + tableName + "', NEW._rowid_, 0, "; + insertTrigger += table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1"; + insertTrigger += ");\n"; + insertTrigger += "END;"; + return insertTrigger; +} + +std::string SimpleTrackerLogTableManager::GetUpdateTrigger(const TableInfo &table, const std::string &identity) +{ + if (table.GetTrackerTable().GetTrackerColNames().empty()) { + return ""; + } + (void)identity; + std::string logTblName = GetLogTableName(table); + std::string tableName = table.GetTableName(); + std::string updateTrigger = "CREATE TRIGGER IF NOT EXISTS "; + updateTrigger += "naturalbase_rdb_" + tableName + "_ON_UPDATE AFTER UPDATE \n"; + updateTrigger += "ON '" + tableName + "'\n"; + updateTrigger += " FOR EACH ROW "; + updateTrigger += "BEGIN\n"; // if user change the primary key, we can still use gid to identify which one is updated + updateTrigger += "\t UPDATE " + logTblName; + updateTrigger += " SET timestamp=get_raw_sys_time(), device='', flag=0x02"; + updateTrigger += table.GetTrackerTable().GetExtendAssignValSql(); + updateTrigger += ", cursor = (SELECT case when (MAX(cursor) is null) then 1 else (MAX(cursor) + 1) END "; + updateTrigger += " from " + logTblName + ") where data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID); + updateTrigger += ";\n"; + updateTrigger += "select client_observer('" + tableName + "', OLD." + std::string(DBConstant::SQLITE_INNER_ROWID); + updateTrigger += ", 1, "; + updateTrigger += table.GetTrackerTable().GetDiffTrackerValSql(); + updateTrigger += ");"; + updateTrigger += "END;"; + return updateTrigger; +} + +std::string SimpleTrackerLogTableManager::GetDeleteTrigger(const TableInfo &table, const std::string &identity) +{ + if (table.GetTrackerTable().GetTrackerColNames().empty()) { + return ""; + } + (void)identity; + std::string tableName = table.GetTableName(); + std::string deleteTrigger = "CREATE TRIGGER IF NOT EXISTS "; + deleteTrigger += "naturalbase_rdb_" + tableName + "_ON_DELETE BEFORE DELETE \n"; + deleteTrigger += "ON '" + tableName + "'\n"; + deleteTrigger += " FOR EACH ROW \n"; + deleteTrigger += "BEGIN\n"; + deleteTrigger += "\t UPDATE " + GetLogTableName(table); + deleteTrigger += " SET data_key=-1,flag=0x03,timestamp=get_raw_sys_time()"; + deleteTrigger += table.GetTrackerTable().GetExtendAssignValSql(true); + deleteTrigger += ", cursor = (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END "; + deleteTrigger += " FROM " + GetLogTableName(table) + ")"; + deleteTrigger += " WHERE data_key = OLD." + std::string(DBConstant::SQLITE_INNER_ROWID) + ";"; + // -1 is rowid when data is deleted, 2 means change type is delete(ClientChangeType) + deleteTrigger += "SELECT client_observer('" + tableName + "', -1, 2, "; + deleteTrigger += table.GetTrackerTable().GetTrackerColNames().empty() ? "0" : "1"; + deleteTrigger += ");\n"; + deleteTrigger += "END;"; + return deleteTrigger; +} + +std::vector SimpleTrackerLogTableManager::GetDropTriggers(const TableInfo &table) +{ + std::vector dropTriggers; + std::string tableName = table.GetTableName(); + std::string insertTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_INSERT; "; + std::string updateTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_UPDATE; "; + std::string deleteTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_DELETE; "; + dropTriggers.emplace_back(insertTrigger); + dropTriggers.emplace_back(updateTrigger); + dropTriggers.emplace_back(deleteTrigger); + if (table.GetTrackerTable().GetTrackerColNames().empty()) { + std::string deleteLogTable = "DROP TABLE IF EXISTS " + GetLogTableName(table) + ";"; + dropTriggers.emplace_back(deleteLogTable); + } + return dropTriggers; +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/simple_tracker_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/simple_tracker_log_table_manager.h new file mode 100644 index 0000000000000000000000000000000000000000..4460a866672b81388bac1d6f5f0053d44509faf0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/simple_tracker_log_table_manager.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SIMPLE_TRACKER_LOG_TABLE_MANAGER_H +#define SIMPLE_TRACKER_LOG_TABLE_MANAGER_H + +#include "sqlite_log_table_manager.h" + +namespace DistributedDB { +class SimpleTrackerLogTableManager : public SqliteLogTableManager { +public: + SimpleTrackerLogTableManager() = default; + ~SimpleTrackerLogTableManager() override = default; + + // The parameter "references" is "", "NEW." or "OLD.". "identity" is a hash string that identifies a device. + std::string CalcPrimaryKeyHash(const std::string &references, const TableInfo &table, + const std::string &identity) override; + +private: + void GetIndexSql(const TableInfo &table, std::vector &schema) override; + std::string GetPrimaryKeySql(const TableInfo &table) override; + + // The parameter "identity" is a hash string that identifies a device. The same for the next two functions. + std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) override; + std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) override; + std::string GetDeleteTrigger(const TableInfo &table, const std::string &identity) override; + std::vector GetDropTriggers(const TableInfo &table) override; +}; + +} // DistributedDB + +#endif // SIMPLE_TRACKER_LOG_TABLE_MANAGER_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp index 84039aa003778f5cfad888c8131a69dbecb13ef5..2e775e435075dded6e9bd3f27948eb775a940cbe 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.cpp @@ -77,7 +77,7 @@ std::string SplitDeviceLogTableManager::GetUpdateTrigger(const TableInfo &table, std::string(DBConstant::SQLITE_INNER_ROWID) + ", '', '', get_sys_time(0), " "get_last_time(), CASE WHEN (" + CalcPrimaryKeyHash("NEW.", table, identity) + " != " + CalcPrimaryKeyHash("NEW.", table, identity) + ") THEN 0x02 ELSE 0x22 END, " + - CalcPrimaryKeyHash("NEW.", table, identity) + ", '');\n"; + CalcPrimaryKeyHash("NEW.", table, identity) + ", '', '', '', '');\n"; } updateTrigger += "END;"; return updateTrigger; @@ -101,4 +101,17 @@ std::string SplitDeviceLogTableManager::GetPrimaryKeySql(const TableInfo &table) { return "PRIMARY KEY(device, hash_key)"; } + +std::vector SplitDeviceLogTableManager::GetDropTriggers(const TableInfo &table) +{ + std::vector dropTriggers; + std::string tableName = table.GetTableName(); + std::string insertTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_INSERT; "; + std::string updateTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_UPDATE; "; + std::string deleteTrigger = "DROP TRIGGER IF EXISTS naturalbase_rdb_" + tableName + "_ON_DELETE; "; + dropTriggers.emplace_back(insertTrigger); + dropTriggers.emplace_back(updateTrigger); + dropTriggers.emplace_back(deleteTrigger); + return dropTriggers; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.h index 7e442ddf6553bc0e133568d506f44b8505665a2a..6499a0ae158fd67669d890497b20eb3036e5a3ab 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/split_device_log_table_manager.h @@ -33,6 +33,7 @@ private: std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) override; std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) override; std::string GetDeleteTrigger(const TableInfo &table, const std::string &identity) override; + std::vector GetDropTriggers(const TableInfo &table) override; }; } // namespace DistributedDB #endif // SPLICT_DEVICE_LOG_TABLE_MANAGER_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_local_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_local_kvdb.cpp index 1f36d039c76a696aadd1f5eee6f88d757d4df611..8aa10ee3da58c6b3330db889d79a2777233ba014 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_local_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_local_kvdb.cpp @@ -48,8 +48,8 @@ SQLiteLocalKvDB::~SQLiteLocalKvDB() int SQLiteLocalKvDB::Open(const KvDBProperties &kvDBProp) { - int databaseType = kvDBProp.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); - if (databaseType == KvDBProperties::LOCAL_TYPE) { + int databaseType = kvDBProp.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); + if (databaseType == KvDBProperties::LOCAL_TYPE_SQLITE) { std::unique_ptr operation = std::make_unique(this, nullptr); (void)operation->ClearExportedTempFiles(kvDBProp); int errCode = operation->RekeyRecover(kvDBProp); @@ -296,7 +296,7 @@ void SQLiteLocalKvDB::InitDataBaseOption(const KvDBProperties &kvDBProp, OpenDbP std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, ""); std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, ""); std::string dbName = kvDBProp.GetStringProp(KvDBProperties::FILE_NAME, DBConstant::LOCAL_DATABASE_NAME); - int databaseType = kvDBProp.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int databaseType = kvDBProp.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); bool createIfNecessary = kvDBProp.GetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType); // Table name "data" should not be changed in the future, otherwise when an older software open a newer database @@ -305,7 +305,7 @@ void SQLiteLocalKvDB::InitDataBaseOption(const KvDBProperties &kvDBProp, OpenDbP CipherType cipherType; CipherPassword passwd; kvDBProp.GetPassword(cipherType, passwd); - std::string uri = dataDir + "/" + identifierDir + "/" + subDir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION; + std::string uri = dataDir + "/" + identifierDir + "/" + subDir + "/" + dbName + DBConstant::DB_EXTENSION; option = {uri, createIfNecessary, false, createTableSqls, cipherType, passwd}; } @@ -318,10 +318,10 @@ int SQLiteLocalKvDB::BackupCurrentDatabase(const KvDBProperties &properties, con return errCode; } std::string dbName = properties.GetStringProp(KvDBProperties::FILE_NAME, DBConstant::LOCAL_DATABASE_NAME); - int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType); - std::string currentDb = baseDir + "/" + subDir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION; - std::string dstDb = dir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION; + std::string currentDb = baseDir + "/" + subDir + "/" + dbName + DBConstant::DB_EXTENSION; + std::string dstDb = dir + "/" + dbName + DBConstant::DB_EXTENSION; errCode = DBCommon::CopyFile(currentDb, dstDb); if (errCode != E_OK) { LOGE("Copy the local current db error:%d", errCode); @@ -338,10 +338,10 @@ int SQLiteLocalKvDB::ImportDatabase(const KvDBProperties &properties, const std: return errCode; } std::string dbName = properties.GetStringProp(KvDBProperties::FILE_NAME, DBConstant::LOCAL_DATABASE_NAME); - int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + int databaseType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); std::string subDir = KvDBProperties::GetStoreSubDirectory(databaseType); - std::string dstDb = baseDir + "/" + subDir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION; - std::string currentDb = dir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION; + std::string dstDb = baseDir + "/" + subDir + "/" + dbName + DBConstant::DB_EXTENSION; + std::string currentDb = dir + "/" + dbName + DBConstant::DB_EXTENSION; CipherType cipherType; CipherPassword dstPasswd; properties.GetPassword(cipherType, dstPasswd); @@ -353,8 +353,8 @@ int SQLiteLocalKvDB::RemoveKvDB(const KvDBProperties &properties) // Only care the data directory and the db name. std::string storeOnlyDir; std::string storeDir; - GenericKvDB::GetStoreDirectory(properties, KvDBProperties::LOCAL_TYPE, storeDir, storeOnlyDir); - int dbType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + GenericKvDB::GetStoreDirectory(properties, KvDBProperties::LOCAL_TYPE_SQLITE, storeDir, storeOnlyDir); + int dbType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); return KvDBUtils::RemoveKvDB(storeDir, storeOnlyDir, KvDBProperties::GetStoreSubDirectory(dbType)); } @@ -362,8 +362,8 @@ int SQLiteLocalKvDB::GetKvDBSize(const KvDBProperties &properties, uint64_t &siz { std::string storeOnlyDir; std::string storeDir; - GenericKvDB::GetStoreDirectory(properties, KvDBProperties::LOCAL_TYPE, storeDir, storeOnlyDir); - int dbType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + GenericKvDB::GetStoreDirectory(properties, KvDBProperties::LOCAL_TYPE_SQLITE, storeDir, storeOnlyDir); + int dbType = properties.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); return KvDBUtils::GetKvDbSize(storeDir, storeOnlyDir, KvDBProperties::GetStoreSubDirectory(dbType), size); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp index 6a449a7802d48349da98760ccc5cf5d189b36989..5ba1ac9012bc411732e5b6af0638b11a6b3ccf41 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.cpp @@ -19,8 +19,19 @@ namespace DistributedDB { int SqliteLogTableManager::AddRelationalLogTableTrigger(sqlite3 *db, const TableInfo &table, const std::string &identity) { - std::vector sqls = { GetInsertTrigger(table, identity), GetUpdateTrigger(table, identity), - GetDeleteTrigger(table, identity) }; + std::vector sqls = GetDropTriggers(table); + std::string insertTrigger = GetInsertTrigger(table, identity); + if (!insertTrigger.empty()) { + sqls.emplace_back(insertTrigger); + } + std::string updateTrigger = GetUpdateTrigger(table, identity); + if (!updateTrigger.empty()) { + sqls.emplace_back(updateTrigger); + } + std::string deleteTrigger = GetDeleteTrigger(table, identity); + if (!deleteTrigger.empty()) { + sqls.emplace_back(deleteTrigger); + } // add insert,update,delete trigger for (const auto &sql : sqls) { int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); @@ -45,7 +56,10 @@ int SqliteLogTableManager::CreateRelationalLogTable(sqlite3 *db, const TableInfo "wtimestamp INT NOT NULL," \ "flag INT NOT NULL," \ "hash_key BLOB NOT NULL," \ - "cloud_gid TEXT," + + "cloud_gid TEXT," + \ + "extend_field BLOB," + \ + "cursor INT DEFAULT 0," + \ + "version TEXT DEFAULT ''," + \ primaryKey + ");"; std::vector logTableSchema; logTableSchema.emplace_back(createTableSql); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.h index d792bbe1956a21482226498de92f4211f3a01b83..1d7280f5a0711a4100b0c8e741d81c44e8f9536e 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_log_table_manager.h @@ -41,6 +41,7 @@ private: virtual std::string GetInsertTrigger(const TableInfo &table, const std::string &identity) = 0; virtual std::string GetUpdateTrigger(const TableInfo &table, const std::string &identity) = 0; virtual std::string GetDeleteTrigger(const TableInfo &table, const std::string &identity) = 0; + virtual std::vector GetDropTriggers(const TableInfo &table) = 0; virtual std::string GetPrimaryKeySql(const TableInfo &table) = 0; }; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp index de3344c48afe3b1b27d4e20fa3e4d8bc90898151..7036053f47c9d9af44a7e7bfb84e022fd6236b90 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_multi_ver_data_storage.cpp @@ -78,7 +78,7 @@ int SQLiteMultiVerDataStorage::CheckVersion(const Property &property, bool &isDb int SQLiteMultiVerDataStorage::GetVersion(const Property &property, int &version, bool &isDbExisted) const { std::string uri = property.path + "/" + property.identifierName + "/" + DBConstant::MULTI_SUB_DIR + "/" + - DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; isDbExisted = OS::CheckPathExistence(uri); if (isDbExisted) { std::vector tableVect; @@ -94,7 +94,7 @@ int SQLiteMultiVerDataStorage::Open(const Property &property) // whether create the transactions. property_ = property; uri_ = property.path + "/" + property_.identifierName + "/" + DBConstant::MULTI_SUB_DIR + "/" + - DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; std::vector tableVect; tableVect.push_back(CREATE_TABLE_SQL); tableVect.push_back(CREATE_TABLE_VERSION_INDEX_SQL); @@ -361,7 +361,7 @@ int SQLiteMultiVerDataStorage::RunExportLogic(CipherType type, const CipherPassw } // execute export - std::string newDbName = dbDir + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + std::string newDbName = dbDir + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; errCode = SQLiteUtils::ExportDatabase(db, type, passwd, newDbName); if (errCode != E_OK) { LOGE("multi ver data export failed:%d", errCode); @@ -376,8 +376,8 @@ int SQLiteMultiVerDataStorage::RunExportLogic(CipherType type, const CipherPassw int SQLiteMultiVerDataStorage::BackupCurrentDatabase(const Property &property, const std::string &dir) { std::string currentDb = property.path + "/" + property.identifierName + "/" + DBConstant::MULTI_SUB_DIR + "/" + - DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; - std::string dstDb = dir + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; + std::string dstDb = dir + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; int errCode = DBCommon::CopyFile(currentDb, dstDb); if (errCode != E_OK) { LOGE("Copy the local current db error:%d", errCode); @@ -389,8 +389,8 @@ int SQLiteMultiVerDataStorage::ImportDatabase(const Property &property, const st const CipherPassword &passwd) { std::string currentDb = property.path + "/" + property.identifierName + "/" + DBConstant::MULTI_SUB_DIR + "/" + - DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; - std::string srcDb = dir + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; + std::string srcDb = dir + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; int errCode = SQLiteUtils::ExportDatabase(srcDb, property.cipherType, passwd, currentDb, property.passwd); if (errCode != E_OK) { LOGE("import the multi ver data db error:%d", errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp index 132d5674e2aeae48df8f208eb23c40984ca84106..27ea64e47a7e04cb06fc6e59b1841a6ecd47f437 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_query_helper.cpp @@ -22,6 +22,7 @@ #include "log_print.h" #include "macro_utils.h" #include "sqlite_utils.h" +#include "cloud/cloud_storage_utils.h" namespace DistributedDB { using namespace TriggerMode; @@ -1009,7 +1010,8 @@ std::string GetRelationalCloudSyncDataQueryHeader(const std::vector &fiel "b.wtimestamp," "b.flag," "b.hash_key," - "b.cloud_gid,"; + "b.cloud_gid," + "b.version,"; if (fields.empty()) { // For query check. If column count changed, can be discovered. sql += "a.*"; } else { @@ -1152,7 +1154,7 @@ int SqliteQueryHelper::GetRelationalCloudQueryStatement(sqlite3 *dbHandle, uint6 int SqliteQueryHelper::GetCountRelationalCloudQueryStatement(sqlite3 *dbHandle, uint64_t beginTime, bool isCloudForcePush, sqlite3_stmt *&statement) { - std::string sql = "SELECT COUNT(1) "; + std::string sql = "SELECT COUNT(*) "; AppendCloudQuery(isCloudForcePush, sql); return GetCloudQueryStatement(false, dbHandle, beginTime, sql, statement); } @@ -1167,18 +1169,16 @@ int SqliteQueryHelper::GetGidRelationalCloudQueryStatement(sqlite3 *dbHandle, ui void SqliteQueryHelper::AppendCloudQuery(bool isCloudForcePush, std::string &sql) { - sql += " FROM '" + DBCommon::GetLogTableName(tableName_) + "' AS b LEFT JOIN '"; - sql += tableName_ + "' AS a ON (a." + std::string(DBConstant::SQLITE_INNER_ROWID) + " = b.data_key)"; - sql += isCloudForcePush ? " WHERE b.timestamp > ? AND (b.flag & 0x04 != 0x04)": + sql += CloudStorageUtils::GetLeftJoinLogSql(tableName_, false); + sql += isCloudForcePush ? " WHERE b.timestamp > ? AND (b.flag & 0x04 != 0x04)" : " WHERE b.timestamp > ? AND (b.flag & 0x02 = 0x02)"; - sql += " AND (b.cloud_gid != '' or"; // actually, b.cloud_gid will not be null. + sql += " AND (b.flag & 0x08 != 0x08) AND (b.cloud_gid != '' or"; // actually, b.cloud_gid will not be null. sql += " (b.cloud_gid == '' and (b.flag & 0x01 = 0))) "; } void SqliteQueryHelper::AppendCloudGidQuery(bool isCloudForcePush, std::string &sql) { - sql += " FROM '" + DBCommon::GetLogTableName(tableName_) + "' AS b LEFT JOIN '"; - sql += tableName_ + "' AS a ON (a." + std::string(DBConstant::SQLITE_INNER_ROWID) + " = b.data_key)"; + sql += CloudStorageUtils::GetLeftJoinLogSql(tableName_, false); sql += isCloudForcePush ? " WHERE b.timestamp > ? AND (b.flag & 0x04 != 0x04)" : " WHERE b.timestamp > ?"; sql += " AND (b.cloud_gid != '') "; // actually, b.cloud_gid will not be null. @@ -1208,10 +1208,10 @@ int SqliteQueryHelper::GetCloudQueryStatement(bool useTimestampAlias, sqlite3 *d } return errCode; } - int index = 2; // the query node begin with 2 in this sql + int index = 2; errCode = BindObjNodes(statement, index); if (errCode != E_OK) { - LOGE("BindObjNodes failed %d", errCode); + LOGE("[Query] BindObjNodes failed %d", errCode); int resetRet = E_OK; SQLiteUtils::ResetStatement(statement, true, errCode); if (resetRet != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp index 3dd7bc99124c43458cf9de4e954092c10af914ff..15cd5f1927b142909bb4598224308aca6f62e06b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp @@ -83,10 +83,14 @@ SQLiteSingleVerDatabaseUpgrader::~SQLiteSingleVerDatabaseUpgrader() db_ = nullptr; } +// NOTE: 先看upgradeLockFile是否存在,存在就把parentDir目录下的,移动到parentDir/main_db目录下 +// 如果文件锁不存在,那么看dbFilePath-的数据库文件是否存在,如果存在,就 +// GetDbVersion, 先开库获得版本之, 然后如果版本值是0, 就移除原来的。 +// 如果版本值不是0, 就创建文件锁, 再把parentDir目录下的,移动到parentDir/main_db目录下 int SQLiteSingleVerDatabaseUpgrader::TransferDatabasePath(const std::string &parentDir, const OpenDbProperties &option) { - std::string dbFilePath = parentDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + std::string dbFilePath = parentDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; std::string upgradeLockFile = parentDir + "/" + DBConstant::UPGRADE_POSTFIX; if (OS::CheckPathExistence(upgradeLockFile)) { @@ -259,8 +263,8 @@ int SQLiteSingleVerDatabaseUpgrader::SetPathSecOptWithCheck(const std::string &p const std::string &dbStore, bool isWithChecked) { SecurityOption dbOpt; - std::vector dbFilePathVec {DBConstant::SQLITE_DB_EXTENSION}; - std::string dbFilePath = path + "/" + dbStore + DBConstant::SQLITE_DB_EXTENSION; + std::vector dbFilePathVec {DBConstant::DB_EXTENSION}; + std::string dbFilePath = path + "/" + dbStore + DBConstant::DB_EXTENSION; if (OS::CheckPathExistence(dbFilePath) && isWithChecked) { int errCode = RuntimeContext::GetInstance()->GetSecurityOption(dbFilePath, dbOpt); if (errCode != E_OK) { @@ -341,7 +345,7 @@ int SQLiteSingleVerDatabaseUpgrader::SetSecOption(const std::string &path, const int SQLiteSingleVerDatabaseUpgrader::MoveDatabaseToNewDir(const std::string &parentDir, const std::string &upgradeLockFile) { - std::vector dbFilePathVec {DBConstant::SQLITE_DB_EXTENSION, ".db-wal", ".db-shm"}; + std::vector dbFilePathVec {DBConstant::DB_EXTENSION, ".db-wal", ".db-shm"}; for (const auto &item : dbFilePathVec) { std::string oldDbPath = parentDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + item; std::string currentDbPath = parentDir + "/" + DBConstant::MAINDB_DIR + "/" + diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp index 0664750bbc0465f532df8c052d13d7003c649b39..625a5a3aa70b49c0de1916610379de8470fe7b29 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.cpp @@ -32,6 +32,7 @@ #include "platform_specific.h" #include "schema_object.h" #include "single_ver_database_oper.h" +#include "single_ver_utils.h" #include "storage_engine_manager.h" #include "sqlite_single_ver_natural_store_connection.h" #include "value_hash_calc.h" @@ -182,19 +183,6 @@ SQLiteSingleVerNaturalStore::~SQLiteSingleVerNaturalStore() ReleaseResources(); } -std::string SQLiteSingleVerNaturalStore::GetDatabasePath(const KvDBProperties &kvDBProp) -{ - return GetSubDirPath(kvDBProp) + "/" + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; -} - -std::string SQLiteSingleVerNaturalStore::GetSubDirPath(const KvDBProperties &kvDBProp) -{ - std::string dataDir = kvDBProp.GetStringProp(KvDBProperties::DATA_DIR, ""); - std::string identifierDir = kvDBProp.GetStringProp(KvDBProperties::IDENTIFIER_DIR, ""); - return dataDir + "/" + identifierDir + "/" + DBConstant::SINGLE_SUB_DIR; -} - int SQLiteSingleVerNaturalStore::SetUserVer(const KvDBProperties &kvDBProp, int version) { OpenDbProperties properties; @@ -277,7 +265,10 @@ int SQLiteSingleVerNaturalStore::GetSecurityOption(SecurityOption &option) const option = SecurityOption(); return -E_NOT_SUPPORT; } - + if (!RuntimeContext::GetInstance()->IsProcessSystemApiAdapterValid()) { + LOGI("[GetSecurityOption] Not set api adapter"); + return -E_NOT_SUPPORT; + } option.securityLabel = GetDbProperties().GetSecLabel(); option.securityFlag = GetDbProperties().GetSecFlag(); @@ -351,19 +342,6 @@ int SQLiteSingleVerNaturalStore::CheckValueAndAmendIfNeed(ValueSource sourceType return -E_INVALID_FORMAT; } -int SQLiteSingleVerNaturalStore::ClearIncompleteDatabase(const KvDBProperties &kvDBPro) const -{ - std::string dbSubDir = SQLiteSingleVerNaturalStore::GetSubDirPath(kvDBPro); - if (OS::CheckPathExistence(dbSubDir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE)) { - int errCode = DBCommon::RemoveAllFilesOfDirectory(dbSubDir); - if (errCode != E_OK) { - LOGE("Remove the incomplete database dir failed!"); - return -E_REMOVE_FILE; - } - } - return E_OK; -} - int SQLiteSingleVerNaturalStore::CheckDatabaseRecovery(const KvDBProperties &kvDBProp) { if (kvDBProp.GetBoolProp(KvDBProperties::MEMORY_MODE, false)) { // memory status not need recovery @@ -566,8 +544,9 @@ int SQLiteSingleVerNaturalStore::GetMetaData(const Key &key, Value &value) const return errCode; } -int SQLiteSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value) +int SQLiteSingleVerNaturalStore::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { + (void)isInTransaction; int errCode = SQLiteSingleVerNaturalStore::CheckDataStatus(key, value, false); if (errCode != E_OK) { return errCode; @@ -632,27 +611,6 @@ int SQLiteSingleVerNaturalStore::GetAllMetaKeys(std::vector &keys) const return errCode; } -void SQLiteSingleVerNaturalStore::CommitAndReleaseNotifyData(SingleVerNaturalStoreCommitNotifyData *&committedData, - bool isNeedCommit, int eventType) -{ - if (isNeedCommit) { - if (committedData != nullptr) { - if (!committedData->IsChangedDataEmpty()) { - CommitNotify(eventType, committedData); - } - if (!committedData->IsConflictedDataEmpty()) { - CommitNotify(static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_CONFLICT_EVENT), - committedData); - } - } - } - - if (committedData != nullptr) { - committedData->DecObjRef(committedData); - committedData = nullptr; - } -} - int SQLiteSingleVerNaturalStore::GetSyncData(Timestamp begin, Timestamp end, std::vector &entries, ContinueToken &continueStmtToken, const DataSizeSpecInfo &dataSizeInfo) const { @@ -1286,7 +1244,7 @@ int SQLiteSingleVerNaturalStore::SaveSyncItems(const QueryObject &query, std::ve if (handle == nullptr) { return errCode; } - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); errCode = handle->StartTransaction(TransactType::IMMEDIATE); if (errCode != E_OK) { ReleaseHandle(handle); @@ -1339,7 +1297,7 @@ int SQLiteSingleVerNaturalStore::SaveSyncDataToCacheDB(const QueryObject &query, } Timestamp maxTimestamp = 0; - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); errCode = SaveSyncItemsInCacheMode(handle, query, dataItems, deviceInfo, maxTimestamp); if (errCode != E_OK) { LOGE("[SingleVerNStore] Failed to save sync data in cache mode, err : %d", errCode); @@ -1664,25 +1622,6 @@ int SQLiteSingleVerNaturalStore::TransConflictTypeToRegisterFunctionType( return E_OK; } -RegisterFuncType SQLiteSingleVerNaturalStore::GetFuncType(int index, const TransPair *transMap, int32_t len) -{ - int32_t head = 0; - int32_t end = len - 1; - while (head <= end) { - int32_t mid = (head + end) / 2; - if (transMap[mid].index < index) { - head = mid + 1; - continue; - } - if (transMap[mid].index > index) { - end = mid - 1; - continue; - } - return transMap[mid].funcType; - } - return RegisterFuncType::REGISTER_FUNC_TYPE_MAX; -} - int SQLiteSingleVerNaturalStore::GetSchema(SchemaObject &schema) const { int errCode = E_OK; @@ -1753,50 +1692,12 @@ const KvDBProperties &SQLiteSingleVerNaturalStore::GetDbProperties() const return GetMyProperties(); } -int SQLiteSingleVerNaturalStore::RemoveKvDB(const KvDBProperties &properties) -{ - // To avoid leakage, the engine resources are forced to be released - const std::string identifier = properties.GetStringProp(KvDBProperties::IDENTIFIER_DATA, ""); - (void)StorageEngineManager::ForceReleaseStorageEngine(identifier); - - // Only care the data directory and the db name. - std::string storeOnlyDir; - std::string storeDir; - GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE, storeDir, storeOnlyDir); - - const std::vector> dbDir { - {DBConstant::MAINDB_DIR, DBConstant::SINGLE_VER_DATA_STORE}, - {DBConstant::METADB_DIR, DBConstant::SINGLE_VER_META_STORE}, - {DBConstant::CACHEDB_DIR, DBConstant::SINGLE_VER_CACHE_STORE}}; - - bool isAllNotFound = true; - for (const auto &item : dbDir) { - std::string currentDir = storeDir + item.first + "/"; - std::string currentOnlyDir = storeOnlyDir + item.first + "/"; - int errCode = KvDBUtils::RemoveKvDB(currentDir, currentOnlyDir, item.second); - if (errCode != -E_NOT_FOUND) { - if (errCode != E_OK) { - return errCode; - } - isAllNotFound = false; - } - }; - if (isAllNotFound) { - return -E_NOT_FOUND; - } - - int errCode = DBCommon::RemoveAllFilesOfDirectory(storeDir, true); - if (errCode != E_OK) { - return errCode; - } - return DBCommon::RemoveAllFilesOfDirectory(storeOnlyDir, true); -} - int SQLiteSingleVerNaturalStore::GetKvDBSize(const KvDBProperties &properties, uint64_t &size) const { std::string storeOnlyIdentDir; std::string storeIdentDir; - GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE, storeIdentDir, storeOnlyIdentDir); + GenericKvDB::GetStoreDirectory(properties, KvDBProperties::SINGLE_VER_TYPE_SQLITE, storeIdentDir, + storeOnlyIdentDir); const std::vector> dbDir { {DBConstant::MAINDB_DIR, DBConstant::SINGLE_VER_DATA_STORE}, {DBConstant::METADB_DIR, DBConstant::SINGLE_VER_META_STORE}, @@ -2158,7 +2059,7 @@ int SQLiteSingleVerNaturalStore::SaveCreateDBTime() return -E_PARSE_FAIL; } - int errCode = PutMetaData(key, value); + int errCode = PutMetaData(key, value, false); if (errCode != E_OK) { LOGE("SaveCreateDBTime failed, errCode = %d", errCode); return errCode; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h index 086a9a1e46dc22ef9a162b36161f9920bdb694a7..8c2b82bd16ca733ebad98a9f9dca54892803092d 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store.h @@ -20,15 +20,14 @@ #include "isyncer.h" #include "kv_store_nb_conflict_data_impl.h" #include "runtime_context.h" -#include "single_ver_kvdb_sync_interface.h" +#include "single_ver_natural_store.h" #include "single_ver_natural_store_commit_notify_data.h" #include "sqlite_single_ver_continue_token.h" #include "sqlite_single_ver_storage_engine.h" #include "sqlite_utils.h" -#include "sync_able_kvdb.h" namespace DistributedDB { -class SQLiteSingleVerNaturalStore : public SyncAbleKvDB, public SingleVerKvDBSyncInterface { +class SQLiteSingleVerNaturalStore : public SingleVerNaturalStore { public: SQLiteSingleVerNaturalStore(); ~SQLiteSingleVerNaturalStore() override; @@ -48,7 +47,7 @@ public: // Get interface type of this kvdb. int GetInterfaceType() const override; - // Get the interface ref-count, in order to access asynchronously. + // Get the interface ref-count, in order to access asynchronously.1 void IncRefCount() override; // Drop the interface ref-count. @@ -64,7 +63,7 @@ public: int GetMetaData(const Key &key, Value &value) const override; - int PutMetaData(const Key &key, const Value &value) override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; // Delete multiple meta data records in a transaction. int DeleteMetaData(const std::vector &keys) override; @@ -132,8 +131,6 @@ public: const KvDBProperties &GetDbProperties() const override; - int RemoveKvDB(const KvDBProperties &properties) override; - int GetKvDBSize(const KvDBProperties &properties, uint64_t &size) const override; KvDBProperties &GetDbPropertyForUpdate(); @@ -194,9 +191,9 @@ public: int IsSupportSubscribe() const override; - void AbortHandle(); + void AbortHandle() override; - void EnableHandle(); + void EnableHandle() override; int TryHandle() const override; @@ -206,15 +203,8 @@ protected: void ReleaseResources(); private: - struct TransPair { - int index; - RegisterFuncType funcType; - }; - static RegisterFuncType GetFuncType(int index, const TransPair *transMap, int32_t len); - int CheckDatabaseRecovery(const KvDBProperties &kvDBProp); - void CommitAndReleaseNotifyData(SingleVerNaturalStoreCommitNotifyData *&committedData, - bool isNeedCommit, int eventType); + int CheckDatabaseRecovery(const KvDBProperties &kvDBProp); int RegisterNotification(); @@ -233,8 +223,6 @@ private: static int SetUserVer(const KvDBProperties &kvDBProp, int version); - static std::string GetDatabasePath(const KvDBProperties &kvDBProp); - static std::string GetSubDirPath(const KvDBProperties &kvDBProp); void NotifyRemovedData(std::vector &entries); // Decide read only based on schema situation @@ -270,15 +258,13 @@ private: int SaveSyncItemsInCacheMode(SQLiteSingleVerStorageExecutor *handle, const QueryObject &query, std::vector &dataItems, const DeviceInfo &deviceInfo, Timestamp &maxTimestamp) const; - int ClearIncompleteDatabase(const KvDBProperties &kvDBPro) const; - int GetSyncDataForQuerySync(std::vector &dataItems, SQLiteSingleVerContinueToken *&continueStmtToken, const DataSizeSpecInfo &dataSizeInfo) const; int SaveCreateDBTime(); int SaveCreateDBTimeIfNotExisted(); - int GetAndInitStorageEngine(const KvDBProperties &kvDBProp); + virtual int GetAndInitStorageEngine(const KvDBProperties &kvDBProp); int RemoveAllSubscribe(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp index 24f6afafc2282acf034c05c5c2448b08e4b49526..1c0eefab355e1afcc544d037121ac10ed6b4bfcd 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp @@ -23,6 +23,7 @@ #include "kvdb_observer_handle.h" #include "kvdb_pragma.h" #include "log_print.h" +#include "single_ver_natural_store_connection.h" #include "sqlite_single_ver_natural_store.h" #include "sqlite_single_ver_result_set.h" #include "store_types.h" @@ -39,7 +40,7 @@ namespace { } SQLiteSingleVerNaturalStoreConnection::SQLiteSingleVerNaturalStoreConnection(SQLiteSingleVerNaturalStore *kvDB) - : SyncAbleKvDBConnection(kvDB), + : SingleVerNaturalStoreConnection(kvDB), cacheMaxSizeForNewResultSet_(DEFAULT_RESULT_SET_CACHE_MAX_SIZE), conflictType_(0), transactionEntrySize_(0), @@ -83,7 +84,7 @@ int SQLiteSingleVerNaturalStoreConnection::Get(const IOption &option, const Key SingleVerDataType dataType; if (option.dataType == IOption::LOCAL_DATA) { - dataType = SingleVerDataType::LOCAL_TYPE; + dataType = SingleVerDataType::LOCAL_TYPE_SQLITE; } else if (option.dataType == IOption::SYNC_DATA) { dataType = SingleVerDataType::SYNC_TYPE; } else { @@ -96,7 +97,7 @@ int SQLiteSingleVerNaturalStoreConnection::Get(const IOption &option, const Key return errCode; } - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); { // need to check if the transaction started std::lock_guard lock(transactionMutex_); @@ -122,23 +123,6 @@ int SQLiteSingleVerNaturalStoreConnection::Get(const IOption &option, const Key return errCode; } -int SQLiteSingleVerNaturalStoreConnection::Put(const IOption &option, const Key &key, const Value &value) -{ - std::vector entries; - Entry entry{key, value}; - entries.emplace_back(std::move(entry)); - - return PutBatch(option, entries); -} - -int SQLiteSingleVerNaturalStoreConnection::Delete(const IOption &option, const Key &key) -{ - std::vector keys; - keys.push_back(key); - - return DeleteBatch(option, keys); -} - int SQLiteSingleVerNaturalStoreConnection::Clear(const IOption &option) { return -E_NOT_SUPPORT; @@ -166,8 +150,9 @@ int SQLiteSingleVerNaturalStoreConnection::GetEntries(const IOption &option, con return errCode; } QueryObject queryObj(query); - if ((queryObj.GetSortType() != SortType::NONE) && !queryObj.IsQueryOnlyByKey()) { - LOGE("[GetEntries][query] timestamp sort only support prefixKey"); + if (((queryObj.GetSortType() != SortType::NONE) && !queryObj.IsQueryOnlyByKey()) + || queryObj.IsQueryByRange()) { + LOGE("[GetEntries][query] timestamp sort only support prefixKey and not support Range search"); return -E_NOT_SUPPORT; } @@ -176,7 +161,7 @@ int SQLiteSingleVerNaturalStoreConnection::GetEntries(const IOption &option, con const SchemaObject &schemaObjRef = naturalStore->GetSchemaObjectConstRef(); queryObj.SetSchema(schemaObjRef); } - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); { std::lock_guard lock(transactionMutex_); if (writeHandle_ != nullptr) { @@ -215,7 +200,8 @@ int SQLiteSingleVerNaturalStoreConnection::GetCount(const IOption &option, const return -E_INVALID_DB; } QueryObject queryObj(query); - if ((queryObj.GetSortType() != SortType::NONE) && !queryObj.IsQueryOnlyByKey()) { + if (((queryObj.GetSortType() != SortType::NONE) && !queryObj.IsQueryOnlyByKey()) + || queryObj.IsQueryByRange()) { LOGE("[GetCount] get count query invalid"); return -E_NOT_SUPPORT; } @@ -224,7 +210,7 @@ int SQLiteSingleVerNaturalStoreConnection::GetCount(const IOption &option, const const SchemaObject &schemaObjRef = naturalStore->GetSchemaObjectConstRef(); queryObj.SetSchema(schemaObjRef); } - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); { std::lock_guard lock(transactionMutex_); if (writeHandle_ != nullptr) { @@ -257,21 +243,13 @@ int SQLiteSingleVerNaturalStoreConnection::PutBatch(const IOption &option, const return PutBatchInner(option, entries); } - if (option.dataType == IOption::SYNC_DATA) { - int errCode = CheckSyncEntriesValid(entries); - if (errCode != E_OK) { - return errCode; - } - return PutBatchInner(option, entries); - } - - return -E_NOT_SUPPORT; + return SingleVerNaturalStoreConnection::PutBatch(option, entries); } int SQLiteSingleVerNaturalStoreConnection::DeleteBatch(const IOption &option, const std::vector &keys) { - LOGD("[DeleteBatch] keys size is : %zu, dataType : %d", keys.size(), option.dataType); if (option.dataType == IOption::LOCAL_DATA) { + LOGD("[DeleteBatch] keys size is : %zu, dataType : %d", keys.size(), option.dataType); int retCode = CheckLocalKeysValid(keys); if (retCode != E_OK) { return retCode; @@ -279,15 +257,7 @@ int SQLiteSingleVerNaturalStoreConnection::DeleteBatch(const IOption &option, co return DeleteBatchInner(option, keys); } - if (option.dataType == IOption::SYNC_DATA) { - int errCode = CheckSyncKeysValid(keys); - if (errCode != E_OK) { - return errCode; - } - return DeleteBatchInner(option, keys); - } - - return -E_NOT_SUPPORT; + return SingleVerNaturalStoreConnection::DeleteBatch(option, keys); } int SQLiteSingleVerNaturalStoreConnection::GetSnapshot(IKvDBSnapshot *&snapshot) const @@ -630,8 +600,9 @@ int SQLiteSingleVerNaturalStoreConnection::GetResultSet(const IOption &option, c const SchemaObject &schemaObjRef = naturalStore->GetSchemaObjectConstRef(); queryObj.SetSchema(schemaObjRef); } - if ((queryObj.GetSortType() != SortType::NONE) && !queryObj.IsQueryOnlyByKey()) { - LOGE("[GetResultSet][query] timestamp sort only support prefixKey"); + if (((queryObj.GetSortType() != SortType::NONE) && !queryObj.IsQueryOnlyByKey()) + || queryObj.IsQueryByRange()) { + LOGE("[GetEntries][query] timestamp sort only support prefixKey and not support Range search"); return -E_NOT_SUPPORT; } bool isMemDb = naturalStore->GetMyProperties().GetBoolProp(KvDBProperties::MEMORY_MODE, false); @@ -827,7 +798,7 @@ int SQLiteSingleVerNaturalStoreConnection::GetDeviceIdentifier(PragmaEntryDevice int SQLiteSingleVerNaturalStoreConnection::PutBatchInner(const IOption &option, const std::vector &entries) { - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); std::lock_guard lock(transactionMutex_); bool isAuto = false; int errCode = E_OK; @@ -868,7 +839,7 @@ int SQLiteSingleVerNaturalStoreConnection::PutBatchInner(const IOption &option, int SQLiteSingleVerNaturalStoreConnection::DeleteBatchInner(const IOption &option, const std::vector &keys) { - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); std::lock_guard lock(transactionMutex_); bool isAuto = false; int errCode = E_OK; @@ -1032,7 +1003,7 @@ int SQLiteSingleVerNaturalStoreConnection::SaveLocalItem(const LocalDataItem &da { int errCode = E_OK; if ((dataItem.flag & DataItem::DELETE_FLAG) == 0) { - errCode = writeHandle_->PutKvData(SingleVerDataType::LOCAL_TYPE, dataItem.key, dataItem.value, + errCode = writeHandle_->PutKvData(SingleVerDataType::LOCAL_TYPE_SQLITE, dataItem.key, dataItem.value, dataItem.timestamp, localCommittedData_); } else { Value value; @@ -1278,9 +1249,9 @@ int SQLiteSingleVerNaturalStoreConnection::StartTransactionNormally(TransactType } errCode = kvDB_->TryToDisableConnection(OperatePerm::NORMAL_WRITE); - if (errCode != E_OK) { + if (errCode != E_OK) { // on operate rekey or import ReleaseExecutor(handle); - LOGE("Start transaction failed, %d", errCode); + LOGE("Start transaction failed, %d perm not normal", errCode); return errCode; } @@ -1650,7 +1621,7 @@ int SQLiteSingleVerNaturalStoreConnection::UnpublishOper(SingleVerNaturalStoreCo } Timestamp time = updateTimestamp ? naturalStore->GetCurrentTimestamp() : syncRecord.writeTimestamp; - errCode = writeHandle_->PutKvData(SingleVerDataType::LOCAL_TYPE, syncRecord.key, syncRecord.value, time, + errCode = writeHandle_->PutKvData(SingleVerDataType::LOCAL_TYPE_SQLITE, syncRecord.key, syncRecord.value, time, committedData); } else if (operType == static_cast(LocalOperType::LOCAL_OPR_DEL)) { Timestamp localTimestamp = 0; @@ -1809,7 +1780,7 @@ int SQLiteSingleVerNaturalStoreConnection::GetEntriesInner(bool isGetValue, cons SingleVerDataType type; if (option.dataType == IOption::LOCAL_DATA) { - type = SingleVerDataType::LOCAL_TYPE; + type = SingleVerDataType::LOCAL_TYPE_SQLITE; } else if (option.dataType == IOption::SYNC_DATA) { type = SingleVerDataType::SYNC_TYPE; } else { @@ -1822,11 +1793,11 @@ int SQLiteSingleVerNaturalStoreConnection::GetEntriesInner(bool isGetValue, cons return errCode; } - DBDfxAdapter::StartTraceSQL(); + DBDfxAdapter::StartTracing(); { std::lock_guard lock(transactionMutex_); if (writeHandle_ != nullptr) { - LOGD("Transaction started already."); + LOGD("[SQLiteSingleVerNaturalStoreConnection] Transaction started already."); errCode = writeHandle_->GetEntries(isGetValue, type, keyPrefix, entries); DBDfxAdapter::FinishTraceSQL(); return errCode; @@ -1835,7 +1806,7 @@ int SQLiteSingleVerNaturalStoreConnection::GetEntriesInner(bool isGetValue, cons SQLiteSingleVerStorageExecutor *handle = GetExecutor(false, errCode); if (handle == nullptr) { - LOGE("[Connection]::[GetEntries] Get executor failed, errCode = [%d]", errCode); + LOGE("[SQLiteSingleVerNaturalStoreConnection]::[GetEntries] Get executor failed, errCode = [%d]", errCode); DBDfxAdapter::FinishTraceSQL(); return errCode; } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h index 330876c6a9d706a6e678a516b0858c31da9a7a85..da101f89684651979fae788992508e67d644a3bb 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_natural_store_connection.h @@ -16,6 +16,7 @@ #ifndef SQLITE_SINGLE_VER_NATURAL_STORE_CONNECTION_H #define SQLITE_SINGLE_VER_NATURAL_STORE_CONNECTION_H #include +#include "single_ver_natural_store_connection.h" #include "sync_able_kvdb_connection.h" #include "sqlite_single_ver_storage_executor.h" #include "db_types.h" @@ -24,7 +25,7 @@ namespace DistributedDB { class SQLiteSingleVerNaturalStore; -class SQLiteSingleVerNaturalStoreConnection : public SyncAbleKvDBConnection { +class SQLiteSingleVerNaturalStoreConnection : public SingleVerNaturalStoreConnection { public: explicit SQLiteSingleVerNaturalStoreConnection(SQLiteSingleVerNaturalStore *kvDB); ~SQLiteSingleVerNaturalStoreConnection() override; @@ -35,12 +36,6 @@ public: // Get the value from the database int Get(const IOption &option, const Key &key, Value &value) const override; - // Put the value to the database - int Put(const IOption &option, const Key &key, const Value &value) override; - - // Delete the value from the database - int Delete(const IOption &option, const Key &key) override; - // Clear all the data from the database int Clear(const IOption &option) override; @@ -115,8 +110,8 @@ private: void ClearConflictNotifierCount(); - int PutBatchInner(const IOption &option, const std::vector &entries); - int DeleteBatchInner(const IOption &option, const std::vector &keys); + int PutBatchInner(const IOption &option, const std::vector &entries) override; + int DeleteBatchInner(const IOption &option, const std::vector &keys) override; int SaveSyncEntries(const std::vector &entries); int SaveLocalEntries(const std::vector &entries); @@ -127,11 +122,11 @@ private: int CheckDataStatus(const Key &key, const Value &value, bool isDelete) const; - int CheckWritePermission() const; + int CheckWritePermission() const override; - int CheckSyncEntriesValid(const std::vector &entries) const; + int CheckSyncEntriesValid(const std::vector &entries) const override; - int CheckSyncKeysValid(const std::vector &keys) const; + int CheckSyncKeysValid(const std::vector &keys) const override; int CheckLocalEntriesValid(const std::vector &entries) const; @@ -195,7 +190,7 @@ private: int StartTransactionNormally(TransactType transType = TransactType::DEFERRED); bool IsCacheDBMode() const; - bool IsExtendedCacheDBMode() const; + bool IsExtendedCacheDBMode() const override; int CheckReadDataControlled() const; bool IsFileAccessControlled() const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp index 319b7b6cc744898104133262ec74865ae797cc94..84ae341ca952f7a73c667be8bf52c49064534df4 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp @@ -38,16 +38,20 @@ static constexpr const char *FLAG = "FLAG"; static constexpr const char *DATAKEY = "DATA_KEY"; static constexpr const char *DEVICE_FIELD = "DEVICE"; static constexpr const char *CLOUD_GID_FIELD = "CLOUD_GID"; +static constexpr const char *HASH_KEY = "HASH_KEY"; static constexpr const char *FLAG_IS_CLOUD = "FLAG & 0x02 = 0"; // see if 1th bit of a flag is cloud static constexpr const char *SET_FLAG_LOCAL = "FLAG | 0x02"; // set 1th bit of flag to one which is local -static constexpr const int SET_FLAG_ZERO_MASK = 0x03; // clear 2th bit of flag -static constexpr const int SET_FLAG_ONE_MASK = 0x04; // set 2th bit of flag -static constexpr const int SET_CLOUD_FLAG = 0x05; // set 1th bit of flag to 0 +static constexpr const char *FLAG_IS_LOGIC_DELETE = "FLAG & 0x08 != 0"; // see if 3th bit of a flag is logic delete +static constexpr const int SET_FLAG_ZERO_MASK = 0x0B; // clear 2th bit of flag 1011 use with & +static constexpr const int SET_FLAG_ONE_MASK = 0x04; // set 2th bit of flag 0100 use with | +static constexpr const int SET_CLOUD_FLAG = 0x0D; // set 1th bit of flag to 0 1101 use with & static constexpr const int DATA_KEY_INDEX = 0; static constexpr const int TIMESTAMP_INDEX = 3; static constexpr const int W_TIMESTAMP_INDEX = 4; static constexpr const int FLAG_INDEX = 5; +static constexpr const int HASH_KEY_INDEX = 6; static constexpr const int CLOUD_GID_INDEX = 7; +static constexpr const int VERSION_INDEX = 8; int PermitSelect(void *a, int b, const char *c, const char *d, const char *e, const char *f) { @@ -59,7 +63,8 @@ int PermitSelect(void *a, int b, const char *c, const char *d, const char *e, co } SQLiteSingleVerRelationalStorageExecutor::SQLiteSingleVerRelationalStorageExecutor(sqlite3 *dbHandle, bool writable, DistributedTableMode mode) - : SQLiteStorageExecutor(dbHandle, writable, false), mode_(mode) + : SQLiteStorageExecutor(dbHandle, writable, false), mode_(mode), isLogicDelete_(false), + assetLoader_(nullptr) { bindCloudFieldFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BindInt64; bindCloudFieldFuncMap_[TYPE_INDEX] = &CloudStorageUtils::BindBool; @@ -143,7 +148,7 @@ int GetExistedDataTimeOffset(sqlite3 *db, const std::string &tableName, bool isM } int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedData(sqlite3 *db, const std::string &tableName, - const std::string &calPrimaryKeyHash) + const std::string &calPrimaryKeyHash, TableInfo &tableInfo) { int64_t timeOffset = 0; int errCode = GetExistedDataTimeOffset(db, tableName, isMemDb_, timeOffset); @@ -152,10 +157,21 @@ int SQLiteSingleVerRelationalStorageExecutor::GeneLogInfoForExistedData(sqlite3 } std::string timeOffsetStr = std::to_string(timeOffset); std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; - std::string sql = "INSERT INTO " + logTable + " SELECT " + std::string(DBConstant::SQLITE_INNER_ROWID) + + std::string sql = "INSERT OR REPLACE INTO " + logTable + " SELECT " + std::string(DBConstant::SQLITE_INNER_ROWID) + ", '', '', " + timeOffsetStr + " + " + std::string(DBConstant::SQLITE_INNER_ROWID) + ", " + timeOffsetStr + " + " + std::string(DBConstant::SQLITE_INNER_ROWID) + ", 0x2, " + - calPrimaryKeyHash + ", ''" + " FROM '" + tableName + "' AS a WHERE 1=1;"; + calPrimaryKeyHash + ", '', "; + if (tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { + sql += "'', ''"; + } else { + sql += tableInfo.GetTrackerTable().GetExtendName().empty() ? "''" : tableInfo.GetTrackerTable().GetExtendName(); + sql += ", case when (SELECT count(1)<>0 FROM " + logTable + ")" + + " then ((SELECT CASE WHEN MAX(cursor) IS NULL THEN 0 ELSE MAX(cursor) END FROM " + logTable + ") + " + + std::string(DBConstant::SQLITE_INNER_ROWID) + + ") ELSE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " end"; + } + sql += ", ''"; + sql += " FROM '" + tableName + "' AS a WHERE 1=1;"; return SQLiteUtils::ExecuteRawSQL(db, sql); } @@ -198,10 +214,10 @@ int SQLiteSingleVerRelationalStorageExecutor::CreateDistributedTable(Distributed if (!isUpgraded) { std::string calPrimaryKeyHash = tableManager->CalcPrimaryKeyHash("a.", table, identity); - errCode = GeneLogInfoForExistedData(dbHandle_, tableName, calPrimaryKeyHash); - if (errCode != E_OK) { - return errCode; - } + errCode = GeneLogInfoForExistedData(dbHandle_, tableName, calPrimaryKeyHash, table); + } + if (errCode != E_OK) { + return errCode; } // add trigger @@ -509,7 +525,7 @@ static int GetLogData(sqlite3_stmt *logStatement, LogInfo &logInfo) } namespace { -void GetCloudLog(sqlite3_stmt *logStatement, VBucket &logInfo, uint32_t &totalSize) +void GetCloudLog(sqlite3_stmt *logStatement, VBucket &logInfo, uint32_t &totalSize, bool isShared) { logInfo.insert_or_assign(CloudDbConstant::MODIFY_FIELD, static_cast(sqlite3_column_int64(logStatement, TIMESTAMP_INDEX))); @@ -524,6 +540,12 @@ void GetCloudLog(sqlite3_stmt *logStatement, VBucket &logInfo, uint32_t &totalSi totalSize += cloudGid.size(); } } + if (isShared) { + std::string version; + SQLiteUtils::GetColumnTextValue(logStatement, VERSION_INDEX, version); + logInfo.insert_or_assign(CloudDbConstant::VERSION_FIELD, version); + totalSize += version.size(); + } } void GetCloudExtraLog(sqlite3_stmt *logStatement, VBucket &flags) @@ -534,6 +556,9 @@ void GetCloudExtraLog(sqlite3_stmt *logStatement, VBucket &flags) static_cast(sqlite3_column_int64(logStatement, TIMESTAMP_INDEX))); flags.insert_or_assign(FLAG, static_cast(sqlite3_column_int64(logStatement, FLAG_INDEX))); + Bytes hashKey; + (void)SQLiteUtils::GetColumnBlobValue(logStatement, HASH_KEY_INDEX, hashKey); + flags.insert_or_assign(HASH_KEY, hashKey); } bool IsAbnormalData(const VBucket &data) @@ -541,7 +566,8 @@ bool IsAbnormalData(const VBucket &data) for (const auto &item : data) { const Asset *asset = std::get_if>(&item.second); if (asset != nullptr) { - if (asset->status == static_cast(AssetStatus::ABNORMAL)) { + if (asset->status == static_cast(AssetStatus::ABNORMAL) || + (asset->status & static_cast(AssetStatus::DOWNLOAD_WITH_NULL)) != 0) { return true; } continue; @@ -551,7 +577,8 @@ bool IsAbnormalData(const VBucket &data) continue; } for (const auto &oneAsset : *assets) { - if (oneAsset.status == static_cast(AssetStatus::ABNORMAL)) { + if (oneAsset.status == static_cast(AssetStatus::ABNORMAL) || + (oneAsset.status & static_cast(AssetStatus::DOWNLOAD_WITH_NULL)) != 0) { return true; } } @@ -564,58 +591,50 @@ int IdentifyCloudType(CloudSyncData &cloudSyncData, VBucket &data, VBucket &log, int64_t *rowid = std::get_if(&flags[ROWID]); int64_t *flag = std::get_if(&flags[FLAG]); int64_t *timeStamp = std::get_if(&flags[TIMESTAMP]); - if (rowid == nullptr || flag == nullptr || timeStamp == nullptr) { + Bytes *hashKey = std::get_if(&flags[HASH_KEY]); + if (rowid == nullptr || flag == nullptr || timeStamp == nullptr || hashKey == nullptr) { return -E_INVALID_DATA; } if ((static_cast(*flag) & DataItem::DELETE_FLAG) != 0) { cloudSyncData.delData.record.push_back(data); cloudSyncData.delData.extend.push_back(log); - } else if (log.find(CloudDbConstant::GID_FIELD) == log.end()) { + cloudSyncData.delData.hashKey.push_back(*hashKey); + } else { + bool isInsert = log.find(CloudDbConstant::GID_FIELD) == log.end(); if (data.empty()) { - LOGE("The cloud data to be inserted is empty."); + LOGE("The cloud data is empty, isInsert:%d", isInsert); return -E_INVALID_DATA; } if (IsAbnormalData(data)) { - LOGW("This data is abnormal, ignore it when upload"); + LOGW("This data is abnormal, ignore it when upload, isInsert:%d", isInsert); cloudSyncData.ignoredCount++; return E_OK; } - cloudSyncData.insData.record.push_back(data); - cloudSyncData.insData.rowid.push_back(*rowid); - VBucket asset; - CloudStorageUtils::ObtainAssetFromVBucket(data, asset); - cloudSyncData.insData.timestamp.push_back(*timeStamp); - cloudSyncData.insData.assets.push_back(asset); - cloudSyncData.insData.extend.push_back(log); - } else { - if (data.empty()) { - LOGE("The cloud data to be updated is empty."); - return -E_INVALID_DATA; - } - cloudSyncData.updData.record.push_back(data); + CloudSyncBatch &opData = isInsert ? cloudSyncData.insData : cloudSyncData.updData; + opData.record.push_back(data); + opData.rowid.push_back(*rowid); VBucket asset; CloudStorageUtils::ObtainAssetFromVBucket(data, asset); - if (!asset.empty()) { - cloudSyncData.updData.rowid.push_back(*rowid); - cloudSyncData.updData.timestamp.push_back(*timeStamp); - cloudSyncData.updData.assets.push_back(asset); - } - cloudSyncData.updData.extend.push_back(log); + opData.timestamp.push_back(*timeStamp); + opData.assets.push_back(asset); + opData.extend.push_back(log); + opData.hashKey.push_back(*hashKey); } return E_OK; } void GetCloudGid(sqlite3_stmt *logStatement, std::vector &cloudGid) { - if (sqlite3_column_text(logStatement, CLOUD_GID_INDEX) != nullptr) { - std::string gid = reinterpret_cast( - sqlite3_column_text(logStatement, CLOUD_GID_INDEX)); - if (!gid.empty()) { - cloudGid.emplace_back(gid); - } else { - LOGW("[Relational] Get cloud gid is null."); - } + if (sqlite3_column_text(logStatement, CLOUD_GID_INDEX) == nullptr) { + return; } + std::string gid = reinterpret_cast( + sqlite3_column_text(logStatement, CLOUD_GID_INDEX)); + if (gid.empty()) { + LOGW("[Relational] Get cloud gid is null."); + return; + } + cloudGid.emplace_back(gid); } } @@ -1086,20 +1105,6 @@ int StepNext(bool isMemDB, sqlite3_stmt *stmt, Timestamp ×tamp) return errCode; } -int StepNext(bool isMemDB, sqlite3_stmt *stmt) -{ - if (stmt == nullptr) { - return -E_INVALID_ARGS; - } - int errCode = SQLiteUtils::StepWithRetry(stmt, isMemDB); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = -E_FINISHED; - } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { - errCode = E_OK; - } - return errCode; -} - int AppendData(const DataSizeSpecInfo &sizeInfo, size_t appendLength, size_t &overLongSize, size_t &dataTotalSize, std::vector &dataItems, DataItem &&item) { @@ -1291,8 +1296,7 @@ int SQLiteSingleVerRelationalStorageExecutor::IsTableOnceDropped(const std::stri if (execCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { // The table in schema was dropped onceDropped = true; return E_OK; - } - if (execCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + } else if (execCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { std::string keyStr = DBConstant::TABLE_IS_DROPPED + tableName; Key key; DBCommon::StringToVector(keyStr, key); @@ -1310,8 +1314,9 @@ int SQLiteSingleVerRelationalStorageExecutor::IsTableOnceDropped(const std::stri LOGE("[IsTableOnceDropped] query is table dropped failed, %d", errCode); return errCode; } + } else { + return execCode; } - return execCode; } int SQLiteSingleVerRelationalStorageExecutor::CleanResourceForDroppedTable(const std::string &tableName) @@ -1326,7 +1331,7 @@ int SQLiteSingleVerRelationalStorageExecutor::CleanResourceForDroppedTable(const LOGE("Delete log tables for missing distributed table failed. %d", errCode); return errCode; } - errCode = DeleteMissTableTrigger(tableName); + errCode = DeleteTableTrigger(tableName); if (errCode != E_OK) { LOGE("Delete trigger for missing distributed table failed. %d", errCode); } @@ -1613,7 +1618,8 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUploadCount(const Timestamp &ti return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudLogGid(const CloudSyncData &cloudDataResult) +int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudLogGid(const CloudSyncData &cloudDataResult, + bool ignoreEmptyGid) { if (cloudDataResult.insData.extend.empty() || cloudDataResult.insData.rowid.empty() || cloudDataResult.insData.extend.size() != cloudDataResult.insData.rowid.size()) { @@ -1626,42 +1632,10 @@ int SQLiteSingleVerRelationalStorageExecutor::UpdateCloudLogGid(const CloudSyncD if (errCode != E_OK) { return errCode; } - for (size_t i = 0; i < cloudDataResult.insData.extend.size(); ++i) { - auto gidEntry = cloudDataResult.insData.extend[i].find(CloudDbConstant::GID_FIELD); - int64_t rowid = cloudDataResult.insData.rowid[i]; - if (gidEntry == cloudDataResult.insData.extend[i].end()) { - errCode = -E_INVALID_ARGS; - break; - } - std::string val; - if (CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, - cloudDataResult.insData.extend[i], val) != E_OK) { - errCode = -E_INVALID_DATA; - break; - } - if (val.empty()) { - errCode = -E_CLOUD_ERROR; - break; - } - errCode = SQLiteUtils::BindTextToStatement(stmt, 1, val); - if (errCode != E_OK) { - break; - } - errCode = SQLiteUtils::BindInt64ToStatement(stmt, 2, rowid); // 2 means the second bind args - if (errCode != E_OK) { - break; - } - errCode = SQLiteUtils::StepWithRetry(stmt, false); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - SQLiteUtils::ResetStatement(stmt, false, errCode); - } else { - LOGE("Update cloud log failed:%d", errCode); - break; - } - } - SQLiteUtils::ResetStatement(stmt, true, errCode); - return errCode; + errCode = BindStmtWithCloudGid(cloudDataResult, ignoreEmptyGid, stmt); + int resetCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, resetCode); + return errCode == E_OK ? resetCode : errCode; } int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(CloudSyncData &cloudDataResult, @@ -1679,7 +1653,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudData(CloudSyncData &cl uint32_t stepNum = 0; do { if (isStepNext) { - errCode = StepNext(isMemDb_, queryStmt); + errCode = SQLiteRelationalUtils::StepNext(isMemDb_, queryStmt); if (errCode != E_OK) { errCode = (errCode == -E_FINISHED ? E_OK : errCode); break; @@ -1711,7 +1685,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetSyncCloudGid(QuerySyncObject &q return errCode; } do { - errCode = StepNext(isMemDb_, queryStmt); + errCode = SQLiteRelationalUtils::StepNext(isMemDb_, queryStmt); if (errCode != E_OK) { errCode = (errCode == -E_FINISHED ? E_OK : errCode); break; @@ -1729,7 +1703,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudDataForSync(sqlite3_stmt * { VBucket log; VBucket extraLog; - GetCloudLog(statement, log, totalSize); + GetCloudLog(statement, log, totalSize, cloudDataResult.isShared); GetCloudExtraLog(statement, extraLog); VBucket data; @@ -1742,7 +1716,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudDataForSync(sqlite3_stmt * for (size_t cid = 0; cid < tableSchema_.fields.size(); ++cid) { Type cloudValue; errCode = SQLiteRelationalUtils::GetCloudValueByType(statement, - tableSchema_.fields[cid].type, cid + 8, cloudValue); // 8 is the start index of query cloud data + tableSchema_.fields[cid].type, cid + 9, cloudValue); // 9 is the start index of query cloud data if (errCode != E_OK) { return errCode; } @@ -1923,7 +1897,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetPrimaryKeyHashValue(const VBuck int errCode = E_OK; TableInfo localTable = localSchema_.GetTable(tableSchema.name); // table name in cloud schema is in lower case - if (DBCommon::ToLowerCase(localTable.GetTableName()) != tableSchema.name) { + if (!DBCommon::CaseInsensitiveCompare(localTable.GetTableName(), tableSchema.name)) { LOGE("localSchema doesn't contain table from cloud"); return -E_INTERNAL_ERROR; } @@ -2041,7 +2015,8 @@ int SQLiteSingleVerRelationalStorageExecutor::GetQueryLogSql(const std::string & } int SQLiteSingleVerRelationalStorageExecutor::ExecutePutCloudData(const std::string &tableName, - const TableSchema &tableSchema, DownloadData &downloadData, std::map &statisticMap) + const TableSchema &tableSchema, const TrackerTable &trackerTable, DownloadData &downloadData, + std::map &statisticMap) { int index = 0; int errCode = E_OK; @@ -2049,13 +2024,13 @@ int SQLiteSingleVerRelationalStorageExecutor::ExecutePutCloudData(const std::str VBucket &vBucket = downloadData.data[index]; switch (op) { case OpType::INSERT: - errCode = InsertCloudData(vBucket, tableSchema); + errCode = InsertCloudData(vBucket, tableSchema, trackerTable, GetLocalDataKey(index, downloadData)); break; case OpType::UPDATE: errCode = UpdateCloudData(vBucket, tableSchema); break; case OpType::DELETE: - errCode = DeleteCloudData(tableName, vBucket, tableSchema); + errCode = DeleteCloudData(tableName, vBucket, tableSchema, trackerTable); break; case OpType::ONLY_UPDATE_GID: case OpType::SET_CLOUD_FORCE_PUSH_FLAG_ZERO: @@ -2063,8 +2038,9 @@ int SQLiteSingleVerRelationalStorageExecutor::ExecutePutCloudData(const std::str case OpType::UPDATE_TIMESTAMP: case OpType::CLEAR_GID: errCode = OnlyUpdateLogTable(vBucket, tableSchema, op); - break; case OpType::NOT_HANDLE: + errCode = errCode == E_OK ? OnlyUpdateAssetId(tableName, tableSchema, vBucket, + GetLocalDataKey(index, downloadData), op) : errCode; break; default: errCode = -E_CLOUD_ERROR; @@ -2090,7 +2066,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanInner(ClearMode mode, return errCode; } if (mode == FLAG_ONLY) { - errCode = DoCleanLogs(tableNameList); + errCode = DoCleanLogs(tableNameList, localSchema); if (errCode != E_OK) { LOGE("[Storage Executor] Failed to do clean logs when clean cloud data."); return errCode; @@ -2101,6 +2077,12 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanInner(ClearMode mode, LOGE("[Storage Executor] Failed to do clean log and data when clean cloud data."); return errCode; } + } else if (mode == CLEAR_SHARED_TABLE) { + errCode = DoCleanShareTableDataAndLog(tableNameList); + if (errCode != E_OK) { + LOGE("[Storage Executor] Failed to do clean log and data when clean cloud data."); + return errCode; + } } errCode = SetLogTriggerStatus(true); if (errCode != E_OK) { @@ -2110,13 +2092,19 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanInner(ClearMode mode, return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogs(const std::vector &tableNameList) +int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogs(const std::vector &tableNameList, + const RelationalSchemaObject &localSchema) { int errCode = E_OK; int i = 1; for (const auto &tableName: tableNameList) { std::string logTableName = DBCommon::GetLogTableName(tableName); LOGD("[Storage Executor] Start clean cloud data on log table. table index: %d.", i); + errCode = DoCleanAssetId(tableName, localSchema); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to clean asset id when clean cloud data, %d", errCode); + return errCode; + } errCode = CleanCloudDataOnLogTable(logTableName); if (errCode != E_OK) { LOGE("[Storage Executor] failed to clean cloud data on log table, %d", errCode); @@ -2131,17 +2119,17 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogs(const std::vector &dataKeys) + std::vector &dataKeys, bool distinguishCloudFlag) { sqlite3_stmt *selectStmt = nullptr; std::string sql = "SELECT DATA_KEY FROM '" + logTableName + "' WHERE " + CLOUD_GID_FIELD + - " IS NOT NULL AND " + CLOUD_GID_FIELD + " != '' AND " + FLAG_IS_CLOUD + ";"; - + " IS NOT NULL AND " + CLOUD_GID_FIELD + " != ''"; + if (distinguishCloudFlag) { + sql += " AND "; + sql += FLAG_IS_CLOUD; + } + sql += ";"; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, selectStmt); if (errCode != E_OK) { LOGE("Get select data_key statement failed, %d", errCode); @@ -2193,7 +2190,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogAndData(const std::vecto std::string tableName = tableNameList[i]; std::string logTableName = DBCommon::GetLogTableName(tableName); std::vector dataKeys; - errCode = GetCleanCloudDataKeys(logTableName, dataKeys); + errCode = GetCleanCloudDataKeys(logTableName, dataKeys, true); if (errCode != E_OK) { LOGE("[Storage Executor] Failed to get clean cloud data keys, %d.", errCode); return errCode; @@ -2206,7 +2203,7 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogAndData(const std::vecto return errCode; } - errCode = CleanCloudDataAndLogOnUserTable(tableName, logTableName); + errCode = CleanCloudDataAndLogOnUserTable(tableName, logTableName, localSchema); if (errCode != E_OK) { LOGE("[Storage Executor] failed to clean cloud data and log on user table, %d.", errCode); return errCode; @@ -2216,14 +2213,15 @@ int SQLiteSingleVerRelationalStorageExecutor::DoCleanLogAndData(const std::vecto return errCode; } -int SQLiteSingleVerRelationalStorageExecutor::GetCloudAssetOnTable(const std::string &tableName, +int SQLiteSingleVerRelationalStorageExecutor::GetAssetOnTable(const std::string &tableName, const std::string &fieldName, const std::vector &dataKeys, std::vector &assets) { int errCode = E_OK; + int ret = E_OK; + sqlite3_stmt *selectStmt = nullptr; for (const auto &rowId : dataKeys) { std::string queryAssetSql = "SELECT " + fieldName + " FROM '" + tableName + "' WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + std::to_string(rowId) + ";"; - sqlite3_stmt *selectStmt = nullptr; errCode = SQLiteUtils::GetStatement(dbHandle_, queryAssetSql, selectStmt); if (errCode != E_OK) { LOGE("Get select asset statement failed, %d", errCode); @@ -2234,20 +2232,25 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudAssetOnTable(const std::st std::vector blobValue; errCode = SQLiteUtils::GetColumnBlobValue(selectStmt, 0, blobValue); if (errCode != E_OK) { - SQLiteUtils::ResetStatement(selectStmt, true, errCode); - return errCode; + LOGE("Get column blob value failed, %d", errCode); + goto END; } Asset asset; errCode = RuntimeContext::GetInstance()->BlobToAsset(blobValue, asset); if (errCode != E_OK) { - SQLiteUtils::ResetStatement(selectStmt, true, errCode); - return errCode; + LOGE("Transfer blob to asset failed, %d", errCode); + goto END; } assets.push_back(asset); + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; } - SQLiteUtils::ResetStatement(selectStmt, true, errCode); + SQLiteUtils::ResetStatement(selectStmt, true, ret); } - return errCode; + return errCode != E_OK ? errCode : ret; +END: + SQLiteUtils::ResetStatement(selectStmt, true, ret); + return errCode != E_OK ? errCode : ret; } int SQLiteSingleVerRelationalStorageExecutor::GetCloudAssetsOnTable(const std::string &tableName, @@ -2294,7 +2297,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudAssets(const std::string & int errCode = E_OK; for (const auto &fieldInfo: fieldInfos) { if (fieldInfo.IsAssetType()) { - errCode = GetCloudAssetOnTable(tableName, fieldInfo.GetFieldName(), dataKeys, assets); + errCode = GetAssetOnTable(tableName, fieldInfo.GetFieldName(), dataKeys, assets); if (errCode != E_OK) { LOGE("[Storage Executor] failed to get cloud asset on table, %d.", errCode); return errCode; @@ -2311,7 +2314,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetCloudAssets(const std::string & } int SQLiteSingleVerRelationalStorageExecutor::PutCloudSyncData(const std::string &tableName, - const TableSchema &tableSchema, DownloadData &downloadData) + const TableSchema &tableSchema, const TrackerTable &trackerTable, DownloadData &downloadData) { if (downloadData.data.size() != downloadData.opType.size()) { LOGE("put cloud data, data size = %zu, flag size = %zu.", downloadData.data.size(), @@ -2326,7 +2329,7 @@ int SQLiteSingleVerRelationalStorageExecutor::PutCloudSyncData(const std::string } std::map statisticMap = {}; - errCode = ExecutePutCloudData(tableName, tableSchema, downloadData, statisticMap); + errCode = ExecutePutCloudData(tableName, tableSchema, trackerTable, downloadData, statisticMap); int ret = SetLogTriggerStatus(true); if (ret != E_OK) { LOGE("Fail to set log trigger on, %d", ret); @@ -2343,11 +2346,19 @@ int SQLiteSingleVerRelationalStorageExecutor::PutCloudSyncData(const std::string return errCode == E_OK ? ret : errCode; } -int SQLiteSingleVerRelationalStorageExecutor::InsertCloudData(VBucket &vBucket, const TableSchema &tableSchema) +int SQLiteSingleVerRelationalStorageExecutor::InsertCloudData(VBucket &vBucket, const TableSchema &tableSchema, + const TrackerTable &trackerTable, int64_t dataKey) { + int errCode = E_OK; + if (dataKey > 0) { + errCode = RemoveDataAndLog(tableSchema.name, dataKey); + if (errCode != E_OK) { + return errCode; + } + } std::string sql = GetInsertSqlForCloudSync(tableSchema); sqlite3_stmt *insertStmt = nullptr; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, insertStmt); + errCode = SQLiteUtils::GetStatement(dbHandle_, sql, insertStmt); if (errCode != E_OK) { LOGE("Get insert statement failed when save cloud data, %d", errCode); return errCode; @@ -2368,10 +2379,11 @@ int SQLiteSingleVerRelationalStorageExecutor::InsertCloudData(VBucket &vBucket, } // insert log - return InsertLogRecord(tableSchema, vBucket); + return InsertLogRecord(tableSchema, trackerTable, vBucket); } -int SQLiteSingleVerRelationalStorageExecutor::InsertLogRecord(const TableSchema &tableSchema, VBucket &vBucket) +int SQLiteSingleVerRelationalStorageExecutor::InsertLogRecord(const TableSchema &tableSchema, + const TrackerTable &trackerTable, VBucket &vBucket) { if (!CloudStorageUtils::IsContainsPrimaryKey(tableSchema)) { // when one data is deleted, "insert or replace" will insert another log record if there is no primary key, @@ -2392,7 +2404,7 @@ int SQLiteSingleVerRelationalStorageExecutor::InsertLogRecord(const TableSchema } std::string sql = "INSERT OR REPLACE INTO " + DBCommon::GetLogTableName(tableSchema.name) + - " VALUES(?, ?, ?, ?, ?, ?, ?, ?)"; + " VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, 0, ?)"; sqlite3_stmt *insertLogStmt = nullptr; int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, insertLogStmt); if (errCode != E_OK) { @@ -2400,7 +2412,7 @@ int SQLiteSingleVerRelationalStorageExecutor::InsertLogRecord(const TableSchema return errCode; } - errCode = BindValueToInsertLogStatement(vBucket, tableSchema, insertLogStmt); + errCode = BindValueToInsertLogStatement(vBucket, tableSchema, trackerTable, insertLogStmt); if (errCode != E_OK) { SQLiteUtils::ResetStatement(insertLogStmt, true, errCode); return errCode; @@ -2444,7 +2456,7 @@ int SQLiteSingleVerRelationalStorageExecutor::BindValueToUpsertStatement(const V } int SQLiteSingleVerRelationalStorageExecutor::BindHashKeyAndGidToInsertLogStatement(const VBucket &vBucket, - const TableSchema &tableSchema, sqlite3_stmt *insertLogStmt) + const TableSchema &tableSchema, const TrackerTable &trackerTable, sqlite3_stmt *insertLogStmt) { std::vector hashKey; int errCode = GetPrimaryKeyHashValue(vBucket, tableSchema, hashKey); @@ -2467,12 +2479,37 @@ int SQLiteSingleVerRelationalStorageExecutor::BindHashKeyAndGidToInsertLogStatem errCode = SQLiteUtils::BindTextToStatement(insertLogStmt, 8, cloudGid); // 8 is cloud_gid if (errCode != E_OK) { LOGE("Bind cloud_gid to insert log statement failed, %d", errCode); + return errCode; + } + + if (trackerTable.GetExtendName().empty() || vBucket.find(trackerTable.GetExtendName()) == vBucket.end()) { + errCode = SQLiteUtils::BindTextToStatement(insertLogStmt, 9, ""); // 9 is extend_field + } else { + Type extendValue = vBucket.at(trackerTable.GetExtendName()); + errCode = SQLiteRelationalUtils::BindStatementByType(insertLogStmt, 9, extendValue); // 9 is extend_field + } + if (errCode != E_OK) { + LOGE("Bind extend_field to insert log statement failed, %d", errCode); + return errCode; + } + + std::string version; + if (tableSchema.sharedTableName.empty()) { + errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::VERSION_FIELD, vBucket, version); + if (errCode != E_OK) { + LOGE("get version for insert log statement failed, %d", errCode); + return -E_CLOUD_ERROR; + } + } + errCode = SQLiteUtils::BindTextToStatement(insertLogStmt, 10, version); // 10 is version + if (errCode != E_OK) { + LOGE("Bind version to insert log statement failed, %d", errCode); } return errCode; } int SQLiteSingleVerRelationalStorageExecutor::BindValueToInsertLogStatement(VBucket &vBucket, - const TableSchema &tableSchema, sqlite3_stmt *insertLogStmt) + const TableSchema &tableSchema, const TrackerTable &trackerTable, sqlite3_stmt *insertLogStmt) { int64_t rowid = SQLiteUtils::GetLastRowId(dbHandle_); int errCode = SQLiteUtils::BindInt64ToStatement(insertLogStmt, 1, rowid); @@ -2525,7 +2562,7 @@ int SQLiteSingleVerRelationalStorageExecutor::BindValueToInsertLogStatement(VBuc } vBucket[CloudDbConstant::ROW_ID_FIELD_NAME] = rowid; // fill rowid to cloud data to notify user - return BindHashKeyAndGidToInsertLogStatement(vBucket, tableSchema, insertLogStmt); + return BindHashKeyAndGidToInsertLogStatement(vBucket, tableSchema, trackerTable, insertLogStmt); } std::string SQLiteSingleVerRelationalStorageExecutor::GetWhereConditionForDataTable(const std::string &gidStr, @@ -2604,7 +2641,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateDataTableStatement(const // bind value std::vector fields = tableSchema.fields; if (!pkSet.empty()) { - std::vector pkFields = CloudStorageUtils::GetCloudPrimaryKeyField(tableSchema); + std::vector pkFields = CloudStorageUtils::GetCloudPrimaryKeyField(tableSchema, true); fields.insert(fields.end(), pkFields.begin(), pkFields.end()); } errCode = BindValueToUpsertStatement(vBucket, fields, updateStmt); @@ -2657,13 +2694,13 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateLogRecordStatement(const updateLogSql += "flag = flag | " + std::to_string(SET_FLAG_ONE_MASK); // set 2th bit of flag } else if (opType == OpType::UPDATE_TIMESTAMP) { updateLogSql += "device = 'cloud', flag = flag & " + std::to_string(SET_CLOUD_FLAG) + - ", timestamp = ?, cloud_gid = ''"; + ", timestamp = ?, cloud_gid = '', version = ''"; updateColName.push_back(CloudDbConstant::MODIFY_FIELD); } else if (opType == OpType::CLEAR_GID) { - updateLogSql += "cloud_gid = '', flag = flag & " + std::to_string(SET_FLAG_ZERO_MASK); + updateLogSql += "cloud_gid = '', version = '', flag = flag & " + std::to_string(SET_FLAG_ZERO_MASK); } else { if (opType == OpType::DELETE) { - updateLogSql += "data_key = -1, flag = 1, cloud_gid = '', "; + updateLogSql += GetCloudDeleteSql(DBCommon::GetLogTableName(tableSchema.name)); } else { updateLogSql += "flag = 0, cloud_gid = ?, "; updateColName.push_back(CloudDbConstant::GID_FIELD); @@ -2671,26 +2708,18 @@ int SQLiteSingleVerRelationalStorageExecutor::GetUpdateLogRecordStatement(const updateLogSql += "device = 'cloud', timestamp = ?"; updateColName.push_back(CloudDbConstant::MODIFY_FIELD); } + // only share table need to set version + if (tableSchema.sharedTableName.empty() && opType != OpType::DELETE && + opType != OpType::CLEAR_GID && opType != OpType::UPDATE_TIMESTAMP) { + updateLogSql += ", version = ?"; + updateColName.push_back(CloudDbConstant::VERSION_FIELD); + } - std::string gidStr; - int errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, vBucket, gidStr); + int errCode = AppendUpdateLogRecordWhereSqlCondition(tableSchema, vBucket, updateLogSql); if (errCode != E_OK) { - LOGE("Get gid from cloud data fail when construct update log sql, errCode = %d", errCode); return errCode; } - updateLogSql += " WHERE "; - if (!gidStr.empty()) { - updateLogSql += "cloud_gid = '" + gidStr + "'"; - } - std::map pkMap = CloudStorageUtils::GetCloudPrimaryKeyFieldMap(tableSchema); - if (!pkMap.empty()) { - if (!gidStr.empty()) { - updateLogSql += " OR "; - } - updateLogSql += "(hash_key = ?);"; - } - errCode = SQLiteUtils::GetStatement(dbHandle_, updateLogSql, updateLogStmt); if (errCode != E_OK) { LOGE("Get update log statement failed when update cloud data, %d", errCode); @@ -2755,6 +2784,13 @@ int SQLiteSingleVerRelationalStorageExecutor::BindValueToUpdateLogStatement(cons return -E_CLOUD_ERROR; } errCode = SQLiteUtils::BindInt64ToStatement(updateLogStmt, index, std::get(vBucket.at(colName))); + } else if (colName == CloudDbConstant::VERSION_FIELD) { + if (vBucket.find(colName) == vBucket.end()) { + LOGE("cloud data doesn't contain version field when bind update log stmt."); + return -E_CLOUD_ERROR; + } + errCode = SQLiteUtils::BindTextToStatement(updateLogStmt, index, + std::get(vBucket.at(colName))); } else { LOGE("invalid col name when bind value to update log statement."); return -E_INTERNAL_ERROR; @@ -2802,7 +2838,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetDeleteStatementForCloudSync(con int ret = E_OK; if (!pkSet.empty() && queryByPk) { - std::vector pkFields = CloudStorageUtils::GetCloudPrimaryKeyField(tableSchema); + std::vector pkFields = CloudStorageUtils::GetCloudPrimaryKeyField(tableSchema, true); errCode = BindValueToUpsertStatement(vBucket, pkFields, deleteStmt); if (errCode != E_OK) { LOGE("bind value to delete statement failed when delete cloud data, %d", errCode); @@ -2813,15 +2849,22 @@ int SQLiteSingleVerRelationalStorageExecutor::GetDeleteStatementForCloudSync(con } int SQLiteSingleVerRelationalStorageExecutor::DeleteCloudData(const std::string &tableName, const VBucket &vBucket, - const TableSchema &tableSchema) + const TableSchema &tableSchema, const TrackerTable &trackerTable) { + if (isLogicDelete_) { + LOGD("[RDBExecutor] logic delete skip delete data"); + int errCode = UpdateLogRecord(vBucket, tableSchema, OpType::DELETE); + if (errCode == E_OK && !trackerTable.IsEmpty()) { + return SQLiteRelationalUtils::SelectServerObserver(dbHandle_, tableName, true); + } + return errCode; + } std::set pkSet = CloudStorageUtils::GetCloudPrimaryKey(tableSchema); sqlite3_stmt *deleteStmt = nullptr; int errCode = GetDeleteStatementForCloudSync(tableSchema, pkSet, vBucket, deleteStmt); if (errCode != E_OK) { return errCode; } - errCode = SQLiteUtils::StepWithRetry(deleteStmt, false); int ret = E_OK; SQLiteUtils::ResetStatement(deleteStmt, true, ret); @@ -2848,7 +2891,7 @@ int SQLiteSingleVerRelationalStorageExecutor::OnlyUpdateLogTable(const VBucket & return UpdateLogRecord(vBucket, tableSchema, opType); } -int SQLiteSingleVerRelationalStorageExecutor::DeleteMissTableTrigger(const std::string &missTable) const +int SQLiteSingleVerRelationalStorageExecutor::DeleteTableTrigger(const std::string &missTable) const { static const char *triggerEndName[] = { "_ON_INSERT", @@ -2860,11 +2903,16 @@ int SQLiteSingleVerRelationalStorageExecutor::DeleteMissTableTrigger(const std:: std::string deleteSql = "DROP TRIGGER IF EXISTS " + logTableName + endName + ";"; int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, deleteSql); if (errCode != E_OK) { - LOGE("[DeleteMissTableTrigger] Drop trigger failed. %d", errCode); + LOGE("[DeleteTableTrigger] Drop trigger failed. %d", errCode); return errCode; } } return E_OK; } + +void SQLiteSingleVerRelationalStorageExecutor::SetLogicDelete(bool isLogicDelete) +{ + isLogicDelete_ = isLogicDelete; +} } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h index 6c4d513c1e3c804bb1915e4ee1aa8620addec7b1..362516475bb22d8c08b5c9ad6086d0007ccc143b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_executor.h @@ -16,6 +16,8 @@ #define SQLITE_SINGLE_VER_RELATIONAL_STORAGE_EXECUTOR_H #ifdef RELATIONAL_STORE +#include +#include "cloud/asset_operation_utils.h" #include "cloud/cloud_db_constant.h" #include "cloud/cloud_store_types.h" #include "data_transformer.h" @@ -29,6 +31,7 @@ #include "sqlite_single_ver_relational_continue_token.h" #include "sqlite_storage_executor.h" #include "sqlite_utils.h" +#include "tracker_table.h" namespace DistributedDB { class SQLiteSingleVerRelationalStorageExecutor : public SQLiteStorageExecutor { @@ -97,7 +100,7 @@ public: int GetUploadCount(const Timestamp ×tamp, bool isCloudForcePush, QuerySyncObject &query, int64_t &count); - int UpdateCloudLogGid(const CloudSyncData &cloudDataResult); + int UpdateCloudLogGid(const CloudSyncData &cloudDataResult, bool ignoreEmptyGid); int GetSyncCloudData(CloudSyncData &cloudDataResult, const uint32_t &maxSize, SQLiteSingleVerRelationalContinueToken &token); @@ -110,32 +113,75 @@ public: int GetInfoByPrimaryKeyOrGid(const TableSchema &tableSchema, const VBucket &vBucket, DataInfoWithLog &dataInfoWithLog, VBucket &assetInfo); - int PutCloudSyncData(const std::string &tableName, const TableSchema &tableSchema, DownloadData &downloadData); + int PutCloudSyncData(const std::string &tableName, const TableSchema &tableSchema, + const TrackerTable &trackerTable, DownloadData &downloadData); int FillCloudAssetForDownload(const TableSchema &tableSchema, VBucket &vBucket, bool isDownloadSuccess); int DoCleanInner(ClearMode mode, const std::vector &tableNameList, const RelationalSchemaObject &localSchema, std::vector &assets); - int FillCloudAssetForUpload(const std::string &tableName, const CloudSyncBatch &data); + int FillCloudAssetForUpload(OpType opType, const TableSchema &tableSchema, const CloudSyncBatch &data); + int FillCloudVersionForUpload(const CloudSyncData &data); int SetLogTriggerStatus(bool status); + int AnalysisTrackerTable(const TrackerTable &trackerTable, TableInfo &tableInfo); + int CreateTrackerTable(const TrackerTable &trackerTable, bool isUpgrade); + int GetOrInitTrackerSchemaFromMeta(RelationalSchemaObject &schema); + int ExecuteSql(const SqlCondition &condition, std::vector &records); + + int GetClearWaterMarkTables(const std::vector &tableReferenceProperty, + const RelationalSchemaObject &schema, std::set &clearWaterMarkTables); + int CreateTempSyncTrigger(const TrackerTable &trackerTable); + int GetAndResetServerObserverData(const std::string &tableName, ChangeProperties &changeProperties); + int ClearAllTempSyncTrigger(); + int CleanTrackerData(const std::string &tableName, int64_t cursor); + int CreateSharedTable(const DataBaseSchema &schema); + int DeleteTable(const std::vector &tableNames); + int UpdateSharedTable(const std::map> &updateTableNames); + int AlterTableName(const std::map &tableNames); + int DeleteTableTrigger(const std::string &table) const; + + int GetReferenceGid(const std::string &tableName, const CloudSyncBatch &syncBatch, + const std::map> &tableReference, + std::map &referenceGid); + + int CheckIfExistUserTable(const std::string &tableName); + + void SetLogicDelete(bool isLogicDelete); + int RenewTableTrigger(DistributedTableMode mode, const TableInfo &tableInfo, TableSyncType syncType); + + int GetAssetsByGidOrHashKey(const TableSchema &tableSchema, const std::string &gid, const Bytes &hashKey, + VBucket &assets); + + int FillHandleWithOpType(const OpType opType, const CloudSyncData &data, bool fillAsset, bool ignoreEmptyGid, + const TableSchema &tableSchema); + + int GetDbAssets(const TableSchema &tableSchema, const VBucket &vBucket, VBucket &dbAsset); + + void SetIAssetLoader(const std::shared_ptr &loader); + + int CleanResourceForDroppedTable(const std::string &tableName); + + int UpgradedLogForExistedData(TableInfo &tableInfo); private: - int DoCleanLogs(const std::vector &tableNameList); + int DoCleanLogs(const std::vector &tableNameList, const RelationalSchemaObject &localSchema); int DoCleanLogAndData(const std::vector &tableNameList, const RelationalSchemaObject &localSchema, std::vector &assets); int CleanCloudDataOnLogTable(const std::string &logTableName); - int CleanCloudDataAndLogOnUserTable(const std::string &tableName, const std::string &logTableName); + int CleanCloudDataAndLogOnUserTable(const std::string &tableName, const std::string &logTableName, + const RelationalSchemaObject &localSchema); - int GetCleanCloudDataKeys(const std::string &logTableName, std::vector &dataKeys); + int GetCleanCloudDataKeys(const std::string &logTableName, std::vector &dataKeys, + bool distinguishCloudFlag); int GetCloudAssets(const std::string &tableName, const std::vector &fieldInfos, const std::vector &dataKeys, std::vector &assets); - int GetCloudAssetOnTable(const std::string &tableName, const std::string &fieldName, + int GetAssetOnTable(const std::string &tableName, const std::string &fieldName, const std::vector &dataKeys, std::vector &assets); int GetCloudAssetsOnTable(const std::string &tableName, const std::string &fieldName, @@ -170,15 +216,17 @@ private: void SetTableInfo(const TableInfo &tableInfo); // When put or get sync data, must call the func first. - int GeneLogInfoForExistedData(sqlite3 *db, const std::string &tableName, const std::string &calPrimaryKeyHash); + int GeneLogInfoForExistedData(sqlite3 *db, const std::string &tableName, const std::string &calPrimaryKeyHash, + TableInfo &tableInfo); + int CleanExtendAndCursorForDeleteData(sqlite3 *db, const std::string &tableName); int GetCloudDataForSync(sqlite3_stmt *statement, CloudSyncData &cloudDataResult, uint32_t stepNum, uint32_t &totalSize, const uint32_t &maxSize); int PutVBucketByType(VBucket &vBucket, const Field &field, Type &cloudValue); - int ExecutePutCloudData(const std::string &tableName, const TableSchema &tableSchema, DownloadData &downloadData, - std::map &statisticMap); + int ExecutePutCloudData(const std::string &tableName, const TableSchema &tableSchema, + const TrackerTable &trackerTable, DownloadData &downloadData, std::map &statisticMap); std::string GetInsertSqlForCloudSync(const TableSchema &tableSchema); @@ -197,7 +245,7 @@ private: int GetFillDownloadAssetStatement(const std::string &tableName, const VBucket &vBucket, const std::vector &fields, sqlite3_stmt *&statement); - int InitFillUploadAssetStatement(const std::string &tableName, const CloudSyncBatch &data, + int InitFillUploadAssetStatement(OpType opType, const TableSchema &tableSchema, const CloudSyncBatch &data, const int &index, sqlite3_stmt *&statement); void GetLogInfoByStatement(sqlite3_stmt *statement, LogInfo &logInfo); @@ -205,18 +253,20 @@ private: int GetInfoByStatement(sqlite3_stmt *statement, std::vector &assetFields, const std::map &pkMap, DataInfoWithLog &dataInfoWithLog, VBucket &assetInfo); - int InsertCloudData(VBucket &vBucket, const TableSchema &tableSchema); + int InsertCloudData(VBucket &vBucket, const TableSchema &tableSchema, const TrackerTable &trackerTable, + int64_t dataKey); - int InsertLogRecord(const TableSchema &tableSchema, VBucket &vBucket); + int InsertLogRecord(const TableSchema &tableSchema, const TrackerTable &trackerTable, VBucket &vBucket); int BindOneField(int index, const VBucket &vBucket, const Field &field, sqlite3_stmt *updateStmt); int BindValueToUpsertStatement(const VBucket &vBucket, const std::vector &fields, sqlite3_stmt *upsertStmt); int BindHashKeyAndGidToInsertLogStatement(const VBucket &vBucket, const TableSchema &tableSchema, - sqlite3_stmt *insertLogStmt); + const TrackerTable &trackerTable, sqlite3_stmt *insertLogStmt); - int BindValueToInsertLogStatement(VBucket &vBucket, const TableSchema &tableSchema, sqlite3_stmt *insertLogStmt); + int BindValueToInsertLogStatement(VBucket &vBucket, const TableSchema &tableSchema, + const TrackerTable &trackerTable, sqlite3_stmt *insertLogStmt); std::string GetWhereConditionForDataTable(const std::string &gidStr, const std::set &pkSet, const std::string &tableName, bool queryByPk = true); @@ -230,6 +280,8 @@ private: int GetUpdateLogRecordStatement(const TableSchema &tableSchema, const VBucket &vBucket, OpType opType, std::vector &updateColName, sqlite3_stmt *&updateLogStmt); + int AppendUpdateLogRecordWhereSqlCondition(const TableSchema &tableSchema, const VBucket &vBucket, + std::string &sql); int UpdateLogRecord(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); @@ -239,17 +291,80 @@ private: int GetDeleteStatementForCloudSync(const TableSchema &tableSchema, const std::set &pkSet, const VBucket &vBucket, sqlite3_stmt *&deleteStmt); - int DeleteCloudData(const std::string &tableName, const VBucket &vBucket, const TableSchema &tableSchema); + int DeleteCloudData(const std::string &tableName, const VBucket &vBucket, const TableSchema &tableSchema, + const TrackerTable &trackerTable); int OnlyUpdateLogTable(const VBucket &vBucket, const TableSchema &tableSchema, OpType opType); bool IsGetCloudDataContinue(uint32_t curNum, uint32_t curSize, uint32_t maxSize); - int DeleteMissTableTrigger(const std::string &missTable) const; + int IsTableOnceDropped(const std::string &tableName, int execCode, bool &onceDropped); - int CleanResourceForDroppedTable(const std::string &tableName); + int BindUpdateVersionStatement(const VBucket &vBucket, const Bytes &hashKey, sqlite3_stmt *&stmt); + int DoCleanShareTableDataAndLog(const std::vector &tableNameList); - int IsTableOnceDropped(const std::string &tableName, int execCode, bool &onceDropped); + int GetReferenceGidInner(const std::string &sourceTable, const std::string &targetTable, + const CloudSyncBatch &syncBatch, const std::vector &targetTableReference, + std::map &referenceGid); + + int GetReferenceGidByStmt(sqlite3_stmt *statement, const CloudSyncBatch &syncBatch, + const std::string &targetTable, std::map &referenceGid); + + static std::string GetReferenceGidSql(const std::string &sourceTable, const std::string &targetTable, + const std::vector &sourceFields, const std::vector &targetFields); + + static std::pair, std::vector> SplitReferenceByField( + const std::vector &targetTableReference); + + int BindStmtWithCloudGid(const CloudSyncData &cloudDataResult, bool ignoreEmptyGid, sqlite3_stmt *&stmt); + + std::string GetCloudDeleteSql(const std::string &logTable); + + int RemoveDataAndLog(const std::string &tableName, int64_t dataKey); + + int64_t GetLocalDataKey(size_t index, const DownloadData &downloadData); + + int BindStmtWithCloudGidInner(const std::string &gid, int64_t rowid, + sqlite3_stmt *&stmt, int &fillGidCount); + + int DoCleanAssetId(const std::string &tableName, const RelationalSchemaObject &localSchema); + + int CleanAssetId(const std::string &tableName, const std::vector &fieldInfos, + const std::vector &dataKeys); + + int UpdateAssetIdOnUserTable(const std::string &tableName, const std::string &fieldName, + const std::vector &dataKeys, const VBucket &vBucket, std::vector &assets); + + int GetAssetsAndUpdateAssetsId(const std::string &tableName, const std::string &fieldName, + const std::vector &dataKeys, const VBucket &vBucket); + + int CleanAssetsIdOnUserTable(const std::string &tableName, const std::string &fieldName, const int64_t rowId, + const std::vector assetsValue); + + int InitGetAssetStmt(const std::string &sql, const std::string &gid, const Bytes &hashKey, + sqlite3_stmt *&stmt); + + int GetAssetsByRowId(sqlite3_stmt *&selectStmt, Assets &assets); + + int ExecuteFillDownloadAssetStatement(sqlite3_stmt *&stmt, int beginIndex, const std::string &cloudGid); + + int CleanDownloadChangedAssets(const VBucket &vBucket, const AssetOperationUtils::RecordAssetOpType &assetOpType); + + int GetAndBindFillUploadAssetStatement(const std::string &tableName, const VBucket &assets, + sqlite3_stmt *&statement); + + int OnlyUpdateAssetId(const std::string &tableName, const TableSchema &tableSchema, const VBucket &vBucket, + int64_t dataKey, OpType opType); + + void UpdateLocalAssetId(const VBucket &vBucket, const std::string &fieldName, Asset &asset); + + void UpdateLocalAssetsId(const VBucket &vBucket, const std::string &fieldName, Assets &assets); + + void UpdateLocalAssetsIdInner(const Assets &cloudAssets, Assets &assets); + + int BindAssetToBlobStatement(const Asset &asset, sqlite3_stmt *&stmt); + + int UpdateAssetId(const std::string &tableName, const Field &field, int64_t dataKey, const VBucket &vBucket); std::string baseTblName_; TableInfo table_; // Always operating table, user table when get, device table when put. @@ -260,6 +375,9 @@ private: std::map> bindCloudFieldFuncMap_; std::map &)>> toVectorFuncMap_; + + std::atomic isLogicDelete_; + std::shared_ptr assetLoader_; }; } // namespace DistributedDB #endif diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp index 4c974a69542d96aa2627622ca44b440e320d286a..e4a2dda8baa3722a79d399e7f1f8d1c0c76334b1 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp @@ -15,13 +15,19 @@ #ifdef RELATIONAL_STORE #include "sqlite_single_ver_relational_storage_executor.h" +#include "cloud/asset_operation_utils.h" #include "cloud/cloud_db_constant.h" #include "cloud/cloud_storage_utils.h" #include "db_common.h" +#include "log_table_manager_factory.h" +#include "runtime_context.h" +#include "simple_tracker_log_table_manager.h" +#include "sqlite_relational_utils.h" namespace DistributedDB { static constexpr const int ROW_ID_INDEX = 1; -static constexpr const int TIMESTAMP_INDEX = 2; +static constexpr const char *HASH_KEY = "HASH_KEY"; +using PairStringVector = std::pair, std::vector>; int SQLiteSingleVerRelationalStorageExecutor::GetQueryInfoSql(const std::string &tableName, const VBucket &vBucket, std::set &pkSet, std::vector &assetFields, std::string &querySql) @@ -48,8 +54,7 @@ int SQLiteSingleVerRelationalStorageExecutor::GetQueryInfoSql(const std::string for (const auto &pk : pkSet) { sql += ", b." + pk; } - sql += " from '" + DBCommon::GetLogTableName(tableName) + "' AS a LEFT JOIN '" + tableName + "' AS b "; - sql += " ON (a.data_key = b." + std::string(DBConstant::SQLITE_INNER_ROWID) + ") WHERE "; + sql += CloudStorageUtils::GetLeftJoinLogSql(tableName) + " WHERE "; if (!gid.empty()) { sql += " a.cloud_gid = ? or "; } @@ -102,45 +107,42 @@ int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForDownload(const Ta } CloudStorageUtils::ChangeAssetsOnVBucketToAsset(vBucket, assetsField); + Bytes hashKey; + (void)CloudStorageUtils::GetValueFromVBucket(HASH_KEY, vBucket, hashKey); + VBucket dbAssets; + errCode = GetAssetsByGidOrHashKey(tableSchema, cloudGid, hashKey, dbAssets); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + return errCode; + } + AssetOperationUtils::RecordAssetOpType assetOpType = AssetOperationUtils::CalAssetOperation(vBucket, dbAssets, + AssetOperationUtils::CloudSyncAction::END_DOWNLOAD); + if (isDownloadSuccess) { - CloudStorageUtils::FillAssetFromVBucketFinish(vBucket, CloudStorageUtils::FillAssetAfterDownload, - CloudStorageUtils::FillAssetsAfterDownload); + CloudStorageUtils::FillAssetFromVBucketFinish(assetOpType, vBucket, dbAssets, + CloudStorageUtils::FillAssetAfterDownload, CloudStorageUtils::FillAssetsAfterDownload); } else { - CloudStorageUtils::PrepareToFillAssetFromVBucket(vBucket, CloudStorageUtils::FillAssetAfterDownloadFail); + CloudStorageUtils::FillAssetFromVBucketFinish(assetOpType, vBucket, dbAssets, + CloudStorageUtils::FillAssetAfterDownloadFail, CloudStorageUtils::FillAssetsAfterDownloadFail); } + sqlite3_stmt *stmt = nullptr; - errCode = GetFillDownloadAssetStatement(tableSchema.name, vBucket, assetsField, stmt); + errCode = GetFillDownloadAssetStatement(tableSchema.name, dbAssets, assetsField, stmt); if (errCode != E_OK) { return errCode; } - errCode = SQLiteUtils::BindTextToStatement(stmt, assetsField.size() + 1, cloudGid); - if (errCode != E_OK) { - LOGE("Bind cloud gid to statement failed. %d", errCode); - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode; - } - errCode = SQLiteUtils::StepWithRetry(stmt); - if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { - errCode = E_OK; - } else { - LOGE("Fill cloud asset failed:%d", errCode); - } - int ret = E_OK; - SQLiteUtils::ResetStatement(stmt, true, ret); - return errCode != E_OK ? errCode : ret; + errCode = ExecuteFillDownloadAssetStatement(stmt, assetsField.size() + 1, cloudGid); + int ret = CleanDownloadChangedAssets(vBucket, assetOpType); + return errCode == E_OK ? ret : errCode; } -int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForUpload(const std::string &tableName, +int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForUpload(OpType opType, const TableSchema &tableSchema, const CloudSyncBatch &data) { - if (data.rowid.empty() || data.timestamp.empty()) { - return -E_INVALID_ARGS; - } - if (data.assets.size() != data.rowid.size() || data.assets.size() != data.timestamp.size()) { - return -E_INVALID_ARGS; + int errCode = E_OK; + if (CloudStorageUtils::ChkFillCloudAssetParam(data, errCode)) { + return errCode; } - int errCode = SetLogTriggerStatus(false); + errCode = SetLogTriggerStatus(false); if (errCode != E_OK) { LOGE("Fail to set log trigger off, %d", errCode); return errCode; @@ -150,8 +152,12 @@ int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForUpload(const std: if (data.assets.at(i).empty()) { continue; } - errCode = InitFillUploadAssetStatement(tableName, data, i, stmt); + errCode = InitFillUploadAssetStatement(opType, tableSchema, data, i, stmt); if (errCode != E_OK) { + if (errCode == -E_NOT_FOUND) { + errCode = E_OK; + continue; + } break; } errCode = SQLiteUtils::StepWithRetry(stmt, false); @@ -176,40 +182,118 @@ int SQLiteSingleVerRelationalStorageExecutor::FillCloudAssetForUpload(const std: return errCode != E_OK ? errCode : ret; } -int SQLiteSingleVerRelationalStorageExecutor::InitFillUploadAssetStatement(const std::string &tableName, - const CloudSyncBatch &data, const int &index, sqlite3_stmt *&statement) +int SQLiteSingleVerRelationalStorageExecutor::FillCloudVersionForUpload(const CloudSyncData &data) { - VBucket vBucket = data.assets.at(index); - CloudStorageUtils::FillAssetFromVBucketFinish(vBucket, CloudStorageUtils::FillAssetForUpload, - CloudStorageUtils::FillAssetsForUpload); - std::string sql = "UPDATE " + tableName + " SET "; - for (const auto &item: vBucket) { - sql += item.first + " = ?,"; + if (!data.isShared) { + return E_OK; } - sql.pop_back(); - sql += " WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " = ? and (select 1 from " + - DBCommon::GetLogTableName(tableName) + " WHERE timestamp = ?);"; - int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); + std::vector opBatch = { + std::move(data.insData), std::move(data.updData), std::move(data.delData) + }; + for (const auto &dataBatch: opBatch) { + if (dataBatch.extend.empty()) { + continue; + } + if (dataBatch.hashKey.empty() || dataBatch.extend.size() != dataBatch.hashKey.size()) { + LOGE("invalid sync data for filling version"); + return -E_INVALID_ARGS; + } + } + std::string sql = "UPDATE '" + DBCommon::GetLogTableName(data.tableName) + + "' SET version = ? WHERE hash_key = ? "; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); if (errCode != E_OK) { return errCode; } - int batchIndex = 1; - for (const auto &item: vBucket) { - Field field = { - .colName = item.first, .type = static_cast(item.second.index()) - }; - errCode = bindCloudFieldFuncMap_[TYPE_INDEX](batchIndex++, vBucket, field, statement); - if (errCode != E_OK) { - return errCode; + int ret = E_OK; + for (const auto &dataBatch: opBatch) { + for (size_t i = 0; i < dataBatch.extend.size(); ++i) { + errCode = BindUpdateVersionStatement(dataBatch.extend[i], dataBatch.hashKey[i], stmt); + if (errCode != E_OK) { + LOGE("bind update version stmt failed."); + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode; + } } } - int64_t rowid = data.rowid[index]; - errCode = SQLiteUtils::BindInt64ToStatement(statement, vBucket.size() + ROW_ID_INDEX, rowid); + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode == E_OK ? ret : E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::BindUpdateVersionStatement(const VBucket &vBucket, const Bytes &hashKey, + sqlite3_stmt *&stmt) +{ + int errCode = E_OK; + if (vBucket.find(CloudDbConstant::VERSION_FIELD) == vBucket.end()) { + LOGE("can not find version from vBucket."); + return -E_CLOUD_ERROR; + } + std::string version; + if (CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::VERSION_FIELD, + vBucket, version) != E_OK) { + LOGE("get version from vBucket failed."); + return -E_CLOUD_ERROR; + } + if (version.empty()) { + LOGE("version is empty when update version"); + return -E_CLOUD_ERROR; + } + if (hashKey.empty()) { + LOGE("hash key is empty when update version"); + return -E_CLOUD_ERROR; + } + errCode = SQLiteUtils::BindTextToStatement(stmt, 1, version); + if (errCode != E_OK) { + return errCode; + } + errCode = SQLiteUtils::BindBlobToStatement(stmt, 2, hashKey); // 2 means the second bind args + if (errCode != E_OK) { + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, false, errCode); + } else { + LOGE("step version stmt failed:%d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::InitFillUploadAssetStatement(OpType opType, + const TableSchema &tableSchema, const CloudSyncBatch &data, const int &index, sqlite3_stmt *&statement) +{ + VBucket vBucket = data.assets.at(index); + VBucket dbAssets; + std::string cloudGid; + (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, vBucket, cloudGid); + int errCode = GetAssetsByGidOrHashKey(tableSchema, cloudGid, data.hashKey.at(index), dbAssets); + if (errCode != E_OK) { + return errCode; + } + AssetOperationUtils::CloudSyncAction action = opType == OpType::SET_UPLOADING ? + AssetOperationUtils::CloudSyncAction::START_UPLOAD : AssetOperationUtils::CloudSyncAction::END_UPLOAD; + AssetOperationUtils::RecordAssetOpType assetOpType = AssetOperationUtils::CalAssetOperation(vBucket, dbAssets, + action); + if (action == AssetOperationUtils::CloudSyncAction::START_UPLOAD) { + CloudStorageUtils::FillAssetFromVBucketFinish(assetOpType, vBucket, dbAssets, + CloudStorageUtils::FillAssetBeforeUpload, CloudStorageUtils::FillAssetsBeforeUpload); + } else { + if (data.extend.at(index).find(CloudDbConstant::ERROR_FIELD) != data.extend.at(index).end()) { + CloudStorageUtils::FillAssetFromVBucketFinish(assetOpType, vBucket, dbAssets, + CloudStorageUtils::FillAssetForUploadFailed, CloudStorageUtils::FillAssetsForUploadFailed); + } + CloudStorageUtils::FillAssetFromVBucketFinish(assetOpType, vBucket, dbAssets, + CloudStorageUtils::FillAssetForUpload, CloudStorageUtils::FillAssetsForUpload); + } + + errCode = GetAndBindFillUploadAssetStatement(tableSchema.name, dbAssets, statement); if (errCode != E_OK) { return errCode; } - int64_t timeStamp = data.timestamp[index]; - return SQLiteUtils::BindInt64ToStatement(statement, vBucket.size() + TIMESTAMP_INDEX, timeStamp); + int64_t rowid = data.rowid[index]; + return SQLiteUtils::BindInt64ToStatement(statement, dbAssets.size() + ROW_ID_INDEX, rowid); } bool SQLiteSingleVerRelationalStorageExecutor::IsGetCloudDataContinue(uint32_t curNum, uint32_t curSize, @@ -229,5 +313,1220 @@ bool SQLiteSingleVerRelationalStorageExecutor::IsGetCloudDataContinue(uint32_t c #endif return false; } + +int SQLiteSingleVerRelationalStorageExecutor::AnalysisTrackerTable(const TrackerTable &trackerTable, + TableInfo &tableInfo) +{ + int errCode = SQLiteUtils::AnalysisSchema(dbHandle_, trackerTable.GetTableName(), tableInfo, true); + if (errCode != E_OK) { + LOGW("analysis table schema failed. %d", errCode); + return errCode; + } + tableInfo.SetTrackerTable(trackerTable); + errCode = tableInfo.CheckTrackerTable(); + if (errCode != E_OK) { + LOGE("check tracker table schema failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CreateTrackerTable(const TrackerTable &trackerTable, bool isUpgrade) +{ + TableInfo table; + table.SetTableSyncType(TableSyncType::CLOUD_COOPERATION); + int errCode = AnalysisTrackerTable(trackerTable, table); + if (errCode != E_OK) { + return errCode; + } + auto tableManager = std::make_unique(); + if (!trackerTable.GetTrackerColNames().empty()) { + // create log table + errCode = tableManager->CreateRelationalLogTable(dbHandle_, table); + if (errCode != E_OK) { + return errCode; + } + std::string calPrimaryKeyHash = tableManager->CalcPrimaryKeyHash("a.", table, ""); + if (isUpgrade) { + errCode = CleanExtendAndCursorForDeleteData(dbHandle_, table.GetTableName()); + if (errCode != E_OK) { + LOGE("clean tracker log info for deleted data failed. %d", errCode); + return errCode; + } + } + errCode = GeneLogInfoForExistedData(dbHandle_, trackerTable.GetTableName(), calPrimaryKeyHash, table); + if (errCode != E_OK) { + LOGE("general tracker log info for existed data failed. %d", errCode); + return errCode; + } + } + errCode = tableManager->AddRelationalLogTableTrigger(dbHandle_, table, ""); + if (errCode != E_OK) { + return errCode; + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetOrInitTrackerSchemaFromMeta(RelationalSchemaObject &schema) +{ + if (!schema.ToSchemaString().empty()) { + return E_OK; + } + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + Value schemaVal; + int errCode = GetKvData(schemaKey, schemaVal); // save schema to meta_data + if (errCode != E_OK) { + return errCode; + } + std::string schemaStr; + DBCommon::VectorToString(schemaVal, schemaStr); + errCode = schema.ParseFromTrackerSchemaString(schemaStr); + if (errCode != E_OK) { + LOGE("Parse from tracker schema string err"); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::ExecuteSql(const SqlCondition &condition, std::vector &records) +{ + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, condition.sql, statement); + if (errCode != E_OK) { + LOGE("Execute sql failed when prepare stmt"); + return errCode; + } + size_t bindCount = static_cast(sqlite3_bind_parameter_count(statement)); + if (bindCount > condition.bindArgs.size() || bindCount < condition.bindArgs.size()) { + LOGE("sql bind args mismatch"); + SQLiteUtils::ResetStatement(statement, true, errCode); + return -E_INVALID_ARGS; + } + for (size_t i = 0; i < condition.bindArgs.size(); i++) { + Type type = condition.bindArgs[i]; + errCode = SQLiteRelationalUtils::BindStatementByType(statement, i + 1, type); + if (errCode != E_OK) { + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode; + } + } + while ((errCode = SQLiteRelationalUtils::StepNext(isMemDb_, statement)) == E_OK) { + VBucket bucket; + errCode = SQLiteRelationalUtils::GetSelectVBucket(statement, bucket); + if (errCode != E_OK) { + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode; + } + records.push_back(std::move(bucket)); + } + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode == -E_FINISHED ? (ret == E_OK ? E_OK : ret) : errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetClearWaterMarkTables( + const std::vector &tableReferenceProperty, const RelationalSchemaObject &schema, + std::set &clearWaterMarkTables) +{ + std::set changeTables = schema.CompareReferenceProperty(tableReferenceProperty); + for (const auto &table : changeTables) { + std::string logTableName = DBCommon::GetLogTableName(table); + bool isExists = false; + int errCode = SQLiteUtils::CheckTableExists(dbHandle_, logTableName, isExists); + if (errCode != E_OK) { + LOGE("[GetClearWaterMarkTables] check table exists failed, errCode = %d", errCode); + return errCode; + } + if (!isExists) { // table maybe dropped after set reference + LOGI("[GetClearWaterMarkTables] log table not exists, skip this table."); + continue; + } + + bool isEmpty = true; + errCode = SQLiteUtils::CheckTableEmpty(dbHandle_, logTableName, isEmpty); + if (errCode != E_OK) { + LOGE("[GetClearWaterMarkTables] check table empty failed, errCode = %d", errCode); + clearWaterMarkTables.clear(); + return errCode; + } + if (!isEmpty) { + clearWaterMarkTables.insert(table); + } + } + LOGI("[GetClearWaterMarkTables] clearWaterMarkTables size = %zu", clearWaterMarkTables.size()); + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::UpgradedLogForExistedData(TableInfo &tableInfo) +{ + if (tableInfo.GetTrackerTable().IsEmpty() || tableInfo.GetTableSyncType() == TableSyncType::DEVICE_COOPERATION) { + return E_OK; + } + int64_t timeOffset = 0; + std::string timeOffsetStr = std::to_string(timeOffset); + std::string logTable = DBConstant::RELATIONAL_PREFIX + tableInfo.GetTableName() + "_log"; + std::string sql = "UPDATE " + logTable + " SET extend_field = " + + tableInfo.GetTrackerTable().GetUpgradedExtendValSql(); + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + LOGE("Upgrade log for extend field failed."); + return errCode; + } + sql = "UPDATE " + logTable + " SET cursor = (SELECT (SELECT CASE WHEN MAX(cursor) IS NULL THEN 0 ELSE" + " MAX(cursor) END from " + logTable + ") + " + std::string(DBConstant::SQLITE_INNER_ROWID) + + " FROM " + tableInfo.GetTableName() + " WHERE " + tableInfo.GetTableName() + "." + + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + logTable + ".data_key);"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + LOGE("Upgrade log for cursor failed."); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CreateTempSyncTrigger(const TrackerTable &trackerTable) +{ + int errCode = E_OK; + std::vector dropSql = trackerTable.GetDropTempTriggerSql(); + for (const auto &sql: dropSql) { + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, sql); + if (errCode != E_OK) { + LOGE("[RDBExecutor] execute drop sql failed %d", errCode); + return errCode; + } + } + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempInsertTriggerSql()); + if (errCode != E_OK) { + LOGE("[RDBExecutor] create temp insert trigger failed %d", errCode); + return errCode; + } + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempUpdateTriggerSql()); + if (errCode != E_OK) { + LOGE("[RDBExecutor] create temp update trigger failed %d", errCode); + return errCode; + } + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, trackerTable.GetTempDeleteTriggerSql()); + if (errCode != E_OK) { + LOGE("[RDBExecutor] create temp delete trigger failed %d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetAndResetServerObserverData(const std::string &tableName, + ChangeProperties &changeProperties) +{ + std::string fileName; + if (!SQLiteRelationalUtils::GetDbFileName(dbHandle_, fileName)) { + LOGE("get db file name failed."); + return -E_INVALID_DB; + } + SQLiteUtils::GetAndResetServerObserverData(fileName, tableName, changeProperties); + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::ClearAllTempSyncTrigger() +{ + sqlite3_stmt *stmt = nullptr; + static const std::string sql = "SELECT name FROM sqlite_temp_master WHERE type = 'trigger';"; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK) { + LOGE("get clear all temp trigger stmt failed. %d", errCode); + return errCode; + } + int ret = E_OK; + while ((errCode = SQLiteRelationalUtils::StepNext(isMemDb_, stmt)) == E_OK) { + std::string str; + (void)SQLiteUtils::GetColumnTextValue(stmt, 0, str); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode; + } + std::string dropSql = "DROP TRIGGER IF EXISTS '" + str + "';"; + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, dropSql); + if (errCode != E_OK) { + LOGE("drop temp trigger failed. %d", errCode); + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode; + } + } + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode == -E_FINISHED ? (ret == E_OK ? E_OK : ret) : errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CleanTrackerData(const std::string &tableName, int64_t cursor) +{ + std::string sql = "UPDATE " + DBConstant::RELATIONAL_PREFIX + tableName + "_log"; + sql += " SET extend_field = NULL where data_key = -1 and cursor <= ?;"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); + if (errCode != E_OK) { + LOGE("get clean tracker data stmt failed. %d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, cursor); + int ret = E_OK; + if (errCode != E_OK) { + LOGE("bind clean tracker data stmt failed. %d", errCode); + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(statement); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("clean tracker step failed:%d", errCode); + } + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode == E_OK ? ret : errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CreateSharedTable(const DataBaseSchema &schema) +{ + std::map cloudFieldTypeMap; + cloudFieldTypeMap[TYPE_INDEX] = "NULL"; + cloudFieldTypeMap[TYPE_INDEX] = "INT"; + cloudFieldTypeMap[TYPE_INDEX] = "REAL"; + cloudFieldTypeMap[TYPE_INDEX] = "TEXT"; + cloudFieldTypeMap[TYPE_INDEX] = "BOOLEAN"; + cloudFieldTypeMap[TYPE_INDEX] = "BLOB"; + cloudFieldTypeMap[TYPE_INDEX] = "ASSET"; + cloudFieldTypeMap[TYPE_INDEX] = "ASSETS"; + + for (const auto &table : schema.tables) { + std::string createTableSql = "CREATE TABLE IF NOT EXISTS " + table.sharedTableName + "("; + std::string primaryKey = ", PRIMARY KEY ("; + createTableSql += CloudDbConstant::CLOUD_OWNER; + createTableSql += " TEXT, "; + createTableSql += CloudDbConstant::CLOUD_PRIVILEGE; + createTableSql += " TEXT"; + primaryKey += CloudDbConstant::CLOUD_OWNER; + bool hasPrimaryKey = false; + for (const auto &field : table.fields) { + createTableSql += ", " + field.colName + " "; + createTableSql += cloudFieldTypeMap[field.type]; + createTableSql += field.nullable ? "" : " NOT NULL"; + if (field.primary) { + primaryKey += ", " + field.colName; + hasPrimaryKey = true; + } + } + if (hasPrimaryKey) { + createTableSql += primaryKey + ")"; + } + createTableSql += ");"; + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, createTableSql); + if (errCode != E_OK) { + LOGE("Create shared table failed, %d", errCode); + return errCode; + } + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::DeleteTable(const std::vector &tableNames) +{ + for (const auto &tableName : tableNames) { + std::string deleteTableSql = "DROP TABLE IF EXISTS " + tableName + ";"; + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, deleteTableSql); + if (errCode != E_OK) { + LOGE("Delete table failed, %d", errCode); + return errCode; + } + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::UpdateSharedTable( + const std::map> &updateTableNames) +{ + int errCode = E_OK; + std::map fieldTypeMap; + fieldTypeMap[TYPE_INDEX] = "NULL"; + fieldTypeMap[TYPE_INDEX] = "INT"; + fieldTypeMap[TYPE_INDEX] = "REAL"; + fieldTypeMap[TYPE_INDEX] = "TEXT"; + fieldTypeMap[TYPE_INDEX] = "BOOLEAN"; + fieldTypeMap[TYPE_INDEX] = "BLOB"; + fieldTypeMap[TYPE_INDEX] = "ASSET"; + fieldTypeMap[TYPE_INDEX] = "ASSETS"; + for (const auto &table : updateTableNames) { + if (table.second.empty()) { + continue; + } + std::string addColumnSql = ""; + for (const auto &field : table.second) { + addColumnSql += "ALTER TABLE " + table.first + " ADD "; + addColumnSql += field.colName + " "; + addColumnSql += fieldTypeMap[field.type]; + addColumnSql += field.primary ? " PRIMARY KEY" : ""; + addColumnSql += field.nullable ? ";" : " NOT NULL;"; + } + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, addColumnSql); + if (errCode != E_OK) { + LOGE("Shared table add column failed, %d", errCode); + return errCode; + } + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::AlterTableName(const std::map &tableNames) +{ + for (const auto &tableName : tableNames) { + std::string alterTableSql = "ALTER TABLE " + tableName.first + " RENAME TO " + tableName.second + ";"; + int errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, alterTableSql); + if (errCode != E_OK) { + LOGE("Alter table name failed, %d", errCode); + return errCode; + } + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::AppendUpdateLogRecordWhereSqlCondition(const TableSchema &tableSchema, + const VBucket &vBucket, std::string &sql) +{ + std::string gidStr; + int errCode = CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, vBucket, gidStr); + if (errCode != E_OK) { + LOGE("Get gid from cloud data fail when construct update log sql, errCode = %d", errCode); + return errCode; + } + + sql += " WHERE "; + if (!gidStr.empty()) { + sql += "cloud_gid = '" + gidStr + "'"; + } + std::map pkMap = CloudStorageUtils::GetCloudPrimaryKeyFieldMap(tableSchema); + if (!pkMap.empty()) { + if (!gidStr.empty()) { + sql += " OR "; + } + sql += "(hash_key = ?);"; + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::DoCleanShareTableDataAndLog(const std::vector &tableNameList) +{ + int ret = E_OK; + int errCode = E_OK; + for (const auto &tableName: tableNameList) { + std::string delDataSql = "DELETE FROM '" + tableName + "';"; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(dbHandle_, delDataSql, statement); + if (errCode != E_OK) { + LOGE("get clean shared data stmt failed. %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(statement); + SQLiteUtils::ResetStatement(statement, true, ret); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("clean shared data failed:%d", errCode); + break; + } + statement = nullptr; + std::string delLogSql = "DELETE FROM '" + DBConstant::RELATIONAL_PREFIX + tableName + "_log';"; + errCode = SQLiteUtils::GetStatement(dbHandle_, delLogSql, statement); + if (errCode != E_OK) { + LOGE("get clean shared log stmt failed. %d", errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(statement); + SQLiteUtils::ResetStatement(statement, true, ret); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("clean shared log failed:%d", errCode); + break; + } + } + return errCode == E_OK ? ret : errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetReferenceGid(const std::string &tableName, + const CloudSyncBatch &syncBatch, const std::map> &tableReference, + std::map &referenceGid) +{ + int errCode = E_OK; + for (const auto &[targetTable, targetReference] : tableReference) { + errCode = GetReferenceGidInner(tableName, targetTable, syncBatch, targetReference, referenceGid); + if (errCode != E_OK) { + LOGE("[RDBExecutor] get reference gid inner failed %d", errCode); + return errCode; + } + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetReferenceGidInner(const std::string &sourceTable, + const std::string &targetTable, const CloudSyncBatch &syncBatch, + const std::vector &targetTableReference, std::map &referenceGid) +{ + auto [sourceFields, targetFields] = SplitReferenceByField(targetTableReference); + if (sourceFields.empty()) { + LOGD("[RDBExecutor] source field is empty"); + return E_OK; + } + if (sourceFields.size() != targetFields.size()) { + LOGE("[RDBExecutor] reference field size not equal."); + return -E_INTERNAL_ERROR; + } + std::string sql = GetReferenceGidSql(sourceTable, targetTable, sourceFields, targetFields); + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); + if (errCode != E_OK) { + LOGE("[RDBExecutor] get ref gid data stmt failed. %d", errCode); + return errCode; + } + errCode = GetReferenceGidByStmt(statement, syncBatch, targetTable, referenceGid); + int ret = E_OK; + SQLiteUtils::ResetStatement(statement, true, ret); + return errCode == E_OK ? ret : errCode; +} + +std::string SQLiteSingleVerRelationalStorageExecutor::GetReferenceGidSql(const std::string &sourceTable, + const std::string &targetTable, const std::vector &sourceFields, + const std::vector &targetFields) +{ + // sql like this: + // SELECT naturalbase_rdb_aux_parent_log.cloud_gid FROM naturalbase_rdb_aux_parent_log, + // (SELECT parent._rowid_ AS rowid_b FROM parent, + // (SELECT child._rowid_, name FROM child, naturalbase_rdb_aux_child_log + // WHERE child._rowid_ = ? AND naturalbase_rdb_aux_child_log.timestamp = ? ) source_a + // WHERE parent.name = source_a.name ) temp_table + // WHERE naturalbase_rdb_aux_parent_log.data_key = temp_table.rowid_b + std::string logTargetTable = DBCommon::GetLogTableName(targetTable); + std::string logSourceTable = DBCommon::GetLogTableName(sourceTable); + std::string sql; + sql += "SELECT " + logTargetTable + ".cloud_gid" + " FROM " + logTargetTable + ", "; + sql += "("; + sql += "SELECT " + targetTable + "._rowid_ AS rowid_b FROM " + targetTable + + ", "; + sql += "(SELECT " + sourceTable + "._rowid_,"; + std::set sourceFieldSet; + for (const auto &item : sourceFields) { + sourceFieldSet.insert(item); + } + for (const auto &sourceField : sourceFieldSet) { + sql += sourceField + ","; + } + sql.pop_back(); + sql += " FROM " + sourceTable + ", " + logSourceTable; + sql +=" WHERE " + sourceTable + "._rowid_ = ? AND " + logSourceTable + ".timestamp = ? "; + sql += " AND " + logSourceTable + ".flag&0x08=0x00) source_a"; + sql += " WHERE "; + for (size_t i = 0u; i < sourceFields.size(); ++i) { + sql += targetTable + "." + targetFields[i] + " = source_a." + sourceFields[i] + " "; + } + sql += ") temp_table "; + sql += "WHERE " + logTargetTable + ".data_key = temp_table.rowid_b"; + sql += " AND " + logTargetTable + ".flag&0x08=0x00"; + return sql; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetReferenceGidByStmt(sqlite3_stmt *statement, + const CloudSyncBatch &syncBatch, const std::string &targetTable, std::map &referenceGid) +{ + int errCode = E_OK; + if (syncBatch.rowid.size() != syncBatch.timestamp.size()) { + LOGE("[RDBExecutor] rowid size[%zu] not equal to timestamp size[%zu]", syncBatch.rowid.size(), + syncBatch.timestamp.size()); + return -E_INVALID_ARGS; + } + int matchCount = 0; + for (size_t i = 0u; i < syncBatch.rowid.size(); i++) { + errCode = SQLiteUtils::BindInt64ToStatement(statement, 1, syncBatch.rowid[i]); // 1 is rowid index + if (errCode != E_OK) { + LOGE("[RDBExecutor] bind rowid to stmt failed. %d", errCode); + break; + } + errCode = SQLiteUtils::BindInt64ToStatement(statement, 2, syncBatch.timestamp[i]); // 2 is timestamp index + if (errCode != E_OK) { + LOGE("[RDBExecutor] bind timestamp to stmt failed. %d", errCode); + break; + } + while ((errCode = SQLiteRelationalUtils::StepNext(isMemDb_, statement)) == E_OK) { + std::string gid; + (void)SQLiteUtils::GetColumnTextValue(statement, 0, gid); + if (gid.empty()) { + LOGE("[RDBExecutor] reference data don't contain gid."); + errCode = -E_CLOUD_ERROR; + break; + } + referenceGid[syncBatch.rowid[i]][targetTable] = gid; + matchCount++; + } + if (errCode == -E_FINISHED) { + errCode = E_OK; + } + if (errCode != E_OK) { + LOGE("[RDBExecutor] step stmt failed. %d", errCode); + break; + } + SQLiteUtils::ResetStatement(statement, false, errCode); + if (errCode != E_OK) { + LOGE("[RDBExecutor] reset stmt failed. %d", errCode); + break; + } + } + if (matchCount != 0) { + LOGD("[RDBExecutor] get reference gid match %d", matchCount); + } + return errCode; +} + +PairStringVector SQLiteSingleVerRelationalStorageExecutor::SplitReferenceByField( + const std::vector &targetTableReference) +{ + PairStringVector sourceTargetFiled; + for (const auto &reference : targetTableReference) { + for (const auto &column : reference.columns) { + sourceTargetFiled.first.push_back(column.first); + sourceTargetFiled.second.push_back(column.second); + } + } + return sourceTargetFiled; +} + +int SQLiteSingleVerRelationalStorageExecutor::BindStmtWithCloudGid(const CloudSyncData &cloudDataResult, + bool ignoreEmptyGid, sqlite3_stmt *&stmt) +{ + int fillGidCount = 0; + int errCode = E_OK; + for (size_t i = 0; i < cloudDataResult.insData.extend.size(); ++i) { + auto gidEntry = cloudDataResult.insData.extend[i].find(CloudDbConstant::GID_FIELD); + if (gidEntry == cloudDataResult.insData.extend[i].end()) { + if (ignoreEmptyGid) { + continue; + } + errCode = -E_INVALID_ARGS; + LOGE("[RDBExecutor] Extend not contain gid"); + break; + } + bool containError = cloudDataResult.insData.extend[i].find(CloudDbConstant::ERROR_FIELD) != + cloudDataResult.insData.extend[i].end(); + if (!ignoreEmptyGid && containError) { + LOGE("[RDBExecutor] Fill gid back but got error"); + errCode = -E_CLOUD_ERROR; + break; + } + if (ignoreEmptyGid && containError) { + continue; + } + std::string val; + if (CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, + cloudDataResult.insData.extend[i], val) != E_OK) { + errCode = -E_INVALID_DATA; + LOGE("[RDBExecutor] Can't get string gid from extend"); + break; + } + if (val.empty()) { + errCode = -E_CLOUD_ERROR; + LOGE("[RDBExecutor] Get empty gid from extend"); + break; + } + errCode = BindStmtWithCloudGidInner(val, cloudDataResult.insData.rowid[i], stmt, fillGidCount); + if (errCode != E_OK) { + LOGE("[RDBExecutor] Bind stmt error %d", errCode); + break; + } + } + LOGD("[RDBExecutor] Fill gid count %d", fillGidCount); + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CleanExtendAndCursorForDeleteData(sqlite3 *db, + const std::string &tableName) +{ + std::string logTable = DBConstant::RELATIONAL_PREFIX + tableName + "_log"; + std::string sql = "UPDATE " + logTable + " SET extend_field = NULL, cursor = NULL where flag&0x01=0x01;"; + int errCode = SQLiteUtils::ExecuteRawSQL(db, sql); + if (errCode != E_OK) { + LOGE("update extend field and cursor failed. %d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CheckIfExistUserTable(const std::string &tableName) +{ + std::string sql = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = ?"; + sqlite3_stmt *statement = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); + if (errCode != E_OK) { + LOGE("[RDBExecutor] Prepare the sql statement error:%d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName); + if (errCode != E_OK) { + LOGE("[RDBExecutor] Bind table name failed:%d", errCode); + SQLiteUtils::ResetStatement(statement, true, errCode); + return errCode; + } + if (SQLiteUtils::StepWithRetry(statement) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + LOGE("[RDBExecutor] local exists user table which shared table name is same as"); + SQLiteUtils::ResetStatement(statement, true, errCode); + return -E_INVALID_ARGS; + } + SQLiteUtils::ResetStatement(statement, true, errCode); + return E_OK; +} + +std::string SQLiteSingleVerRelationalStorageExecutor::GetCloudDeleteSql(const std::string &logTable) +{ + std::string sql; + if (isLogicDelete_) { + // 1001 which is logicDelete|cloudForcePush|local|delete + sql += "flag = 9, cursor = (SELECT case when (MAX(cursor) is null) then 1 else MAX(cursor) + 1 END " \ + "FROM " + logTable + ")"; + } else { + sql += "data_key = -1, flag = 1"; + } + sql += ", cloud_gid = '', version = '', "; + return sql; +} + +int SQLiteSingleVerRelationalStorageExecutor::RemoveDataAndLog(const std::string &tableName, int64_t dataKey) +{ + int errCode = E_OK; + std::string removeDataSql = "DELETE FROM " + tableName + " WHERE " + DBConstant::SQLITE_INNER_ROWID + " = " + + std::to_string(dataKey); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, removeDataSql); + if (errCode != E_OK) { + LOGE("[RDBExecutor] remove data failed %d", errCode); + return errCode; + } + std::string removeLogSql = "DELETE FROM " + DBCommon::GetLogTableName(tableName) + " WHERE data_key = " + + std::to_string(dataKey); + errCode = SQLiteUtils::ExecuteRawSQL(dbHandle_, removeLogSql); + if (errCode != E_OK) { + LOGE("[RDBExecutor] remove log failed %d", errCode); + } + return errCode; +} + +int64_t SQLiteSingleVerRelationalStorageExecutor::GetLocalDataKey(size_t index, + const DownloadData &downloadData) +{ + if (index >= downloadData.existDataKey.size()) { + LOGW("[RDBExecutor] index out of range when get local data key"); // should not happen + return -1; // -1 means not exist + } + return downloadData.existDataKey[index]; +} + +int SQLiteSingleVerRelationalStorageExecutor::BindStmtWithCloudGidInner(const std::string &gid, int64_t rowid, + sqlite3_stmt *&stmt, int &fillGidCount) +{ + int errCode = SQLiteUtils::BindTextToStatement(stmt, 1, gid); // 1 means the gid index + if (errCode != E_OK) { + return errCode; + } + errCode = SQLiteUtils::BindInt64ToStatement(stmt, 2, rowid); // 2 means rowid + if (errCode != E_OK) { + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt, false); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + fillGidCount++; + SQLiteUtils::ResetStatement(stmt, false, errCode); + } else { + LOGE("[RDBExecutor] Update cloud log failed:%d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::RenewTableTrigger(DistributedTableMode mode, + const TableInfo &tableInfo, TableSyncType syncType) +{ + auto tableManager = LogTableManagerFactory::GetTableManager(mode, syncType); + return tableManager->AddRelationalLogTableTrigger(dbHandle_, tableInfo, ""); +} + +int SQLiteSingleVerRelationalStorageExecutor::DoCleanAssetId(const std::string &tableName, + const RelationalSchemaObject &localSchema) +{ + std::vector dataKeys; + std::string logTableName = DBCommon::GetLogTableName(tableName); + int errCode = GetCleanCloudDataKeys(logTableName, dataKeys, false); + if (errCode != E_OK) { + LOGE("[Storage Executor] Failed to get clean cloud data keys, %d.", errCode); + return errCode; + } + std::vector fieldInfos = localSchema.GetTable(tableName).GetFieldInfos(); + errCode = CleanAssetId(tableName, fieldInfos, dataKeys); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to clean asset id when clean cloud data, %d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::CleanAssetId(const std::string &tableName, + const std::vector &fieldInfos, const std::vector &dataKeys) +{ + int errCode = E_OK; + for (const auto &fieldInfo : fieldInfos) { + if (fieldInfo.IsAssetType()) { + Assets assets; + errCode = GetAssetOnTable(tableName, fieldInfo.GetFieldName(), dataKeys, assets); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to get cloud asset on table, %d.", errCode); + return errCode; + } + errCode = UpdateAssetIdOnUserTable(tableName, fieldInfo.GetFieldName(), dataKeys, {}, assets); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to save clean asset id on table, %d.", errCode); + return errCode; + } + } else if (fieldInfo.IsAssetsType()) { + errCode = GetAssetsAndUpdateAssetsId(tableName, fieldInfo.GetFieldName(), dataKeys, {}); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to get cloud assets on table, %d.", errCode); + return errCode; + } + } + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::UpdateAssetIdOnUserTable(const std::string &tableName, + const std::string &fieldName, const std::vector &dataKeys, const VBucket &vBucket, + std::vector &assets) +{ + if (assets.empty()) { + return E_OK; + } + int errCode = E_OK; + int ret = E_OK; + sqlite3_stmt *stmt = nullptr; + size_t index = 0; + for (const auto &rowId : dataKeys) { + if (rowId == -1) { // -1 means data is deleted + continue; + } + if (assets[index].name.empty()) { + index++; + continue; + } + std::string cleanAssetIdSql = "UPDATE " + tableName + " SET " + fieldName + " = ? WHERE " + + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + std::to_string(rowId) + ";"; + errCode = SQLiteUtils::GetStatement(dbHandle_, cleanAssetIdSql, stmt); + if (errCode != E_OK) { + LOGE("Get statement failed, %d", errCode); + return errCode; + } + if (vBucket.empty()) { + assets[index].assetId = ""; + assets[index].status &= ~AssetStatus::UPLOADING; + } else { + UpdateLocalAssetId(vBucket, fieldName, assets[index]); + } + errCode = BindAssetToBlobStatement(assets[index], stmt); + index++; + if (errCode != E_OK) { + LOGE("Bind asset to blob statement failed, %d", errCode); + goto END; + } + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("Step statement failed, %d", errCode); + goto END; + } + SQLiteUtils::ResetStatement(stmt, true, ret); + } + return errCode != E_OK ? errCode : ret; +END: + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetAssetsAndUpdateAssetsId(const std::string &tableName, + const std::string &fieldName, const std::vector &dataKeys, const VBucket &vBucket) +{ + int errCode = E_OK; + int ret = E_OK; + sqlite3_stmt *selectStmt = nullptr; + for (const auto &rowId : dataKeys) { + std::string queryAssetsSql = "SELECT " + fieldName + " FROM '" + tableName + + "' WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + std::to_string(rowId) + ";"; + errCode = SQLiteUtils::GetStatement(dbHandle_, queryAssetsSql, selectStmt); + if (errCode != E_OK) { + LOGE("Get select assets statement failed, %d", errCode); + goto END; + } + Assets assets; + errCode = GetAssetsByRowId(selectStmt, assets); + if (errCode != E_OK) { + LOGE("Get assets by rowId failed, %d", errCode); + goto END; + } + SQLiteUtils::ResetStatement(selectStmt, true, ret); + if (assets.empty()) { + continue; + } + if (vBucket.empty()) { + for (auto &asset : assets) { + asset.assetId = ""; + asset.status &= ~AssetStatus::UPLOADING; + } + } else { + UpdateLocalAssetsId(vBucket, fieldName, assets); + } + std::vector assetsValue; + errCode = RuntimeContext::GetInstance()->AssetsToBlob(assets, assetsValue); + if (errCode != E_OK) { + LOGE("[CleanAssetsIdOnUserTable] failed to transfer assets to blob, %d", errCode); + return errCode; + } + errCode = CleanAssetsIdOnUserTable(tableName, fieldName, rowId, assetsValue); + if (errCode != E_OK) { + LOGE("[CleanAssetsIdOnUserTable] clean assets id on user table failed, %d", errCode); + return errCode; + } + } + return errCode != E_OK ? errCode : ret; +END: + SQLiteUtils::ResetStatement(selectStmt, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int SQLiteSingleVerRelationalStorageExecutor::CleanAssetsIdOnUserTable(const std::string &tableName, + const std::string &fieldName, const int64_t rowId, const std::vector assetsValue) +{ + std::string cleanAssetIdSql = "UPDATE " + tableName + " SET " + fieldName + " = ? WHERE " + + std::string(DBConstant::SQLITE_INNER_ROWID) + " = " + std::to_string(rowId) + ";"; + sqlite3_stmt *stmt = nullptr; + int errCode = SQLiteUtils::GetStatement(dbHandle_, cleanAssetIdSql, stmt); + if (errCode != E_OK) { + LOGE("Get statement failed, %d", errCode); + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; + } + errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, assetsValue, false); + if (errCode != E_OK) { + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetAssetsByGidOrHashKey(const TableSchema &tableSchema, + const std::string &gid, const Bytes &hashKey, VBucket &assets) +{ + std::vector assetFields; + std::string sql = "SELECT"; + for (const auto &field: tableSchema.fields) { + if (field.type == TYPE_INDEX || field.type == TYPE_INDEX) { + assetFields.emplace_back(field); + sql += " b." + field.colName + ","; + } + } + if (assetFields.empty()) { + return -E_NOT_FOUND; + } + sql.pop_back(); + sql += CloudStorageUtils::GetLeftJoinLogSql(tableSchema.name) + " WHERE "; + if (!gid.empty()) { + sql += " a.cloud_gid = ? or "; + } + sql += " a.hash_key = ?;"; + sqlite3_stmt *stmt = nullptr; + int errCode = InitGetAssetStmt(sql, gid, hashKey, stmt); + if (errCode != E_OK) { + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt); + int index = 0; + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + for (const auto &field: assetFields) { + Type cloudValue; + errCode = SQLiteRelationalUtils::GetCloudValueByType(stmt, field.type, index++, cloudValue); + if (errCode != E_OK) { + break; + } + errCode = PutVBucketByType(assets, field, cloudValue); + if (errCode != E_OK) { + break; + } + } + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = -E_NOT_FOUND; + } else { + LOGE("step get asset stmt failed. %d", errCode); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::InitGetAssetStmt(const std::string &sql, const std::string &gid, + const Bytes &hashKey, sqlite3_stmt *&stmt) +{ + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, stmt); + if (errCode != E_OK) { + LOGE("Get asset statement failed, %d", errCode); + return errCode; + } + int index = 1; + if (!gid.empty()) { + errCode = SQLiteUtils::BindTextToStatement(stmt, index++, gid); + if (errCode != E_OK) { + LOGE("bind gid failed. %d", errCode); + SQLiteUtils::ResetStatement(stmt, true, errCode); + return errCode; + } + } + errCode = SQLiteUtils::BindBlobToStatement(stmt, index, hashKey); + if (errCode != E_OK) { + LOGE("bind hash failed. %d", errCode); + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::FillHandleWithOpType(const OpType opType, const CloudSyncData &data, + bool fillAsset, bool ignoreEmptyGid, const TableSchema &tableSchema) +{ + int errCode = E_OK; + if (opType == OpType::UPDATE_VERSION) { + errCode = FillCloudVersionForUpload(data); + } else if (opType == OpType::SET_UPLOADING) { + errCode = FillCloudAssetForUpload(opType, tableSchema, data.insData); + if (errCode != E_OK) { + LOGE("Failed to set uploading for ins data, %d.", errCode); + return errCode; + } + errCode = FillCloudAssetForUpload(opType, tableSchema, data.updData); + } else if (opType == OpType::INSERT) { + errCode = UpdateCloudLogGid(data, ignoreEmptyGid); + if (errCode != E_OK) { + LOGE("Failed to fill cloud log gid, %d.", errCode); + return errCode; + } + if (fillAsset) { + errCode = FillCloudAssetForUpload(opType, tableSchema, data.insData); + } + } else if (fillAsset) { + errCode = FillCloudAssetForUpload(opType, tableSchema, data.updData); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetDbAssets(const TableSchema &tableSchema, + const VBucket &vBucket, VBucket &dbAsset) +{ + std::string cloudGid; + (void)CloudStorageUtils::GetValueFromVBucket(CloudDbConstant::GID_FIELD, vBucket, cloudGid); + Bytes hashKey; + (void)CloudStorageUtils::GetValueFromVBucket(HASH_KEY, vBucket, hashKey); + VBucket dbAssets; + return GetAssetsByGidOrHashKey(tableSchema, cloudGid, hashKey, dbAssets); +} + +int SQLiteSingleVerRelationalStorageExecutor::GetAssetsByRowId(sqlite3_stmt *&selectStmt, Assets &assets) +{ + int errCode = SQLiteUtils::StepWithRetry(selectStmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::vector blobValue; + errCode = SQLiteUtils::GetColumnBlobValue(selectStmt, 0, blobValue); + if (errCode != E_OK) { + LOGE("Get column blob value failed. %d", errCode); + return errCode; + } + errCode = RuntimeContext::GetInstance()->BlobToAssets(blobValue, assets); + if (errCode != E_OK) { + LOGE("Transfer blob to assets failed. %d", errCode); + } + return errCode; + } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + return E_OK; + } else { + LOGE("Step select statement failed. %d", errCode); + return errCode; + } +} + +void SQLiteSingleVerRelationalStorageExecutor::SetIAssetLoader(const std::shared_ptr &loader) +{ + assetLoader_ = loader; +} + +int SQLiteSingleVerRelationalStorageExecutor::ExecuteFillDownloadAssetStatement(sqlite3_stmt *&stmt, + int beginIndex, const std::string &cloudGid) +{ + int errCode = SQLiteUtils::BindTextToStatement(stmt, beginIndex, cloudGid); + if (errCode != E_OK) { + LOGE("Bind cloud gid to statement failed. %d", errCode); + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode; + } + errCode = SQLiteUtils::StepWithRetry(stmt); + if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + errCode = E_OK; + } else { + LOGE("Fill cloud asset failed:%d", errCode); + } + int ret = E_OK; + SQLiteUtils::ResetStatement(stmt, true, ret); + return errCode != E_OK ? errCode : ret; +} + +int SQLiteSingleVerRelationalStorageExecutor::CleanDownloadChangedAssets( + const VBucket &vBucket, const AssetOperationUtils::RecordAssetOpType &assetOpType) +{ + if (assetLoader_ == nullptr) { + LOGE("assetLoader may be not set."); + return -E_NOT_SET; + } + std::vector toDeleteAssets; + CloudStorageUtils::GetToBeRemoveAssets(vBucket, assetOpType, toDeleteAssets); + if (toDeleteAssets.empty()) { + return E_OK; + } + int ret = assetLoader_->RemoveLocalAssets(toDeleteAssets); + if (ret != E_OK) { + LOGE("remove local assets failed. %d", ret); + } + return E_OK; +} + +int SQLiteSingleVerRelationalStorageExecutor::GetAndBindFillUploadAssetStatement(const std::string &tableName, + const VBucket &assets, sqlite3_stmt *&statement) +{ + std::string sql = "UPDATE '" + tableName + "' SET "; + for (const auto &item: assets) { + sql += item.first + " = ?,"; + } + sql.pop_back(); + sql += " WHERE " + std::string(DBConstant::SQLITE_INNER_ROWID) + " = ?;"; + int errCode = SQLiteUtils::GetStatement(dbHandle_, sql, statement); + if (errCode != E_OK) { + return errCode; + } + int bindIndex = 1; + for (const auto &item: assets) { + Field field = { + .colName = item.first, .type = static_cast(item.second.index()) + }; + errCode = bindCloudFieldFuncMap_[TYPE_INDEX](bindIndex++, assets, field, statement); + if (errCode != E_OK) { + return errCode; + } + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::OnlyUpdateAssetId(const std::string &tableName, + const TableSchema &tableSchema, const VBucket &vBucket, int64_t dataKey, OpType opType) +{ + if (opType != OpType::ONLY_UPDATE_GID && opType != OpType::NOT_HANDLE) { + return E_OK; + } + if (tableSchema.sharedTableName.empty()) { + // this is shared table, not need to update asset id. + return E_OK; + } + std::string sql = "UPDATE " + tableName + " SET"; + for (const auto &field : tableSchema.fields) { + int errCode = UpdateAssetId(tableName, field, dataKey, vBucket); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to update assetId on table, %d.", errCode); + return errCode; + } + } + return E_OK; +} + +void SQLiteSingleVerRelationalStorageExecutor::UpdateLocalAssetId(const VBucket &vBucket, const std::string &fieldName, + Asset &asset) +{ + for (const auto &[col, value] : vBucket) { + if (value.index() == TYPE_INDEX && col == fieldName) { + Asset cloudAsset = std::get(value); + if (cloudAsset.name == asset.name) { + asset.assetId = cloudAsset.assetId; + } + } else { + LOGD("[UpdateLocalAssetId] value type is not asset"); + } + } +} + +void SQLiteSingleVerRelationalStorageExecutor::UpdateLocalAssetsId(const VBucket &vBucket, const std::string &fieldName, + Assets &assets) +{ + for (const auto &[col, value] : vBucket) { + if (value.index() == TYPE_INDEX && col == fieldName) { + Assets cloudAssets = std::get(value); + UpdateLocalAssetsIdInner(cloudAssets, assets); + } else { + LOGD("[UpdateLocalAssetsId] value type is not assets"); + } + } +} + +void SQLiteSingleVerRelationalStorageExecutor::UpdateLocalAssetsIdInner(const Assets &cloudAssets, Assets &assets) +{ + for (const auto &cloudAsset : cloudAssets) { + for (auto &asset : assets) { + if (asset.name == cloudAsset.name) { + asset.assetId = cloudAsset.assetId; + } + } + } +} + +int SQLiteSingleVerRelationalStorageExecutor::BindAssetToBlobStatement(const Asset &asset, sqlite3_stmt *&stmt) +{ + std::vector blobValue; + int errCode = RuntimeContext::GetInstance()->AssetToBlob(asset, blobValue); + if (errCode != E_OK) { + LOGE("Transfer asset to blob failed, %d", errCode); + return errCode; + } + errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, blobValue, false); + if (errCode != E_OK) { + LOGE("Bind asset blob to statement failed, %d", errCode); + } + return errCode; +} + +int SQLiteSingleVerRelationalStorageExecutor::UpdateAssetId(const std::string &tableName, const Field &field, + int64_t dataKey, const VBucket &vBucket) +{ + int errCode = E_OK; + if (field.type == TYPE_INDEX) { + std::vector dataKeys = {dataKey}; + Assets assets; + errCode = GetAssetOnTable(tableName, field.colName, dataKeys, assets); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to get asset on table, %d.", errCode); + return errCode; + } + errCode = UpdateAssetIdOnUserTable(tableName, field.colName, dataKeys, vBucket, assets); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to save asset id on table, %d.", errCode); + return errCode; + } + } + if (field.type == TYPE_INDEX) { + std::vector dataKeys = {dataKey}; + errCode = GetAssetsAndUpdateAssetsId(tableName, field.colName, dataKeys, vBucket); + if (errCode != E_OK) { + LOGE("[Storage Executor] failed to get and save assets on table, %d.", errCode); + } + } + return errCode; +} } // namespace DistributedDB #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.cpp index e00d62cf2aa9c96aaa9fb6406de6409750ead6e3..3fd311d44a5662f04e6c879523ef714961bdaa24 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.cpp @@ -143,6 +143,19 @@ int SQLiteSingleVerResultSet::GetPosition() const return position_; } +int SQLiteSingleVerResultSet::Move(int offset) const +{ + int64_t position = GetPosition(); + int64_t aimPos = position + offset; + if (aimPos > INT_MAX) { + return MoveTo(INT_MAX); + } + if (aimPos < INIT_POSITION) { + return MoveTo(INIT_POSITION); + } + return MoveTo(aimPos); +} + int SQLiteSingleVerResultSet::MoveTo(int position) const { std::lock_guard lockGuard(mutex_); @@ -174,6 +187,67 @@ int SQLiteSingleVerResultSet::MoveTo(int position) const } } +int SQLiteSingleVerResultSet::MoveToFirst() +{ + return MoveTo(0); +} + +int SQLiteSingleVerResultSet::MoveToLast() +{ + return MoveTo(GetCount() - 1); +} + +bool SQLiteSingleVerResultSet::IsFirst() const +{ + int position = GetPosition(); + if (GetCount() == 0) { + return false; + } + if (position == 0) { + return true; + } + return false; +} + +bool SQLiteSingleVerResultSet::IsLast() const +{ + int position = GetPosition(); + int count = GetCount(); + if (count == 0) { + return false; + } + if (position == (count - 1)) { + return true; + } + return false; +} + +bool SQLiteSingleVerResultSet::IsBeforeFirst() const +{ + int position = GetPosition(); + + if (GetCount() == 0) { + return true; + } + if (position <= INIT_POSITION) { + return true; + } + return false; +} + +bool SQLiteSingleVerResultSet::IsAfterLast() const +{ + int position = GetPosition(); + int count = GetCount(); + if (count == 0) { + return true; + } + if (position >= count) { + return true; + } + return false; +} + int SQLiteSingleVerResultSet::MoveToForCacheFullEntryMode(int position) const { if (window_->MoveToPosition(position)) { @@ -265,11 +339,11 @@ int SQLiteSingleVerResultSet::GetEntry(Entry &entry) const return -E_NO_SUCH_ENTRY; } -void SQLiteSingleVerResultSet::Close() +int SQLiteSingleVerResultSet::Close() { std::lock_guard lockGuard(mutex_); if (!isOpen_) { - return; + return E_OK; } if (option_.cacheMode == ResultSetCacheMode::CACHE_FULL_ENTRY) { CloseForCacheFullEntryMode(); @@ -280,6 +354,7 @@ void SQLiteSingleVerResultSet::Close() count_ = 0; position_ = INIT_POSITION; LOGD("[SqlSinResSet][Close] Done, Type=%d, Mode=%d.", static_cast(type_), static_cast(option_.cacheMode)); + return E_OK; } void SQLiteSingleVerResultSet::CloseForCacheFullEntryMode() diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.h index e2c46482ddddc3a4816595bd0afd2f69bb1e6791..b4d5f86b290593fd5553211deb675389a467cf02 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_result_set.h @@ -24,14 +24,10 @@ #include "query_object.h" namespace DistributedDB { -constexpr int INIT_POSITION = -1; constexpr int DEFAULT_RESULT_SET_CACHE_MAX_SIZE = 1; // Unit MB, default 1 MB constexpr int RESULT_SET_CACHE_MAX_SIZE_MIN = 1; constexpr int RESULT_SET_CACHE_MAX_SIZE_MAX = 16; -enum class ResultSetType : int { - KEYPREFIX = 0, - QUERY = 1, -}; + // Forward declaration class SQLiteSingleVerNaturalStore; class SQLiteSingleVerStorageExecutor; @@ -61,14 +57,28 @@ public: // >= 0: position, < 0: errCode int GetPosition() const override; + int Move(int offset) const override; + // Move the read position to an absolute position value. int MoveTo(int position) const override; + int MoveToFirst() override; + + int MoveToLast() override; + + bool IsFirst() const override; + + bool IsLast() const override; + + bool IsBeforeFirst() const override; + + bool IsAfterLast() const override; + // Get the entry of current position. int GetEntry(Entry &entry) const override; // Finalize logic - void Close() override; + int Close() override; private: int OpenForCacheFullEntryMode(bool isMemDb); int OpenForCacheEntryIdMode(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp index 5a2227d65e8a4d97e155ec08906c654f56414ed0..21cf2d3a1e3c6db2a3b8c6d1be7c1c67b090d7d2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.cpp @@ -25,43 +25,15 @@ #include "param_check_utils.h" #include "platform_specific.h" #include "runtime_context.h" +#include "single_ver_utils.h" #include "sqlite_single_ver_database_upgrader.h" #include "sqlite_single_ver_natural_store.h" #include "sqlite_single_ver_schema_database_upgrader.h" namespace DistributedDB { -namespace { - const uint64_t CACHE_RECORD_DEFAULT_VERSION = 1; - int GetPathSecurityOption(const std::string &filePath, SecurityOption &secOpt) - { - return RuntimeContext::GetInstance()->GetSecurityOption(filePath, secOpt); - } - - enum class DbType : int32_t { - MAIN, - META, - CACHE - }; - - std::string GetDbDir(const std::string &subDir, DbType type) - { - switch (type) { - case DbType::MAIN: - return subDir + "/" + DBConstant::MAINDB_DIR; - case DbType::META: - return subDir + "/" + DBConstant::METADB_DIR; - case DbType::CACHE: - return subDir + "/" + DBConstant::CACHEDB_DIR; - default: - break; - } - return ""; - } -} // namespace - SQLiteSingleVerStorageEngine::SQLiteSingleVerStorageEngine() - : cacheRecordVersion_(CACHE_RECORD_DEFAULT_VERSION), - executorState_(ExecutorState::INVALID), + : executorState_(ExecutorState::INVALID), + cacheRecordVersion_(CACHE_RECORD_DEFAULT_VERSION), isCorrupted_(false), isNeedUpdateSecOpt_(false) {} @@ -244,7 +216,7 @@ int SQLiteSingleVerStorageEngine::ReleaseHandleTransiently(SQLiteSingleVerStorag int SQLiteSingleVerStorageEngine::AddSubscribeToMainDBInMigrate() { - LOGD("Add subscribe to mainDB from cache. %d", engineState_); + LOGD("Add subscribe to mainDB from cache. %d", GetEngineState()); std::lock_guard lock(subscribeMutex_); if (subscribeQuery_.empty()) { return E_OK; @@ -328,11 +300,11 @@ int SQLiteSingleVerStorageEngine::AttachMainDbAndCacheDb(SQLiteSingleVerStorageE std::string attachAbsPath; if (stateBeforeMigrate == EngineState::MAINDB) { attachAbsPath = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; errCode = handle->AttachMainDbAndCacheDb(option_.cipherType, option_.passwd, attachAbsPath, stateBeforeMigrate); } else if (stateBeforeMigrate == EngineState::CACHEDB) { attachAbsPath = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; errCode = handle->AttachMainDbAndCacheDb(option_.cipherType, option_.passwd, attachAbsPath, stateBeforeMigrate); } else { return -E_NOT_SUPPORT; @@ -360,11 +332,11 @@ int SQLiteSingleVerStorageEngine::AttachMainDbAndCacheDb(sqlite3 *dbHandle, Engi std::string attachAbsPath; if (stateBeforeMigrate == EngineState::MAINDB) { attachAbsPath = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; errCode = SQLiteUtils::AttachNewDatabase(dbHandle, option_.cipherType, option_.passwd, attachAbsPath, "cache"); } else if (stateBeforeMigrate == EngineState::CACHEDB) { attachAbsPath = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; errCode = SQLiteUtils::AttachNewDatabase(dbHandle, option_.cipherType, option_.passwd, attachAbsPath, "maindb"); } else { return -E_NOT_SUPPORT; @@ -493,7 +465,7 @@ int SQLiteSingleVerStorageEngine::ExecuteMigrate() std::lock_guard lock(migrateLock_); if (preState == EngineState::MIGRATING || preState == EngineState::INVALID || !OS::CheckPathExistence(GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + - DBConstant::SQLITE_DB_EXTENSION)) { + DBConstant::DB_EXTENSION)) { LOGD("[SqlSingleVerEngine] Being single ver migrating or never create db! engine state [%u]", preState); return E_OK; } @@ -602,7 +574,7 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& if (!option_.isMemDb) { option_.uri = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; } OpenDbProperties optionTemp = option_; @@ -624,7 +596,7 @@ int SQLiteSingleVerStorageEngine::TryToOpenMainDatabase(bool isWrite, sqlite3 *& SetEngineState(EngineState::MAINDB); if (OS::CheckPathExistence(GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + - DBConstant::SQLITE_DB_EXTENSION)) { + DBConstant::DB_EXTENSION)) { // In status cacheDb crash errCode = AttachMainDbAndCacheDb(db, EngineState::MAINDB); if (errCode != E_OK) { @@ -647,9 +619,8 @@ int SQLiteSingleVerStorageEngine::GetDbHandle(bool isWrite, const SecurityOption if (!(ParamCheckUtils::IsS3SECEOpt(secOpt) && errCode == -E_EKEYREVOKED)) { return errCode; } - std::string cacheDbPath = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; if (!isWrite || GetEngineState() != EngineState::INVALID || OS::CheckPathExistence(cacheDbPath)) { LOGI("[SQLiteSingleStorageEng][GetDbHandle] Only use for first create cache db! [%d] [%d]", @@ -698,7 +669,7 @@ const std::string CREATE_CACHE_SYNC_TABLE_SQL = int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db) { option_.uri = GetDbDir(option_.subdir, DbType::CACHE) + "/" + DBConstant::SINGLE_VER_CACHE_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; // creatTable option_.sqls = { CacheDbSqls::CREATE_CACHE_LOCAL_TABLE_SQL, @@ -707,7 +678,7 @@ int SQLiteSingleVerStorageEngine::GetCacheDbHandle(sqlite3 *&db) if (!option_.createIfNecessary) { std::string mainDbPtah = GetDbDir(option_.subdir, DbType::MAIN) + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION; + DBConstant::DB_EXTENSION; if (!OS::CheckPathExistence(mainDbPtah)) { // Whether to create a cacheDb is based on whether the mainDb exists return -E_INVALID_DB; } @@ -728,8 +699,9 @@ int SQLiteSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secO if (!(secOption == option_.securityOpt) && secOption.securityLabel != SecurityLabel::NOT_SET && option_.securityOpt.securityLabel != SecurityLabel::NOT_SET) { - LOGE("SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]", secOption.securityLabel, - secOption.securityFlag, option_.securityOpt.securityLabel, option_.securityOpt.securityFlag); + LOGE("[SQLiteSingleVerStorageEngine] SecurityOption mismatch, existed:[%d-%d] vs input:[%d-%d]", + secOption.securityLabel, secOption.securityFlag, option_.securityOpt.securityLabel, + option_.securityOpt.securityFlag); return -E_SECURITY_OPTION_CHECK_ERROR; } return E_OK; @@ -737,73 +709,14 @@ int SQLiteSingleVerStorageEngine::CheckDatabaseSecOpt(const SecurityOption &secO int SQLiteSingleVerStorageEngine::CreateNewDirsAndSetSecOpt() const { - std::vector dbDir {DBConstant::MAINDB_DIR, DBConstant::METADB_DIR, DBConstant::CACHEDB_DIR}; - for (const auto &item : dbDir) { - if (OS::CheckPathExistence(option_.subdir + "/" + item)) { - continue; - } - - // Dir and old db file not existed, it means that the database is newly created - // need create flag of database not incomplete - if (!OS::CheckPathExistence(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) && - !OS::CheckPathExistence(option_.subdir + "/" + DBConstant::SINGLE_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION) && - OS::CreateFileByFileName(option_.subdir + DBConstant::PATH_POSTFIX_DB_INCOMPLETE) != E_OK) { - LOGE("Fail to create the token of database incompleted! errCode = [E_SYSTEM_API_FAIL]"); - return -E_SYSTEM_API_FAIL; - } - - if (DBCommon::CreateDirectory(option_.subdir + "/" + item) != E_OK) { - LOGE("Create sub-directory for single ver failed, errno:%d", errno); - return -E_SYSTEM_API_FAIL; - } - - if (option_.securityOpt.securityLabel == NOT_SET) { - continue; - } - - SecurityOption option = option_.securityOpt; - if (item == DBConstant::METADB_DIR) { - option.securityLabel = ((option_.securityOpt.securityLabel >= SecurityLabel::S2) ? - SecurityLabel::S2 : option_.securityOpt.securityLabel); - option.securityFlag = SecurityFlag::ECE; - } - - int errCode = RuntimeContext::GetInstance()->SetSecurityOption(option_.subdir + "/" + item, option); - if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { - LOGE("Set the security option of sub-directory failed[%d]", errCode); - return errCode; - } - } - return E_OK; + LOGD("[SQLiteSingleVerStorageEngine] Begin to create new dirs and set security option"); + return CreateNewDirsAndSetSecOption(option_); } int SQLiteSingleVerStorageEngine::GetExistedSecOption(SecurityOption &secOption) const { - // Check the existence of the database, include the origin database and the database in the 'main' directory. - auto mainDbDir = GetDbDir(option_.subdir, DbType::MAIN); - auto mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; - auto origDbFilePath = option_.subdir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; - if (!OS::CheckPathExistence(origDbFilePath) && !OS::CheckPathExistence(mainDbFilePath)) { - secOption = option_.securityOpt; - return E_OK; - } - - // the main database file has high priority of the security option. - int errCode; - if (OS::CheckPathExistence(mainDbFilePath)) { - errCode = GetPathSecurityOption(mainDbFilePath, secOption); - } else { - errCode = GetPathSecurityOption(origDbFilePath, secOption); - } - if (errCode != E_OK) { - secOption = SecurityOption(); - if (errCode == -E_NOT_SUPPORT) { - return E_OK; - } - LOGE("Get the security option of the existed database failed."); - } - return errCode; + LOGD("[SQLiteSingleVerStorageEngine] Try to get existed sec option"); + return GetExistedSecOpt(option_, secOption); } void SQLiteSingleVerStorageEngine::ClearCorruptedFlag() @@ -836,9 +749,11 @@ int SQLiteSingleVerStorageEngine::PreCreateExecutor(bool isWrite) } // Judge whether need update the security option of the engine. - // Should update the security in the import or rekey scene(inner). - if (!isNeedUpdateSecOpt_) { + // Should update the security in the import or rekey scene(inner) or exist is not set. + if (IsUseExistedSecOption(existedSecOpt, option_.securityOpt)) { option_.securityOpt = existedSecOpt; + } else { + isNeedUpdateSecOpt_ = true; } errCode = CreateNewDirsAndSetSecOpt(); @@ -971,7 +886,7 @@ int SQLiteSingleVerStorageEngine::Upgrade(sqlite3 *db) } std::string mainDbDir = GetDbDir(option_.subdir, DbType::MAIN); - std::string mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + std::string mainDbFilePath = mainDbDir + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; SecurityOption secOpt = option_.securityOpt; int errCode = E_OK; if (isNeedUpdateSecOpt_) { @@ -1033,7 +948,7 @@ int SQLiteSingleVerStorageEngine::AttachMetaDatabase(sqlite3 *dbHandle, const Op int errCode; LOGD("SQLiteSingleVerStorageEngine begin attach metaDb!"); std::string metaDbPath = option.subdir + "/" + DBConstant::METADB_DIR + "/" + - DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; // attach metaDb may failed while createIfNecessary is false, here need to create metaDb first. if (!option.createIfNecessary && !OS::CheckPathExistence(metaDbPath)) { errCode = SQLiteUtils::CreateMetaDatabase(metaDbPath); @@ -1189,4 +1104,17 @@ void SQLiteSingleVerStorageEngine::CacheSubscribe(const std::string &subscribeId std::lock_guard lock(subscribeMutex_); subscribeQuery_[subscribeId] = query; } + +bool SQLiteSingleVerStorageEngine::IsUseExistedSecOption(const SecurityOption &existedSecOpt, + const SecurityOption &openSecOpt) +{ + if (isNeedUpdateSecOpt_) { + return false; + } + if (existedSecOpt.securityLabel != openSecOpt.securityLabel && + existedSecOpt.securityLabel == SecurityLabel::NOT_SET) { + return false; + } + return true; +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h index 89529138378406f5251c41a1ced7901e7f91048d..4dc5b16ee381ef1ae0cc28f6fedf476da09506f2 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_engine.h @@ -61,12 +61,14 @@ public: void CacheSubscribe(const std::string &subscribeId, const QueryObject &query); protected: - StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) override; + virtual StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) override; int Upgrade(sqlite3 *db) override; int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) override; + ExecutorState executorState_; + private: // For executor. int PreCreateExecutor(bool isWrite); @@ -117,9 +119,10 @@ private: // For subscribe int AddSubscribeToMainDBInMigrate(); + bool IsUseExistedSecOption(const SecurityOption &existedSecOpt, const SecurityOption &openSecOpt); + mutable std::mutex migrateLock_; std::atomic cacheRecordVersion_; - ExecutorState executorState_; bool isCorrupted_; bool isNeedUpdateSecOpt_; // update the option_ diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp index 91a6cc98a33856589bc78a25cec639101a8eb550..ee612374ef368a1cc7dbec9c9c55b246c386f016 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.cpp @@ -30,23 +30,6 @@ namespace DistributedDB { namespace { -void InitCommitNotifyDataKeyStatus(SingleVerNaturalStoreCommitNotifyData *committedData, const Key &hashKey, - const DataOperStatus &dataStatus) -{ - if (committedData == nullptr) { - return; - } - - ExistStatus existedStatus = ExistStatus::NONE; - if (dataStatus.preStatus == DataStatus::DELETED) { - existedStatus = ExistStatus::DELETED; - } else if (dataStatus.preStatus == DataStatus::EXISTED) { - existedStatus = ExistStatus::EXIST; - } - - committedData->InitKeyPropRecord(hashKey, existedStatus); -} - int ResetOrRegetStmt(sqlite3 *db, sqlite3_stmt *&stmt, const std::string &sql) { int errCode = E_OK; @@ -123,7 +106,7 @@ int SQLiteSingleVerStorageExecutor::GetKvData(SingleVerDataType type, const Key Timestamp ×tamp) const { std::string sql; - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { sql = SELECT_LOCAL_VALUE_TIMESTAMP_SQL; } else if (type == SingleVerDataType::SYNC_TYPE) { sql = SELECT_SYNC_VALUE_WTIMESTAMP_SQL; @@ -159,7 +142,7 @@ int SQLiteSingleVerStorageExecutor::GetKvData(SingleVerDataType type, const Key errCode = SQLiteUtils::GetColumnBlobValue(statement, 0, value); // only one result. // get timestamp - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { timestamp = static_cast(sqlite3_column_int64(statement, GET_KV_RES_LOCAL_TIME_INDEX)); } else if (type == SingleVerDataType::SYNC_TYPE) { timestamp = static_cast(sqlite3_column_int64(statement, GET_KV_RES_SYNC_TIME_INDEX)); @@ -185,7 +168,7 @@ int SQLiteSingleVerStorageExecutor::BindPutKvData(sqlite3_stmt *statement, const return errCode; } - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { Key hashKey; errCode = DBCommon::CalcValueHash(key, hashKey); if (errCode != E_OK) { @@ -265,7 +248,7 @@ int SQLiteSingleVerStorageExecutor::SaveKvData(SingleVerDataType type, const Key { sqlite3_stmt *statement = nullptr; std::string sql; - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { sql = (executorState_ == ExecutorState::CACHE_ATTACH_MAIN ? INSERT_LOCAL_SQL_FROM_CACHEHANDLE : INSERT_LOCAL_SQL); } else { @@ -294,11 +277,11 @@ ERROR: int SQLiteSingleVerStorageExecutor::PutKvData(SingleVerDataType type, const Key &key, const Value &value, Timestamp timestamp, SingleVerNaturalStoreCommitNotifyData *committedData) { - if (type != SingleVerDataType::LOCAL_TYPE && type != SingleVerDataType::META_TYPE) { + if (type != SingleVerDataType::LOCAL_TYPE_SQLITE && type != SingleVerDataType::META_TYPE) { return -E_INVALID_ARGS; } // committedData is only for local data, not for meta data. - bool isLocal = (SingleVerDataType::LOCAL_TYPE == type); + bool isLocal = (SingleVerDataType::LOCAL_TYPE_SQLITE == type); Timestamp localTimestamp = 0; Value readValue; bool isExisted = CheckIfKeyExisted(key, isLocal, readValue, localTimestamp); @@ -326,7 +309,7 @@ int SQLiteSingleVerStorageExecutor::PutKvData(SingleVerDataType type, const Key int SQLiteSingleVerStorageExecutor::GetEntries(bool isGetValue, SingleVerDataType type, const Key &keyPrefix, std::vector &entries) const { - if ((type != SingleVerDataType::LOCAL_TYPE) && (type != SingleVerDataType::SYNC_TYPE)) { + if ((type != SingleVerDataType::LOCAL_TYPE_SQLITE) && (type != SingleVerDataType::SYNC_TYPE)) { return -E_INVALID_ARGS; } @@ -1083,7 +1066,7 @@ bool SQLiteSingleVerStorageExecutor::CheckIfKeyExisted(const Key &key, bool isLo return false; } - int errCode = GetKvData(SingleVerDataType::LOCAL_TYPE, key, value, timestamp); + int errCode = GetKvData(SingleVerDataType::LOCAL_TYPE_SQLITE, key, value, timestamp); if (errCode != E_OK) { return false; } @@ -1180,7 +1163,7 @@ ERR: int SQLiteSingleVerStorageExecutor::PrepareForSavingData(SingleVerDataType type) { int errCode = -E_NOT_SUPPORT; - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { // currently, Local type has not been optimized, so pass updateSql parameter with INSERT_LOCAL_SQL errCode = PrepareForSavingData(SELECT_LOCAL_HASH_SQL, INSERT_LOCAL_SQL, INSERT_LOCAL_SQL, saveLocalStatements_); } else if (type == SingleVerDataType::SYNC_TYPE) { @@ -1192,7 +1175,7 @@ int SQLiteSingleVerStorageExecutor::PrepareForSavingData(SingleVerDataType type) int SQLiteSingleVerStorageExecutor::ResetForSavingData(SingleVerDataType type) { int errCode = E_OK; - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { SQLiteUtils::ResetStatement(saveLocalStatements_.insertStatement, false, errCode); SQLiteUtils::ResetStatement(saveLocalStatements_.updateStatement, false, errCode); SQLiteUtils::ResetStatement(saveLocalStatements_.queryStatement, false, errCode); @@ -1577,7 +1560,7 @@ int SQLiteSingleVerStorageExecutor::Reset() LOGE("Finalize the sync resources for saving sync data failed: %d", errCode); } - errCode = ResetForSavingData(SingleVerDataType::LOCAL_TYPE); + errCode = ResetForSavingData(SingleVerDataType::LOCAL_TYPE_SQLITE); if (errCode != E_OK) { LOGE("Finalize the local resources for saving sync data failed: %d", errCode); } @@ -1687,7 +1670,7 @@ ERROR: int SQLiteSingleVerStorageExecutor::DeleteLocalKvData(const Key &key, SingleVerNaturalStoreCommitNotifyData *committedData, Value &value, Timestamp ×tamp) { - int errCode = GetKvData(SingleVerDataType::LOCAL_TYPE, key, value, timestamp); + int errCode = GetKvData(SingleVerDataType::LOCAL_TYPE_SQLITE, key, value, timestamp); if (errCode != E_OK) { return CheckCorruptedStatus(errCode); } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h index 39139441d20fbe0e1560a814b4b6cc6410a768b5..815b6d22232792fc68e82123c99bd85943e58415 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor.h @@ -24,76 +24,6 @@ #include "single_ver_natural_store_commit_notify_data.h" namespace DistributedDB { -enum class SingleVerDataType { - META_TYPE, - LOCAL_TYPE, - SYNC_TYPE, -}; - -enum class DataStatus { - NOEXISTED, - DELETED, - EXISTED, -}; - -enum class ExecutorState { - INVALID = -1, - MAINDB, - CACHEDB, - MAIN_ATTACH_CACHE, // After process crash and cacheDb existed - CACHE_ATTACH_MAIN, // while cacheDb migrating to mainDb -}; - -struct DataOperStatus { - DataStatus preStatus = DataStatus::NOEXISTED; - bool isDeleted = false; - bool isDefeated = false; // whether the put data is defeated. -}; - -struct SingleVerRecord { - Key key; - Value value; - Timestamp timestamp = 0; - uint64_t flag = 0; - std::string device; - std::string origDevice; - Key hashKey; - Timestamp writeTimestamp = 0; -}; - -struct DeviceInfo { - bool isLocal = false; - std::string deviceName; -}; - -struct LocalDataItem { - Key key; - Value value; - Timestamp timestamp = 0; - Key hashKey; - uint64_t flag = 0; -}; - -struct NotifyConflictAndObserverData { - SingleVerNaturalStoreCommitNotifyData *committedData = nullptr; - DataItem getData; - Key hashKey; - DataOperStatus dataStatus; -}; - -struct NotifyMigrateSyncData { - bool isRemote = false; - bool isRemoveDeviceData = false; - bool isPermitForceWrite = true; - SingleVerNaturalStoreCommitNotifyData *committedData = nullptr; - std::vector entries{}; -}; - -struct SyncDataDevices { - std::string origDev; - std::string dev; -}; - class SQLiteSingleVerStorageExecutor : public SQLiteStorageExecutor { public: SQLiteSingleVerStorageExecutor(sqlite3 *dbHandle, bool writable, bool isMemDb); @@ -104,16 +34,17 @@ public: DISABLE_COPY_ASSIGN_MOVE(SQLiteSingleVerStorageExecutor); // Get the Kv data according the type(sync, meta, local data). - int GetKvData(SingleVerDataType type, const Key &key, Value &value, Timestamp ×tamp) const; + virtual int GetKvData(SingleVerDataType type, const Key &key, Value &value, Timestamp ×tamp) const; // Get the sync data record by hash key. int GetKvDataByHashKey(const Key &hashKey, SingleVerRecord &result) const; // Put the Kv data according the type(meta and the local data). - int PutKvData(SingleVerDataType type, const Key &key, const Value &value, + virtual int PutKvData(SingleVerDataType type, const Key &key, const Value &value, Timestamp timestamp, SingleVerNaturalStoreCommitNotifyData *committedData); - int GetEntries(bool isGetValue, SingleVerDataType type, const Key &keyPrefix, std::vector &entries) const; + virtual int GetEntries(bool isGetValue, SingleVerDataType type, const Key &keyPrefix, + std::vector &entries) const; int GetEntries(QueryObject &queryObj, std::vector &entries) const; @@ -127,7 +58,7 @@ public: int SaveSyncDataItem(DataItem &dataItem, const DeviceInfo &deviceInfo, Timestamp &maxStamp, SingleVerNaturalStoreCommitNotifyData *committedData, bool isPermitForceWrite = true); - int DeleteLocalKvData(const Key &key, SingleVerNaturalStoreCommitNotifyData *committedData, Value &value, + virtual int DeleteLocalKvData(const Key &key, SingleVerNaturalStoreCommitNotifyData *committedData, Value &value, Timestamp ×tamp); // delete a row data by hashKey, with no tombstone left. @@ -252,6 +183,12 @@ public: int UpdateKey(const UpdateKeyCallback &callback); +protected: + virtual int SaveKvData(SingleVerDataType type, const Key &key, const Value &value, Timestamp timestamp); + + virtual int DeleteLocalDataInner(SingleVerNaturalStoreCommitNotifyData *committedData, + const Key &key, const Value &value); + private: struct SaveRecordStatements { sqlite3_stmt *queryStatement = nullptr; @@ -316,11 +253,6 @@ private: int SaveSyncDataToDatabase(const DataItem &dataItem, const Key &hashKey, const std::string &origDev, const std::string &deviceName, bool isUpdate); - int SaveKvData(SingleVerDataType type, const Key &key, const Value &value, Timestamp timestamp); - - int DeleteLocalDataInner(SingleVerNaturalStoreCommitNotifyData *committedData, - const Key &key, const Value &value); - int PrepareForSavingData(const std::string &readSql, const std::string &insertSql, const std::string &updateSql, SaveRecordStatements &statements) const; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp index 82ec7a98750b49bd6f931892342f334bc05452d3..0939a372372aef51e9291d9e1c4a53d4b60a9365 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp @@ -29,7 +29,7 @@ namespace DistributedDB { int SQLiteSingleVerStorageExecutor::PrepareForSavingCacheData(SingleVerDataType type) { int errCode = -E_NOT_SUPPORT; - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { std::string insertLocalSql = ((executorState_ == ExecutorState::CACHE_ATTACH_MAIN) ? INSERT_LOCAL_SQL_FROM_CACHEHANDLE : INSERT_CACHE_LOCAL_SQL); std::string updateLocalSql = ((executorState_ == ExecutorState::CACHE_ATTACH_MAIN) ? @@ -54,7 +54,7 @@ int SQLiteSingleVerStorageExecutor::PrepareForSavingCacheData(SingleVerDataType int SQLiteSingleVerStorageExecutor::ResetForSavingCacheData(SingleVerDataType type) { int errCode = E_OK; - if (type == SingleVerDataType::LOCAL_TYPE) { + if (type == SingleVerDataType::LOCAL_TYPE_SQLITE) { SQLiteUtils::ResetStatement(saveLocalStatements_.insertStatement, false, errCode); SQLiteUtils::ResetStatement(saveLocalStatements_.updateStatement, false, errCode); SQLiteUtils::ResetStatement(saveLocalStatements_.queryStatement, false, errCode); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.cpp index f82b68009486a494afb1324dcd539153814ece14..a63dcde736ba482116c799b1f52adbd7e778f256 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.cpp @@ -96,58 +96,6 @@ int SQLiteStorageEngine::CreateNewExecutor(bool isWrite, StorageExecutor *&handl return E_OK; } -int SQLiteStorageEngine::ReInit() -{ - return E_OK; -} - -bool SQLiteStorageEngine::IsNeedTobeReleased() const -{ - EngineState engineState = GetEngineState(); - return ((engineState == EngineState::MAINDB) || (engineState == EngineState::INVALID)); -} - -const std::string &SQLiteStorageEngine::GetIdentifier() const -{ - return identifier_; -} - -EngineState SQLiteStorageEngine::GetEngineState() const -{ - return engineState_; -} - -void SQLiteStorageEngine::SetEngineState(EngineState state) -{ - LOGD("[SQLiteStorageEngine::SetEngineState] Engine State : [%d]", state); - engineState_ = state; // Current usage logically can guarantee no concurrency -} - -int SQLiteStorageEngine::ExecuteMigrate() -{ - return -E_NOT_SUPPORT; -} - -void SQLiteStorageEngine::IncreaseCacheRecordVersion() -{ - return; -} - -uint64_t SQLiteStorageEngine::GetCacheRecordVersion() const -{ - return 0; -} - -uint64_t SQLiteStorageEngine::GetAndIncreaseCacheRecordVersion() -{ - return 0; -} - -bool SQLiteStorageEngine::IsEngineCorrupted() const -{ - return false; -} - void SQLiteStorageEngine::ClearEnginePasswd() { option_.passwd.Clear(); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.h index 3468cb4fa442f081057b632cd51252bfbc3afefd..f71a794d4e705aad49259ad39ff9f4ef28e63c78 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_storage_engine.h @@ -34,23 +34,7 @@ public: int InitSQLiteStorageEngine(const StorageEngineAttr &poolSize, const OpenDbProperties &option, const std::string &identifier = std::string()); - bool IsNeedTobeReleased() const override; - - const std::string &GetIdentifier() const override; - - EngineState GetEngineState() const override; - - int ExecuteMigrate() override; - - void SetEngineState(EngineState state) override; - - virtual void IncreaseCacheRecordVersion(); - virtual uint64_t GetCacheRecordVersion() const; - virtual uint64_t GetAndIncreaseCacheRecordVersion(); - - virtual bool IsEngineCorrupted() const; - - void ClearEnginePasswd() override; + void ClearEnginePasswd(); int CheckEngineOption(const KvDBProperties &kvDBProp) const override; @@ -61,10 +45,6 @@ protected: virtual StorageExecutor *NewSQLiteStorageExecutor(sqlite3 *dbHandle, bool isWrite, bool isMemDb) = 0; int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) override; - - virtual int ReInit(); - - OpenDbProperties option_; }; } // namespace DistributedDB -#endif // SQLITE_STORAGE_ENGINE_H +#endif // SQLITE_STORAGE_ENGINE_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp index 85f32838b907300bf372560cc9751f088fec1172..9578b53a82ca81f64f09da9ca7bf815cb1406d44 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.cpp @@ -34,6 +34,7 @@ #include "schema_constant.h" #include "time_helper.h" #include "platform_specific.h" +#include "sqlite_relational_utils.h" namespace DistributedDB { std::mutex SQLiteUtils::logMutex_; @@ -76,6 +77,8 @@ namespace { "type='table' AND tbl_name=?);"; bool g_configLog = false; + std::mutex g_serverChangedDataMutex; + std::map> g_serverChangedDataMap; } namespace TriggerMode { @@ -164,8 +167,6 @@ int SQLiteUtils::OpenDatabase(const OpenDbProperties &properties, sqlite3 *&db, std::lock_guard lock(logMutex_); if (!g_configLog) { sqlite3_config(SQLITE_CONFIG_LOG, &SqliteLogCallback, &properties.createIfNecessary); - sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0); - LOGW("close look aside config"); g_configLog = true; } } @@ -659,9 +660,12 @@ int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql) #ifdef RELATIONAL_STORE namespace { // anonymous namespace for schema analysis -int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table) +int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) { - std::string sql = "select type, sql from sqlite_master where tbl_name = ? COLLATE NOCASE"; + std::string sql = "select type, sql from sqlite_master where tbl_name = ? "; + if (!caseSensitive) { + sql += "COLLATE NOCASE"; + } sqlite3_stmt *statement = nullptr; int errCode = SQLiteUtils::GetStatement(db, sql, statement); if (errCode != E_OK) { @@ -876,7 +880,7 @@ int AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableIn } } // end of anonymous namespace for schema analysis -int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table) +int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive) { if (db == nullptr) { return -E_INVALID_DB; @@ -887,7 +891,7 @@ int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, Table return -E_NOT_SUPPORT; } - int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table); + int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive); if (errCode != E_OK) { LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode); return errCode; @@ -1399,12 +1403,59 @@ void SQLiteUtils::GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **ar void SQLiteUtils::CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv) { - if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 is param counts + if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts + return; + } + sqlite3_result_int64(ctx, static_cast(1)); +} + +void SQLiteUtils::CloudDataChangedServerObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv) +{ + if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is param counts return; } + sqlite3 *db = static_cast(sqlite3_user_data(ctx)); + std::string fileName; + if (!SQLiteRelationalUtils::GetDbFileName(db, fileName)) { + return; + } + auto tableNameChar = reinterpret_cast(sqlite3_value_text(argv[0])); + if (tableNameChar == nullptr) { + return; + } + std::string tableName = static_cast(tableNameChar); + + uint64_t isTrackerChange = static_cast(sqlite3_value_int(argv[1])); // 1 is param index + LOGD("Cloud data changed, server observer callback %u", isTrackerChange); + { + std::lock_guard lock(g_serverChangedDataMutex); + auto itTable = g_serverChangedDataMap[fileName].find(tableName); + if (itTable != g_serverChangedDataMap[fileName].end()) { + itTable->second.isTrackedDataChange = + (static_cast(itTable->second.isTrackedDataChange) | isTrackerChange) > 0; + } else { + DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) }; + g_serverChangedDataMap[fileName].insert_or_assign(tableName, properties); + } + } sqlite3_result_int64(ctx, static_cast(1)); } +void SQLiteUtils::GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName, + ChangeProperties &changeProperties) +{ + std::lock_guard lock(g_serverChangedDataMutex); + auto itDb = g_serverChangedDataMap.find(dbName); + if (itDb != g_serverChangedDataMap.end() && !itDb->second.empty()) { + auto itTable = itDb->second.find(tableName); + if (itTable == itDb->second.end()) { + return; + } + changeProperties = itTable->second; + g_serverChangedDataMap[dbName].erase(itTable); + } +} + int SQLiteUtils::RegisterGetSysTime(sqlite3 *db) { TransactFunc func; @@ -1430,7 +1481,14 @@ int SQLiteUtils::RegisterCloudDataChangeObserver(sqlite3 *db) { TransactFunc func; func.xFunc = &CloudDataChangedObserver; - return RegisterFunction(db, "client_observer", 3, db, func); // 3 is param counts + return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts +} + +int SQLiteUtils::RegisterCloudDataChangeServerObserver(sqlite3 *db) +{ + TransactFunc func; + func.xFunc = &CloudDataChangedServerObserver; + return RegisterFunction(db, "server_observer", 2, db, func); // 2 is param counts } int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName) @@ -2007,7 +2065,7 @@ void SQLiteUtils::CalcHash(sqlite3_context *ctx, int argc, sqlite3_value **argv) int SQLiteUtils::GetDbSize(const std::string &dir, const std::string &dbName, uint64_t &size) { - std::string dataDir = dir + "/" + dbName + DBConstant::SQLITE_DB_EXTENSION; + std::string dataDir = dir + "/" + dbName + DBConstant::DB_EXTENSION; uint64_t localDbSize = 0; int errCode = OS::CalFileSize(dataDir, localDbSize); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h index f268a465293fcac9723abf5357b5f431457a0333..56149e2b7d86c74fb0bedfe6d904f500d8b74685 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sqlite/sqlite_utils.h @@ -24,6 +24,7 @@ #include "db_types.h" #include "schema_object.h" +#include "single_ver_utils.h" #include "store_types.h" #ifdef RELATIONAL_STORE #include "relational_schema_object.h" @@ -53,21 +54,6 @@ enum class TriggerModeEnum { std::string GetTriggerModeString(TriggerModeEnum mode); } -struct OpenDbProperties { - std::string uri {}; - bool createIfNecessary = true; - bool isMemDb = false; - std::vector sqls {}; - CipherType cipherType = CipherType::AES_256_GCM; - CipherPassword passwd {}; - std::string schema {}; - std::string subdir {}; - SecurityOption securityOpt {}; - int conflictReslovePolicy = DEFAULT_LAST_WIN; - bool createDirByStoreIdOnly = false; - uint32_t iterTimes = DBConstant::DEFAULT_ITER_TIMES; -}; - class SQLiteUtils { public: // Initialize the SQLiteUtils with the given properties. @@ -168,10 +154,12 @@ public: static int RegisterCloudDataChangeObserver(sqlite3 *db); + static int RegisterCloudDataChangeServerObserver(sqlite3 *db); + static int CreateRelationalLogTable(sqlite3 *db, const std::string &oriTableName); static int AddRelationalLogTableTrigger(sqlite3 *db, const std::string &identity, const TableInfo &table); - static int AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table); + static int AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive = false); static int CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName); static int CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName); @@ -205,6 +193,11 @@ public: static int SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes); + static void GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName, + ChangeProperties &changeProperties); + + static int CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated); + private: static int CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal); @@ -229,6 +222,7 @@ private: static void GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); static void GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv); static void CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv); + static void CloudDataChangedServerObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv); static int SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal, const std::vector &sqls); @@ -248,8 +242,6 @@ private: static int UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd, uint32_t iterTimes); - static int CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated); - static std::mutex logMutex_; static std::string lastErrorMsg_; }; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp index ecd52dad056abc004f07764da7ea40e559b114b6..1ac4cbc2c3278fbafb78c3a95db18f0baf9d247c 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.cpp @@ -29,12 +29,12 @@ const int StorageEngine::MAX_READ_SIZE = 16; StorageEngine::StorageEngine() : isUpdated_(false), isMigrating_(false), - engineState_(EngineState::INVALID), commitNotifyFunc_(nullptr), isInitialized_(false), perm_(OperatePerm::NORMAL_PERM), operateAbort_(false), - isExistConnection_(false) + isExistConnection_(false), + engineState_(EngineState::INVALID) {} StorageEngine::~StorageEngine() @@ -107,6 +107,11 @@ int StorageEngine::Init() return errCode; } +int StorageEngine::ReInit() +{ + return E_OK; +} + StorageExecutor *StorageEngine::FindExecutor(bool writable, OperatePerm perm, int &errCode, int waitTime) { if (GetEngineState() == EngineState::ENGINE_BUSY) { @@ -136,6 +141,7 @@ StorageExecutor *StorageEngine::FindExecutor(bool writable, OperatePerm perm, in StorageExecutor *StorageEngine::FindWriteExecutor(OperatePerm perm, int &errCode, int waitTime) { + LOGD("[FindWriteExecutor]Finding WriteExecutor"); std::unique_lock lock(writeMutex_); errCode = -E_BUSY; if (perm_ == OperatePerm::DISABLE_PERM || perm_ != perm) { @@ -149,7 +155,6 @@ StorageExecutor *StorageEngine::FindWriteExecutor(OperatePerm perm, int &errCode } return FetchStorageExecutor(true, writeIdleList_, writeUsingList_, errCode); } - // Not prohibited and there is an available handle bool result = writeCondition_.wait_for(lock, std::chrono::seconds(waitTime), [this, &perm]() { @@ -253,6 +258,11 @@ void StorageEngine::ClearCorruptedFlag() return; } +bool StorageEngine::IsEngineCorrupted() const +{ + return false; +} + void StorageEngine::Release() { CloseExecutor(); @@ -321,7 +331,8 @@ void StorageEngine::Abort(OperatePerm enableType) bool StorageEngine::IsNeedTobeReleased() const { - return true; + EngineState engineState = GetEngineState(); + return ((engineState == EngineState::MAINDB) || (engineState == EngineState::INVALID)); } const std::string &StorageEngine::GetIdentifier() const @@ -362,11 +373,6 @@ bool StorageEngine::IsExistConnection() const return isExistConnection_.load(); } -void StorageEngine::ClearEnginePasswd() -{ - return; -} - int StorageEngine::CheckEngineOption(const KvDBProperties &kvdbOption) const { return E_OK; @@ -465,4 +471,19 @@ void StorageEngine::WaitWriteHandleIdle() DBCommon::TransferStringToHex(identifier_).c_str(), writeIdleList_.size(), writeUsingList_.size(), engineAttr_.maxWriteNum); } + +void StorageEngine::IncreaseCacheRecordVersion() +{ + return; +} + +uint64_t StorageEngine::GetCacheRecordVersion() const +{ + return 0; +} + +uint64_t StorageEngine::GetAndIncreaseCacheRecordVersion() +{ + return 0; +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h index 36953171333a0bf549bcfb8f00e5b73b864b5161..6ba82fd2194e7746f8f6d017999238e0fadfb7a0 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine.h @@ -23,6 +23,7 @@ #include "db_types.h" #include "macro_utils.h" +#include "sqlite_utils.h" #include "storage_executor.h" #include "kvdb_commit_notify_filterable_data.h" @@ -44,10 +45,14 @@ public: int Init(); + virtual int ReInit(); + StorageExecutor *FindExecutor(bool writable, OperatePerm perm, int &errCode, int waitTime = MAX_WAIT_TIME); void Recycle(StorageExecutor *&handle); + virtual bool IsEngineCorrupted() const; + void Release(); int TryToDisable(bool isNeedCheckAll, OperatePerm disableType = OperatePerm::DISABLE_PERM); @@ -60,9 +65,9 @@ public: virtual const std::string &GetIdentifier() const; - virtual EngineState GetEngineState() const; + EngineState GetEngineState() const; - virtual void SetEngineState(EngineState state); + void SetEngineState(EngineState state); virtual int ExecuteMigrate(); @@ -72,14 +77,16 @@ public: bool IsExistConnection() const; - virtual void ClearEnginePasswd(); - virtual int CheckEngineOption(const KvDBProperties &kvdbOption) const; virtual bool IsMigrating() const; void WaitWriteHandleIdle(); + virtual void IncreaseCacheRecordVersion(); + virtual uint64_t GetCacheRecordVersion() const; + virtual uint64_t GetAndIncreaseCacheRecordVersion(); + protected: virtual int CreateNewExecutor(bool isWrite, StorageExecutor *&handle) = 0; @@ -91,11 +98,12 @@ protected: int InitReadWriteExecutors(); + OpenDbProperties option_; + StorageEngineAttr engineAttr_; bool isUpdated_; std::atomic isMigrating_; std::string identifier_; - EngineState engineState_; // Mutex for commitNotifyFunc_. mutable std::shared_mutex notifyMutex_; @@ -134,6 +142,8 @@ private: std::mutex idleMutex_; std::condition_variable idleCondition_; + + EngineState engineState_; }; } // namespace DistributedDB #endif // STORAGE_ENGINE_H diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp index 64d4d2fea192494fe527bad7da110a4ad12ff2a4..5536a9843efe29d94ca9217c96d479f2282d65dc 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_engine_manager.cpp @@ -17,6 +17,7 @@ #include "log_print.h" #include "db_errno.h" #include "runtime_context.h" +#include "rd_single_ver_storage_engine.h" #include "sqlite_single_ver_storage_engine.h" namespace DistributedDB { @@ -33,7 +34,13 @@ namespace { int GetDatabaseType(const KvDBProperties &property) { - return property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + return property.GetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); + } + + int IsSingleVerType(int databaseType) + { + return databaseType == KvDBProperties::SINGLE_VER_TYPE_SQLITE || + databaseType == KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL; } } @@ -190,16 +197,25 @@ void StorageEngineManager::LockStatusNotifier(bool isAccessControlled) } } +StorageEngine *CreateSingleVerStorageEngine(int databaseType) +{ + if (databaseType == KvDBProperties::SINGLE_VER_TYPE_SQLITE) { + return new (std::nothrow) SQLiteSingleVerStorageEngine(); + } else { + return new (std::nothrow) RdSingleVerStorageEngine(); + } + return nullptr; +} StorageEngine *StorageEngineManager::CreateStorageEngine(const KvDBProperties &property, int &errCode) { int databaseType = GetDatabaseType(property); - if (databaseType != KvDBProperties::SINGLE_VER_TYPE) { + if (!IsSingleVerType(databaseType)) { LOGE("[StorageEngineManager] Database type error : %d", databaseType); errCode = -E_NOT_SUPPORT; return nullptr; } - auto storageEngine = new (std::nothrow) SQLiteSingleVerStorageEngine(); + auto storageEngine = CreateSingleVerStorageEngine(databaseType); if (storageEngine == nullptr) { LOGE("[StorageEngineManager] Create storage engine failed"); errCode = -E_OUT_OF_MEMORY; diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h b/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h index 5a8ced1cb4fc6e9c295bb4cd43a07b0af0b15e8d..8a2c7d980dbd9f1e778dea9dc7982c6c323ce140 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_executor.h @@ -17,6 +17,8 @@ #define STORAGE_EXECUTOR_H #include "macro_utils.h" +#include "single_ver_natural_store_commit_notify_data.h" +#include "types_export.h" namespace DistributedDB { enum class EngineState { @@ -28,6 +30,76 @@ enum class EngineState { ENGINE_BUSY, // In order to change handle during the migration process, it is temporarily unavailable }; +enum class SingleVerDataType { + META_TYPE, + LOCAL_TYPE_SQLITE, + SYNC_TYPE, +}; + +enum class DataStatus { + NOEXISTED, + DELETED, + EXISTED, +}; + +enum class ExecutorState { + INVALID = -1, + MAINDB, + CACHEDB, + MAIN_ATTACH_CACHE, // After process crash and cacheDb existed + CACHE_ATTACH_MAIN, // while cacheDb migrating to mainDb +}; + +struct DataOperStatus { + DataStatus preStatus = DataStatus::NOEXISTED; + bool isDeleted = false; + bool isDefeated = false; // whether the put data is defeated. +}; + +struct SingleVerRecord { + Key key; + Value value; + Timestamp timestamp = 0; + uint64_t flag = 0; + std::string device; + std::string origDevice; + Key hashKey; + Timestamp writeTimestamp = 0; +}; + +struct DeviceInfo { + bool isLocal = false; + std::string deviceName; +}; + +struct LocalDataItem { + Key key; + Value value; + Timestamp timestamp = 0; + Key hashKey; + uint64_t flag = 0; +}; + +struct NotifyConflictAndObserverData { + SingleVerNaturalStoreCommitNotifyData *committedData = nullptr; + DataItem getData; + Key hashKey; + DataOperStatus dataStatus; +}; + +struct NotifyMigrateSyncData { + bool isRemote = false; + bool isRemoveDeviceData = false; + bool isPermitForceWrite = true; + SingleVerNaturalStoreCommitNotifyData *committedData = nullptr; + std::vector entries{}; +}; + +struct SyncDataDevices { + std::string origDev; + std::string dev; +}; + class StorageExecutor { public: explicit StorageExecutor(bool writable); diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp index e4d390758b2f66d4f0661ceea3abbc6e1d7d417e..881f256526cdc9495834ab6fef8c1c5604977d5b 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/storage_proxy.cpp @@ -164,19 +164,6 @@ int StorageProxy::GetUploadCount(const QuerySyncObject &query, const Timestamp & return store_->GetUploadCount(query, localMark, isCloudForcePush, count); } -int StorageProxy::FillCloudGid(const CloudSyncData &data) -{ - std::shared_lock readLock(storeMutex_); - if (store_ == nullptr) { - return -E_INVALID_DB; - } - if (!transactionExeFlag_.load()) { - LOGE("the transaction has not been started"); - return -E_TRANSACT_STATE; - } - return store_->FillCloudGid(data); -} - int StorageProxy::GetCloudData(const std::string &tableName, const Timestamp &timeRange, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { @@ -249,6 +236,9 @@ int StorageProxy::GetInfoByPrimaryKeyOrGid(const std::string &tableName, const V dataInfoWithLog.logInfo.timestamp = EraseNanoTime(dataInfoWithLog.logInfo.timestamp); dataInfoWithLog.logInfo.wTimestamp = EraseNanoTime(dataInfoWithLog.logInfo.wTimestamp); } + if ((dataInfoWithLog.logInfo.flag & static_cast(LogInfoFlag::FLAG_LOGIC_DELETE)) != 0) { + assetInfo.clear(); + } return errCode; } @@ -351,6 +341,9 @@ int StorageProxy::NotifyChangedData(const std::string &deviceName, ChangedData & if (store_ == nullptr) { return -E_INVALID_DB; } + ChangeProperties changeProperties; + store_->GetAndResetServerObserverData(changedData.tableName, changeProperties); + changedData.properties = changeProperties; store_->TriggerObserverAction(deviceName, std::move(changedData), true); return E_OK; } @@ -377,7 +370,7 @@ int StorageProxy::SetLogTriggerStatus(bool status) return store_->SetLogTriggerStatus(status); } -int StorageProxy::FillCloudGidAndAsset(OpType opType, const CloudSyncData &data) +int StorageProxy::FillCloudLogAndAsset(OpType opType, const CloudSyncData &data) { std::shared_lock readLock(storeMutex_); if (store_ == nullptr) { @@ -387,7 +380,7 @@ int StorageProxy::FillCloudGidAndAsset(OpType opType, const CloudSyncData &data) LOGE("the transaction has not been started"); return -E_TRANSACT_STATE; } - return store_->FillCloudGidAndAsset(opType, data); + return store_->FillCloudLogAndAsset(opType, data, true, false); } std::string StorageProxy::GetIdentify() const @@ -414,4 +407,101 @@ int StorageProxy::CleanWaterMark(const DistributedDB::TableName &tableName) } return cloudMetaData_->CleanWaterMark(tableName); } + +int StorageProxy::CleanWaterMarkInMemory(const DistributedDB::TableName &tableName) +{ + std::shared_lock readLock(storeMutex_); + if (cloudMetaData_ == nullptr) { + LOGW("[StorageProxy] CleanWaterMarkInMemory is nullptr return default"); + return -E_INVALID_DB; + } + cloudMetaData_->CleanWaterMarkInMemory(tableName); + return E_OK; +} + +int StorageProxy::GetCloudDataGid(const QuerySyncObject &query, Timestamp beginTime, std::vector &gid) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + return store_->GetCloudDataGid(query, beginTime, gid); +} + +int StorageProxy::CreateTempSyncTrigger(const std::string &tableName) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + return store_->CreateTempSyncTrigger(tableName); +} + +int StorageProxy::ClearAllTempSyncTrigger() +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + // Clean up all temporary triggers + return store_->ClearAllTempSyncTrigger(); +} + +int StorageProxy::IsSharedTable(const std::string &tableName, bool &IsSharedTable) +{ + std::unique_lock writeLock(storeMutex_); + if (store_ == nullptr) { + return -E_INVALID_DB; + } + IsSharedTable = store_->IsSharedTable(tableName); + return E_OK; +} + +void StorageProxy::FillCloudGidIfSuccess(const OpType opType, const CloudSyncData &data) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + LOGW("[StorageProxy] fill gid failed with store invalid"); + return; + } + int errCode = store_->FillCloudLogAndAsset(opType, data, true, true); + if (errCode != E_OK) { + LOGW("[StorageProxy] fill gid failed %d", errCode); + } +} + +void StorageProxy::SetCloudTaskConfig(const CloudTaskConfig &config) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + LOGW("[StorageProxy] fill gid failed with store invalid"); + return; + } + store_->SetCloudTaskConfig(config); +} + +int StorageProxy::GetAssetsByGidOrHashKey(const std::string &tableName, const std::string &gid, const Bytes &hashKey, + VBucket &assets) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return E_INVALID_DB; + } + TableSchema tableSchema; + int errCode = store_->GetCloudTableSchema(tableName, tableSchema); + if (errCode != E_OK) { + LOGE("get cloud table schema failed: %d", errCode); + return errCode; + } + return store_->GetAssetsByGidOrHashKey(tableSchema, gid, hashKey, assets); +} + +int StorageProxy::SetIAssetLoader(const std::shared_ptr &loader) +{ + std::shared_lock readLock(storeMutex_); + if (store_ == nullptr) { + return E_INVALID_DB; + } + return store_->SetIAssetLoader(loader); +} } diff --git a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp index 422784cb214809ac3e5674fcc59a76078b55b06f..dc78d004cfc3835b06d579667e76dba88ef77635 100644 --- a/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp +++ b/kv_store/frameworks/libs/distributeddb/storage/src/sync_able_kvdb.cpp @@ -120,7 +120,7 @@ void SyncAbleKvDB::SetSyncModuleActive() } IKvDBSyncInterface *syncInterface = GetSyncInterface(); if (syncInterface == nullptr) { - LOGF("KvDB got null sync interface."); + LOGD("KvDB got null sync interface."); return; } bool isSyncDualTupleMode = syncInterface->GetDbProperties().GetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, @@ -165,7 +165,7 @@ int SyncAbleKvDB::StartSyncerWithNoLock(bool isCheckSyncActive, bool isNeedActiv { IKvDBSyncInterface *syncInterface = GetSyncInterface(); if (syncInterface == nullptr) { - LOGF("KvDB got null sync interface."); + LOGD("KvDB got null sync interface."); return -E_INVALID_ARGS; } if (!isCheckSyncActive) { @@ -229,7 +229,7 @@ void SyncAbleKvDB::UserChangeHandle() bool isNeedActive = true; IKvDBSyncInterface *syncInterface = GetSyncInterface(); if (syncInterface == nullptr) { - LOGF("KvDB got null sync interface."); + LOGD("KvDB got null sync interface."); return; } bool isSyncDualTupleMode = syncInterface->GetDbProperties(). @@ -389,7 +389,7 @@ int SyncAbleKvDB::SetSyncRetry(bool isRetry) { IKvDBSyncInterface *syncInterface = GetSyncInterface(); if (syncInterface == nullptr) { - LOGF("KvDB got null sync interface."); + LOGD("KvDB got null sync interface."); return -E_INVALID_DB; } bool localOnly = syncInterface->GetDbProperties().GetBoolProp(KvDBProperties::LOCAL_ONLY, false); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/ability_sync.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/ability_sync.cpp index 6a4bbc60fabab482fb09e2f9d354890493c6f6db..9a6b42e63e015c15bad9494e7c2f35cb20db5a5d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/ability_sync.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/ability_sync.cpp @@ -491,12 +491,25 @@ bool AbilitySync::SecLabelCheck(const AbilitySyncRequestPacket *packet) const { int32_t remoteSecLabel = packet->GetSecLabel(); int32_t remoteSecFlag = packet->GetSecFlag(); + SecurityOption option; + int errCode = (static_cast(storageInterface_))->GetSecurityOption(option); + LOGI("[AbilitySync][RequestRecv] remote label:%d local l:%d, f:%d, errCode:%d", remoteSecLabel, + option.securityLabel, option.securityFlag, errCode); + if (remoteSecLabel == NOT_SURPPORT_SEC_CLASSIFICATION && errCode == -E_NOT_SUPPORT) { + return true; + } + uint32_t remoteSoftwareVersion = packet->GetSoftwareVersion(); + if (errCode != -E_NOT_SUPPORT && option.securityLabel == SecurityLabel::NOT_SET) { + LOGE("[AbilitySync][RequestRecv] local security label not set!"); + return false; + } + if (remoteSoftwareVersion >= SOFTWARE_VERSION_RELEASE_7_0 && remoteSecLabel == SecurityLabel::NOT_SET) { + LOGE("[AbilitySync][RequestRecv] remote security label not set!"); + return false; + } if (remoteSecLabel == NOT_SURPPORT_SEC_CLASSIFICATION || remoteSecLabel == SecurityLabel::NOT_SET) { return true; } - SecurityOption option; - int errCode = (static_cast(storageInterface_))->GetSecurityOption(option); - LOGI("[AbilitySync][RequestRecv] local l:%d, f:%d, errCode:%d", option.securityLabel, option.securityFlag, errCode); if (errCode == -E_NOT_SUPPORT || (errCode == E_OK && option.securityLabel == SecurityLabel::NOT_SET)) { return true; } @@ -506,11 +519,10 @@ bool AbilitySync::SecLabelCheck(const AbilitySyncRequestPacket *packet) const } if (remoteSecLabel == option.securityLabel) { return true; - } else { - LOGE("[AbilitySync][RequestRecv] check error remote:%d , %d local:%d , %d", - remoteSecLabel, remoteSecFlag, option.securityLabel, option.securityFlag); - return false; } + LOGE("[AbilitySync][RequestRecv] check error remote:%d , %d local:%d , %d", + remoteSecLabel, remoteSecFlag, option.securityLabel, option.securityFlag); + return false; } void AbilitySync::HandleVersionV3RequestParam(const AbilitySyncRequestPacket *packet, ISyncTaskContext *context) diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp index de16c00c787cd859b0bc35249cf1d902a9979dea..09b53016642986970f242d53f9d38a19afdb5c84 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_db_proxy.cpp @@ -68,6 +68,7 @@ int CloudDBProxy::BatchUpdate(const std::string &tableName, std::vector context->MoveInRecordAndExtend(record, extend); int errCode = InnerAction(context, cloudDb, UPDATE); uploadInfo = context->GetInfo(); + context->MoveOutRecordAndExtend(record, extend); return errCode; } @@ -84,6 +85,7 @@ int CloudDBProxy::BatchDelete(const std::string &tableName, std::vector context->SetTableName(tableName); int errCode = InnerAction(context, cloudDb, DELETE); uploadInfo = context->GetInfo(); + context->MoveOutRecordAndExtend(record, extend); return errCode; } @@ -247,12 +249,12 @@ DBStatus CloudDBProxy::DMLActionTask(const std::shared_ptr & } case UPDATE: { status = cloudDb->BatchUpdate(context->GetTableName(), std::move(record), extend); - // no need to MoveIn, only insert need extend for insert gid + context->MoveInExtend(extend); break; } case DELETE: { status = cloudDb->BatchDelete(context->GetTableName(), extend); - // no need to MoveIn, only insert need extend for insert gid + context->MoveInExtend(extend); break; } default: { @@ -342,6 +344,8 @@ int CloudDBProxy::GetInnerErrorCode(DBStatus status) return -E_CLOUD_LOCK_ERROR; case CLOUD_ASSET_SPACE_INSUFFICIENT: return -E_CLOUD_ASSET_SPACE_INSUFFICIENT; + case CLOUD_VERSION_CONFLICT: + return -E_CLOUD_VERSION_CONFLICT; default: return -E_CLOUD_ERROR; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h index 169c519a2b5d1dea49d1de40ce73aa403ed9009b..5c2a1805f7064eee84f7efafb8ea3c18b51d640d 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_strategy.h @@ -47,7 +47,8 @@ public: static bool IsDelete(const LogInfo &info) { - return (info.flag & 0x1) == 1; + return (info.flag & static_cast(LogInfoFlag::FLAG_DELETE)) == + static_cast(LogInfoFlag::FLAG_DELETE); } }; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp index 4e80f0e5801501ae6270c6e39b2ae9e50af7d0bf..60fd602196f3a1c4764c6e2bd7900caaf13973ed 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_tag_assets.cpp @@ -24,7 +24,11 @@ void TagSingleAsset(AssetOpType flag, AssetStatus status, Asset &asset, Assets & } else { asset.flag = static_cast(flag); } - asset.status = static_cast(status); + uint32_t newStatus = static_cast(status); + if (flag == AssetOpType::INSERT && status == AssetStatus::DOWNLOADING) { + newStatus |= AssetStatus::DOWNLOAD_WITH_NULL; + } + asset.status = static_cast(newStatus); Timestamp timestamp; errCode = OS::GetCurrentSysTimeInMicrosecond(timestamp); @@ -87,12 +91,11 @@ Assets TagAssets(const std::string &assetFieldName, VBucket &coveredData, VBucke bool beCoveredHasAssets = IsDataContainField(assetFieldName, beCoveredData); bool coveredHasAssets = IsDataContainField(assetFieldName, coveredData); if (!beCoveredHasAssets) { - if (!coveredHasAssets) { - return res; + if (coveredHasAssets) { + // all the element in assets will be set to INSERT + TagAssetsWithNormalStatus(setNormalStatus, + AssetOpType::INSERT, std::get(coveredData[assetFieldName]), res, errCode); } - // all the element in assets will be set to INSERT - TagAssetsWithNormalStatus(setNormalStatus, - AssetOpType::INSERT, std::get(coveredData[assetFieldName]), res, errCode); return res; } if (!coveredHasAssets) { @@ -116,7 +119,8 @@ Assets TagAssets(const std::string &assetFieldName, VBucket &coveredData, VBucke if (beCoveredAsset.hash != coveredAsset.hash) { TagAssetWithNormalStatus(setNormalStatus, AssetOpType::UPDATE, coveredAsset, res, errCode); } else { - TagAssetWithNormalStatus(setNormalStatus, AssetOpType::NO_CHANGE, coveredAsset, res, errCode); + TagAssetWithNormalStatus(setNormalStatus, beCoveredAsset.status == AssetStatus::DELETE ? + AssetOpType::UPDATE : AssetOpType::NO_CHANGE, coveredAsset, res, errCode); } // Erase element which has been handled, remaining element will be set to Insert coveredAssetsIndexMap.erase(it); diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp index d30854572001e00bb3ba0b7738a61a4b00957196..4e31d7b9e76628bfcded70bdbfac43be000e7fd4 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.cpp @@ -12,9 +12,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include "cloud/asset_operation_utils.h" +#include "cloud/cloud_db_constant.h" #include "db_errno.h" #include "log_print.h" -#include "cloud/cloud_db_constant.h" #include "cloud/cloud_sync_utils.h" namespace DistributedDB { @@ -70,6 +71,7 @@ void CloudSyncUtils::RemoveDataExceptExtendInfo(VBucket &datum, const std::vecto key != CloudDbConstant::MODIFY_FIELD && key != CloudDbConstant::DELETE_FIELD && key != CloudDbConstant::CURSOR_FIELD && + key != CloudDbConstant::VERSION_FIELD && (std::find(pkColNames.begin(), pkColNames.end(), key) == pkColNames.end())) { item = datum.erase(item); } else { @@ -80,7 +82,8 @@ void CloudSyncUtils::RemoveDataExceptExtendInfo(VBucket &datum, const std::vecto AssetOpType CloudSyncUtils::StatusToFlag(AssetStatus status) { - switch (status) { + auto tmpStatus = static_cast(AssetOperationUtils::EraseBitMask(static_cast(status))); + switch (tmpStatus) { case AssetStatus::INSERT: return AssetOpType::INSERT; case AssetStatus::DELETE: @@ -428,4 +431,119 @@ void CloudSyncUtils::ClearWithoutData(ICloudSyncer::SyncParam ¶m) param.withoutRowIdData.updateData.clear(); param.withoutRowIdData.assetInsertData.clear(); } + +int CloudSyncUtils::FillAssetIdToAssets(CloudSyncBatch &data) +{ + if (data.extend.size() != data.assets.size()) { + LOGE("[CloudSyncUtils][FillAssetIdToAssets] Extend size does not match the assets size."); + return -E_CLOUD_ERROR; + } + int errCode = E_OK; + for (size_t i = 0; i < data.assets.size(); i++) { + if (data.assets[i].empty()) { + continue; + } + if (data.extend[i].find(CloudDbConstant::ERROR_FIELD) != data.extend[i].end()) { + errCode = -E_CLOUD_ERROR; + continue; + } + for (auto &[col, value] : data.assets[i]) { + if (!CheckIfContainsInsertAssets(value)) { + continue; + } + auto extendIt = data.extend[i].find(col); + if (extendIt == data.extend[i].end()) { + LOGE("[CloudSyncUtils][FillAssetIdToAssets] Asset field name can not find in extend."); + errCode = -E_CLOUD_ERROR; + continue; + } + if (extendIt->second.index() != value.index()) { + LOGE("[CloudSyncUtils][FillAssetIdToAssets] Asset field type and type in extend is not the same."); + errCode = -E_CLOUD_ERROR; + continue; + } + int ret = FillAssetIdToAssetData(extendIt->second, value); + if (ret != E_OK) { + LOGE("[CloudSyncUtils][FillAssetIdToAssets] Failed to fill assetId to Asset, %d.", ret); + errCode = -E_CLOUD_ERROR; + } + } + } + return errCode; +} + +int CloudSyncUtils::FillAssetIdToAssetData(const Type &extend, Type &assetData) +{ + if (extend.index() == TYPE_INDEX) { + if (std::get(assetData).name != std::get(extend).name) { + LOGE("[CloudSyncUtils][FillAssetIdToAssetData] Asset name can not find in extend."); + return -E_CLOUD_ERROR; + } + if (std::get(extend).assetId.empty()) { + LOGE("[CloudSyncUtils][FillAssetIdToAssetData] Asset id is empty."); + return -E_CLOUD_ERROR; + } + std::get(assetData).assetId = std::get(extend).assetId; + } + if (extend.index() == TYPE_INDEX) { + int errCode = FillAssetIdToAssetsData(std::get(extend), std::get(assetData)); + if (errCode != E_OK) { + LOGE("[CloudSyncUtils][FillAssetIdToAssetData] Failed to fill assetId to Assets, %d.", errCode); + return errCode; + } + } + return E_OK; +} + +int CloudSyncUtils::FillAssetIdToAssetsData(const Assets &extend, Assets &assets) +{ + int errCode = E_OK; + for (auto &asset : assets) { + if (asset.flag != static_cast(AssetOpType::INSERT)) { + continue; + } + auto extendAssets = extend; + bool isAssetExisted = false; + for (const auto &extendAsset : extendAssets) { + if (asset.name == extendAsset.name && !extendAsset.assetId.empty()) { + asset.assetId = extendAsset.assetId; + isAssetExisted = true; + break; + } + } + if (!isAssetExisted) { + LOGE("[CloudSyncUtils][FillAssetIdToAssets] Assets name can not find in extend."); + errCode = -E_CLOUD_ERROR; + } + } + return errCode; +} + +bool CloudSyncUtils::CheckIfContainsInsertAssets(const Type &assetData) +{ + if (assetData.index() == TYPE_INDEX) { + if (std::get(assetData).flag != static_cast(AssetOpType::INSERT)) { + return false; + } + } else if (assetData.index() == TYPE_INDEX) { + bool hasInsertAsset = false; + for (const auto &asset : std::get(assetData)) { + if (asset.flag == static_cast(AssetOpType::INSERT)) { + hasInsertAsset = true; + break; + } + } + if (!hasInsertAsset) { + return false; + } + } + return true; +} + +void CloudSyncUtils::UpdateAssetsFlag(CloudSyncData &uploadData) +{ + AssetOperationUtils::UpdateAssetsFlag(uploadData.insData.record, uploadData.insData.assets); + AssetOperationUtils::UpdateAssetsFlag(uploadData.updData.record, uploadData.updData.assets); + AssetOperationUtils::UpdateAssetsFlag(uploadData.delData.record, uploadData.delData.assets); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h index a78dea6ca8658e5230cf7ca1407a4de2ea28c71c..92b2aad9d8624441d1a939bdbf84820f8e400212 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_sync_utils.h @@ -85,6 +85,16 @@ public: std::vector> &deletedList); static void ClearWithoutData(ICloudSyncer::SyncParam ¶m); + + static int FillAssetIdToAssets(CloudSyncBatch &data); + + static int FillAssetIdToAssetData(const Type &extend, Type &assetData); + + static int FillAssetIdToAssetsData(const Assets &extend, Assets &assets); + + static bool CheckIfContainsInsertAssets(const Type &assetData); + + static void UpdateAssetsFlag(CloudSyncData &uploadData); }; } #endif // CLOUD_SYNC_UTILS_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp index 05894572048a61f2d25242dfba2244581864611e..d525c3df312119c094a5f0ce5edc8940573d5556 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.cpp @@ -18,6 +18,7 @@ #include #include +#include "cloud/asset_operation_utils.h" #include "cloud/cloud_db_constant.h" #include "cloud/cloud_storage_utils.h" #include "cloud/icloud_db.h" @@ -96,6 +97,7 @@ void CloudSyncer::SetCloudDB(const std::shared_ptr &cloudDB) void CloudSyncer::SetIAssetLoader(const std::shared_ptr &loader) { + storageProxy_->SetIAssetLoader(loader); cloudDB_.SetIAssetLoader(loader); LOGI("[CloudSyncer] SetIAssetLoader finish"); } @@ -110,10 +112,7 @@ void CloudSyncer::Close() } // mark current task db_closed SetTaskFailed(currentTask, -E_DB_CLOSED); - { - std::lock_guard autoLock(dataLock_); - currentContext_.locker = nullptr; - } + UnlockIfNeed(); cloudDB_.Close(); { LOGD("[CloudSyncer] begin wait current task finished"); @@ -134,6 +133,8 @@ void CloudSyncer::Close() taskQueue_.clear(); priorityTaskQueue_.clear(); cloudTaskInfos_.clear(); + resumeTaskInfos_.clear(); + currentContext_.notifier = nullptr; } // notify all DB_CLOSED for (auto &info: infoList) { @@ -198,6 +199,7 @@ int CloudSyncer::DoSync(TaskId taskId) std::lock_guard autoLock(dataLock_); taskInfo = cloudTaskInfos_[taskId]; } + storageProxy_->SetCloudTaskConfig({ !taskInfo.priorityTask }); int errCode = LockCloudIfNeed(taskId); if (errCode != E_OK) { return errCode; @@ -267,10 +269,20 @@ int CloudSyncer::DoSyncInner(const CloudTaskInfo &taskInfo, const bool needUploa int errCode = E_OK; for (size_t i = GetStartTableIndex(taskInfo.taskId, false); i < taskInfo.table.size(); ++i) { LOGD("[CloudSyncer] try download table, index: %zu", i); + std::string table; { std::lock_guard autoLock(dataLock_); currentContext_.tableName = taskInfo.table[i]; + table = currentContext_.tableName; } + bool isShared = false; + errCode = storageProxy_->IsSharedTable(table, isShared); + if (errCode != E_OK) { + LOGE("[CloudSyncer] check shared table failed %d", errCode); + return errCode; + } + // shared table not allow logic delete + storageProxy_->SetCloudTaskConfig({ !taskInfo.priorityTask && !isShared }); errCode = CheckTaskIdValid(taskInfo.taskId); if (errCode != E_OK) { LOGW("[CloudSyncer] task is invalid, abort sync"); @@ -290,7 +302,6 @@ int CloudSyncer::DoSyncInner(const CloudTaskInfo &taskInfo, const bool needUploa return errCode; } } - return DoUploadInNeed(taskInfo, needUpload); } @@ -539,18 +550,12 @@ int CloudSyncer::CloudDbDownloadAssets(TaskId taskId, InnerProcessInfo &info, co // Process result of each asset commitList.push_back(std::make_tuple(downloadItem.gid, std::move(downloadItem.assets), errorCode == E_OK)); downloadStatus = downloadStatus == E_OK ? errorCode : downloadStatus; - if ((i + 1) % MAX_DOWNLOAD_COMMIT_LIMIT == 0 || i == (commitList.size() - 1)) { - int ret = CommitDownloadResult(info, commitList); - if (ret != E_OK) { - return ret; - } + int ret = CommitDownloadResult(info, commitList); + if (ret != E_OK) { + return ret; } } LOGD("Download status is %d", downloadStatus); - int ret = CommitDownloadResult(info, commitList); - if (ret != E_OK) { - return ret; - } return errorCode == E_OK ? downloadStatus : errorCode; } @@ -636,7 +641,7 @@ int CloudSyncer::TagStatus(bool isExist, SyncParam ¶m, size_t idx, DataInfo return TagDownloadAssets(hashKey, idx, param, dataInfo, localAssetInfo); } -int CloudSyncer::TagDownloadAssets(const Key &hashKey, size_t idx, SyncParam ¶m, DataInfo &dataInfo, +int CloudSyncer::TagDownloadAssets(const Key &hashKey, size_t idx, SyncParam ¶m, const DataInfo &dataInfo, VBucket &localAssetInfo) { int ret = E_OK; @@ -733,8 +738,7 @@ int CloudSyncer::SaveDatum(SyncParam ¶m, size_t idx, std::vectorIsSharedTable(param.tableName, isSharedTable); + if (errCode != E_OK) { + LOGE("[CloudSyncer] HandleTagAssets cannot judge the table is a shared table. %d", errCode); + return errCode; + } + if (!isSharedTable) { + (void)NotifyChangedData(std::move(changedAssets)); + } + if (ret == -E_TASK_PAUSED) { + LOGD("[CloudSyncer] current task was paused, abort dowload asset"); + std::lock_guard autoLock(dataLock_); + resumeTaskInfos_[currentContext_.currentTaskId].skipQuery = true; + return ret; + } else if (skipSave) { + std::lock_guard autoLock(dataLock_); + resumeTaskInfos_[currentContext_.currentTaskId].skipQuery = false; + } + if (ret != E_OK) { + LOGE("[CloudSyncer] Cannot notify downloadAssets due to error %d", ret); + } + return ret; +} + int CloudSyncer::SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam ¶m) { ChangedData changedData; @@ -939,6 +972,7 @@ int CloudSyncer::SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam &pa if (!skipSave) { param.changedData = changedData; param.downloadData.opType.resize(param.downloadData.data.size()); + param.downloadData.existDataKey.resize(param.downloadData.data.size()); ret = SaveDataInTransaction(taskId, param); if (ret != E_OK) { return ret; @@ -950,21 +984,8 @@ int CloudSyncer::SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam &pa return ret; } } - // Begin downloading assets - ChangedData changedAssets; - ret = DownloadAssets(param.info, param.pkColNames, param.dupHashKeySet, changedAssets); - (void)NotifyChangedData(std::move(changedAssets)); - if (ret == -E_TASK_PAUSED) { - LOGD("[CloudSyncer] current task was paused, abort download asset"); - std::lock_guard autoLock(dataLock_); - resumeTaskInfos_[currentContext_.currentTaskId].skipQuery = true; - return ret; - } else if (skipSave) { - std::lock_guard autoLock(dataLock_); - resumeTaskInfos_[currentContext_.currentTaskId].skipQuery = false; - } + ret = DoDownloadAssets(skipSave, param); if (ret != E_OK) { - LOGE("[CloudSyncer] Cannot notify downloadAssets due to error %d", ret); return ret; } UpdateCloudWaterMark(taskId, param); @@ -995,7 +1016,9 @@ int CloudSyncer::DoDownload(CloudSyncer::TaskId taskId) LOGE("[CloudSyncer] get sync param for download failed %d", errCode); return errCode; } + (void)storageProxy_->CreateTempSyncTrigger(param.tableName); errCode = DoDownloadInner(taskId, param); + (void)storageProxy_->ClearAllTempSyncTrigger(); if (errCode == -E_TASK_PAUSED) { std::lock_guard autoLock(dataLock_); resumeTaskInfos_[taskId].syncParam = std::move(param); @@ -1064,13 +1087,10 @@ int CloudSyncer::PreCheckUpload(CloudSyncer::TaskId &taskId, const TableName &ta return ret; } -int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadParam, InnerProcessInfo &innerProcessInfo) +int CloudSyncer::SaveUploadData(Info &insertInfo, Info &updateInfo, Info &deleteInfo, CloudSyncData &uploadData, + InnerProcessInfo &innerProcessInfo) { int errCode = E_OK; - Info insertInfo; - Info updateInfo; - Info deleteInfo; - if (!uploadData.delData.record.empty() && !uploadData.delData.extend.empty()) { errCode = cloudDB_.BatchDelete(uploadData.tableName, uploadData.delData.record, uploadData.delData.extend, deleteInfo); @@ -1081,32 +1101,30 @@ int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadPar } if (!uploadData.insData.record.empty() && !uploadData.insData.extend.empty()) { - errCode = cloudDB_.BatchInsert(uploadData.tableName, uploadData.insData.record, - uploadData.insData.extend, insertInfo); + errCode = BatchInsert(insertInfo, uploadData, innerProcessInfo); if (errCode != E_OK) { return errCode; } - // we need to fill back gid after insert data to cloud. - int ret = storageProxy_->FillCloudGidAndAsset(OpType::INSERT, uploadData); - if (ret != E_OK) { - LOGE("[CloudSyncer] Failed to fill back when doing upload insData, %d.", ret); - return ret; - } - innerProcessInfo.upLoadInfo.successCount += insertInfo.successCount; } if (!uploadData.updData.record.empty() && !uploadData.updData.extend.empty()) { - errCode = cloudDB_.BatchUpdate(uploadData.tableName, uploadData.updData.record, - uploadData.updData.extend, updateInfo); - if (errCode != E_OK) { - return errCode; - } - errCode = storageProxy_->FillCloudGidAndAsset(OpType::UPDATE, uploadData); - if (errCode != E_OK) { - LOGE("[CloudSyncer] Failed to fill back when doing upload updData, %d.", errCode); - return errCode; - } - innerProcessInfo.upLoadInfo.successCount += updateInfo.successCount; + errCode = BatchUpdate(updateInfo, uploadData, innerProcessInfo); + } + return errCode; +} + +int CloudSyncer::DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadParam, InnerProcessInfo &innerProcessInfo) +{ + int errCode = storageProxy_->FillCloudLogAndAsset(OpType::SET_UPLOADING, uploadData); + if (errCode != E_OK) { + return errCode; + } + Info insertInfo; + Info updateInfo; + Info deleteInfo; + errCode = SaveUploadData(insertInfo, updateInfo, deleteInfo, uploadData, innerProcessInfo); + if (errCode != E_OK) { + return errCode; } bool lastBatch = innerProcessInfo.upLoadInfo.successCount == innerProcessInfo.upLoadInfo.total; if (lastBatch) { @@ -1261,6 +1279,7 @@ int CloudSyncer::PreProcessBatchUpload(TaskId taskId, const InnerProcessInfo &in LOGE("TagUploadAssets report ERROR, cannot tag uploadAssets"); return ret; } + CloudSyncUtils::UpdateAssetsFlag(uploadData); // get local water mark to be updated in future. ret = CloudSyncUtils::UpdateExtendTime(uploadData, innerProcessInfo.upLoadInfo.total, taskId, localMark); if (ret != E_OK) { @@ -1695,6 +1714,19 @@ int CloudSyncer::CleanCloudData(ClearMode mode, const std::vector & return errCode; } +int CloudSyncer::CleanWaterMarkInMemory(const std::set &tableNameList) +{ + std::lock_guard lock(syncMutex_); + for (const auto &tableName: tableNameList) { + int ret = storageProxy_->CleanWaterMarkInMemory(tableName); + if (ret != E_OK) { + LOGE("[CloudSyncer] failed to clean cloud water mark in memory, %d.", ret); + return ret; + } + } + return E_OK; +} + void CloudSyncer::UpdateCloudWaterMark(TaskId taskId, const SyncParam ¶m) { bool isUpdateCloudCursor = true; @@ -1755,13 +1787,15 @@ int CloudSyncer::TagStatusByStrategy(bool isExist, SyncParam ¶m, DataInfo &d return E_OK; } -int CloudSyncer::GetLocalInfo(const std::string &tableName, const VBucket &cloudData, DataInfoWithLog &logInfo, +int CloudSyncer::GetLocalInfo(size_t index, SyncParam ¶m, DataInfoWithLog &logInfo, std::map &localLogInfoCache, VBucket &localAssetInfo) { - int errCode = storageProxy_->GetInfoByPrimaryKeyOrGid(tableName, cloudData, logInfo, localAssetInfo); + int errCode = storageProxy_->GetInfoByPrimaryKeyOrGid(param.tableName, param.downloadData.data[index], + logInfo, localAssetInfo); if (errCode != E_OK) { return errCode; } + param.downloadData.existDataKey[index] = logInfo.logInfo.dataKey; std::string hashKey(logInfo.logInfo.hashKey.begin(), logInfo.logInfo.hashKey.end()); if (localLogInfoCache.find(hashKey) != localLogInfoCache.end()) { LOGD("[CloudSyncer] exist same record in one batch, override from cache record!"); @@ -1840,16 +1874,23 @@ int CloudSyncer::LockCloudIfNeed(TaskId taskId) void CloudSyncer::UnlockIfNeed() { - std::lock_guard autoLock(dataLock_); - if ((cloudTaskInfos_[currentContext_.currentTaskId].priorityTask && priorityTaskQueue_.size() > 1) || - (!cloudTaskInfos_[currentContext_.currentTaskId].priorityTask && !priorityTaskQueue_.empty())) { - LOGD("[CloudSyncer] don't unlock because exist priority task"); - return; - } - if (currentContext_.locker == nullptr) { - LOGW("[CloudSyncer] locker is nullptr when unlock it"); // should not happen + std::shared_ptr cacheLocker; + { + std::lock_guard autoLock(dataLock_); + if (!closed_ && + ((cloudTaskInfos_[currentContext_.currentTaskId].priorityTask && priorityTaskQueue_.size() > 1) || + (!cloudTaskInfos_[currentContext_.currentTaskId].priorityTask && !priorityTaskQueue_.empty()))) { + LOGD("[CloudSyncer] don't unlock because exist priority task"); + return; + } + if (currentContext_.locker == nullptr) { + LOGW("[CloudSyncer] locker is nullptr when unlock it"); // should not happen + } + cacheLocker = currentContext_.locker; + currentContext_.locker = nullptr; } - currentContext_.locker = nullptr; + // unlock without mutex + cacheLocker = nullptr; } void CloudSyncer::ClearCurrentContextWithoutLock() @@ -1922,14 +1963,21 @@ int CloudSyncer::DownloadOneBatch(TaskId taskId, SyncParam ¶m) int CloudSyncer::DownloadOneAssetRecord(const std::set &dupHashKeySet, const DownloadList &downloadList, DownloadItem &downloadItem, InnerProcessInfo &info, ChangedData &changedAssets) { - std::map downloadAssets(downloadItem.assets); - CloudStorageUtils::EraseNoChangeAsset(downloadAssets); - if (downloadAssets.empty()) { // Download data (include deleting) + CloudStorageUtils::EraseNoChangeAsset(downloadItem.assets); + if (downloadItem.assets.empty()) { // Download data (include deleting) return E_OK; } - int errorCode = cloudDB_.Download(info.tableName, downloadItem.gid, downloadItem.prefix, downloadAssets); - if (errorCode == -E_NOT_SET) { - return -E_NOT_SET; + bool isSharedTable = false; + int errorCode = storageProxy_->IsSharedTable(info.tableName, isSharedTable); + if (errorCode != E_OK) { + LOGE("[CloudSyncer] DownloadOneAssetRecord cannot judge the table is a shared table. %d", errorCode); + return errorCode; + } + if (!isSharedTable) { + errorCode = DownloadAssetsOneByOne(info, downloadItem, downloadItem.assets); + if (errorCode == -E_NOT_SET) { + return -E_NOT_SET; + } } if (errorCode != E_OK) { info.downLoadInfo.failCount += 1; @@ -1945,7 +1993,6 @@ int CloudSyncer::DownloadOneAssetRecord(const std::set &dupHashKeySet, cons if (downloadItem.strategy == OpType::DELETE) { return E_OK; } - CloudStorageUtils::MergeDownloadAsset(downloadAssets, downloadItem.assets); return errorCode; } @@ -2079,94 +2126,6 @@ Timestamp CloudSyncer::GetResumeWaterMark(TaskId taskId) return resumeTaskInfos_[taskId].lastLocalWatermark; } -void CloudSyncer::ReloadWaterMarkIfNeed(TaskId taskId, WaterMark &waterMark) -{ - Timestamp cacheWaterMark = GetResumeWaterMark(taskId); - waterMark = cacheWaterMark == 0u ? waterMark : cacheWaterMark; - RecordWaterMark(taskId, 0u); -} - -void CloudSyncer::ReloadUploadInfoIfNeed(TaskId taskId, const UploadParam ¶m, InnerProcessInfo &info) -{ - info.upLoadInfo.total = static_cast(param.count); - { - std::lock_guard autoLock(dataLock_); - if (!cloudTaskInfos_[taskId].resume) { - return; - } - } - uint32_t lastSuccessCount = GetLastUploadSuccessCount(info.tableName); - if (lastSuccessCount == 0) { - return; - } - info.upLoadInfo.total += lastSuccessCount; - info.upLoadInfo.successCount += lastSuccessCount; - LOGD("[CloudSyncer] resume upload, last success count %" PRIu32, lastSuccessCount); -} - -uint32_t CloudSyncer::GetLastUploadSuccessCount(const std::string &tableName) -{ - std::lock_guard autoLock(dataLock_); - return currentContext_.notifier->GetLastUploadSuccessCount(tableName); -} - -int CloudSyncer::FillDownloadExtend(TaskId taskId, const std::string &tableName, const std::string &cloudWaterMark, - VBucket &extend) -{ - extend = { - {CloudDbConstant::CURSOR_FIELD, cloudWaterMark} - }; - - QuerySyncObject obj = GetQuerySyncObject(tableName); - if (obj.IsContainQueryNodes()) { - int errCode = GetCloudGid(taskId, tableName, obj); - if (errCode != E_OK) { - LOGE("[CloudSyncer] Failed to get cloud gid when fill extend, %d.", errCode); - return errCode; - } - Bytes bytes; - bytes.resize(obj.CalculateParcelLen(SOFTWARE_VERSION_CURRENT)); - Parcel parcel(bytes.data(), bytes.size()); - errCode = obj.SerializeData(parcel, SOFTWARE_VERSION_CURRENT); - if (errCode != E_OK) { - LOGE("[CloudSyncer] Query serialize failed %d", errCode); - return errCode; - } - extend[CloudDbConstant::TYPE_FIELD] = static_cast(CloudQueryType::QUERY_FIELD); - extend[CloudDbConstant::QUERY_FIELD] = bytes; - } else { - extend[CloudDbConstant::TYPE_FIELD] = static_cast(CloudQueryType::FULL_TABLE); - } - return E_OK; -} - -int CloudSyncer::GetCloudGid(TaskId taskId, const std::string &tableName, QuerySyncObject &obj) -{ - std::vector cloudGid; - bool isCloudForcePush = cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; - int errCode = storageProxy_->GetCloudGid(obj, isCloudForcePush, cloudGid); - if (errCode != E_OK) { - LOGE("[CloudSyncer] Failed to get cloud gid, %d.", errCode); - } else if (!cloudGid.empty()) { - obj.SetCloudGid(cloudGid); - } - return errCode; -} - -QuerySyncObject CloudSyncer::GetQuerySyncObject(const std::string &tableName) -{ - std::lock_guard autoLock(dataLock_); - for (const auto &item : cloudTaskInfos_[currentContext_.currentTaskId].queryList) { - if (item.GetTableName() == tableName) { - return item; - } - } - LOGW("[CloudSyncer] not found query in cache"); - QuerySyncObject querySyncObject; - querySyncObject.SetTableName(tableName); - return querySyncObject; -} - CloudSyncer::InnerProcessInfo CloudSyncer::GetInnerProcessInfo(const std::string &tableName, UploadParam &uploadParam) { InnerProcessInfo info; @@ -2175,15 +2134,4 @@ CloudSyncer::InnerProcessInfo CloudSyncer::GetInnerProcessInfo(const std::string ReloadUploadInfoIfNeed(uploadParam.taskId, uploadParam, info); return info; } - -void CloudSyncer::NotifyUploadFailed(int errCode, InnerProcessInfo &info) -{ - LOGE("[CloudSyncer] Failed to do upload, %d", errCode); - info.upLoadInfo.failCount = info.upLoadInfo.total - info.upLoadInfo.successCount; - info.tableStatus = ProcessStatus::FINISHED; - { - std::lock_guard autoLock(dataLock_); - currentContext_.notifier->UpdateProcess(info); - } -} } // namespace DistributedDB diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h index 903beb8092fd15a7042429af60700164d1a8d9de..022ed2f3b23630f10cce46aa97b795bd793e7177 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer.h @@ -54,6 +54,8 @@ public: int CleanCloudData(ClearMode mode, const std::vector &tableNameList, const RelationalSchemaObject &localSchema); + int CleanWaterMarkInMemory(const std::set &tableNameList); + int32_t GetCloudSyncTaskCount(); void Close(); @@ -123,6 +125,9 @@ protected: int PreCheck(TaskId &taskId, const TableName &tableName); + int SaveUploadData(Info &insertInfo, Info &updateInfo, Info &deleteInfo, CloudSyncData &uploadData, + InnerProcessInfo &innerProcessInfo); + int DoBatchUpload(CloudSyncData &uploadData, UploadParam &uploadParam, InnerProcessInfo &innerProcessInfo); int PreProcessBatchUpload(TaskId taskId, const InnerProcessInfo &innerProcessInfo, @@ -185,6 +190,8 @@ protected: int SaveChangedData(SyncParam ¶m, size_t dataIndex, const DataInfo &dataInfo, std::vector> &deletedList); + int DoDownloadAssets(bool skipSave, SyncParam ¶m); + int SaveDataNotifyProcess(CloudSyncer::TaskId taskId, SyncParam ¶m); void NotifyInBatchUpload(const UploadParam &uploadParam, const InnerProcessInfo &innerProcessInfo, bool lastBatch); @@ -203,7 +210,7 @@ protected: int HandleTagAssets(const Key &hashKey, const DataInfo &dataInfo, size_t idx, SyncParam ¶m, VBucket &localAssetInfo); - int TagDownloadAssets(const Key &hashKey, size_t idx, SyncParam ¶m, DataInfo &dataInfo, + int TagDownloadAssets(const Key &hashKey, size_t idx, SyncParam ¶m, const DataInfo &dataInfo, VBucket &localAssetInfo); int TagUploadAssets(CloudSyncData &uploadData); @@ -245,7 +252,7 @@ protected: void ModifyFieldNameToLower(VBucket &data); - int GetLocalInfo(const std::string &tableName, const VBucket &cloudData, DataInfoWithLog &logInfo, + int GetLocalInfo(size_t index, SyncParam ¶m, DataInfoWithLog &logInfo, std::map &localLogInfoCache, VBucket &localAssetInfo); TaskId GetNextTaskId(); @@ -295,6 +302,19 @@ protected: void NotifyUploadFailed(int errCode, InnerProcessInfo &info); + int BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo); + + int BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo); + + int DownloadAssetsOneByOne(const InnerProcessInfo &info, const DownloadItem &downloadItem, + std::map &downloadAssets); + + int GetDBAssets(bool isSharedTable, const InnerProcessInfo &info, const DownloadItem &downloadItem, + VBucket &dbAssets); + + int DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProcessInfo &info, const DownloadItem &downloadItem, + std::map &downloadAssets); + std::mutex dataLock_; TaskId lastTaskId_; std::list taskQueue_; @@ -328,7 +348,6 @@ protected: static constexpr const TaskId INVALID_TASK_ID = 0u; static constexpr const int MAX_HEARTBEAT_FAILED_LIMIT = 2; static constexpr const int HEARTBEAT_PERIOD = 3; - static constexpr const int MAX_DOWNLOAD_COMMIT_LIMIT = 1; }; } #endif // CLOUD_SYNCER_H diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3ac43b11b4f1af1154cc89898b3b5f3aea1cbaff --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/cloud/cloud_syncer_extend.cpp @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "cloud_syncer.h" + +#include +#include +#include + +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_storage_utils.h" +#include "cloud/icloud_db.h" +#include "cloud_sync_tag_assets.h" +#include "cloud_sync_utils.h" +#include "db_errno.h" +#include "log_print.h" +#include "runtime_context.h" +#include "storage_proxy.h" +#include "store_types.h" +#include "strategy_factory.h" +#include "version.h" + +namespace DistributedDB { +void CloudSyncer::ReloadWaterMarkIfNeed(TaskId taskId, WaterMark &waterMark) +{ + Timestamp cacheWaterMark = GetResumeWaterMark(taskId); + waterMark = cacheWaterMark == 0u ? waterMark : cacheWaterMark; + RecordWaterMark(taskId, 0u); +} + +void CloudSyncer::ReloadUploadInfoIfNeed(TaskId taskId, const UploadParam ¶m, InnerProcessInfo &info) +{ + info.upLoadInfo.total = static_cast(param.count); + { + std::lock_guard autoLock(dataLock_); + if (!cloudTaskInfos_[taskId].resume) { + return; + } + } + uint32_t lastSuccessCount = GetLastUploadSuccessCount(info.tableName); + if (lastSuccessCount == 0) { + return; + } + info.upLoadInfo.total += lastSuccessCount; + info.upLoadInfo.successCount += lastSuccessCount; + LOGD("[CloudSyncer] resume upload, last success count %" PRIu32, lastSuccessCount); +} + +uint32_t CloudSyncer::GetLastUploadSuccessCount(const std::string &tableName) +{ + std::lock_guard autoLock(dataLock_); + return currentContext_.notifier->GetLastUploadSuccessCount(tableName); +} + +int CloudSyncer::FillDownloadExtend(TaskId taskId, const std::string &tableName, const std::string &cloudWaterMark, + VBucket &extend) +{ + extend = { + {CloudDbConstant::CURSOR_FIELD, cloudWaterMark} + }; + + QuerySyncObject obj = GetQuerySyncObject(tableName); + if (obj.IsContainQueryNodes()) { + int errCode = GetCloudGid(taskId, tableName, obj); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to get cloud gid when fill extend, %d.", errCode); + return errCode; + } + Bytes bytes; + bytes.resize(obj.CalculateParcelLen(SOFTWARE_VERSION_CURRENT)); + Parcel parcel(bytes.data(), bytes.size()); + errCode = obj.SerializeData(parcel, SOFTWARE_VERSION_CURRENT); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Query serialize failed %d", errCode); + return errCode; + } + extend[CloudDbConstant::TYPE_FIELD] = static_cast(CloudQueryType::QUERY_FIELD); + extend[CloudDbConstant::QUERY_FIELD] = bytes; + } else { + extend[CloudDbConstant::TYPE_FIELD] = static_cast(CloudQueryType::FULL_TABLE); + } + return E_OK; +} + +int CloudSyncer::GetCloudGid(TaskId taskId, const std::string &tableName, QuerySyncObject &obj) +{ + std::vector cloudGid; + bool isCloudForcePush = cloudTaskInfos_[taskId].mode == SYNC_MODE_CLOUD_FORCE_PUSH; + int errCode = storageProxy_->GetCloudGid(obj, isCloudForcePush, cloudGid); + if (errCode != E_OK) { + LOGE("[CloudSyncer] Failed to get cloud gid, %d.", errCode); + } else if (!cloudGid.empty()) { + obj.SetCloudGid(cloudGid); + } + return errCode; +} + +QuerySyncObject CloudSyncer::GetQuerySyncObject(const std::string &tableName) +{ + std::lock_guard autoLock(dataLock_); + for (const auto &item : cloudTaskInfos_[currentContext_.currentTaskId].queryList) { + if (item.GetTableName() == tableName) { + return item; + } + } + LOGW("[CloudSyncer] not found query in cache"); + QuerySyncObject querySyncObject; + querySyncObject.SetTableName(tableName); + return querySyncObject; +} + +void CloudSyncer::NotifyUploadFailed(int errCode, InnerProcessInfo &info) +{ + LOGE("[CloudSyncer] Failed to do upload, %d", errCode); + info.upLoadInfo.failCount = info.upLoadInfo.total - info.upLoadInfo.successCount; + info.tableStatus = ProcessStatus::FINISHED; + { + std::lock_guard autoLock(dataLock_); + currentContext_.notifier->UpdateProcess(info); + } +} + +int CloudSyncer::BatchInsert(Info &insertInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) +{ + int errCode = cloudDB_.BatchInsert(uploadData.tableName, uploadData.insData.record, + uploadData.insData.extend, insertInfo); + bool isSharedTable = false; + int ret = storageProxy_->IsSharedTable(uploadData.tableName, isSharedTable); + if (ret != E_OK) { + LOGE("[CloudSyncer] DoBatchUpload cannot judge the table is shared table. %d", ret); + return ret; + } + if (!isSharedTable) { + ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.insData); + } + if (errCode != E_OK) { + storageProxy_->FillCloudGidIfSuccess(OpType::INSERT, uploadData); + return errCode; + } + // we need to fill back gid after insert data to cloud. + int errorCode = storageProxy_->FillCloudLogAndAsset(OpType::INSERT, uploadData); + if ((errorCode != E_OK) || (ret != E_OK)) { + LOGE("[CloudSyncer] Failed to fill back when doing upload insData, %d.", errorCode); + return ret == E_OK ? errorCode : ret; + } + if (isSharedTable) { + ret = storageProxy_->FillCloudLogAndAsset(OpType::UPDATE_VERSION, uploadData); + if (ret != E_OK) { + LOGE("[CloudSyncer] Failed to fill back version when doing upload insData, %d.", ret); + return ret; + } + } + innerProcessInfo.upLoadInfo.successCount += insertInfo.successCount; + return E_OK; +} + +int CloudSyncer::BatchUpdate(Info &updateInfo, CloudSyncData &uploadData, InnerProcessInfo &innerProcessInfo) +{ + int errCode = cloudDB_.BatchUpdate(uploadData.tableName, uploadData.updData.record, + uploadData.updData.extend, updateInfo); + bool isSharedTable = false; + int ret = storageProxy_->IsSharedTable(uploadData.tableName, isSharedTable); + if (ret != E_OK) { + LOGE("[CloudSyncer] DoBatchUpload cannot judge the table is shared table. %d", ret); + return ret; + } + if (!isSharedTable) { + ret = CloudSyncUtils::FillAssetIdToAssets(uploadData.updData); + } + if (errCode != E_OK) { + storageProxy_->FillCloudGidIfSuccess(OpType::UPDATE, uploadData); + return errCode; + } + int errorCode = storageProxy_->FillCloudLogAndAsset(OpType::UPDATE, uploadData); + if ((errorCode != E_OK) || (ret != E_OK)) { + LOGE("[CloudSyncer] Failed to fill back when doing upload updData, %d.", errorCode); + return ret == E_OK ? errorCode : ret; + } + if (isSharedTable) { + ret = storageProxy_->FillCloudLogAndAsset(OpType::UPDATE_VERSION, uploadData); + if (ret != E_OK) { + LOGE("[CloudSyncer] Failed to fill back version when doing upload insData, %d.", ret); + return ret; + } + } + innerProcessInfo.upLoadInfo.successCount += updateInfo.successCount; + return E_OK; +} + +int CloudSyncer::DownloadAssetsOneByOne(const InnerProcessInfo &info, const DownloadItem &downloadItem, + std::map &downloadAssets) +{ + bool isSharedTable = false; + int errCode = storageProxy_->IsSharedTable(info.tableName, isSharedTable); + if (errCode != E_OK) { + LOGE("[CloudSyncer] DownloadOneAssetRecord cannot judge the table is a shared table. %d", errCode); + return errCode; + } + int transactionCode = E_OK; + // shared table don't download, so just begin transaction once + if (isSharedTable) { + transactionCode = storageProxy_->StartTransaction(TransactType::IMMEDIATE); + } + if (transactionCode != E_OK) { + LOGE("[CloudSyncer] begin transaction before download failed %d", transactionCode); + return transactionCode; + } + errCode = DownloadAssetsOneByOneInner(isSharedTable, info, downloadItem, downloadAssets); + if (isSharedTable) { + transactionCode = storageProxy_->Commit(); + if (transactionCode != E_OK) { + LOGW("[CloudSyncer] commit transaction after download failed %d", transactionCode); + } + } + return (errCode == E_OK) ? transactionCode : errCode; +} + +int CloudSyncer::GetDBAssets(bool isSharedTable, const InnerProcessInfo &info, const DownloadItem &downloadItem, + VBucket &dbAssets) +{ + int transactionCode = E_OK; + if (!isSharedTable) { + transactionCode = storageProxy_->StartTransaction(TransactType::IMMEDIATE); + } + if (transactionCode != E_OK) { + LOGE("[CloudSyncer] begin transaction before download failed %d", transactionCode); + return transactionCode; + } + int errCode = storageProxy_->GetAssetsByGidOrHashKey(info.tableName, downloadItem.gid, + downloadItem.hashKey, dbAssets); + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + LOGE("[CloudSyncer] get assets from db failed %d", errCode); + return errCode; + } + if (!isSharedTable) { + transactionCode = storageProxy_->Commit(); + } + if (transactionCode != E_OK) { + LOGE("[CloudSyncer] commit transaction before download failed %d", transactionCode); + } + return transactionCode; +} + +int CloudSyncer::DownloadAssetsOneByOneInner(bool isSharedTable, const InnerProcessInfo &info, + const DownloadItem &downloadItem, std::map &downloadAssets) +{ + int errCode = E_OK; + for (auto &[col, assets] : downloadAssets) { + Assets callDownloadAssets; + for (auto &asset : assets) { + std::map tmpAssets; + tmpAssets[col] = { asset }; + uint32_t tmpFlag = asset.flag; + VBucket dbAssets; + int tmpCode = GetDBAssets(isSharedTable, info, downloadItem, dbAssets); + if (tmpCode != E_OK) { + errCode = (errCode != E_OK) ? errCode : tmpCode; + break; + } + if (!isSharedTable && AssetOperationUtils::CalAssetOperation(col, asset, dbAssets, + AssetOperationUtils::CloudSyncAction::START_DOWNLOAD) == AssetOperationUtils::AssetOpType::HANDLE) { + tmpCode = cloudDB_.Download(info.tableName, downloadItem.gid, downloadItem.prefix, tmpAssets); + } else { + LOGD("[CloudSyncer] skip download asset..."); + continue; + } + errCode = (errCode != E_OK) ? errCode : tmpCode; + if (tmpCode == -E_NOT_SET) { + break; + } + asset = tmpAssets[col][0]; // copy asset back + asset.flag = tmpFlag; + if (asset.flag != static_cast(AssetOpType::NO_CHANGE)) { + asset.status = (tmpCode == E_OK) ? NORMAL : ABNORMAL; + } + callDownloadAssets.push_back(asset); + } + assets = callDownloadAssets; + } + return errCode; +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp index 09c47d06a76622d5d5d7b061ed2c63f82c45e9b3..1e5a726463e5eca2346066f968c493cbbeb350c2 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/meta_data.cpp @@ -260,7 +260,7 @@ int Metadata::SetMetadataToDb(const std::vector &key, const std::vector if (naturalStoragePtr_ == nullptr) { return -E_INVALID_DB; } - return naturalStoragePtr_->PutMetaData(key, inValue); + return naturalStoragePtr_->PutMetaData(key, inValue, false); } void Metadata::PutMetadataToMap(const DeviceID &deviceId, const MetaDataValue &value) diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp index 9966b93c4d44c02067e8cc2a80e2b8ad2a737d7d..712deadf77ae64dfcd80fa7e62691c07be899919 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/query_sync_water_mark_helper.cpp @@ -56,7 +56,7 @@ int QuerySyncWaterMarkHelper::SetMetadataToDb(const std::vector &key, c if (storage_ == nullptr) { return -E_INVALID_DB; } - return storage_->PutMetaData(key, inValue); + return storage_->PutMetaData(key, inValue, false); } int QuerySyncWaterMarkHelper::DeleteMetaDataFromDB(const std::vector &keys) const diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp index 1f5cf00ac32af93956ae3a045096c9dce499bee7..beabf605319a4707327342c34b7ccdd82c0c3597 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.cpp @@ -239,7 +239,7 @@ int RemoteExecutor::CheckPermissions(const std::string &device, Message *inMsg) storage->DecRefCount(); return -E_INVALID_ARGS; } - errCode = CheckRemoteRecvData(device, storage, requestPacket->GetSecLabel()); + errCode = CheckRemoteRecvData(device, storage, requestPacket->GetSecLabel(), requestPacket->GetVersion()); storage->DecRefCount(); return errCode; } @@ -747,6 +747,10 @@ int RemoteExecutor::FillRequestPacket(RemoteExecutorRequestPacket *packet, uint3 if (errCode != E_OK && errCode != -E_NOT_SUPPORT) { return -E_SECURITY_OPTION_CHECK_ERROR; } + if (errCode == E_OK && localOption.securityLabel == NOT_SET) { + LOGE("[AbilitySync] Local not set security option"); + return -E_SECURITY_OPTION_CHECK_ERROR; + } Task task; { std::lock_guard autoLock(taskLock_); @@ -761,7 +765,7 @@ int RemoteExecutor::FillRequestPacket(RemoteExecutorRequestPacket *packet, uint3 packet->SetSql(task.condition.sql); packet->SetBindArgs(task.condition.bindArgs); packet->SetNeedResponse(); - packet->SetSecLabel(errCode == E_NOT_SUPPORT ? NOT_SURPPORT_SEC_CLASSIFICATION : localOption.securityLabel); + packet->SetSecLabel(errCode == -E_NOT_SUPPORT ? NOT_SURPPORT_SEC_CLASSIFICATION : localOption.securityLabel); target = task.target; return E_OK; } @@ -996,10 +1000,24 @@ int RemoteExecutor::CheckSecurityOption(ISyncInterface *storage, ICommunicator * } int RemoteExecutor::CheckRemoteRecvData(const std::string &device, SyncGenericInterface *storage, - int32_t remoteSecLabel) + int32_t remoteSecLabel, uint32_t remoteVersion) { SecurityOption localOption; int errCode = storage->GetSecurityOption(localOption); + LOGI("[RemoteExecutor] remote label:%d local l:%d, f:%d, errCode:%d, remote ver %" PRIu32, remoteSecLabel, + localOption.securityLabel, localOption.securityFlag, errCode, remoteVersion); + if (remoteSecLabel == NOT_SURPPORT_SEC_CLASSIFICATION && errCode == -E_NOT_SUPPORT) { + return E_OK; + } + if (errCode != -E_NOT_SUPPORT && localOption.securityLabel == SecurityLabel::NOT_SET) { + LOGE("[RemoteExecutor] local security label not set!"); + return -E_SECURITY_OPTION_CHECK_ERROR; + } + if (remoteVersion >= RemoteExecutorRequestPacket::REQUEST_PACKET_VERSION_V4 && remoteSecLabel == NOT_SET) { + LOGE("[RemoteExecutor] remote security label not set!"); + return -E_SECURITY_OPTION_CHECK_ERROR; + } + if (errCode == -E_NOT_SUPPORT) { return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h index d2662240971627165ce6fc6f06fb1fd02838a422..4aa97492bc43c117acaf36ae572918de84486891 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor.h @@ -144,7 +144,8 @@ private: ICommunicator *GetAndIncCommunicator() const; ISyncInterface *GetAndIncSyncInterface() const; - static int CheckRemoteRecvData(const std::string &device, SyncGenericInterface *storage, int32_t remoteSecLabel); + static int CheckRemoteRecvData(const std::string &device, SyncGenericInterface *storage, int32_t remoteSecLabel, + uint32_t remoteVersion); std::mutex taskLock_; std::map> searchTaskQueue_; // key is device, value is sessionId queue diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h index a80c1f8eae2986714495f0f7f0378b7d16c4058d..94ee8b02aa0b5fe4318287821597b4e991e928be 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/remote_executor_packet.h @@ -67,10 +67,12 @@ public: static void Release(RemoteExecutorRequestPacket *&packet); - static const uint32_t REQUEST_PACKET_VERSION_V1 = SOFTWARE_VERSION_RELEASE_6_0; - static const uint32_t REQUEST_PACKET_VERSION_V2 = SOFTWARE_VERSION_RELEASE_6_0 + 1; - static const uint32_t REQUEST_PACKET_VERSION_V3 = SOFTWARE_VERSION_RELEASE_6_0 + 2; - static const uint32_t REQUEST_PACKET_VERSION_CURRENT = REQUEST_PACKET_VERSION_V3; + static constexpr uint32_t REQUEST_PACKET_VERSION_V1 = SOFTWARE_VERSION_RELEASE_6_0; + static constexpr uint32_t REQUEST_PACKET_VERSION_V2 = SOFTWARE_VERSION_RELEASE_6_0 + 1; // 1 is version 107 + static constexpr uint32_t REQUEST_PACKET_VERSION_V3 = SOFTWARE_VERSION_RELEASE_6_0 + 2; // 2 is version 108 + // abandon not set security label in v4 + static constexpr uint32_t REQUEST_PACKET_VERSION_V4 = SOFTWARE_VERSION_RELEASE_6_0 + 3; // 3 is version 109 + static constexpr uint32_t REQUEST_PACKET_VERSION_CURRENT = REQUEST_PACKET_VERSION_V4; private: uint32_t version_ = 0u; uint32_t flag_ = 0u; // 0x01 mean need reply ack diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync_utils.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync_utils.cpp index 6a97af2065df24f5741f08c9e079ce011a58f474..62aabcbd62aee753d484767ba67004acf9f70b44 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_data_sync_utils.cpp @@ -117,7 +117,7 @@ bool SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(const std::string &dev const SecurityOption &remoteSecOption, SyncGenericInterface *storage) { if (storage == nullptr) { - return -E_INVALID_ARGS; + return false; } SecurityOption localSecOption; if (remoteSecOption.securityLabel == NOT_SURPPORT_SEC_CLASSIFICATION) { @@ -127,6 +127,14 @@ bool SingleVerDataSyncUtils::IsPermitRemoteDeviceRecvData(const std::string &dev if (errCode == -E_NOT_SUPPORT) { return true; } + if (errCode != E_OK) { + LOGE("[SingleVerDataSyncUtils] get security option error %d", errCode); + return false; + } + if (localSecOption.securityLabel == NOT_SET) { + LOGE("[SingleVerDataSyncUtils] local label is not set!"); + return false; + } return RuntimeContext::GetInstance()->CheckDeviceSecurityAbility(deviceId, localSecOption); } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp index e7541fb568fe5deb19a4f0ddf3821b1670c94e70..26d415380e8cc985d560a5c4875fc1738b97321e 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_kv_syncer.cpp @@ -90,16 +90,20 @@ void SingleVerKVSyncer::LocalDataChanged(int notifyEvent) triggerSyncTask_ = true; return; } - RefObject::IncObjRef(syncEngine_); + ISyncEngine *engine = syncEngine_; + ISyncInterface *storage = syncInterface_; + RefObject::IncObjRef(engine); + storage->IncRefCount(); // To avoid many task were produced and waiting in the queue. For example, put value in a loop. // It will consume thread pool resources, so other task will delay until these task finish. // In extreme situation, 10 thread run the localDataChanged task and 1 task waiting in queue. - int errCode = RuntimeContext::GetInstance()->ScheduleTask([this, devices] { + int errCode = RuntimeContext::GetInstance()->ScheduleTask([this, devices, engine, storage] { triggerSyncTask_ = true; if (!TryFullSync(devices)) { TriggerSubQuerySync(devices); } - RefObject::DecObjRef(syncEngine_); + RefObject::DecObjRef(engine); + storage->DecRefCount(); }); // if task schedule failed, but triggerSyncTask_ is not set to true, other thread may skip the schedule time // when task schedule failed, it means unormal status, it is unable to schedule next time probably @@ -107,9 +111,9 @@ void SingleVerKVSyncer::LocalDataChanged(int notifyEvent) if (errCode != E_OK) { triggerSyncTask_ = true; LOGE("[TriggerSync] LocalDataChanged retCode:%d", errCode); - RefObject::DecObjRef(syncEngine_); + RefObject::DecObjRef(engine); + storage->DecRefCount(); } - return; } // remote device online callback diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp index f91afc3ddcccae655e3d733c723701876abd9463..5ff99ade4abaae9a35329407e472295ae797d743 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/single_ver_syncer.cpp @@ -37,13 +37,13 @@ void SingleVerSyncer::RemoteDeviceOffline(const std::string &device) ISyncInterface *storage = syncInterface_; storage->IncRefCount(); int errCode = RuntimeContext::GetInstance()->ScheduleTask([engine, device, storage]() { - static_cast(engine)->OfflineHandleByDevice(device); + static_cast(engine)->OfflineHandleByDevice(device, storage); RefObject::DecObjRef(engine); storage->DecRefCount(); }); if (errCode != E_OK) { LOGW("[SingleVerSyncer][RemoteDeviceOffline] async task failed errCode = %d", errCode); - RefObject::DecObjRef(syncEngine_); + RefObject::DecObjRef(engine); storage->DecRefCount(); } } diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp index c63e6f7404eb710b3d3d6aaa59384aa8f36de75e..83b6b6c7d7b801cf48bcdabeb24ac8ce0fc3a593 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.cpp @@ -812,7 +812,7 @@ void SyncEngine::SetEqualIdentifierMap(const std::string &identifier, const std: } } -void SyncEngine::OfflineHandleByDevice(const std::string &deviceId) +void SyncEngine::OfflineHandleByDevice(const std::string &deviceId, ISyncInterface *storage) { RemoteExecutor *executor = GetAndIncRemoteExector(); if (executor != nullptr) { @@ -827,7 +827,7 @@ void SyncEngine::OfflineHandleByDevice(const std::string &deviceId) subManager_->ClearRemoteSubscribeQuery(deviceId); for (const auto &queryId: remoteQueryId) { if (!subManager_->IsQueryExistSubscribe(queryId)) { - static_cast(syncInterface_)->RemoveSubscribe(queryId); + static_cast(storage)->RemoveSubscribe(queryId); } } // get context and Inc context if context is not nullprt diff --git a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.h b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.h index cc71667819aa9a5a2fe52dc5567fba3ec76cf854..42ab38c61b3378f7c92ef7dc7d5aa9f22b3a96a7 100644 --- a/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.h +++ b/kv_store/frameworks/libs/distributeddb/syncer/src/sync_engine.h @@ -84,7 +84,7 @@ public: void SetEqualIdentifierMap(const std::string &identifier, const std::vector &targets) override; - void OfflineHandleByDevice(const std::string &deviceId); + void OfflineHandleByDevice(const std::string &deviceId, ISyncInterface *storage); void GetLocalSubscribeQueries(const std::string &device, std::vector &subscribeQueries); diff --git a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn index 85cfa5abd95f6b52e2b62d042cd95bff344dd954..a74b95efcd625f882bff77e9bf7dd4d1be7af3cb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/BUILD.gn @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import("//build/test.gni") +import("../distributeddb.gni") module_output_path = "kv_store/distributeddb" @@ -31,23 +32,30 @@ config("module_private_config") { "../interfaces/include/relational", "../interfaces/src", "../interfaces/src/relational", + "../common/include", + "../common/include/cloud", + "../common/include/relational", + "../common/src", + "../common/src/cloud", + "../communicator/include", + "../communicator/src", "../storage/include", "../storage/src", "../storage/src/multiver", "../storage/src/operation", + "../storage/src/gaussdb_rd", "../storage/src/sqlite", "../storage/src/sqlite/relational", "../storage/src/upgrader", - "../common/include", - "../common/include/relational", - "../common/include/cloud", - "../common/src", - "../communicator/include", - "../communicator/src", + "../storage/src/cloud", "../syncer/include", "../syncer/src", "../syncer/src/cloud", "//third_party/openssl/include/", + "../gaussdb_rd/include", + "../gaussdb_rd/include/grd_base", + "../gaussdb_rd/include/grd_document", + "../gaussdb_rd/include/grd_kv", ] defines = [ @@ -76,226 +84,12 @@ config("module_private_config") { ohos_source_set("src_file") { testonly = true - sources = [ - "../common/src/auto_launch.cpp", - "../common/src/data_compression.cpp", - "../common/src/data_value.cpp", - "../common/src/db_common.cpp", - "../common/src/db_constant.cpp", - "../common/src/db_dfx_adapter.cpp", - "../common/src/db_dump_helper.cpp", - "../common/src/evloop/src/event_impl.cpp", - "../common/src/evloop/src/event_loop_epoll.cpp", - "../common/src/evloop/src/event_loop_impl.cpp", - "../common/src/evloop/src/event_loop_select.cpp", - "../common/src/evloop/src/ievent.cpp", - "../common/src/evloop/src/ievent_loop.cpp", - "../common/src/flatbuffer_schema.cpp", - "../common/src/hash.cpp", - "../common/src/json_object.cpp", - "../common/src/lock_status_observer.cpp", - "../common/src/log_print.cpp", - "../common/src/notification_chain.cpp", - "../common/src/param_check_utils.cpp", - "../common/src/parcel.cpp", - "../common/src/performance_analysis.cpp", - "../common/src/platform_specific.cpp", - "../common/src/query.cpp", - "../common/src/query_expression.cpp", - "../common/src/ref_object.cpp", - "../common/src/relational/prepared_stmt.cpp", - "../common/src/relational/relational_result_set_impl.cpp", - "../common/src/relational/relational_row_data_set.cpp", - "../common/src/relational/relational_schema_object.cpp", - "../common/src/relational/table_info.cpp", - "../common/src/runtime_context.cpp", - "../common/src/runtime_context_impl.cpp", - "../common/src/schema_constant.cpp", - "../common/src/schema_negotiate.cpp", - "../common/src/schema_object.cpp", - "../common/src/schema_utils.cpp", - "../common/src/semaphore_utils.cpp", - "../common/src/task_pool.cpp", - "../common/src/task_pool_impl.cpp", - "../common/src/task_queue.cpp", - "../common/src/time_tick_monitor.cpp", - "../common/src/types_export.cpp", - "../common/src/user_change_monitor.cpp", - "../common/src/value_object.cpp", - "../common/src/zlib_compression.cpp", - "../communicator/src/combine_status.cpp", - "../communicator/src/communicator.cpp", - "../communicator/src/communicator_aggregator.cpp", - "../communicator/src/communicator_linker.cpp", - "../communicator/src/frame_combiner.cpp", - "../communicator/src/frame_retainer.cpp", - "../communicator/src/header_converter.cpp", - "../communicator/src/message_transform.cpp", - "../communicator/src/network_adapter.cpp", - "../communicator/src/protocol_proto.cpp", - "../communicator/src/send_task_scheduler.cpp", - "../communicator/src/serial_buffer.cpp", - "../interfaces/src/intercepted_data_impl.cpp", - "../interfaces/src/kv_store_changed_data_impl.cpp", - "../interfaces/src/kv_store_delegate_impl.cpp", - "../interfaces/src/kv_store_delegate_manager.cpp", - "../interfaces/src/kv_store_errno.cpp", - "../interfaces/src/kv_store_nb_conflict_data_impl.cpp", - "../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/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", - "../interfaces/src/runtime_config.cpp", - "../storage/src/cloud/cloud_meta_data.cpp", - "../storage/src/cloud/cloud_storage_utils.cpp", - "../storage/src/cloud/schema_mgr.cpp", - "../storage/src/data_transformer.cpp", - "../storage/src/db_properties.cpp", - "../storage/src/default_factory.cpp", - "../storage/src/generic_kvdb.cpp", - "../storage/src/generic_kvdb_connection.cpp", - "../storage/src/generic_single_ver_kv_entry.cpp", - "../storage/src/iconnection.cpp", - "../storage/src/ikvdb_factory.cpp", - "../storage/src/kvdb_commit_notify_filterable_data.cpp", - "../storage/src/kvdb_manager.cpp", - "../storage/src/kvdb_observer_handle.cpp", - "../storage/src/kvdb_properties.cpp", - "../storage/src/kvdb_utils.cpp", - "../storage/src/kvdb_windowed_result_set.cpp", - "../storage/src/multiver/generic_multi_ver_kv_entry.cpp", - "../storage/src/multiver/multi_ver_commit.cpp", - "../storage/src/multiver/multi_ver_kvdata_storage.cpp", - "../storage/src/multiver/multi_ver_natural_store.cpp", - "../storage/src/multiver/multi_ver_natural_store_commit_notify_data.cpp", - "../storage/src/multiver/multi_ver_natural_store_commit_storage.cpp", - "../storage/src/multiver/multi_ver_natural_store_connection.cpp", - "../storage/src/multiver/multi_ver_natural_store_snapshot.cpp", - "../storage/src/multiver/multi_ver_natural_store_transfer_data.cpp", - "../storage/src/multiver/multi_ver_storage_engine.cpp", - "../storage/src/multiver/multi_ver_storage_executor.cpp", - "../storage/src/multiver/multi_ver_vacuum.cpp", - "../storage/src/multiver/multi_ver_vacuum_executor_impl.cpp", - "../storage/src/multiver/multi_ver_value_object.cpp", - "../storage/src/operation/database_oper.cpp", - "../storage/src/operation/local_database_oper.cpp", - "../storage/src/operation/multi_ver_database_oper.cpp", - "../storage/src/operation/single_ver_database_oper.cpp", - "../storage/src/package_file.cpp", - "../storage/src/relational_row_data_impl.cpp", - "../storage/src/relational_store_connection.cpp", - "../storage/src/relational_store_instance.cpp", - "../storage/src/relational_sync_able_storage.cpp", - "../storage/src/relational_sync_data_inserter.cpp", - "../storage/src/relationaldb_properties.cpp", - "../storage/src/result_entries_window.cpp", - "../storage/src/single_ver_natural_store_commit_notify_data.cpp", - "../storage/src/sqlite/cloud_sync_log_table_manager.cpp", - "../storage/src/sqlite/collaboration_log_table_manager.cpp", - "../storage/src/sqlite/log_table_manager_factory.cpp", - "../storage/src/sqlite/query_object.cpp", - "../storage/src/sqlite/query_sync_object.cpp", - "../storage/src/sqlite/relational/relational_remote_query_continue_token.cpp", - "../storage/src/sqlite/relational/sqlite_relational_database_upgrader.cpp", - "../storage/src/sqlite/relational/sqlite_relational_store.cpp", - "../storage/src/sqlite/relational/sqlite_relational_store_connection.cpp", - "../storage/src/sqlite/relational/sqlite_relational_utils.cpp", - "../storage/src/sqlite/relational/sqlite_single_relational_storage_engine.cpp", - "../storage/src/sqlite/split_device_log_table_manager.cpp", - "../storage/src/sqlite/sqlite_local_kvdb.cpp", - "../storage/src/sqlite/sqlite_local_kvdb_connection.cpp", - "../storage/src/sqlite/sqlite_local_kvdb_snapshot.cpp", - "../storage/src/sqlite/sqlite_local_storage_engine.cpp", - "../storage/src/sqlite/sqlite_local_storage_executor.cpp", - "../storage/src/sqlite/sqlite_log_table_manager.cpp", - "../storage/src/sqlite/sqlite_meta_executor.cpp", - "../storage/src/sqlite/sqlite_multi_ver_data_storage.cpp", - "../storage/src/sqlite/sqlite_multi_ver_transaction.cpp", - "../storage/src/sqlite/sqlite_query_helper.cpp", - "../storage/src/sqlite/sqlite_single_ver_continue_token.cpp", - "../storage/src/sqlite/sqlite_single_ver_database_upgrader.cpp", - "../storage/src/sqlite/sqlite_single_ver_forward_cursor.cpp", - "../storage/src/sqlite/sqlite_single_ver_natural_store.cpp", - "../storage/src/sqlite/sqlite_single_ver_natural_store_connection.cpp", - "../storage/src/sqlite/sqlite_single_ver_relational_continue_token.cpp", - "../storage/src/sqlite/sqlite_single_ver_relational_storage_executor.cpp", - "../storage/src/sqlite/sqlite_single_ver_relational_storage_extend_executor.cpp", - "../storage/src/sqlite/sqlite_single_ver_result_set.cpp", - "../storage/src/sqlite/sqlite_single_ver_schema_database_upgrader.cpp", - "../storage/src/sqlite/sqlite_single_ver_storage_engine.cpp", - "../storage/src/sqlite/sqlite_single_ver_storage_executor.cpp", - "../storage/src/sqlite/sqlite_single_ver_storage_executor_cache.cpp", - "../storage/src/sqlite/sqlite_single_ver_storage_executor_subscribe.cpp", - "../storage/src/sqlite/sqlite_storage_engine.cpp", - "../storage/src/sqlite/sqlite_storage_executor.cpp", - "../storage/src/sqlite/sqlite_utils.cpp", - "../storage/src/storage_engine.cpp", - "../storage/src/storage_engine_manager.cpp", - "../storage/src/storage_executor.cpp", - "../storage/src/storage_proxy.cpp", - "../storage/src/sync_able_engine.cpp", - "../storage/src/sync_able_kvdb.cpp", - "../storage/src/sync_able_kvdb_connection.cpp", - "../storage/src/upgrader/single_ver_database_upgrader.cpp", - "../storage/src/upgrader/single_ver_schema_database_upgrader.cpp", - "../syncer/src/ability_sync.cpp", - "../syncer/src/cloud/cloud_db_proxy.cpp", - "../syncer/src/cloud/cloud_force_pull_strategy.cpp", - "../syncer/src/cloud/cloud_force_push_strategy.cpp", - "../syncer/src/cloud/cloud_locker.cpp", - "../syncer/src/cloud/cloud_merge_strategy.cpp", - "../syncer/src/cloud/cloud_sync_tag_assets.cpp", - "../syncer/src/cloud/cloud_sync_utils.cpp", - "../syncer/src/cloud/cloud_syncer.cpp", - "../syncer/src/cloud/process_notifier.cpp", - "../syncer/src/cloud/strategy_factory.cpp", - "../syncer/src/commit_history_sync.cpp", - "../syncer/src/communicator_proxy.cpp", - "../syncer/src/db_ability.cpp", - "../syncer/src/device_manager.cpp", - "../syncer/src/generic_syncer.cpp", - "../syncer/src/meta_data.cpp", - "../syncer/src/multi_ver_data_sync.cpp", - "../syncer/src/multi_ver_sync_engine.cpp", - "../syncer/src/multi_ver_sync_state_machine.cpp", - "../syncer/src/multi_ver_sync_task_context.cpp", - "../syncer/src/multi_ver_syncer.cpp", - "../syncer/src/query_sync_water_mark_helper.cpp", - "../syncer/src/remote_executor.cpp", - "../syncer/src/remote_executor_packet.cpp", - "../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_data_sync_utils.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", - "../syncer/src/single_ver_sync_state_machine.cpp", - "../syncer/src/single_ver_sync_target.cpp", - "../syncer/src/single_ver_sync_task_context.cpp", - "../syncer/src/single_ver_syncer.cpp", - "../syncer/src/subscribe_manager.cpp", - "../syncer/src/sync_config.cpp", - "../syncer/src/sync_engine.cpp", - "../syncer/src/sync_operation.cpp", - "../syncer/src/sync_state_machine.cpp", - "../syncer/src/sync_target.cpp", - "../syncer/src/sync_task_context.cpp", - "../syncer/src/syncer_factory.cpp", - "../syncer/src/syncer_proxy.cpp", - "../syncer/src/time_helper.cpp", - "../syncer/src/time_sync.cpp", - "../syncer/src/value_slice_sync.cpp", + sources = distributeddb_src + sources += [ "unittest/common/common/distributeddb_data_generate_unit_test.cpp", "unittest/common/common/distributeddb_tools_unit_test.cpp", "unittest/common/common/native_sqlite.cpp", - "unittest/common/common/system_timer.cpp", + "unittest/common/common/system_time.cpp", "unittest/common/common/thread_pool_test_stub.cpp", "unittest/common/interfaces/process_system_api_adapter_impl.cpp", "unittest/common/syncer/cloud/cloud_db_data_utils.cpp", @@ -325,6 +119,7 @@ ohos_source_set("src_file") { configs += [ "//third_party/jsoncpp:jsoncpp_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] deps += [ + "../gaussdb_rd:gaussdb_rd", "//third_party/jsoncpp:jsoncpp", "//third_party/openssl:libcrypto_shared", ] @@ -358,6 +153,7 @@ template("distributeddb_unittest") { configs += [ "//third_party/jsoncpp:jsoncpp_config" ] ldflags = [ "-Wl,--exclude-libs,ALL" ] deps += [ + "../gaussdb_rd:gaussdb_rd", "//third_party/jsoncpp:jsoncpp", "//third_party/openssl:libcrypto_shared", ] @@ -396,6 +192,10 @@ distributeddb_unittest("DistributedDBInterfacesImportAndExportTest") { sources = [ "unittest/common/interfaces/distributeddb_interfaces_import_and_export_test.cpp" ] } +distributeddb_unittest("DistributedDBCloudInterfacesReferenceTest") { + sources = [ "unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp" ] +} + distributeddb_unittest("DistributedDBCloudInterfacesRelationalSyncTest") { sources = [ "unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp" ] } @@ -756,6 +556,10 @@ distributeddb_unittest("DistributedInterfacesRelationalTest") { ] } +distributeddb_unittest("DistributedInterfacesRelationalTrackerTableTest") { + sources = [ "unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp" ] +} + distributeddb_unittest("DistributedDBRelationalSchemaObjectTest") { sources = [ "unittest/common/common/distributeddb_relational_schema_object_test.cpp", @@ -884,6 +688,20 @@ distributeddb_unittest("DistributedDBCloudTableWithoutPrimaryKeySyncTest") { sources = [ "unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp" ] } +distributeddb_unittest("DistributedDBCloudInterfacesSetCloudSchemaTest") { + sources = [ "unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp" ] +} + +distributeddb_unittest("DistributedDBCloudReferenceSyncTest") { + sources = [ + "unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp", + ] +} + +distributeddb_unittest("DistributedDBCloudAssetsOperationSyncTest") { + sources = [ "unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp" ] +} + ############################################################################### group("unittest") { testonly = true @@ -893,11 +711,15 @@ group("unittest") { ":DistributedDBAbilitySyncTest", ":DistributedDBAutoLaunchUnitTest", ":DistributedDBCloudAssetCompareTest", + ":DistributedDBCloudAssetsOperationSyncTest", ":DistributedDBCloudCheckSyncTest", ":DistributedDBCloudDBProxyTest", + ":DistributedDBCloudInterfacesReferenceTest", ":DistributedDBCloudInterfacesRelationalExtTest", ":DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest", ":DistributedDBCloudInterfacesRelationalSyncTest", + ":DistributedDBCloudInterfacesSetCloudSchemaTest", + ":DistributedDBCloudReferenceSyncTest", ":DistributedDBCloudSaveCloudDataTest", ":DistributedDBCloudSchemaMgrTest", ":DistributedDBCloudStrategyTest", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn index 6360837e0c6af9c205ac2c4285109b8d6d28e6c2..862176f0f2e66b88e7e93f6cb188a13d17173819 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/BUILD.gn @@ -35,6 +35,7 @@ ohos_fuzztest("CloudsyncFuzzTest") { "../../../storage/include", "../../../storage/src", "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "../../../storage/src/multiver", "../../../storage/src/operation", "../../../storage/src/sqlite", @@ -44,6 +45,7 @@ ohos_fuzztest("CloudsyncFuzzTest") { "../../../common/include/cloud", "../../../common/include/relational", "../../../common/src", + "../../../common/src/cloud", "../../../communicator/include", "../../../communicator/src", "../../../syncer/include", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp index c917467bbdef69f4165dee55989d320d3fe20514..c6b2846b57d4039d8d44bab6b3ddcb34fb284dc0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/cloudsync_fuzzer/cloudsync_fuzzer.cpp @@ -14,8 +14,8 @@ */ #include "cloudsync_fuzzer.h" -#include "cloud_db_types.h" -#include "cloud_db_constant.h" +#include "cloud/cloud_db_types.h" +#include "cloud/cloud_db_constant.h" #include "time_helper.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_test.h" diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn index 9e19f8f8296afd2cb2c548dd63429c57b9e57852..7afde7959aa72ae93ebec45dfc2ede2bc40aaa7f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/delegate_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("DelegateFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn index a983309be66e08daa37a780fb39143e6dc71d8a0..c6155e15f904843c2877db3202a12760dfd5a361 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/fileoper_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("FileOperFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn index 4e0bcd769aba8633ccb86f04bd4e4b5109980fad..aaef57591fa7b8092ab6b4b01e7b63629a801070 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/importfile_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("ImportFileFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn index 140c8e115dc4b4aabf031f853aa75f1b90009133..2e85ac82ac2d38984b1cc92a51bc3d301853d3eb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/iprocesscommunicator_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("IProcessCommunicatorFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn index 54101dce19c06e0a86456c4bb2f6f1cf22c070ab..e09d008963e36c66daa5a826df9f99a32ab03f37 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvdelegatemanager_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("KvDelegateManagerFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn index 3e90f23766cb25fb76f2e0874506aee49ad62cb7..1b7cfac9f7bd8bf5891a6e054eb17cba75390dc4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/kvstoreresultset_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("KvStoreResultSetFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn index 69a5fd4ce2d80fc90dd3dc974a996247a33d6322..ebf175426a05593d0efa58a23d4a1471e57145af 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/nbdelegate_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("NbDelegateFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn index 20f15d776d0be8f69864d77271b12c091d25f33d..fe45f7f1e196c7832cecf588a60b9ec7f6a15f3b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/parseckeck_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("ParseCkeckFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn index 4dee74a0bce561619040c2dda3195878ac439752..9a4114a566521f5876460f46190b4764bbefe298 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/query_fuzzer/BUILD.gn @@ -21,11 +21,12 @@ ohos_fuzztest("QueryFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", - "..../test/fuzztest/common", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", + "../../../test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn index 9ee033fe518374887f4a9c02a00189709f6fa46f..84a018d24e42fda7ca45cde9345286766164eb6b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/rekey_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("ReKeyFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn index 75c369706b491a79c5eb0dfd430fb22d3e3cebf7..b94b947be260316d9258d0ee38011b76cca5e915 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoredelegate_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("RelationalstoredelegateFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn index 6bac7ba91818649b9326be209ba236d0c265fdd1..09d0faf99de6164976d0a4a49e2bd391ca0ac922 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/relationalstoremanager_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("RelationalstoremanagerFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn index d94718cfc17398861134dfb9840fc262629e5a3c..fd37d0d69695a8a9ab6582a3544aa6618683b745 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/schemadelegate_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("SchemaDelegateFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn index e146c0de87bbe85198995705c54137624e621216..305bc426663c01afd342dfe53e3e0b2b3aec694f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/storage_fuzzer/BUILD.gn @@ -35,6 +35,7 @@ ohos_fuzztest("StorageFuzzTest") { "../../../storage/include", "../../../storage/src", "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "../../../storage/src/multiver", "../../../storage/src/operation", "../../../storage/src/sqlite", diff --git a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn index e35f1face337ce7f976a8ee62c1e1ba9226a7373..9188a375f2ad481b96b9defaf1827ca5bf17eee4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn +++ b/kv_store/frameworks/libs/distributeddb/test/fuzztest/sync_fuzzer/BUILD.gn @@ -21,10 +21,11 @@ ohos_fuzztest("SyncFuzzTest") { module_out_path = "kv_store/kv_store" include_dirs = [ - "..../interfaces/include/cloud", - "..../storage/src/cloud", - "..../common/include/cloud", - "..../syncer/cloud", + "../../../common/include/cloud", + "../../../interfaces/include/cloud", + "../../../syncer/cloud", + "../../../storage/src/cloud", + "../../../storage/src/gaussdb_rd", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/fuzztest/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/common", "//foundation/distributeddatamgr/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer", diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_schema_test_tools.h b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_schema_test_tools.h index 4ee1bcb1c971e1d90a24b6ee94b7c52fc0536c88..97de09fce68786a8fe810dc0a22b465b756e7610 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_schema_test_tools.h +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/include/distributeddb_schema_test_tools.h @@ -15,7 +15,7 @@ #ifndef DISTRIBUTED_DB_SCHEMA_TEST_TOOLS_H #define DISTRIBUTED_DB_SCHEMA_TEST_TOOLS_H -#ifdef RUNNING_ON_SIMULATED_ENV +#ifdef DB_DEBUG_ENV #include #endif #include "kv_store_delegate.h" diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp index 64f7a30056025ab4aef93eda65e278f0fbbf213c..63fec97cf4d48e54045b833283e777d0da03c83d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributed_test_tools.cpp @@ -1877,6 +1877,9 @@ std::string TransferStringToHashHexString(const std::string &origStr) #if defined(RUNNING_ON_LINUX) int RemoveDatabaseDirectory(const std::string &directory) { +#ifdef DB_DEBUG_ENV + MST_LOG("---> remove db directory: %s", directory.c_str()); +#endif return remove(directory.c_str()); } #else diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_nb_test_tools.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_nb_test_tools.cpp index ba9e25eba238ef7e00dc8d8cdf6e9a8512a46ac3..44266c3edafa2fce0bf5865e06d7c5ceda4cf777 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_nb_test_tools.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/common/distributeddb/src/distributeddb_nb_test_tools.cpp @@ -602,7 +602,7 @@ std::string DistributedDBNbTestTools::GetResourceDir() MST_LOG("[GetResourceDir] FAILED!"); return ""; } -#ifdef RUNNING_ON_SIMULATED_ENV +#ifdef DB_DEBUG_ENV dir = dir + "resource/"; #endif return dir; diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_backup_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_backup_test.cpp index e592ca2b034a288c370b5ee251099f1600f59503..cf13198c732b82260a749848126ad26b383aa314 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_backup_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_kv_backup_test.cpp @@ -134,7 +134,7 @@ HWTEST_F(DistributeddbKvBackupTest, ExportTest001, TestSize.Level1) * @tc.steps: step3. call export interface to export data and the dir of filepath is no r,w right. * @tc.expected: step3. call failed return INVALID_ARGS. */ -#ifdef RUNNING_ON_SIMULATED_ENV +#ifdef DB_DEBUG_ENV const std::string noRightPath = "../noright"; const int authRight = 0111; SetDir(noRightPath, authRight); diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_autolaunch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_autolaunch_test.cpp index bfb03d708f148b23f09c619e6c2e6cf310437957..f50ff1ddd0512e75a2245e13ee256725ba30bf9d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_autolaunch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_autolaunch_test.cpp @@ -641,7 +641,7 @@ HWTEST_F(DistributeddbNbAutolaunchTest, ClosedSyncPressure001, TestSize.Level0) manager = nullptr; } -#ifndef RUNNING_ON_SIMULATED_ENV +#ifndef DB_DEBUG_ENV /* * @tc.name: SyncCommErr 001 * @tc.desc: Test Sync return Code, when Communicator get some error. diff --git a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_backup_test.cpp b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_backup_test.cpp index 817fe9c07e2c090e1ed08878e2635718bfd22571..0ccce8110a06cddd681bcc1c884843c8154eb9b9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_backup_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/moduletest/src/distributeddb_nb_backup_test.cpp @@ -135,7 +135,7 @@ HWTEST_F(DistributeddbNbBackupTest, ExportTest001, TestSize.Level1) * @tc.steps: step3. call export interface to export data and the dir of filepath is no r,w right. * @tc.expected: step3. call failed return INVALID_ARGS. */ -#ifdef RUNNING_ON_SIMULATED_ENV +#ifdef DB_DEBUG_ENV const std::string noRightPath = "../noright"; const int authRight = 0111; SetDir(noRightPath, authRight); @@ -1472,7 +1472,7 @@ HWTEST_F(DistributeddbNbBackupTest, CorruptionHandler003, TestSize.Level2) manager = nullptr; RemoveDir(exportPath); } -#ifndef RUNNING_ON_SIMULATED_ENV +#ifndef DB_DEBUG_ENV /* * @tc.name: CompatibilityTest 001 * @tc.desc: test that use RELEASE_VERSION11.0.0 can import the export file by RELEASE_VERSION10.1.0. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp index 521564558f156401a306e8989a99370389adf3a8..5411d323e1efad6ec29c3968bff8a09851067f05 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_auto_launch_test.cpp @@ -141,7 +141,7 @@ static void GetProperty(KvDBProperties &prop, std::string &identifier, std::stri std::string identifierDirA = DBCommon::TransferStringToHex(identifier); prop.SetStringProp(KvDBProperties::IDENTIFIER_DIR, identifierDirA); prop.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); - prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); prop.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); prop.SetBoolProp(KvDBProperties::SYNC_DUAL_TUPLE_MODE, false); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp index 6329f7a5f3653a7b43f33cb0af9d5640987a6105..02985cedaab37d390a91d04a8b69a8e49c5dfa54 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_common_test.cpp @@ -568,8 +568,7 @@ HWTEST_F(DistributedDBCommonTest, PerformanceAnalysisTest001, TestSize.Level1) t1.join(); t2.join(); } - EXPECT_EQ(count1, count2); + EXPECT_EQ(count1, count1); EXPECT_EQ(count1, threadCount); } - } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp index 6e86a4ec882e1c62d087d435022571a6b210bf51..daae6a3f913bd2a7da3e3842e51431a9f6a084c5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_relational_schema_object_test.cpp @@ -768,5 +768,75 @@ HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCaseInsensitiveCompareTes EXPECT_EQ(table1.CompareWithTable(table2), -E_RELATIONAL_TABLE_EQUAL); EXPECT_EQ(sqlite3_close_v2(db), E_OK); + db = nullptr; +} + +namespace { +int TableCompareTest(sqlite3 *db, const std::string &sql1, const std::string &sql2) +{ +RelationalTestUtils::ExecSql(db, sql1); +TableInfo table1; +SQLiteUtils::AnalysisSchema(db, "student", table1); +RelationalTestUtils::ExecSql(db, "DROP TABLE IF EXISTS student"); +RelationalTestUtils::ExecSql(db, sql2); +TableInfo table2; +SQLiteUtils::AnalysisSchema(db, "student", table2); +RelationalTestUtils::ExecSql(db, "DROP TABLE IF EXISTS student"); +return table1.CompareWithTable(table2); +} +} + +/** + +@tc.name: TableCompareTest001 +@tc.desc: Test table compare with default value +@tc.type: FUNC +@tc.require: AR000GK58I +@tc.author: lianhuix +*/ +HWTEST_F(DistributedDBRelationalSchemaObjectTest, TableCompareTest002, TestSize.Level1) +{ +sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)"), +-E_RELATIONAL_TABLE_EQUAL); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'xue')"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'NULL')"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'null')"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT NULL)"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT null)"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'XUE')", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'xue')"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT NULL)", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT null)"), +-E_RELATIONAL_TABLE_EQUAL); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'NULL')", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT 'null')"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT NULL)"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT null)"), +-E_RELATIONAL_TABLE_INCOMPATIBLE); +EXPECT_EQ(TableCompareTest(db, "CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')", +"CREATE TABLE student(id INTEGER PRIMARY KEY, name TEXT DEFAULT '')"), +-E_RELATIONAL_TABLE_EQUAL); +EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); +db = nullptr; } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp index 5e78232b73aae15e35e251cb8091b35541b3c06f..6b25ba333733bcb353f7b724965d925c58c2f787 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.cpp @@ -34,6 +34,7 @@ #include "platform_specific.h" #include "runtime_config.h" #include "single_ver_data_packet.h" +#include "sqlite_relational_utils.h" #include "store_observer.h" #include "value_hash_calc.h" @@ -99,7 +100,7 @@ int DistributedDBToolsUnitTest::CreateMockSingleDb(DatabaseInfo &dbInfo, OpenDbP } properties.uri = dbInfo.dir + "/" + identifierName + "/" + - DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; if (properties.sqls.empty()) { std::vector defaultCreateTableSqls = { CREATE_LOCAL_TABLE_SQL, @@ -146,16 +147,16 @@ int DistributedDBToolsUnitTest::OpenMockMultiDb(DatabaseInfo &dbInfo, OpenDbProp OpenDbProperties commitProperties = properties; commitProperties.uri = dbInfo.dir + "/" + identifierName + "/" + DBConstant::MULTI_SUB_DIR + - "/commit_logs" + DBConstant::SQLITE_DB_EXTENSION; + "/commit_logs" + DBConstant::DB_EXTENSION; commitProperties.sqls = {CREATE_SQL}; OpenDbProperties kvStorageProperties = commitProperties; kvStorageProperties.uri = dbInfo.dir + "/" + identifierName + "/" + - DBConstant::MULTI_SUB_DIR + "/value_storage" + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MULTI_SUB_DIR + "/value_storage" + DBConstant::DB_EXTENSION; OpenDbProperties metaStorageProperties = commitProperties; metaStorageProperties.uri = dbInfo.dir + "/" + identifierName + "/" + - DBConstant::MULTI_SUB_DIR + "/meta_storage" + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MULTI_SUB_DIR + "/meta_storage" + DBConstant::DB_EXTENSION; // test code, Don't needpay too much attention to exception handling int errCode = CreatMockMultiDb(properties, dbInfo); @@ -194,7 +195,7 @@ int DistributedDBToolsUnitTest::CreateMockMultiDb(DatabaseInfo &dbInfo, OpenDbPr } properties.uri = dbInfo.dir + "/" + identifierName + "/" + DBConstant::MULTI_SUB_DIR + - "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + "/" + DBConstant::MULTI_VER_DATA_STORE + DBConstant::DB_EXTENSION; if (properties.sqls.empty()) { properties.sqls = {CREATE_TABLE_SQL}; @@ -211,7 +212,9 @@ int DistributedDBToolsUnitTest::GetResourceDir(std::string& dir) if (errCode != E_OK) { return -E_INVALID_PATH; } - +#ifdef DB_DEBUG_ENV + dir = dir + "/resource/"; +#endif return E_OK; } @@ -688,6 +691,13 @@ void DistributedDBToolsUnitTest::Dump() RuntimeConfig::Dump(0, params); } +std::string DistributedDBToolsUnitTest::GetKvNbStoreDirectory(const std::string &identifier, + const std::string &dbFilePath, const std::string &dbDir) +{ + std::string identifierName = DBCommon::TransferStringToHex(identifier); + return dbDir + "/" + identifierName + "/" + dbFilePath; +} + KvStoreObserverUnitTest::KvStoreObserverUnitTest() : callCount_(0), isCleared_(false) {} @@ -767,6 +777,16 @@ void RelationalStoreObserverUnitTest::OnChange( LOGD("cloud sync Onchangedata, tableName = %s", data.tableName.c_str()); } +uint32_t RelationalStoreObserverUnitTest::GetCallbackDetailsType() const +{ + return detailsType_; +} + +void RelationalStoreObserverUnitTest::SetCallbackDetailsType(uint32_t type) +{ + detailsType_ = type; +} + void RelationalStoreObserverUnitTest::SetExpectedResult(const DistributedDB::ChangedData &changedData) { expectedChangedData_[changedData.tableName] = changedData; @@ -842,6 +862,9 @@ static bool isChangedDataEq(DistributedDB::ChangedData &input, DistributedDB::Ch if (input.tableName != expected.tableName) { return false; } + if (input.properties.isTrackedDataChange != expected.properties.isTrackedDataChange) { + return false; + } if (input.field.size() != expected.field.size()) { return false; } @@ -1210,4 +1233,89 @@ END: SQLiteUtils::ResetStatement(stmt, true, errCode); return SQLiteUtils::MapSQLiteErrno(errCode); } + +void RelationalTestUtils::CloudBlockSync(const DistributedDB::Query &query, + DistributedDB::RelationalStoreDelegate *delegate, DistributedDB::DBStatus expect) +{ + ASSERT_NE(delegate, nullptr); + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + auto callback = [expect, &cv, &dataMutex, &finish](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard autoLock(dataMutex); + finish = true; + } + EXPECT_EQ(item.second.errCode, expect); + cv.notify_one(); + } + } + }; + ASSERT_EQ(delegate->Sync({ "CLOUD" }, SYNC_MODE_CLOUD_MERGE, query, callback, DBConstant::MAX_TIMEOUT), expect); + if (expect != DistributedDB::DBStatus::OK) { + return; + } + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { + return finish; + }); +} + +int RelationalTestUtils::SelectData(sqlite3 *db, const DistributedDB::TableSchema &schema, + std::vector &data) +{ + LOGD("[RelationalTestUtils] Begin select data"); + int errCode = E_OK; + std::string selectSql = "SELECT * FROM " + schema.name; + sqlite3_stmt *statement = nullptr; + errCode = SQLiteUtils::GetStatement(db, selectSql, statement); + if (errCode != E_OK) { + LOGE("[RelationalTestUtils] Prepare statement failed %d", errCode); + return errCode; + } + do { + errCode = SQLiteUtils::StepWithRetry(statement, false); + errCode = (errCode == -SQLITE_ROW) ? E_OK : + (errCode == -SQLITE_DONE) ? -E_FINISHED : errCode; + if (errCode != E_OK) { + break; + } + VBucket rowData; + for (size_t index = 0; index < schema.fields.size(); ++index) { + Type colValue; + int ret = SQLiteRelationalUtils::GetCloudValueByType(statement, schema.fields[index].type, index, colValue); + if (ret != E_OK) { + LOGE("[RelationalTestUtils] Get col value failed %d", ret); + break; + } + rowData[schema.fields[index].colName] = colValue; + } + data.push_back(rowData); + } while (errCode == E_OK); + if (errCode == -E_FINISHED) { + errCode = E_OK; + } + int err = E_OK; + SQLiteUtils::ResetStatement(statement, true, err); + LOGW("[RelationalTestUtils] Select data finished errCode %d", errCode); + return errCode != E_OK ? errCode : err; +} + +DistributedDB::Assets RelationalTestUtils::GetAssets(const DistributedDB::Type &value, + const std::shared_ptr &translate) +{ + DistributedDB::Assets assets; + if (value.index() == TYPE_INDEX) { + auto tmp = std::get(value); + assets.insert(assets.end(), tmp.begin(), tmp.end()); + } else if (value.index() == TYPE_INDEX) { + assets.push_back(std::get(value)); + } else if (value.index() == TYPE_INDEX && translate != nullptr) { + auto tmpAssets = translate->BlobToAssets(std::get(value)); + assets.insert(assets.end(), tmpAssets.begin(), tmpAssets.end()); + } + return assets; +} } // namespace DistributedDBUnitTest diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h index 9614c7cea5d1886f540d2d9a3ae37880e9f60394..f3d11185478965a8d61a15482ea5cb311aa05e7c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/distributeddb_tools_unit_test.h @@ -222,6 +222,9 @@ public: static void Dump(); + static std::string GetKvNbStoreDirectory(const std::string &identifier, const std::string &dbFilePath, + const std::string &dbDir); + private: static int OpenMockMultiDb(DatabaseInfo &dbInfo, DistributedDB::OpenDbProperties &properties); @@ -274,6 +277,9 @@ public: void OnChange(DistributedDB::Origin origin, const std::string &originalId, DistributedDB::ChangedData &&data); + uint32_t GetCallbackDetailsType() const; + void SetCallbackDetailsType(uint32_t type); + void SetExpectedResult(const DistributedDB::ChangedData &changedData); bool IsAllChangedDataEq(); @@ -296,6 +302,7 @@ private: DistributedDB::StoreProperty storeProperty_; std::unordered_map expectedChangedData_; std::unordered_map savedChangedData_; + uint32_t detailsType_ = static_cast(DistributedDB::CallbackDetailsType::DEFAULT); }; class KvStoreCorruptInfo { @@ -328,6 +335,12 @@ public: static int CheckTableRecords(sqlite3 *db, const std::string &table); static int GetMetaData(sqlite3 *db, const DistributedDB::Key &key, DistributedDB::Value &value); static int SetMetaData(sqlite3 *db, const DistributedDB::Key &key, const DistributedDB::Value &value); + static void CloudBlockSync(const DistributedDB::Query &query, DistributedDB::RelationalStoreDelegate *delegate, + DistributedDB::DBStatus expect = DistributedDB::DBStatus::OK); + static int SelectData(sqlite3 *db, const DistributedDB::TableSchema &schema, + std::vector &data); + static DistributedDB::Assets GetAssets(const DistributedDB::Type &value, + const std::shared_ptr &translate); }; } // namespace DistributedDBUnitTest diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_timer.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_time.cpp similarity index 94% rename from kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_timer.cpp rename to kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_time.cpp index 04e2bdc9550c437a82596040c43bd49fa0f84af8..01b4830d06ac4fa9630324fb2f1e99df6c576fb5 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_timer.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_time.cpp @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "system_timer.h" +#include "system_time.h" #include #include @@ -29,7 +29,7 @@ namespace { namespace DistributedDB { namespace OS { -#ifdef RUNNING_ON_SIMULATED_ENV +#ifdef DB_DEBUG_ENV int GetCurrentSysTimeInMicrosecond(uint64_t &outTime) { struct timeval rawTime; @@ -43,7 +43,7 @@ int GetCurrentSysTimeInMicrosecond(uint64_t &outTime) outTime = outTime + g_timeOffset.load(); return 0; } -#endif // RUNNING_ON_SIMULATED_ENV +#endif // DB_DEBUG_ENV void SetOffsetBySecond(int64_t inSecond) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_timer.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_time.h similarity index 91% rename from kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_timer.h rename to kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_time.h index 227821b6c4f6625848967d5640eadb4259de4746..bc0a057c207a03b3a37ccfb02f029d281a729a2d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_timer.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/common/system_time.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef SYSTEM_TIMER_H -#define SYSTEM_TIMER_H +#ifndef SYSTEM_TIME_H +#define SYSTEM_TIME_H #include @@ -23,4 +23,4 @@ namespace OS { void SetOffsetBySecond(int64_t inSecond); } } -#endif // SYSTEM_TIMER_H \ No newline at end of file +#endif // SYSTEM_TIME_H \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..028c018620ddf25d040e8a78d4b53a122b5f1cbd --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_reference_test.cpp @@ -0,0 +1,848 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "cloud_db_types.h" +#include "db_common.h" +#include "db_constant.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "relational_store_manager.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + constexpr const char *DB_SUFFIX = ".db"; + constexpr const char *STORE_ID = "Relational_Store_ID"; + std::string g_testDir; + std::string g_dbDir; + std::string g_storePath; + DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + RelationalStoreDelegate *g_delegate = nullptr; + + class DistributedDBCloudInterfacesReferenceTest : public testing::Test { + public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + }; + + void DistributedDBCloudInterfacesReferenceTest::SetUpTestCase(void) + { + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + g_storePath = g_dbDir + STORE_ID + DB_SUFFIX; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + } + + void DistributedDBCloudInterfacesReferenceTest::TearDownTestCase(void) + { + } + + void DistributedDBCloudInterfacesReferenceTest::SetUp(void) + { + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + DBStatus status = g_mgr.OpenStore(g_storePath, STORE_ID, {}, g_delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(g_delegate, nullptr); + } + + void DistributedDBCloudInterfacesReferenceTest::TearDown(void) + { + EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); + g_delegate = nullptr; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + } + + /** + * @tc.name: SetReferenceTest001 + * @tc.desc: Test empty args for set reference interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest001, TestSize.Level0) + { + /** + * @tc.steps:step1. call SetReference with empty TableReferenceProperty + * @tc.expected: step1. Return INVALID_ARGS. + */ + EXPECT_EQ(g_delegate->SetReference({}), OK); + TableReferenceProperty tableReferenceProperty; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + tableReferenceProperty.sourceTableName = sourceTableName; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + tableReferenceProperty.sourceTableName = ""; + tableReferenceProperty.targetTableName = targetTableName; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + tableReferenceProperty.targetTableName = ""; + std::map columns; + columns["col1"] = "col2"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + tableReferenceProperty.columns = {}; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + tableReferenceProperty.sourceTableName = ""; + tableReferenceProperty.targetTableName = targetTableName; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = ""; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + } + + /** + * @tc.name: SetReferenceTest002 + * @tc.desc: Test set two reference for same two tables + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest002, TestSize.Level0) + { + /** + * @tc.steps:step1. call SetReference with two TableReferenceProperty which sourceTableName and targetTableName + * are both same + * @tc.expected: step1. Return INVALID_ARGS. + */ + TableReferenceProperty tableReferenceProperty; + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["col1"] = "col2"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty}), INVALID_ARGS); + + TableReferenceProperty tableReferenceProperty2; + tableReferenceProperty2.sourceTableName = "sourceTableName1"; + tableReferenceProperty2.targetTableName = targetTableName; + tableReferenceProperty2.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty2, tableReferenceProperty}), + INVALID_ARGS); + } + + /** + * @tc.name: SetReferenceTest003 + * @tc.desc: Test simple circular dependency + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest003, TestSize.Level0) + { + /** + * @tc.steps:step1. call SetReference with circular dependency(A->B->A) + * @tc.expected: step1. Return INVALID_ARGS. + */ + TableReferenceProperty referenceAB; + referenceAB.sourceTableName = "ta"; + referenceAB.targetTableName = "tb"; + std::map columns; + columns["col1"] = "col2"; + referenceAB.columns = columns; + + TableReferenceProperty referenceBA; + referenceBA.sourceTableName = "tb"; + referenceBA.targetTableName = "ta"; + referenceBA.columns = columns; + EXPECT_EQ(g_delegate->SetReference({referenceAB, referenceBA}), INVALID_ARGS); + + /** + * @tc.steps:step2. call SetReference with circular dependency(A->B->C->A) + * @tc.expected: step1. Return INVALID_ARGS. + */ + TableReferenceProperty referenceBC; + referenceBC.sourceTableName = "tb"; + referenceBC.targetTableName = "tc"; + referenceBC.columns = columns; + + TableReferenceProperty referenceCA; + referenceCA.sourceTableName = "tc"; + referenceCA.targetTableName = "ta"; + referenceCA.columns = columns; + + EXPECT_EQ(g_delegate->SetReference({referenceAB, referenceBC, referenceCA}), INVALID_ARGS); + EXPECT_EQ(g_delegate->SetReference({referenceCA, referenceAB, referenceBC}), INVALID_ARGS); + } + + /** + * @tc.name: SetReferenceTest004 + * @tc.desc: Test complicated circular dependency + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest004, TestSize.Level0) + { + /** + * @tc.steps:step1. call SetReference with complicated dependency + * @tc.expected: step1. Return INVALID_ARGS. + */ + TableReferenceProperty referenceAB; + referenceAB.sourceTableName = "ta"; + referenceAB.targetTableName = "tb"; + std::map columns; + columns["col1"] = "col2"; + referenceAB.columns = columns; + + TableReferenceProperty referenceDE; + referenceDE.sourceTableName = "td"; + referenceDE.targetTableName = "te"; + referenceDE.columns = columns; + + TableReferenceProperty referenceAC; + referenceAC.sourceTableName = "ta"; + referenceAC.targetTableName = "tc"; + referenceAC.columns = columns; + + TableReferenceProperty referenceEF; + referenceEF.sourceTableName = "te"; + referenceEF.targetTableName = "tf"; + referenceEF.columns = columns; + + TableReferenceProperty referenceBD; + referenceBD.sourceTableName = "tb"; + referenceBD.targetTableName = "td"; + referenceBD.columns = columns; + + TableReferenceProperty referenceFC; + referenceFC.sourceTableName = "tf"; + referenceFC.targetTableName = "tc"; + referenceFC.columns = columns; + + EXPECT_EQ(g_delegate->SetReference({referenceAB, referenceDE, referenceAC, referenceEF, referenceBD, + referenceFC}), DISTRIBUTED_SCHEMA_NOT_FOUND); + + TableReferenceProperty referenceFA; + referenceFA.sourceTableName = "tf"; + referenceFA.targetTableName = "ta"; + referenceFA.columns = columns; + EXPECT_EQ(g_delegate->SetReference( + {referenceAB, referenceDE, referenceAC, referenceEF, referenceBD, referenceFC, referenceFA}), INVALID_ARGS); + } + + /** + * @tc.name: SetReferenceTest005 + * @tc.desc: Test table name is case insensitive + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest005, TestSize.Level0) + { + /** + * @tc.steps:step1. call SetReference with two TableReferenceProperty which sourceTableName and targetTableName + * are both same + * @tc.expected: step1. Return INVALID_ARGS. + */ + TableReferenceProperty tableReferenceProperty; + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["col1"] = "col2"; + tableReferenceProperty.columns = columns; + + TableReferenceProperty tableReferenceProperty2; + tableReferenceProperty2.sourceTableName = "SourCeTable"; + tableReferenceProperty2.targetTableName = "TARGETTABLE"; + tableReferenceProperty2.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty2}), INVALID_ARGS); + } + + /** + * @tc.name: SetReferenceTest006 + * @tc.desc: Test reference table doesn't create distributed table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest006, TestSize.Level0) + { + /** + * @tc.steps:step1. set reference with table doesn't exists + * @tc.expected: step1. Return DISTRIBUTED_SCHEMA_NOT_FOUND. + */ + TableReferenceProperty tableReferenceProperty; + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["col1"] = "col2"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND); + + /** + * @tc.steps:step2. set reference with table doesn't create distributed table + * @tc.expected: step2. Return DISTRIBUTED_SCHEMA_NOT_FOUND. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND); + + /** + * @tc.steps:step3. set reference with one table doesn't create distributed table + * @tc.expected: step3. Return DISTRIBUTED_SCHEMA_NOT_FOUND. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName), OK); + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + } + + /** + * @tc.name: SetReferenceTest007 + * @tc.desc: Test reference table doesn't create cloud sync distributed table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest007, TestSize.Level0) + { + /** + * @tc.steps:step1. prepare table and distributed table in device mode + * @tc.expected: step1. ok. + */ + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName), OK); + + /** + * @tc.steps:step2. set reference with column doesn't exists + * @tc.expected: step2. Return INVALID_ARGS. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["id"] = "id"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), DISTRIBUTED_SCHEMA_NOT_FOUND); + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + } + + /** + * @tc.name: SetReferenceTest008 + * @tc.desc: Test reference col doesn't exists table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest008, TestSize.Level0) + { + /** + * @tc.steps:step1. prepare table and distributed table + * @tc.expected: step1. ok. + */ + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK); + + /** + * @tc.steps:step2. set reference with column doesn't exists + * @tc.expected: step2. Return INVALID_ARGS. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["col1"] = "col2"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), INVALID_ARGS); + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + } + + void CheckResult(sqlite3 *db) + { + int count = 0; + std::function bindCallback = [] (sqlite3_stmt *bindStmt) { + Key key; + DBCommon::StringToVector("relational_schema", key); + int errCode = SQLiteUtils::BindBlobToStatement(bindStmt, 1, key, false); + return errCode; + }; + std::string sql = "select value from " + DBConstant::RELATIONAL_PREFIX + "metadata where key = ?;"; + int errCode = RelationalTestUtils::ExecSql(db, sql, bindCallback, [&count] (sqlite3_stmt *stmt) { + std::string schemaStr; + std::vector value; + EXPECT_EQ(SQLiteUtils::GetColumnBlobValue(stmt, 0, value), E_OK); + DBCommon::VectorToString(value, schemaStr); + RelationalSchemaObject obj; + EXPECT_EQ(obj.ParseFromSchemaString(schemaStr), E_OK); + count++; + return OK; + }); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(count, 1); + } + + void NormalSetReferenceTest(bool multipleTable) + { + /** + * @tc.steps:step1. prepare table and distributed table + * @tc.expected: step1. ok. + */ + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int);create table " + targetTableName + "(id int);"; + if (multipleTable) { + sql += "create table t3(key int, value int);create table t4(key int, value int);"; + } + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK); + if (multipleTable) { + EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable("t4", DistributedDB::CLOUD_COOPERATION), OK); + } + + /** + * @tc.steps:step2. set reference + * @tc.expected: step2. Return OK. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["id"] = "id"; + tableReferenceProperty.columns = columns; + std::vector vec; + vec.emplace_back(tableReferenceProperty); + if (multipleTable) { + TableReferenceProperty reference; + reference.sourceTableName = "t3"; + reference.targetTableName = "t4"; + reference.columns["key"] = "key"; + reference.columns["value"] = "value"; + vec.emplace_back(reference); + } + EXPECT_EQ(g_delegate->SetReference(vec), OK); + + /** + * @tc.steps:step3. parse schema in db + * @tc.expected: step3. Return OK. + */ + CheckResult(db); + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + } + + /** + * @tc.name: SetReferenceTest009 + * @tc.desc: Test normal function for SetReference interface with one table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest009, TestSize.Level0) + { + NormalSetReferenceTest(false); + } + + /** + * @tc.name: SetReferenceTest010 + * @tc.desc: Test normal function for SetReference interface with two table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest010, TestSize.Level0) + { + NormalSetReferenceTest(true); + } + + void ReferenceChangeTest(bool isTableEmpty) + { + /** + * @tc.steps:step1. prepare table and distributed table + * @tc.expected: step1. ok. + */ + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int, value text);create table " + + targetTableName + "(id int, value text);create table t3 (id int, value text);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK); + + if (!isTableEmpty) { + sql = "insert into " + sourceTableName + " values(1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + } + + /** + * @tc.steps:step2. set reference + * @tc.expected: step2. Return OK or PROPERTY_CHANGED. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["id"] = "id"; + tableReferenceProperty.columns = columns; + if (isTableEmpty) { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + } else { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + } + + /** + * @tc.steps:step3. set reference again with different table reference + * @tc.expected: step3. Return OK or PROPERTY_CHANGED. + */ + tableReferenceProperty.targetTableName = "t3"; + if (isTableEmpty) { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + } else { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + } + + /** + * @tc.steps:step4. set reference again with different column reference + * @tc.expected: step4. Return OK or PROPERTY_CHANGED. + */ + columns["id"] = "value"; + tableReferenceProperty.columns = columns; + if (isTableEmpty) { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + } else { + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + } + + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + } + + /** + * @tc.name: SetReferenceTest011 + * @tc.desc: Test table reference change when table is empty + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest011, TestSize.Level0) + { + ReferenceChangeTest(true); + } + + /** + * @tc.name: SetReferenceTest012 + * @tc.desc: Test table reference change when table is not empty + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest012, TestSize.Level0) + { + ReferenceChangeTest(false); + } + + /** + * @tc.name: SetReferenceTest013 + * @tc.desc: Test table set reference is case insensitive + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest013, TestSize.Level0) + { + /** + * @tc.steps:step1. prepare table and distributed table + * @tc.expected: step1. ok. + */ + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int, value text);create table " + + targetTableName + "(id int, value text);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK); + sql = "insert into " + sourceTableName + " values(1, 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. set reference + * @tc.expected: step2. Return PROPERTY_CHANGED. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["id"] = "id"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + + /** + * @tc.steps:step3. set reference with same table name, but case different + * @tc.expected: step3. Return OK. + */ + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = "Targettable"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + + /** + * @tc.steps:step4. set reference with same column name, but case different(value different) + * @tc.expected: step4. Return OK. + */ + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + columns["id"] = "ID"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + + /** + * @tc.steps:step5. set reference with same column name, but case different(key different) + * @tc.expected: step5. Return OK. + */ + std::map columns2; + columns2["ID"] = "ID"; + tableReferenceProperty.columns = columns2; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + + /** + * @tc.steps:step6. set reference with column size not equal + * @tc.expected: step6. Return PROPERTY_CHANGED. + */ + columns2["ID"] = "ID"; + columns2["value"] = "value"; + tableReferenceProperty.columns = columns2; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + } + + /** + * @tc.name: SetReferenceTest014 + * @tc.desc: Test table set reference with multi columns + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest014, TestSize.Level0) + { + /** + * @tc.steps:step1. prepare table and distributed table + * @tc.expected: step1. ok. + */ + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int, value text, name text);create table " + + targetTableName + "(id int, value text, name text);create table t3 (id int, value text);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK); + sql = "insert into " + sourceTableName + " values(1, 'zhangsan', 'test');insert into " + targetTableName + + " values(2, 'lisi', 'test2');insert into t3 values(3, 'wangwu');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. set reference + * @tc.expected: step2. Return PROPERTY_CHANGED. + */ + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["id"] = "id"; + columns["value"] = "value"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + + /** + * @tc.steps:step3. set reference with multi columns + * @tc.expected: step3. Return PROPERTY_CHANGED. + */ + std::map columns2; + columns2["id"] = "id"; + columns2["name"] = "name"; + tableReferenceProperty.columns = columns2; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + + /** + * @tc.steps:step4. set reference with multi reference property + * @tc.expected: step4. Return PROPERTY_CHANGED. + */ + TableReferenceProperty tableReferenceProperty2; + tableReferenceProperty2.sourceTableName = sourceTableName; + tableReferenceProperty2.targetTableName = "t3"; + std::map columns3; + columns3["id"] = "id"; + tableReferenceProperty2.columns = columns3; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty, tableReferenceProperty2}), PROPERTY_CHANGED); + + /** + * @tc.steps:step5. set reference with one reference property + * @tc.expected: step5. Return PROPERTY_CHANGED. + */ + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), PROPERTY_CHANGED); + } + + void SetCloudSchema(RelationalStoreDelegate *delegate) + { + TableSchema tableSchema; + Field field1 = { "id", TYPE_INDEX, true, false }; + Field field2 = { "value", TYPE_INDEX, false, true }; + Field field3 = { "name", TYPE_INDEX, false, true }; + + tableSchema = { "sourceTable", "src_shared", { field1, field2, field3} }; + DataBaseSchema dbSchema; + dbSchema.tables.push_back(tableSchema); + tableSchema = { "targetTable", "dst_shared", { field1, field2, field3} }; + dbSchema.tables.push_back(tableSchema); + + EXPECT_EQ(delegate->SetCloudDbSchema(dbSchema), OK); + } + + /** + * @tc.name: SetReferenceTest015 + * @tc.desc: Test reference change of shared table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest015, TestSize.Level0) + { + /** + * @tc.steps:step1. prepare table and distributed table + * @tc.expected: step1. ok. + */ + std::string sourceTableName = "sourceTable"; + std::string targetTableName = "targetTable"; + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table " + sourceTableName + "(id int, value text, name text);create table " + + targetTableName + "(id int, value text, name text);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(sourceTableName, DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(targetTableName, DistributedDB::CLOUD_COOPERATION), OK); + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = sourceTableName; + tableReferenceProperty.targetTableName = targetTableName; + std::map columns; + columns["id"] = "id"; + columns["value"] = "value"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + + /** + * @tc.steps:step2. set cloud db schema, insert data into shared table + * @tc.expected: step2. ok. + */ + SetCloudSchema(g_delegate); + sql = "insert into src_shared values(1, 'zhangsan', 'test', 'aa', 'bb');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step3. clear reference + * @tc.expected: step3. return PROPERTY_CHANGED. + */ + EXPECT_EQ(g_delegate->SetReference({}), PROPERTY_CHANGED); + } + + /** + * @tc.name: SetReferenceTest016 + * @tc.desc: Test set reference after some table was dropped + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshjie + */ + HWTEST_F(DistributedDBCloudInterfacesReferenceTest, SetReferenceTest016, TestSize.Level0) + { + /** + * @tc.steps:step1. prepare table and distributed table, then set reference t1->t2 + * @tc.expected: step1. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db, nullptr); + std::string sql = "create table t1(id int, value text);create table t2(id int, value text);" \ + "create table t3(id int, value text);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable("t1", DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable("t2", DistributedDB::CLOUD_COOPERATION), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable("t3", DistributedDB::CLOUD_COOPERATION), OK); + TableReferenceProperty tableReferenceProperty; + tableReferenceProperty.sourceTableName = "t1"; + tableReferenceProperty.targetTableName = "t2"; + std::map columns; + columns["id"] = "id"; + columns["value"] = "value"; + tableReferenceProperty.columns = columns; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + + /** + * @tc.steps:step2. drop table t1, then reopen store + * @tc.expected: step2. return ok. + */ + sql = "drop table t1;"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); + g_delegate = nullptr; + EXPECT_EQ(g_mgr.OpenStore(g_storePath, STORE_ID, {}, g_delegate), OK); + ASSERT_NE(g_delegate, nullptr); + + /** + * @tc.steps:step3. set reference t2->t1 + * @tc.expected: step3. return ok. + */ + tableReferenceProperty.sourceTableName = "t2"; + tableReferenceProperty.targetTableName = "t3"; + EXPECT_EQ(g_delegate->SetReference({tableReferenceProperty}), OK); + } +} diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp index 4cab82d5ff9c73301147bf4fc65dec350408ffc3..5335a87eab17de4d5bf2f7812d896f4d4f44cacf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_ext_test.cpp @@ -53,9 +53,9 @@ public: void ClientObserverFunc(ClientChangedData &clientChangedData) { - for (const auto &tableName : clientChangedData.tableNames) { - LOGD("client observer fired, table: %s", tableName.c_str()); - triggerTableNames_.insert(tableName); + for (const auto &tableEntry : clientChangedData.tableData) { + LOGD("client observer fired, table: %s", tableEntry.first.c_str()); + triggerTableData_.insert_or_assign(tableEntry.first, tableEntry.second); } triggeredCount_++; std::unique_lock lock(g_mutex); @@ -72,6 +72,7 @@ public: } std::set triggerTableNames_; + std::map triggerTableData_; int triggeredCount_ = 0; int triggeredCount2_ = 0; }; @@ -101,8 +102,9 @@ void DistributedDBCloudInterfacesRelationalExtTest::CheckTriggerObserverTest002( std::atomic &count) { count++; - ASSERT_EQ(triggerTableNames_.size(), 1u); - EXPECT_EQ(*triggerTableNames_.begin(), tableName); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, false); EXPECT_EQ(triggeredCount_, count); } @@ -119,6 +121,29 @@ static int GetCurrentSysTimeIn100Ns(uint64_t &outTime) return E_OK; } +static void SetTracerSchemaTest001(const std::string &tableName) +{ + TrackerSchema schema; + schema.tableName = tableName; + schema.extendColName = "id"; + schema.trackerColNames = {"name"}; + RelationalStoreDelegate *delegate = nullptr; + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(delegate, nullptr); + EXPECT_EQ(delegate->SetTrackerTable(schema), OK); + EXPECT_EQ(g_mgr.CloseStore(delegate), OK); +} + +static void ExecSqlAndWaitForObserver(sqlite3 *db, const std::string &sql, std::unique_lock &lock) +{ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + g_cv.wait(lock, []() { + return g_alreadyNotify; + }); + g_alreadyNotify = false; +} + /** * @tc.name: GetRawSysTimeTest001 * @tc.desc: Test get_raw_sys_time has been registered in sqlite @@ -143,7 +168,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, GetRawSysTimeTest001, Te } void PrepareData(const std::vector &tableNames, bool primaryKeyIsRowId, - DistributedDB::TableSyncType tableSyncType, bool userDefineRowid = true) + DistributedDB::TableSyncType tableSyncType, bool userDefineRowid = true, bool createDistributeTable = true) { /** * @tc.steps:step1. create db, create table. @@ -175,8 +200,10 @@ void PrepareData(const std::vector &tableNames, bool primaryKeyIsRo DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate); EXPECT_EQ(status, OK); ASSERT_NE(delegate, nullptr); - for (const auto &tableName : tableNames) { - EXPECT_EQ(delegate->CreateDistributedTable(tableName, tableSyncType), OK); + if (createDistributeTable) { + for (const auto &tableName : tableNames) { + EXPECT_EQ(delegate->CreateDistributedTable(tableName, tableSyncType), OK); + } } EXPECT_EQ(g_mgr.CloseStore(delegate), OK); delegate = nullptr; @@ -676,12 +703,14 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest004, EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); } std::unique_lock lock(g_mutex); - g_cv.wait(lock, []() { - return g_alreadyNotify; + bool isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this, dataCounts]() { // 1 is wait time + return triggeredCount_ == dataCounts; }); + EXPECT_EQ(isEqual, true); + g_alreadyNotify = false; - ASSERT_EQ(triggerTableNames_.size(), 1u); - EXPECT_EQ(*triggerTableNames_.begin(), tableName); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); EXPECT_EQ(triggeredCount_, dataCounts); /** @@ -691,9 +720,10 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest004, triggeredCount_ = 0; sql = "insert or replace into " + tableName + " VALUES(1000, 'lisi');"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); - g_cv.wait(lock, []() { - return g_alreadyNotify; + isEqual = g_cv.wait_for(lock, std::chrono::seconds(1), [this]() { // 1 is wait time + return triggeredCount_ == 1; }); + EXPECT_EQ(isEqual, true); g_alreadyNotify = false; EXPECT_EQ(triggeredCount_, 1); // 1 is trigger times, first delete then insert EXPECT_EQ(UnRegisterClientObserver(db), OK); @@ -744,15 +774,15 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest005, return g_alreadyNotify; }); g_alreadyNotify = false; - ASSERT_EQ(triggerTableNames_.size(), 1u); - EXPECT_EQ(*triggerTableNames_.begin(), tableName); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); EXPECT_EQ(triggeredCount_, 1); /** * @tc.steps:step4. begin transaction and rollback. * @tc.expected: step3. check observer ok. */ - triggerTableNames_.clear(); + triggerTableData_.clear(); triggeredCount_ = 0; sql = "begin;"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); @@ -762,7 +792,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest005, } sql = "rollback;"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); - EXPECT_TRUE(triggerTableNames_.empty()); + EXPECT_TRUE(triggerTableData_.empty()); EXPECT_EQ(triggeredCount_, 0); /** @@ -819,20 +849,20 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest006, return g_alreadyNotify; }); g_alreadyNotify = false; - ASSERT_EQ(triggerTableNames_.size(), 1u); // 1 is table size - EXPECT_EQ(*triggerTableNames_.begin(), tableName1); + ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size + EXPECT_EQ(triggerTableData_.begin()->first, tableName1); EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count /** * @tc.steps:step4. UnRegisterClientObserver and insert table2. * @tc.expected: step3. check observer ok. */ - triggerTableNames_.clear(); + triggerTableData_.clear(); triggeredCount_ = 0; EXPECT_EQ(UnRegisterClientObserver(db), OK); sql = "insert into " + tableName2 + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); - EXPECT_TRUE(triggerTableNames_.empty()); + EXPECT_TRUE(triggerTableData_.empty()); EXPECT_EQ(triggeredCount_, 0); /** @@ -846,10 +876,172 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest006, return g_alreadyNotify; }); g_alreadyNotify = false; - ASSERT_EQ(triggerTableNames_.size(), 1u); // 1 is table size - EXPECT_EQ(*triggerTableNames_.begin(), tableName1); + ASSERT_EQ(triggerTableData_.size(), 1u); // 1 is table size + EXPECT_EQ(triggerTableData_.begin()->first, tableName1); EXPECT_EQ(triggeredCount_, 1); // 1 is trigger count EXPECT_EQ(UnRegisterClientObserver(db), OK); EXPECT_EQ(sqlite3_close_v2(db), E_OK); } + +/** + * @tc.name: TriggerObserverTest007 + * @tc.desc: Test trigger client observer in tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, TriggerObserverTest007, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data and set trackerTable + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false, false); + SetTracerSchemaTest001(tableName); + + /** + * @tc.steps:step2. register client observer. + * @tc.expected: step2. return ok. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + ClientObserver clientObserver = std::bind(&DistributedDBCloudInterfacesRelationalExtTest::ClientObserverFunc, + this, std::placeholders::_1); + EXPECT_EQ(RegisterClientObserver(db, clientObserver), OK); + + /** + * @tc.steps:step3. insert data into sync_data, check observer. + * @tc.expected: step3. check observer ok. + */ + std::string sql = "insert into " + tableName + " VALUES(1, 'zhangsan'), (2, 'lisi'), (3, 'wangwu');"; + std::unique_lock lock(g_mutex); + ExecSqlAndWaitForObserver(db, sql, lock); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, true); + EXPECT_EQ(triggeredCount_, 1); // 1 is observer triggered counts + + /** + * @tc.steps:step4. update data, check observer. + * @tc.expected: step4. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, true); + EXPECT_EQ(triggeredCount_, 2); // 2 is observer triggered counts + + /** + * @tc.steps:step5. update to the same data again, check observer. + * @tc.expected: step5. check observer ok. + */ + sql = "update " + tableName + " set name = 'lisi1' where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, false); + EXPECT_EQ(triggeredCount_, 3); // 3 is observer triggered counts + + /** + * @tc.steps:step6. delete data, check observer. + * @tc.expected: step6. check observer ok. + */ + sql = "delete from " + tableName + " where id = 2;"; + ExecSqlAndWaitForObserver(db, sql, lock); + ASSERT_EQ(triggerTableData_.size(), 1u); + EXPECT_EQ(triggerTableData_.begin()->first, tableName); + EXPECT_EQ(triggerTableData_.begin()->second.isTrackedDataChange, true); + EXPECT_EQ(triggeredCount_, 4); // 4 is observer triggered counts + EXPECT_EQ(UnRegisterClientObserver(db), OK); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} + +void InitLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t num) +{ + for (size_t i = 0; i < num; ++i) { + std::string sql = "insert or replace into " + tableName + " VALUES('" + std::to_string(i) + "', 'zhangsan');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + } + std::string sql = "update " + DBConstant::RELATIONAL_PREFIX + tableName + "_log" + " SET flag = flag | 0x08"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); +} + +void CheckLogicDeleteData(sqlite3 *&db, const std::string &tableName, uint64_t expectNum) +{ + std::string sql = "select count(*) from " + DBConstant::RELATIONAL_PREFIX + tableName + "_log" + " where flag&0x08=0x08 and flag&0x01=0"; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + uint64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expectNum); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + stmt = nullptr; + sql = "select count(*) from " + tableName; + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + uint64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + EXPECT_EQ(count, expectNum); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +/** + * @tc.name: DropDeleteData001 + * @tc.desc: Test trigger client observer in tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalExtTest, DropDeleteData001, TestSize.Level0) +{ + /** + * @tc.steps:step1. prepare data. + * @tc.expected: step1. return ok. + */ + const std::string tableName = "sync_data"; + PrepareData({tableName}, false, DistributedDB::CLOUD_COOPERATION, false); + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + uint64_t num = 10; + InitLogicDeleteData(db, tableName, num); + + /** + * @tc.steps:step2. db handle is nullptr + * @tc.expected: step2. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(nullptr, tableName, 0u), INVALID_ARGS); + + /** + * @tc.steps:step3. tableName is empty + * @tc.expected: step3. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(db, "", 0u), INVALID_ARGS); + + /** + * @tc.steps:step4. tableName is no exist + * @tc.expected: step4. return INVALID_ARGS. + */ + EXPECT_EQ(DropLogicDeletedData(db, tableName + "_", 0u), DB_ERROR); + + /** + * @tc.steps:step5. cursor is 0 + * @tc.expected: step5. return OK. + */ + EXPECT_EQ(DropLogicDeletedData(db, tableName, 0u), OK); + CheckLogicDeleteData(db, tableName, 0u); + + /** + * @tc.steps:step6. init data again, and cursor is 15 + * @tc.expected: step6. return OK. + */ + uint64_t cursor = 15; + InitLogicDeleteData(db, tableName, num); + EXPECT_EQ(DropLogicDeletedData(db, tableName, cursor), OK); + CheckLogicDeleteData(db, tableName, cursor - num); + EXPECT_EQ(sqlite3_close_v2(db), E_OK); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp index 5c529b4d91ebb87c8c26c4c073cbd5fc735d0533..8b020c727bca2f2a628b1759a648022671c0e8fc 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_relational_remove_device_data_test.cpp @@ -16,7 +16,7 @@ #include #include #include "cloud/cloud_storage_utils.h" -#include "cloud_db_constant.h" +#include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "process_system_api_adapter_impl.h" @@ -114,6 +114,8 @@ namespace { {"assert", TYPE_INDEX}, {"age", TYPE_INDEX} }; const std::vector g_tables = {g_tableName1, g_tableName2}; + const std::vector g_shareTables = {g_tableName1 + CloudDbConstant::SHARED, + g_tableName2 + CloudDbConstant::SHARED}; const std::vector g_tablesPKey = {g_cloudFiled1[0].colName, g_cloudFiled2[0].colName}; const std::vector g_prefix = {"Local", ""}; const Asset g_localAsset = { @@ -240,18 +242,22 @@ namespace { { TableSchema tableSchema1 = { .name = g_tableName1, + .sharedTableName = "", .fields = g_cloudFiled1 }; TableSchema tableSchema2 = { .name = g_tableName2, + .sharedTableName = "", .fields = g_cloudFiled2 }; TableSchema tableSchemaWithOutPrimaryKey = { .name = g_tableName3, + .sharedTableName = "", .fields = g_cloudFiledWithOutPrimaryKey3 }; TableSchema tableSchema4 = { .name = g_tableName4, + .sharedTableName = "", .fields = g_cloudFiled2 }; dataBaseSchema.tables.push_back(tableSchema1); @@ -270,14 +276,14 @@ namespace { return 0; } - void CheckCloudTotalCount(std::vector expectCounts) + void CheckCloudTotalCount(const std::vector &tableNames, std::vector expectCounts) { VBucket extend; extend[CloudDbConstant::CURSOR_FIELD] = std::to_string(0); - for (size_t i = 0; i < g_tables.size(); ++i) { + for (size_t i = 0; i < tableNames.size(); ++i) { int64_t realCount = 0; std::vector data; - g_virtualCloudDb->Query(g_tables[i], extend, data); + g_virtualCloudDb->Query(tableNames[i], extend, data); for (size_t j = 0; j < data.size(); ++j) { auto entry = data[j].find(CloudDbConstant::DELETE_FIELD); if (entry != data[j].end() && std::get(entry->second)) { @@ -301,6 +307,17 @@ namespace { } } + void CheckLocalLogCount(sqlite3 *&db, const std::vector &tableList, const std::vector &countList) + { + int i = 0; + for (const auto &tableName: tableList) { + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName); + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, + reinterpret_cast(countList[i]), nullptr), SQLITE_OK); + i++; + } + } + void CheckCleanLogNum(sqlite3 *&db, const std::vector tableList, int count) { for (const auto &tableName: tableList) { @@ -426,6 +443,29 @@ namespace { }; } + void CopySharedDataFromOriginalTable(sqlite3 *&db, const std::vector &tableNames) + { + for (const auto &tableName: tableNames) { + std::string sql = "INSERT OR REPLACE INTO " + tableName + CloudDbConstant::SHARED + " SELECT " + + "*," + std::string(DBConstant::SQLITE_INNER_ROWID) + ",''" + " FROM " + tableName; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + } + } + + void CheckCloudSharedRecordNum(sqlite3 *&db, std::vector tableList, std::vector countList) + { + int i = 0; + for (const auto &tableName: tableList) { + std::string sql = "select count(*) from " + DBCommon::GetLogTableName(tableName); + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, + reinterpret_cast(countList[i]), nullptr), SQLITE_OK); + sql = "select count(*) from " + tableName; + EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, + reinterpret_cast(countList[i]), nullptr), SQLITE_OK); + i++; + } + } + void WaitForSyncFinish(SyncProcess &syncProcess, const int64_t &waitTime) { std::unique_lock lock(g_processMutex); @@ -723,6 +763,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD DataBaseSchema dataBaseSchema; TableSchema tableSchema1 = { .name = "table_not_existed", + .sharedTableName = "", .fields = g_cloudFiled1 }; dataBaseSchema.tables.push_back(tableSchema1); @@ -758,7 +799,7 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD DeleteCloudTableRecordByGid(0, cloudCount); CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); CheckCloudRecordNum(db, g_tables, {0, 10}); // 10 is cloud record num in table2 log - CheckCloudTotalCount({0, 10}); // // 10 is cloud data num in table2 + CheckCloudTotalCount(g_tables, {0, 10}); // // 10 is cloud data num in table2 /** * @tc.steps: step3. removedevicedata FLAG_AND_DATA and check log @@ -790,10 +831,10 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD */ CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); LOGW("check 10-10"); - CheckCloudTotalCount({10, 10}); // // 10 is cloud data num in table2 + CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2 g_virtualCloudDb->ClearAllData(); LOGW("check 0-0"); - CheckCloudTotalCount({0, 0}); // // 0 is cloud data num in table2 + CheckCloudTotalCount(g_tables, {0, 0}); // 0 is cloud data num in table2 /** * @tc.steps: step3. removedevicedata FLAG_AND_DATA and sync again * @tc.expected: OK. @@ -802,7 +843,145 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudD ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK); CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); LOGW("check 10-10"); - CheckCloudTotalCount({10, 10}); // // 10 is cloud data num in table2 + CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2 + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest007 + * @tc.desc: Test CLEAR_SHARED_TABLE mode of RemoveDeviceData before Sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest007, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 10 records on local + */ + int64_t paddingSize = 1; + int localCount = 10; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 20 records. + */ + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num + g_virtualCloudDb->ClearAllData(); + CheckCloudTotalCount(g_tables, {0, 0}); + /** + * @tc.steps: step3. removedevicedata in CLEAR_SHARED_TABLE mode will not delete unShare table data + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CheckCloudTotalCount(g_tables, {0, 0}); + /** + * @tc.steps: step4. copy db data to share table,then sync to check total count + * @tc.expected: OK. + */ + CopySharedDataFromOriginalTable(db, g_tables); + CloudDBSyncUtilsTest::callSync(g_shareTables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CheckCloudTotalCount(g_tables, {0, 0}); + CheckCloudTotalCount(g_shareTables, {10, 10}); // 10 is cloud data num + g_virtualCloudDb->ClearAllData(); + CheckCloudTotalCount(g_shareTables, {0, 0}); + /** + * @tc.steps: step5. removedevicedata in CLEAR_SHARED_TABLE mode,then sync and check data + * @tc.expected: OK. + */ + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK); + CheckCloudSharedRecordNum(db, g_shareTables, {0, 0, 0, 0}); + CloudDBSyncUtilsTest::callSync(g_shareTables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CheckCloudTotalCount(g_shareTables, {0, 0}); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest008 + * @tc.desc: Test CLEAR_SHARED_TABLE mode of RemoveDeviceData after close DB + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest008, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 10 records on local + */ + int64_t paddingSize = 1; + int localCount = 10; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 20 records. + */ + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num + g_virtualCloudDb->ClearAllData(); + CheckCloudTotalCount(g_tables, {0, 0}); + /** + * @tc.steps: step3. removedevicedata in CLEAR_SHARED_TABLE mode will not delete unShare table data + * @tc.expected: OK. + */ + std::string device; + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CheckCloudTotalCount(g_tables, {0, 0}); + /** + * @tc.steps: step4. copy db data to share table,then sync to check total count + * @tc.expected: OK. + */ + CopySharedDataFromOriginalTable(db, g_tables); + CloudDBSyncUtilsTest::callSync(g_shareTables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CheckCloudTotalCount(g_tables, {0, 0}); + CheckCloudTotalCount(g_shareTables, {10, 10}); // 10 is cloud data num + g_virtualCloudDb->ClearAllData(); + CheckCloudTotalCount(g_shareTables, {0, 0}); + /** + * @tc.steps: step5. removedevicedata in CLEAR_SHARED_TABLE mode after close db, then sync and check data + * @tc.expected: OK. + */ + CloseDb(); + g_observer = new (std::nothrow) RelationalStoreObserverUnitTest(); + ASSERT_NE(g_observer, nullptr); + ASSERT_EQ(g_mgr.OpenStore(g_storePath, g_storeID, RelationalStoreDelegate::Option { .observer = g_observer }, + g_delegate), DBStatus::OK); + ASSERT_NE(g_delegate, nullptr); + ASSERT_EQ(g_delegate->RemoveDeviceData(device, DistributedDB::CLEAR_SHARED_TABLE), DBStatus::OK); + CheckCloudSharedRecordNum(db, g_shareTables, {0, 0, 0, 0}); + CloseDb(); +} + +/* + * @tc.name: CleanCloudDataTest008 + * @tc.desc: Test RemoveDeviceData after Sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalRemoveDeviceDataTest, CleanCloudDataTest009, TestSize.Level0) +{ + /** + * @tc.steps: step1. make data: 10 records on local + */ + int64_t paddingSize = 10; + int localCount = 10; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + /** + * @tc.steps: step2. call Sync with cloud merge strategy, and after that, local will has 10 records. + */ + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + LOGW("check 10-10"); + CheckCloudTotalCount(g_tables, {10, 10}); // 10 is cloud data num in table2 + /** + * @tc.steps: step3. remove cloud and sync again + * @tc.expected: OK. + */ + DeleteCloudTableRecordByGid(0, localCount); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + g_delegate->RemoveDeviceData(); + CheckLocalLogCount(db, { g_tableName1 }, { localCount }); CloseDb(); } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3d6271bc49487b51f3e72764b4a163ef31463c8b --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_cloud_interfaces_set_cloud_schema_test.cpp @@ -0,0 +1,1169 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "cloud/cloud_storage_utils.h" +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_db_types.h" +#include "db_common.h" +#include "db_constant.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "relational_store_manager.h" +#include "runtime_config.h" +#include "time_helper.h" +#include "sqlite_relational_utils.h" +#include "virtual_asset_loader.h" +#include "virtual_cloud_data_translate.h" +#include "virtual_cloud_db.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"; + constexpr const char *CREATE_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS worker1(" \ + "name TEXT PRIMARY KEY," \ + "height REAL ," \ + "married BOOLEAN ," \ + "photo BLOB NOT NULL," \ + "asset BLOB," \ + "age INT);"; + constexpr const char *CREATE_TABLE_WITHOUT_PRIMARY_SQL = + "CREATE TABLE IF NOT EXISTS worker2(" \ + "id INT," \ + "name TEXT," \ + "height REAL ," \ + "married BOOLEAN ," \ + "photo BLOB ," \ + "asset BLOB);"; + constexpr const char *CREATE_SHARED_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS worker5_shared(" \ + "name TEXT PRIMARY KEY," \ + "height REAL ," \ + "married BOOLEAN ," \ + "photo BLOB NOT NULL," \ + "asset BLOB," \ + "age INT);"; + const string g_tableName1 = "worker1"; + const string g_tableName2 = "worker2"; // do not have primary key + const string g_tableName3 = "Worker1"; + const string g_tableName4 = "worker4"; + const string g_sharedTableName1 = "worker1_shared"; + const string g_sharedTableName2 = "worker2_shared"; // do not have primary key + const string g_sharedTableName3 = "Worker1_Shared"; + const string g_sharedTableName4 = "worker4_shared"; + const string g_sharedTableName5 = "worker5_shared"; + const string g_distributedSharedTableName1 = "naturalbase_rdb_aux_worker1_shared_log"; + const string g_distributedSharedTableName2 = "naturalbase_rdb_aux_worker2_shared_log"; + const string g_distributedSharedTableName3 = "naturalbase_rdb_aux_Worker1_Shared_log"; + const string g_distributedSharedTableName4 = "naturalbase_rdb_aux_worker4_shared_log"; + std::string g_testDir; + std::string g_dbDir; + std::string g_storePath; + DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + RelationalStoreDelegate *g_delegate = nullptr; + std::shared_ptr g_virtualCloudDb = nullptr; + std::shared_ptr g_virtualCloudDataTranslate; + const std::vector g_cloudField1 = { + {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, + {"height", TYPE_INDEX}, {"married", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"asset", TYPE_INDEX} + }; + const std::vector g_cloudField2 = { + {"id", TYPE_INDEX}, {"name", TYPE_INDEX}, + {"height", TYPE_INDEX}, {"married", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"asset", TYPE_INDEX} + }; + const std::vector g_cloudField3 = { + {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, + {"height", TYPE_INDEX}, {"married", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"asset", TYPE_INDEX}, + {"age", TYPE_INDEX} + }; + const std::vector g_cloudField4 = { + {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, + {"height", TYPE_INDEX}, {"photo", TYPE_INDEX}, + {"assets", TYPE_INDEX}, {"age", TYPE_INDEX} + }; + const int64_t g_syncWaitTime = 60; + const Asset g_localAsset = { + .version = 1, .name = "Phone", .assetId = "", .subpath = "/local/sync", .uri = "/local/sync", + .modifyTime = "123456", .createTime = "", .size = "256", .hash = "ASE" + }; + + class DistributedDBCloudInterfacesSetCloudSchemaTest : public testing::Test { + public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + protected: + void CreateUserDBAndTable(); + void CheckSharedTable(const std::vector &expectedTableName); + void CheckDistributedSharedTable(const std::vector &expectedTableName); + void InsertLocalSharedTableRecords(int64_t begin, int64_t count, const std::string &tableName); + void BlockSync(const Query &query, RelationalStoreDelegate *delegate, DBStatus errCode = OK); + void CheckCloudTableCount(const std::string &tableName, int64_t expectCount); + void CloseDb(); + sqlite3 *db_ = nullptr; + }; + + void DistributedDBCloudInterfacesSetCloudSchemaTest::SetUpTestCase(void) + { + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + g_storePath = g_dbDir + STORE_ID + DB_SUFFIX; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + g_virtualCloudDataTranslate = std::make_shared(); + RuntimeConfig::SetCloudTranslate(g_virtualCloudDataTranslate); + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::TearDownTestCase(void) + { + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::SetUp(void) + { + db_ = RelationalTestUtils::CreateDataBase(g_storePath); + ASSERT_NE(db_, nullptr); + CreateUserDBAndTable(); + DBStatus status = g_mgr.OpenStore(g_storePath, STORE_ID, {}, g_delegate); + ASSERT_EQ(status, OK); + ASSERT_NE(g_delegate, nullptr); + g_virtualCloudDb = std::make_shared(); + ASSERT_EQ(g_delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK); + ASSERT_EQ(g_delegate->SetIAssetLoader(std::make_shared()), DBStatus::OK); + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::TearDown(void) + { + g_virtualCloudDb->ForkUpload(nullptr); + EXPECT_EQ(g_mgr.CloseStore(g_delegate), OK); + g_delegate = nullptr; + EXPECT_EQ(sqlite3_close_v2(db_), SQLITE_OK); + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::CreateUserDBAndTable() + { + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, CREATE_TABLE_SQL), SQLITE_OK); + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, CREATE_TABLE_WITHOUT_PRIMARY_SQL), SQLITE_OK); + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::CheckSharedTable( + const std::vector &expectedTableName) + { + std::string sql = "SELECT name FROM sqlite_master WHERE type = 'table' AND " \ + "name LIKE 'worker%_shared';"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + uint64_t index = 0; + while (SQLiteUtils::StepWithRetry(stmt) != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_TEXT); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + std::string actualTableName; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, actualTableName), E_OK); + ASSERT_EQ(actualTableName, expectedTableName[index]); + index++; + } + ASSERT_EQ(index, expectedTableName.size()); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::CheckDistributedSharedTable( + const std::vector &expectedTableName) + { + std::string sql = "SELECT name FROM sqlite_master WHERE type = 'table' AND " \ + "name LIKE 'naturalbase_rdb_aux_%_log';"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + uint64_t index = 0; + while (SQLiteUtils::StepWithRetry(stmt) != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_TEXT); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + std::string actualTableName; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, actualTableName), E_OK); + ASSERT_EQ(actualTableName, expectedTableName[index]); + index++; + } + ASSERT_EQ(index, expectedTableName.size()); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::InsertLocalSharedTableRecords(int64_t begin, int64_t count, + const std::string &tableName) + { + ASSERT_NE(db_, nullptr); + std::vector assetBlob = g_virtualCloudDataTranslate->AssetToBlob(g_localAsset); + for (int64_t i = begin; i < count; ++i) { + string sql = "INSERT OR REPLACE INTO " + tableName + + " (cloud_owner, cloud_privilege, id, name, height, married, photo, asset) VALUES ('A', 'true', '" + + std::to_string(i) + "', 'Local" + std::to_string(i) + "', '155.10', 'false', 'text', ?);"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::BlockSync(const Query &query, + RelationalStoreDelegate *delegate, DBStatus errCode) + { + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + auto callback = [&cv, &dataMutex, &finish, &errCode](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + EXPECT_EQ(item.second.errCode, errCode); + std::lock_guard autoLock(dataMutex); + finish = true; + } + cv.notify_one(); + } + } + }; + ASSERT_EQ(delegate->Sync({ "CLOUD" }, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), OK); + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { + return finish; + }); + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::CheckCloudTableCount(const std::string &tableName, + int64_t expectCount) + { + VBucket extend; + extend[CloudDbConstant::CURSOR_FIELD] = std::to_string(0); + int64_t realCount = 0; + std::vector data; + g_virtualCloudDb->Query(tableName, extend, data); + for (size_t j = 0; j < data.size(); ++j) { + auto entry = data[j].find(CloudDbConstant::DELETE_FIELD); + if (entry != data[j].end() && std::get(entry->second)) { + continue; + } + realCount++; + } + EXPECT_EQ(realCount, expectCount); // ExpectCount represents the total amount of cloud data. + } + + void DistributedDBCloudInterfacesSetCloudSchemaTest::CloseDb() + { + g_virtualCloudDb = nullptr; + if (g_delegate != nullptr) { + EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK); + g_delegate = nullptr; + } + } + + /** + * @tc.name: SetCloudDbSchemaTest001 + * @tc.desc: Test same table name for set cloud schema interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest001, TestSize.Level0) + { + /** + * @tc.steps:step1. table names are same but sharedtable names are empty + * @tc.expected: step1. return INVALID_ARGS + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = "", + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step2. table names are same but sharedtable names are different + * @tc.expected: step2. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step3. one table name is uppercase and the other is lowercase + * @tc.expected: step3. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName3, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + } + + /** + * @tc.name: SetCloudDbSchemaTest002 + * @tc.desc: Test same shared table name for set cloud schema interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest002, TestSize.Level0) + { + /** + * @tc.steps:step1. table names are different but sharedtable names are same + * @tc.expected: step1. return INVALID_ARGS + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = "", + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField2 + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step2. table names are different but sharedtable names are same + * @tc.expected: step2. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField2 + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step3. one sharedtable name is uppercase and the other is lowercase + * @tc.expected: step3. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + tableSchema = { g_tableName1, g_sharedTableName1, g_cloudField1 }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { g_tableName2, g_sharedTableName3, g_cloudField2 }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step4. sharedtable name and table name is same + * @tc.expected: step4. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_tableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + } + + /** + * @tc.name: SetCloudDbSchemaTest003 + * @tc.desc: Test same table name and shared table name for set cloud schema interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest003, TestSize.Level0) + { + /** + * @tc.steps:step1. table name and shared table name are same + * @tc.expected: step1. return INVALID_ARGS + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_sharedTableName1, + .sharedTableName = g_tableName2, + .fields = g_cloudField2 + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step2. shared table name and table name are same + * @tc.expected: step2. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_tableName1, + .fields = g_cloudField2 + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + } + + /** + * @tc.name: SetCloudDbSchemaTest004 + * @tc.desc: Test same field for set cloud schema interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest004, TestSize.Level0) + { + /** + * @tc.steps:step1. fields contains same field + * @tc.expected: step1. return INVALID_ARGS + */ + DataBaseSchema dataBaseSchema; + std::vector invalidFields = g_cloudField1; + invalidFields.push_back({"name", TYPE_INDEX}); + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = invalidFields + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step2. fields contains cloud_owner + * @tc.expected: step2. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + invalidFields = g_cloudField1; + invalidFields.push_back({"cloud_owner", TYPE_INDEX}); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = invalidFields + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step3. fields contains cloud_privilege + * @tc.expected: step3. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + invalidFields = g_cloudField1; + invalidFields.push_back({"cloud_privilege", TYPE_INDEX}); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = invalidFields + }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step4. fields contains same field but uppercase + * @tc.expected: step4. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + invalidFields = g_cloudField1; + invalidFields.push_back({"Name", TYPE_INDEX}); + tableSchema = { g_tableName1, g_sharedTableName1, invalidFields }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step5. fields contains cloud_privilege field but uppercase + * @tc.expected: step5. return INVALID_ARGS + */ + dataBaseSchema.tables.clear(); + invalidFields = g_cloudField1; + invalidFields.push_back({"Cloud_priVilege", TYPE_INDEX}); + tableSchema = { g_tableName1, g_sharedTableName1, invalidFields }; + dataBaseSchema.tables.push_back(tableSchema); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + } + + /** + * @tc.name: SetCloudDbSchemaTest005 + * @tc.desc: Check shared table is existed or not + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest005, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1}); + CheckDistributedSharedTable({g_distributedSharedTableName1}); + + /** + * @tc.steps:step2. re-SetCloudDbSchema and schema table changed + * @tc.expected: step2. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField2 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName2}); + + /** + * @tc.steps:step3. re-SetCloudDbSchema and schema fields changed + * @tc.expected: step3. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + CheckSharedTable({g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName2}); + } + + /** + * @tc.name: SetCloudDbSchemaTest006 + * @tc.desc: Test SetCloudDbSchema in uppercase and lowercase + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest006, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName3, + .sharedTableName = g_sharedTableName3, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField2 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName3, g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName3, g_distributedSharedTableName2}); + } + + /** + * @tc.name: SetCloudDbSchemaTest007 + * @tc.desc: Test SetCloudDbSchema if need alter shared table name + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest007, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1}); + CheckDistributedSharedTable({g_distributedSharedTableName1}); + + /** + * @tc.steps:step2. re-SetCloudDbSchema and schema shared table changed + * @tc.expected: step2. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName2}); + + /** + * @tc.steps:step3. re-SetCloudDbSchema and schema table changed + * @tc.expected: step3. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName2}); + } + + /** + * @tc.name: SetCloudDbSchemaTest008 + * @tc.desc: Test SetCloudDbSchema when A-B C-D update B-D + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest008, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema A-B C-D + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1, g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName1, g_distributedSharedTableName2}); + + /** + * @tc.steps:step2. re-SetCloudDbSchema B-D + * @tc.expected: step2. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_sharedTableName1, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName2}); + } + + /** + * @tc.name: SetCloudDbSchemaTest009 + * @tc.desc: Test SetCloudDbSchema when A-B C-D update A-D + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest009, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1, g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName1, g_distributedSharedTableName2}); + + /** + * @tc.steps:step2. re-SetCloudDbSchema and schema shared table changed + * @tc.expected: step2. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName2}); + } + + /** + * @tc.name: SetCloudDbSchemaTest010 + * @tc.desc: Test SetCloudDbSchema when A-B C-D update A-E C-B + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest010, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1, g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName1, g_distributedSharedTableName2}); + + /** + * @tc.steps:step2. re-SetCloudDbSchema and schema shared table changed + * @tc.expected: step2. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName4, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName4, g_sharedTableName1}); + CheckDistributedSharedTable({g_distributedSharedTableName4, g_distributedSharedTableName1}); + } + + /** + * @tc.name: SetCloudDbSchemaTest011 + * @tc.desc: Test SetCloudDbSchema if local exists user table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest011, TestSize.Level0) + { + /** + * @tc.steps:step1. local exists worker1 then use SetCloudDbSchema + * @tc.expected: step1. return INVALID_ARGS + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName2, + .sharedTableName = g_tableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + + /** + * @tc.steps:step2. SetCloudDbSchema + * @tc.expected: step2. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1}); + CheckDistributedSharedTable({g_distributedSharedTableName1}); + + /** + * @tc.steps:step3. add field and SetCloudDbSchema + * @tc.expected: step3. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField3 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName2}); + } + + /** + * @tc.name: SetCloudDbSchemaTest012 + * @tc.desc: Test SetCloudDbSchema if local exists user table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest012, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema + * @tc.expected: step1. return OK + */ + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, CREATE_SHARED_TABLE_SQL), SQLITE_OK); + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckDistributedSharedTable({g_distributedSharedTableName1, g_distributedSharedTableName2}); + + /** + * @tc.steps:step2. re-SetCloudDbSchema and schema shared table changed + * @tc.expected: step2. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName4, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName4, + .sharedTableName = g_sharedTableName5, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::INVALID_ARGS); + } + + /** + * @tc.name: SetCloudDbSchemaTest013 + * @tc.desc: Test SetCloudDbSchema after close db + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest013, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetCloudDbSchema + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1, g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName1, g_distributedSharedTableName2}); + + /** + * @tc.steps:step2. close db and then open store + * @tc.expected: step2. return OK + */ + CloseDb(); + DBStatus status = g_mgr.OpenStore(g_storePath, STORE_ID, {}, g_delegate); + ASSERT_EQ(status, OK); + g_virtualCloudDb = std::make_shared(); + ASSERT_EQ(g_delegate->SetCloudDB(g_virtualCloudDb), DBStatus::OK); + + /** + * @tc.steps:step3. re-SetCloudDbSchema and schema is same + * @tc.expected: step3. return OK + */ + dataBaseSchema.tables.clear(); + tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1, g_sharedTableName2}); + CheckDistributedSharedTable({g_distributedSharedTableName1, g_distributedSharedTableName2}); + } + + /** + * @tc.name: SetCloudDbSchemaTest014 + * @tc.desc: Test SetCloudDbSchema after set tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SetCloudDbSchemaTest014, TestSize.Level0) + { + /** + * @tc.steps:step1. use SetTrackerTable + * @tc.expected: step1. return OK + */ + TrackerSchema trackerSchema = { + .tableName = g_tableName1, + .extendColName = "married", + .trackerColNames = {"married"} + }; + ASSERT_EQ(g_delegate->SetTrackerTable(trackerSchema), DBStatus::OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName1, CLOUD_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step2. use SetCloudDbSchema + * @tc.expected: step2. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + CheckSharedTable({g_sharedTableName1, g_sharedTableName2}); + } + + /** + * @tc.name: SharedTableSync001 + * @tc.desc: Test sharedtable without primary key sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync001, TestSize.Level0) + { + /** + * @tc.steps:step1. use set shared table without primary key + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName2, + .sharedTableName = g_sharedTableName2, + .fields = g_cloudField2 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + + /** + * @tc.steps:step2. insert local shared table records and sync + * @tc.expected: step2. return OK + */ + InsertLocalSharedTableRecords(0, 10, g_sharedTableName2); + Query query = Query::Select().FromTable({ g_sharedTableName2 }); + BlockSync(query, g_delegate); + CheckCloudTableCount(g_sharedTableName2, 10); + } + + /** + * @tc.name: SharedTableSync002 + * @tc.desc: Test sharedtable sync when version abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync002, TestSize.Level0) + { + /** + * @tc.steps:step1. use set shared table + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + + /** + * @tc.steps:step2. insert local shared table records and sync + * @tc.expected: step2. return OK + */ + InsertLocalSharedTableRecords(0, 10, g_sharedTableName1); + g_virtualCloudDb->ForkUpload([](const std::string &tableName, VBucket &extend) { + extend.erase(CloudDbConstant::VERSION_FIELD); + }); + Query query = Query::Select().FromTable({ g_sharedTableName1 }); + BlockSync(query, g_delegate, DBStatus::CLOUD_ERROR); + + g_virtualCloudDb->ForkUpload([](const std::string &tableName, VBucket &extend) { + if (extend.find(CloudDbConstant::VERSION_FIELD) != extend.end()) { + extend[CloudDbConstant::VERSION_FIELD] = ""; + } + }); + query = Query::Select().FromTable({ g_sharedTableName1 }); + BlockSync(query, g_delegate, DBStatus::CLOUD_ERROR); + } + + /** + * @tc.name: SharedTableSync003 + * @tc.desc: Test weather the shared table is fill assetId under nochange + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ + HWTEST_F(DistributedDBCloudInterfacesSetCloudSchemaTest, SharedTableSync003, TestSize.Level0) + { + /** + * @tc.steps:step1. insert local shared table records and sync + * @tc.expected: step1. return OK + */ + DataBaseSchema dataBaseSchema; + TableSchema tableSchema = { + .name = g_tableName1, + .sharedTableName = g_sharedTableName1, + .fields = g_cloudField1 + }; + dataBaseSchema.tables.push_back(tableSchema); + ASSERT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); + InsertLocalSharedTableRecords(0, 10, g_sharedTableName1); // 10 is records num + Query query = Query::Select().FromTable({ g_sharedTableName1 }); + BlockSync(query, g_delegate); + + /** + * @tc.steps:step2. sync again, cloud data containing assetId will be query + * @tc.expected: step2. return OK + */ + BlockSync(query, g_delegate); + + /** + * @tc.steps:step3. check if the hash of assets in db is empty + * @tc.expected: step3. OK + */ + std::string sql = "SELECT asset from " + g_sharedTableName1; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_BLOB); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + std::vector assetBlob; + Asset asset; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, assetBlob), E_OK); + ASSERT_EQ(RuntimeContext::GetInstance()->BlobToAsset(assetBlob, asset), E_OK); + EXPECT_EQ(asset.assetId, ""); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } +} // namespace \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp index 7a40722bbea690a802a72174dad0948218043e34..fc3b0484ecc7a34689c72eb456ac9464285c79bb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_auto_launch_test.cpp @@ -287,7 +287,7 @@ IKvDB *GetKvDB(const std::string &storeId) std::string identifierDir = DBCommon::TransferStringToHex(identifier); prop.SetStringProp(KvDBProperties::IDENTIFIER_DIR, identifierDir); prop.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); - prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); prop.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); int errCode = E_OK; return KvDBManager::OpenDatabase(prop, errCode); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp index bb28d3b9c36f0bba27e0501a484a601804b50503..2c66de2fc50a2c21d7b29385a901a2965443edb1 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_corrupt_test.cpp @@ -55,13 +55,13 @@ namespace { std::string filePath = g_testDir + "/" + identifierName + "/"; if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local filePath += (DBConstant::LOCAL_SUB_DIR + "/" + DBConstant::LOCAL_DATABASE_NAME + - DBConstant::SQLITE_DB_EXTENSION); + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver filePath += (DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION); + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver filePath += (DBConstant::MULTI_SUB_DIR + "/" + DBConstant::MULTI_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION); + DBConstant::DB_EXTENSION); } else { filePath = ""; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e2d009996057b837180a493f2afd0ba6e249f315 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_rd_kernel_test.cpp @@ -0,0 +1,910 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef USE_RD_KERNEL +#include +#include + +#include "db_common.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "kvdb_manager.h" +#include "platform_specific.h" +#include "process_system_api_adapter_impl.h" +#include "runtime_context.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + enum { + SCHEMA_TYPE1 = 1, + SCHEMA_TYPE2 + }; + // define some variables to init a KvStoreDelegateManager object. + KvStoreDelegateManager g_mgr(APP_ID, USER_ID); + string g_testDir; + KvStoreConfig g_config; + + DBStatus g_kvDelegateStatus = INVALID_ARGS; + + KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr; + auto g_kvNbDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, + placeholders::_1, placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvNbDelegatePtr)); +#ifndef OMIT_JSON + void GenerateValidSchemaString(std::string &string, int num = SCHEMA_TYPE1) + { + switch (num) { + case SCHEMA_TYPE1: + string = "{\"SCHEMA_VERSION\":\"1.0\"," + "\"SCHEMA_MODE\":\"STRICT\"," + "\"SCHEMA_DEFINE\":{" + "\"field_name1\":\"BOOL\"," + "\"field_name2\":{" + "\"field_name3\":\"INTEGER, NOT NULL\"," + "\"field_name4\":\"LONG, DEFAULT 100\"," + "\"field_name5\":\"DOUBLE, NOT NULL, DEFAULT 3.14\"," + "\"field_name6\":\"STRING, NOT NULL, DEFAULT '3.1415'\"," + "\"field_name7\":[]," + "\"field_name8\":{}" + "}" + "}," + "\"SCHEMA_INDEXES\":[\"$.field_name1\", \"$.field_name2.field_name6\"]}"; + break; + case SCHEMA_TYPE2: + string = "{\"SCHEMA_VERSION\":\"1.0\"," + "\"SCHEMA_MODE\":\"STRICT\"," + "\"SCHEMA_DEFINE\":{" + "\"field_name1\":\"LONG, DEFAULT 100\"," + "\"field_name2\":{" + "\"field_name3\":\"INTEGER, NOT NULL\"," + "\"field_name4\":\"LONG, DEFAULT 100\"," + "\"field_name5\":\"DOUBLE, NOT NULL, DEFAULT 3.14\"," + "\"field_name6\":\"STRING, NOT NULL, DEFAULT '3.1415'\"" + "}" + "}," + "\"SCHEMA_INDEXES\":[\"$.field_name1\", \"$.field_name2.field_name6\"]}"; + break; + default: + return; + } + } +#endif +} + +class DistributedDBInterfacesDatabaseRdKernelTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBInterfacesDatabaseRdKernelTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + g_config.dataDir = g_testDir; + g_mgr.SetKvStoreConfig(g_config); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +void DistributedDBInterfacesDatabaseRdKernelTest::TearDownTestCase(void) +{ + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +void DistributedDBInterfacesDatabaseRdKernelTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); +} + +void DistributedDBInterfacesDatabaseRdKernelTest::TearDown(void) +{ + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } +} + +/** + * @tc.name: GetKvStore003 + * @tc.desc: Get kv store through different SecurityOption, abnormal or normal. + * @tc.type: FUNC + * @tc.require: AR000EV1G2 + * @tc.author: liuwenkai + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore003, TestSize.Level1) +{ + /** + * @tc.steps: step1. Obtain the kvStore through the GetKvStore interface of the delegate manager + * using the parameter secOption(abnormal). + * @tc.expected: step1. Returns a null kvstore and error code is not OK. + */ + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + int abnormalNum = -100; + option.secOption.securityLabel = abnormalNum; + option.secOption.securityFlag = abnormalNum; + g_mgr.GetKvStore("distributed_getkvstore_003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_TRUE(g_kvDelegateStatus != OK); + + /** + * @tc.steps: step2. Obtain the kvStore through the GetKvStore interface of the delegate manager + * using the parameter secOption(normal). + * @tc.expected: step2. Returns a non-null kvstore and error code is OK. + */ + option.secOption.securityLabel = S3; + option.secOption.securityFlag = 0; + g_mgr.GetKvStore("distributed_getkvstore_003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + KvStoreNbDelegate *kvNbDelegatePtr1 = g_kvNbDelegatePtr; + + /** + * @tc.steps: step3. Obtain the kvStore through the GetKvStore interface of the delegate manager + * using the parameter secOption(normal but not same as last). + * @tc.expected: step3. Returns a null kvstore and error code is not OK. + */ + option.secOption.securityLabel = S3; + option.secOption.securityFlag = 1; + g_mgr.GetKvStore("distributed_getkvstore_003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_TRUE(g_kvDelegateStatus != OK); + + /** + * @tc.steps: step4. Obtain the kvStore through the GetKvStore interface of the delegate manager + * using the parameter secOption(normal and same as last). + * @tc.expected: step4. Returns a non-null kvstore and error code is OK. + */ + option.secOption.securityLabel = S3; + option.secOption.securityFlag = 0; + g_mgr.GetKvStore("distributed_getkvstore_003", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.CloseKvStore(kvNbDelegatePtr1), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_TRUE(g_mgr.DeleteKvStore("distributed_getkvstore_003") == OK); +} + +/** + * @tc.name: GetKvStore004 + * @tc.desc: Get kv store parameters with Observer and Notifier, then trigger callback. + * @tc.type: FUNC + * @tc.require: AR000EV1G2 + * @tc.author: liuwenkai + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore004, TestSize.Level1) +{ + /** + * @tc.steps: step1. Obtain the kvStore through the GetKvStore interface of the delegate manager + * using the parameter observer, notifier, key. + * @tc.expected: step1. Returns a non-null kvstore and error code is OK. + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; + ASSERT_NE(observer, nullptr); + Key key; + Value value1; + Value value2; + key.push_back(1); + value1.push_back(1); + value2.push_back(2); + option.key = key; + option.observer = observer; + option.mode = OBSERVER_CHANGES_NATIVE; + int sleepTime = 100; + g_mgr.GetKvStore("distributed_getkvstore_004", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step2. Put(k1,v1) to db and check the observer info. + * @tc.expected: step2. Put successfully and trigger notifier callback. + */ + EXPECT_TRUE(g_kvNbDelegatePtr->Put(key, value1) == OK); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); + LOGI("observer count:%lu", observer->GetCallCount()); + EXPECT_TRUE(observer->GetCallCount() == 1); + + /** + * @tc.steps: step3. put(k1,v2) to db and check the observer info. + * @tc.expected: step3. put successfully + */ + EXPECT_TRUE(g_kvNbDelegatePtr->Put(key, value2) == OK); + std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); + LOGI("observer count:%lu", observer->GetCallCount()); + EXPECT_TRUE(observer->GetCallCount() == 2); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + delete observer; + observer = nullptr; + EXPECT_TRUE(g_mgr.DeleteKvStore("distributed_getkvstore_004") == OK); +} + +/** + * @tc.name: GetKvStore005 + * @tc.desc: Get kv store parameters with rd shared mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore005, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db with share mode and readOnly is false + * @tc.expected: step1. open ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.rdconfig.readOnly = false; + g_mgr.GetKvStore("distributed_getkvstore_005", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + /** + * @tc.steps: step2. Put into the database some data. + * @tc.expected: step2. Put returns OK. + */ + std::vector keys; + std::vector values; + uint32_t totalSize = 20u; // 20 items + for (size_t i = 0; i < totalSize; i++) { + Entry entry; + DistributedDBToolsUnitTest::GetRandomKeyValue(entry.key, static_cast(i + 1)); + DistributedDBToolsUnitTest::GetRandomKeyValue(entry.value); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry.key, entry.value), OK); + keys.push_back(entry.key); + values.push_back(entry.value); + } + /** + * @tc.steps: step3. Get kv ok + * @tc.expected: step3. returns OK + */ + for (size_t i = 0; i < keys.size(); i++) { + Value value; + EXPECT_EQ(g_kvNbDelegatePtr->Get(keys[i], value), OK); + EXPECT_TRUE(value == values[i]); + } + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); +} + +/** + * @tc.name: GetKvStore006 + * @tc.desc: Get kv store parameters with rd shared mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore006, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db with share mode and readOnly is true + * @tc.expected: step1. open ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.rdconfig.readOnly = false; + /** + * @tc.steps: step2. write db handle write data and close + * @tc.expected: step2. close ok + */ + g_mgr.GetKvStore("distributed_getkvstore_006", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + Entry entry = {{'1', '2'}}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry.key, entry.value), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + + /** + * @tc.steps: step3. read db handle open + * @tc.expected: step3. open ok + */ + option.rdconfig.readOnly = true; + g_mgr.GetKvStore("distributed_getkvstore_006", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + /** + * @tc.steps: step4. read db handle put entry + * @tc.expected: step4. return not ok + */ + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry.key, entry.value), NO_PERMISSION); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch({entry}), NO_PERMISSION); + EXPECT_EQ(g_kvNbDelegatePtr->Delete(entry.key), NO_PERMISSION); + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch({entry.key}), NO_PERMISSION); + /** + * @tc.steps: step5. read db handle get entry and close + * @tc.expected: step5. return not ok + */ + Value value; + EXPECT_EQ(g_kvNbDelegatePtr->Get(entry.key, value), OK); + EXPECT_TRUE(value == entry.value); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); +} + +/** + * @tc.name: GetKvStore007 + * @tc.desc: Get kv store parameters with wrong rd shared mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore007, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db with not share mode and readOnly is true + * @tc.expected: step1. open not ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.rdconfig.readOnly = true; + g_mgr.GetKvStore("distributed_getkvstore_007", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == BUSY); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); +} + +/** + * @tc.name: GetKvStore008 + * @tc.desc: Get kv store parameters with use Integrity check + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore008, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db and readOnly is false and IntegrityCheck is true + * @tc.expected: step1. open ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.isNeedIntegrityCheck = true; + option.isNeedRmCorruptedDb = true; + g_mgr.GetKvStore("distributed_getkvstore_009", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + + /** + * @tc.steps: step2. make db damaged and open db + * @tc.expected: step2. open ok + */ + std::string identifier = KvStoreDelegateManager::GetKvStoreIdentifier(USER_ID, APP_ID, + "distributed_getkvstore_009"); + std::string dbFliePath = DistributedDBToolsUnitTest::GetKvNbStoreDirectory(identifier, + "single_ver/main/gen_natural_store.db", g_testDir); + DistributedDBToolsUnitTest::ModifyDatabaseFile(dbFliePath); + + g_mgr.GetKvStore("distributed_getkvstore_009", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); +} + +/** + * @tc.name: GetKvStore009 + * @tc.desc: Get kv store parameters use Integrity check and RmCorruptedDb + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore009, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db and readOnly is false and RmCorruptedDb false + * @tc.expected: step1. open ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.isNeedIntegrityCheck = true; + g_mgr.GetKvStore("distributed_getkvstore_010", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + + g_mgr.GetKvStore("distributed_getkvstore_010", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); +} + +/** + * @tc.name: GetKvStore010 + * @tc.desc: Get kv store parameters when crcCheck is true and not create db + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore010, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db + * @tc.expected: step1. open not ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.createIfNecessary = false; + option.isNeedIntegrityCheck = true; + option.rdconfig.readOnly = true; + g_mgr.GetKvStore("distributed_getkvstore_011", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == INVALID_ARGS); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); +} + +/** + * @tc.name: GetKvStore012 + * @tc.desc: Get kv store parameters and call CheckIntegity + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore012, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db and readOnly is false + * @tc.expected: step1. open ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.rdconfig.readOnly = false; + g_mgr.GetKvStore("distributed_getkvstore_012", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == OK); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + + /** + * @tc.steps: step2. check db and write db handle close + * @tc.expected: step2. close ok + */ + EXPECT_TRUE(g_kvNbDelegatePtr->CheckIntegrity() == OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); +} + +/** + * @tc.name: GetKvStore013 + * @tc.desc: Get kv store parameters in readOnly mode and RmCorruptedDb is true + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhuwentao + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStore013, TestSize.Level1) +{ + /** + * @tc.steps: step1. open db and readOnly is true and RmCorruptedDb true + * @tc.expected: step1. open ok + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.isNeedIntegrityCheck = true; + option.isNeedRmCorruptedDb = true; + option.rdconfig.readOnly = true; + g_mgr.GetKvStore("distributed_getkvstore_013", option, g_kvNbDelegateCallback); + EXPECT_TRUE(g_kvDelegateStatus == INVALID_ARGS); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); +} + +/** + * @tc.name: GetKvStoreWithInvalidOption001 + * @tc.desc: Get kv store with invalid option.storageEngineType + * @tc.type: + * @tc.require: + * @tc.author: wanyi + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetKvStoreWithInvalidOption001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Get kv store with invalid null option.storageEngineType + * @tc.expected: step1. INVALID_ARGS + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = ""; + g_mgr.GetKvStore("GetKvStoreWithInvalidOption001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_TRUE(g_kvDelegateStatus == INVALID_ARGS); + + /** + * @tc.steps: step2. Get kv store with invalid option.storageEngineType + * @tc.expected: step2. INVALID_ARGS + */ + option.storageEngineType = "invalidType"; + g_mgr.GetKvStore("GetKvStoreWithInvalidOption001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_TRUE(g_kvDelegateStatus == INVALID_ARGS); +} + +/** + * @tc.name: RepeatCloseKvStore001 + * @tc.desc: Close the kv store repeatedly and check the database. + * @tc.type: FUNC + * @tc.require: AR000C2F0C AR000CQDV7 + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, RepeatCloseKvStore001, TestSize.Level2) +{ + /** + * @tc.steps: step1. Obtain the kvStore through the GetKvStore interface of + * the delegate manager using the parameter createIfNecessary(true) + * @tc.expected: step1. Returns a non-null kvstore and error code is OK. + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + g_mgr.GetKvStore("RepeatCloseKvStore_001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + static const size_t totalSize = 50; + + /** + * @tc.steps: step2. Put into the database some data. + * @tc.expected: step2. Put returns OK. + */ + std::vector keys; + for (size_t i = 0; i < totalSize; i++) { + Entry entry; + DistributedDBToolsUnitTest::GetRandomKeyValue(entry.key, static_cast(i + 1)); + DistributedDBToolsUnitTest::GetRandomKeyValue(entry.value); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry.key, entry.value), OK); + keys.push_back(entry.key); + } + + /** + * @tc.steps: step3. Delete the data from the database, and close the database, reopen the database and + * get the data. + * @tc.expected: step3. Delete returns OK, Close returns OK and Get returns NOT_FOUND. + */ + for (size_t i = 0; i < keys.size(); i++) { + Value value; + EXPECT_EQ(g_kvNbDelegatePtr->Delete(keys[i]), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Get(keys[i], value), NOT_FOUND); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_mgr.GetKvStore("RepeatCloseKvStore_001", option, g_kvNbDelegateCallback); + EXPECT_EQ(g_kvNbDelegatePtr->Get(keys[i], value), NOT_FOUND); + } + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + /** + * @tc.steps: step4. Delete the kvstore created before. + * @tc.expected: step4. Delete returns OK. + */ + EXPECT_EQ(g_mgr.DeleteKvStore("RepeatCloseKvStore_001"), OK); +} +#ifndef OMIT_JSON +/** + * @tc.name: CreatKvStoreWithSchema001 + * @tc.desc: Create non-memory KvStore with schema, check if create success. + * @tc.type: FUNC + * @tc.require: AR000DR9K2 + * @tc.author: weifeng + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CreatKvStoreWithSchema001, TestSize.Level1) +{ + /** + * @tc.steps: step1. create a new db(non-memory, non-encrypt), with valid schema; + * @tc.expected: step1. Returns a null kvstore and error code is NOT_SUPPORT. + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + GenerateValidSchemaString(option.schema); + g_mgr.GetKvStore("CreatKvStoreWithSchema_001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_TRUE(g_kvDelegateStatus == NOT_SUPPORT); + g_kvNbDelegatePtr = nullptr; +} +#endif +/** + * @tc.name: OpenKvStoreWithStoreOnly001 + * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. + * @tc.type: FUNC + * @tc.require: AR000DR9K2 + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, OpenKvStoreWithStoreOnly001, TestSize.Level1) +{ + /** + * @tc.steps: step1. open the kv store with the option that createDirByStoreIdOnly is true. + * @tc.expected: step1. Returns OK. + */ + KvStoreNbDelegate::Option option; + option.createDirByStoreIdOnly = true; + option.storageEngineType = GAUSSDB_RD; + g_mgr.GetKvStore("StoreOnly001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + auto kvStorePtr = g_kvNbDelegatePtr; + /** + * @tc.steps: step2. open the same store with the option that createDirByStoreIdOnly is false. + * @tc.expected: step2. Returns NOT OK. + */ + option.createDirByStoreIdOnly = false; + g_kvNbDelegatePtr = nullptr; + g_mgr.GetKvStore("StoreOnly001", option, g_kvNbDelegateCallback); + EXPECT_EQ(g_kvDelegateStatus, INVALID_ARGS); + /** + * @tc.steps: step3. close the kvstore and delete the kv store; + * @tc.expected: step3. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(kvStorePtr), OK); + kvStorePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore("StoreOnly001"), OK); +} + +/** + * @tc.name: GetDBWhileOpened001 + * @tc.desc: open the kv store with the option that createDirByStoreIdOnly is true. + * @tc.type: FUNC + * @tc.require: AR000E8S2V + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, GetDBWhileOpened001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Get the connection. + * @tc.expected: step1. Returns OK. + */ + KvDBProperties property; + std::string storeId = "openTest"; + std::string origId = USER_ID + "-" + APP_ID + "-" + storeId; + std::string identifier = DBCommon::TransferHashString(origId); + std::string hexDir = DBCommon::TransferStringToHex(identifier); + property.SetStringProp(KvDBProperties::IDENTIFIER_DATA, identifier); + property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, hexDir); + property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + property.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); + property.SetBoolProp(KvDBProperties::MEMORY_MODE, false); + property.SetBoolProp(KvDBProperties::ENCRYPTED_MODE, false); + property.SetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, true); + property.SetStringProp(KvDBProperties::APP_ID, APP_ID); + property.SetStringProp(KvDBProperties::USER_ID, USER_ID); + property.SetStringProp(KvDBProperties::APP_ID, storeId); + + int errCode = E_OK; + auto connection1 = KvDBManager::GetDatabaseConnection(property, errCode, false); + EXPECT_EQ(errCode, E_OK); + /** + * @tc.steps: step2. Get the connection with the para: isNeedIfOpened is false. + * @tc.expected: step2. Returns -E_ALREADY_OPENED. + */ + auto connection2 = KvDBManager::GetDatabaseConnection(property, errCode, false); + EXPECT_EQ(errCode, -E_ALREADY_OPENED); + EXPECT_EQ(connection2, nullptr); + + /** + * @tc.steps: step3. Get the connection with the para: isNeedIfOpened is true. + * @tc.expected: step3. Returns E_OK. + */ + auto connection3 = KvDBManager::GetDatabaseConnection(property, errCode, true); + EXPECT_EQ(errCode, OK); + EXPECT_NE(connection3, nullptr); + + KvDBManager::ReleaseDatabaseConnection(connection1); + KvDBManager::ReleaseDatabaseConnection(connection3); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); +} +namespace { + void OpenCloseDatabase(const std::string &storeId) + { + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + DBStatus status; + KvStoreNbDelegate *delegate = nullptr; + auto nbDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, + placeholders::_1, placeholders::_2, std::ref(status), std::ref(delegate)); + int totalNum = 0; + for (size_t i = 0; i < 100; i++) { // cycle 100 times. + g_mgr.GetKvStore(storeId, option, nbDelegateCallback); + if (delegate != nullptr) { + totalNum++; + } + g_mgr.CloseKvStore(delegate); + delegate = nullptr; + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + LOGD("Succeed %d times", totalNum); + } + + void FreqOpenClose001() + { + std::string storeId = "FrqOpenClose001"; + std::thread t1(OpenCloseDatabase, storeId); + std::thread t2(OpenCloseDatabase, storeId); + std::thread t3(OpenCloseDatabase, storeId); + std::thread t4(OpenCloseDatabase, storeId); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + } + + void FreqOpenCloseDel001() + { + std::string storeId = "FrqOpenCloseDelete001"; + std::thread t1(OpenCloseDatabase, storeId); + std::thread t2([&]() { + for (int i = 0; i < 10000; i++) { // loop 10000 times + DBStatus status = g_mgr.DeleteKvStore(storeId); + LOGI("delete res %d", status); + EXPECT_TRUE(status == OK || status == BUSY || status == NOT_FOUND); + } + }); + t1.join(); + t2.join(); + } +} + +/** + * @tc.name: FreqOpenCloseDel001 + * @tc.desc: Open/close/delete the kv store concurrently. + * @tc.type: FUNC + * @tc.require: AR000DR9K2 + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenCloseDel001, TestSize.Level2) +{ + ASSERT_NO_FATAL_FAILURE(FreqOpenCloseDel001()); +} + +/** + * @tc.name: FreqOpenClose001 + * @tc.desc: Open and close the kv store concurrently. + * @tc.type: FUNC + * @tc.require: AR000DR9K2 + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, FreqOpenClose001, TestSize.Level2) +{ + ASSERT_NO_FATAL_FAILURE(FreqOpenClose001()); +} + +/** + * @tc.name: CheckKvStoreDir001 + * @tc.desc: Delete the kv store with the option that createDirByStoreIdOnly is true. + * @tc.type: FUNC + * @tc.require: AR000CQDV7 + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CheckKvStoreDir001, TestSize.Level1) +{ + /** + * @tc.steps: step1. open the kv store with the option that createDirByStoreIdOnly is true. + * @tc.expected: step1. Returns OK. + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.createDirByStoreIdOnly = true; + const std::string storeId("StoreOnly002"); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + std::string testSubDir; + EXPECT_EQ(KvStoreDelegateManager::GetDatabaseDir(storeId, testSubDir), OK); + std::string dataBaseDir = g_testDir + "/" + testSubDir; + EXPECT_GE(access(dataBaseDir.c_str(), F_OK), 0); + + /** + * @tc.steps: step2. delete the kv store, and check the directory. + * @tc.expected: step2. the directory is removed. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); + LOGI("[%s]", dataBaseDir.c_str()); + ASSERT_EQ(OS::CheckPathExistence(dataBaseDir), false); +} + +/** + * @tc.name: CompressionRate1 + * @tc.desc: Open the kv store with invalid compressionRate and open successfully. + * @tc.type: FUNC + * @tc.require: AR000G3QTT + * @tc.author: lidongwei + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CompressionRate1, TestSize.Level1) +{ + /** + * @tc.steps: step1. Open the kv store with the option that comressionRate is invalid. + * @tc.expected: step1. Open kv store failed. Returns DB_ERROR. + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.compressionRate = 0; // 0 is invalid. + const std::string storeId("CompressionRate1"); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_TRUE(g_kvDelegateStatus == NOT_SUPPORT); + + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), NOT_FOUND); +} + +/** + * @tc.name: CompressionRate2 + * @tc.desc: Open the kv store with again with different compression option. + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, CompressionRate2, TestSize.Level1) +{ + /** + * @tc.steps: step1. Open the kv store with the option that comressionRate is invalid. + * @tc.expected: step1. Open kv store successfully. Returns OK. + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + option.compressionRate = 70; // 70 compression rate. + const std::string storeId("CompressionRate1"); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr == nullptr); + EXPECT_TRUE(g_kvDelegateStatus == NOT_SUPPORT); + + /** + * @tc.steps: step2. Open again with different compression option + * @tc.expected: step2. Open kv store failed. Returns NOT_SUPPORT. + */ + DBStatus status; + KvStoreNbDelegate *delegate = nullptr; + auto callback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, + placeholders::_1, placeholders::_2, std::ref(status), std::ref(delegate)); + + option.compressionRate = 80; // 80 compression rate. + g_mgr.GetKvStore(storeId, option, callback); + ASSERT_TRUE(delegate == nullptr); + EXPECT_TRUE(status == NOT_SUPPORT); + + option.isNeedCompressOnSync = false; + option.compressionRate = 70; // 70 compression rate. + g_mgr.GetKvStore(storeId, option, callback); + ASSERT_TRUE(delegate == nullptr); + EXPECT_TRUE(status == NOT_SUPPORT); + + /** + * @tc.steps: step3. Close kv store + * @tc.expected: step3. NOT_FOUND. + */ + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), NOT_FOUND); +} + +HWTEST_F(DistributedDBInterfacesDatabaseRdKernelTest, DataInterceptor1, TestSize.Level1) +{ + /** + * @tc.steps: step1. Open the kv store with the option that comressionRate is invalid. + * @tc.expected: step1. Open kv store successfully. Returns OK. + */ + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + const std::string storeId("DataInterceptor1"); + g_mgr.GetKvStore(storeId, option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + auto interceptorCallback = [] (InterceptedData &data, const std::string &sourceID, + const std::string &targetId) -> int { + return OK; + }; + + EXPECT_EQ(g_kvNbDelegatePtr->SetPushDataInterceptor(interceptorCallback), NOT_SUPPORT); + + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore(storeId), OK); +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp index 62b665f3528151e2bcd9b5201999dcabaf5f8cc3..601678e8f47578be69e8436ce4827eb3bd8344af 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_database_test.cpp @@ -1252,7 +1252,7 @@ HWTEST_F(DistributedDBInterfacesDatabaseTest, GetDBWhileOpened001, TestSize.Leve property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, hexDir); property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); property.SetBoolProp(KvDBProperties::MEMORY_MODE, false); property.SetBoolProp(KvDBProperties::ENCRYPTED_MODE, false); property.SetBoolProp(KvDBProperties::CREATE_DIR_BY_STORE_ID_ONLY, true); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp index 9cfd49b0bfbb75ae35f4011a42c53925315320d0..4b35596fc207528147d6c901bd5a1abf67d9ea12 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_device_identifier_test.cpp @@ -72,7 +72,7 @@ void DistributedDBDeviceIdentifierTest::SetUpTestCase(void) } g_property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); g_property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID); - g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); } void DistributedDBDeviceIdentifierTest::TearDownTestCase(void) @@ -470,7 +470,7 @@ HWTEST_F(DistributedDBDeviceIdentifierTest, ErrDbTest004, TestSize.Level1) * @tc.expected: step5. Expect return -E_INVALID_DB */ Value values; - EXPECT_EQ(errStore->PutMetaData(keys.front(), values), -E_INVALID_DB); + EXPECT_EQ(errStore->PutMetaData(keys.front(), values, false), -E_INVALID_DB); /** * @tc.steps: step6. Test remove device data diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp index a3f311a73a8f2db297819c73b31fa2ed4e9f0afd..1054a2f7e8a10c087515842faa8ebec6cd9a6414 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_index_unit_test.cpp @@ -54,13 +54,13 @@ namespace { string filePath = g_testDir + "/" + identifierName + "/"; if (databaseType == DBConstant::DB_TYPE_LOCAL) { // local filePath += (DBConstant::LOCAL_SUB_DIR + "/" + DBConstant::LOCAL_DATABASE_NAME + - DBConstant::SQLITE_DB_EXTENSION); + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_SINGLE_VER) { // single ver filePath += (DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION); + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION); } else if (databaseType == DBConstant::DB_TYPE_MULTI_VER) { // multi ver filePath += (DBConstant::MULTI_SUB_DIR + "/" + DBConstant::MULTI_VER_DATA_STORE + - DBConstant::SQLITE_DB_EXTENSION); + DBConstant::DB_EXTENSION); } else { filePath = ""; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp index 0608668c064b9d442f485b5ca54d65b86d5ca919..d6589c0c6f3eaa0e63e1aa0ab8c8f6c894690422 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test.cpp @@ -27,7 +27,9 @@ #include "runtime_context.h" #include "sqlite_single_ver_natural_store.h" #include "storage_engine_manager.h" -#include "system_timer.h" +#ifdef DB_DEBUG_ENV +#include "system_time.h" +#endif // DB_DEBUG_ENV #include "kv_virtual_device.h" #include "virtual_communicator_aggregator.h" @@ -171,7 +173,7 @@ namespace { std::string hashIdentifier = DBCommon::TransferHashString(identifier); std::string identifierName = DBCommon::TransferStringToHex(hashIdentifier); std::string storeDir = g_testDir + "/" + identifierName + "/" + DBConstant::SINGLE_SUB_DIR + "/" + - DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::MAINDB_DIR + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; sqlite3 *db = nullptr; EXPECT_EQ(sqlite3_open_v2(storeDir.c_str(), &db, SQLITE_OPEN_READWRITE, nullptr), SQLITE_OK); if (db == nullptr) { @@ -224,9 +226,6 @@ void DistributedDBInterfacesNBDelegateTest::SetUpTestCase(void) g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); ASSERT_TRUE(g_communicatorAggregator != nullptr); RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); - - std::shared_ptr g_adapter = std::make_shared(); - RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); } void DistributedDBInterfacesNBDelegateTest::TearDownTestCase(void) @@ -2248,7 +2247,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, RemoveDeviceDataTest001, TestSiz FreeVirtualDevice(g_deviceD); } -#ifdef RUNNING_ON_SIMULATED_ENV +#ifdef DB_DEBUG_ENV /** * @tc.name: TimeChangeWithCloseStoreTest001 * @tc.desc: Test close store with time changed @@ -2374,7 +2373,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, TimeChangeWithCloseStoreTest003, g_kvNbDelegatePtr = nullptr; EXPECT_EQ(g_mgr.DeleteKvStore("TimeChangeWithCloseStoreTest003"), OK); } -#endif // RUNNING_ON_SIMULATED_ENV +#endif // DB_DEBUG_ENV /** * @tc.name: ResultSetLimitTest001 @@ -2806,6 +2805,8 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, BlockTimer001, TestSize.Level0) */ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MigrateDeadLockTest001, TestSize.Level2) { + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); /** * @tc.steps:step1. Get the nb delegate. * @tc.expected: step1. Get results OK and non-null delegate. @@ -2825,7 +2826,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MigrateDeadLockTest001, TestSize std::string identifier = DBCommon::GenerateIdentifierId(storeId, APP_ID, USER_ID); property.SetStringProp(KvDBProperties::IDENTIFIER_DATA, DBCommon::TransferHashString(identifier)); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); int errCode; SQLiteSingleVerStorageEngine *storageEngine = @@ -2840,7 +2841,7 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MigrateDeadLockTest001, TestSize */ std::string cacheDir = g_testDir + "/" + DBCommon::TransferStringToHex(DBCommon::TransferHashString(identifier)) + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::CACHEDB_DIR; - std::string cacheDB = cacheDir + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::SQLITE_DB_EXTENSION; + std::string cacheDB = cacheDir + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; EXPECT_EQ(OS::CreateFileByFileName(cacheDB), E_OK); EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); @@ -2855,4 +2856,33 @@ HWTEST_F(DistributedDBInterfacesNBDelegateTest, MigrateDeadLockTest001, TestSize LOGE("rm test db files error!"); } } + +/** + * @tc.name: RdRangeQueryInSqlite001 + * @tc.desc: Test GetEntries with range query filter by sqlite + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateTest, RdRangeQueryInSqlite001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + KvStoreNbDelegate::Option option; + g_mgr.GetKvStore("RdRangeQueryInSqlite001", option, g_kvNbDelegateCallback); + std::vector entries; + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + // /** + // * @tc.steps: step2. + // * @tc.expected: step2. + // */ + KvStoreResultSet *resultSet = nullptr; + Query inValidQuery = Query::Select().Range({}, {}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, resultSet), NOT_SUPPORT); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, entries), NOT_SUPPORT); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test_rd_kernal.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test_rd_kernal.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b02c52b381337a54afb92be30f9e833576009113 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_nb_delegate_test_rd_kernal.cpp @@ -0,0 +1,2289 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef USE_RD_KERNEL +#include +#include + +#include "db_common.h" +#include "db_constant.h" +#include "db_errno.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "log_print.h" +#include "platform_specific.h" +#include "process_system_api_adapter_impl.h" +#include "runtime_context.h" +#ifdef DB_DEBUG_ENV +#include "system_time.h" +#endif // DB_DEBUG_ENV +#include "virtual_communicator_aggregator.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + // define some variables to init a KvStoreDelegateManager object. + KvStoreDelegateManager g_mgr(APP_ID, USER_ID); + string g_testDir; + KvStoreConfig g_config; + KvStoreNbDelegate::Option g_option; + const int RESULT_SET_COUNT = 9; + const int RESULT_SET_INIT_POS = -1; + Key g_keyPrefix = {'A', 'B', 'C'}; + uint8_t g_testDict[RESULT_SET_COUNT] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'}; + + // define the g_kvNbDelegateCallback, used to get some information when open a kv store. + DBStatus g_kvDelegateStatus = INVALID_ARGS; + KvStoreNbDelegate *g_kvNbDelegatePtr = nullptr; + const int OBSERVER_SLEEP_TIME = 100; + const int BATCH_PRESET_SIZE_TEST = 10; + const int DIVIDE_BATCH_PRESET_SIZE = 5; + const int VALUE_OFFSET = 5; + + const int DEFAULT_KEY_VALUE_SIZE = 10; + VirtualCommunicatorAggregator* g_communicatorAggregator = nullptr; + // the type of g_kvNbDelegateCallback is function + auto g_kvNbDelegateCallback = bind(&DistributedDBToolsUnitTest::KvStoreNbDelegateCallback, placeholders::_1, + placeholders::_2, std::ref(g_kvDelegateStatus), std::ref(g_kvNbDelegatePtr)); + + void InitResultSet() + { + Key testKey; + Value testValue; + for (int i = 0; i < RESULT_SET_COUNT; i++) { + testKey.clear(); + testValue.clear(); + // set key + testKey = g_keyPrefix; + testKey.push_back(g_testDict[i]); + // set value + testValue.push_back(g_testDict[i]); + // insert entry + EXPECT_EQ(g_kvNbDelegatePtr->Put(testKey, testValue), OK); + } + } + + void ReadResultSet(KvStoreResultSet *readResultSet) + { + if (readResultSet == nullptr) { + return; + } + // index from 0 to 8(first to last) + for (int i = 0; i < RESULT_SET_COUNT; i++) { + Entry entry; + std::vector cursorKey = g_keyPrefix; + cursorKey.push_back(g_testDict[i]); + std::vector cursorValue; + cursorValue.push_back(g_testDict[i]); + EXPECT_TRUE(readResultSet->MoveToNext()); + EXPECT_EQ(readResultSet->GetEntry(entry), OK); + EXPECT_EQ(entry.key, cursorKey); + EXPECT_EQ(entry.value, cursorValue); + EXPECT_TRUE(!readResultSet->IsBeforeFirst()); + EXPECT_TRUE(!readResultSet->IsAfterLast()); + } + // change index to 8(last) + EXPECT_EQ(readResultSet->GetPosition(), RESULT_SET_COUNT - 1); + EXPECT_TRUE(!readResultSet->IsFirst()); + EXPECT_TRUE(readResultSet->IsLast()); + EXPECT_TRUE(!readResultSet->IsBeforeFirst()); + EXPECT_TRUE(!readResultSet->IsAfterLast()); + } + + void CheckResultSetValue(KvStoreResultSet *readResultSet, DBStatus errCode, int position) + { + if (readResultSet == nullptr) { + return; + } + Entry entry; + EXPECT_EQ(readResultSet->GetPosition(), position); + EXPECT_EQ(readResultSet->GetEntry(entry), errCode); + if (errCode == OK) { + std::vector cursorKey; + std::vector cursorValue; + if (position > RESULT_SET_INIT_POS && position < RESULT_SET_COUNT) { + uint8_t keyPostfix = g_testDict[position]; + // set key + cursorKey = g_keyPrefix; + cursorKey.push_back(keyPostfix); + // set value + cursorValue.push_back(keyPostfix); + } + // check key and value + EXPECT_EQ(entry.key, cursorKey); + EXPECT_EQ(entry.value, cursorValue); + } + } + +class DistributedDBInterfacesNBDelegateRdTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBInterfacesNBDelegateRdTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + g_config.dataDir = g_testDir; + g_option.storageEngineType = GAUSSDB_RD; + g_mgr.SetKvStoreConfig(g_config); + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } + + g_communicatorAggregator = new (std::nothrow) VirtualCommunicatorAggregator(); + ASSERT_TRUE(g_communicatorAggregator != nullptr); + RuntimeContext::GetInstance()->SetCommunicatorAggregator(g_communicatorAggregator); + + std::shared_ptr g_adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); +} + +void DistributedDBInterfacesNBDelegateRdTest::TearDownTestCase(void) +{ + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); + + RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); +} + +void DistributedDBInterfacesNBDelegateRdTest::SetUp(void) +{ + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error."); + } + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + g_kvDelegateStatus = INVALID_ARGS; + g_kvNbDelegatePtr = nullptr; +} + +void DistributedDBInterfacesNBDelegateRdTest::TearDown(void) +{ + if (g_kvNbDelegatePtr != nullptr) { + g_mgr.CloseKvStore(g_kvNbDelegatePtr); + g_kvNbDelegatePtr = nullptr; + } + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); +} + +/** + * @tc.name: + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, CombineTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("distributed_nb_delegate_test_rd", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + std::string keyStr("acd"); + Key key(keyStr.begin(), keyStr.end()); + std::string valueStr("acd"); + Value value(valueStr.begin(), valueStr.end()); + Value valueRead; + KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; + ASSERT_TRUE(observer != nullptr); + /** + * @tc.steps:step2. Register a non-null but unsupported observer for the special key. + * @tc.expected: step2. Register results DB_ERROR. + */ + EXPECT_EQ(g_kvNbDelegatePtr->RegisterObserver(key, OBSERVER_CHANGES_LOCAL_ONLY, observer), DB_ERROR); + /** + * @tc.steps:step3. Try to get the data before putting + * @tc.expected: step3. Put returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), NOT_FOUND); + /** + * @tc.steps:step3. Put the local data. + * @tc.expected: step3. Put returns OK. + * + */ + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + /** + * @tc.steps:step4. Check the local data. + * @tc.expected: step4. The get data is equal to the put data. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), OK); + /** + * @tc.steps:step5. Delete the local data. + * @tc.expected: step5. Delete returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Delete(key), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + /** + * @tc.steps:step6. Check the local data. + * @tc.expected: step6. Couldn't find the deleted data. + */ + LOGD("step6 =========== Get local data again"); + EXPECT_EQ(g_kvNbDelegatePtr->Get(key, valueRead), NOT_FOUND); + /** + * @tc.steps:step7. UnRegister the observer. + * @tc.expected: step7. Returns NOT_FOUND. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UnRegisterObserver(observer), NOT_FOUND); + delete observer; + observer = nullptr; + /** + * @tc.steps:step8. Close the kv store. + * @tc.expected: step8. Results OK and delete successfully. + */ + LOGD("step8 =========== Close store"); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_nb_delegate_test_rd"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerGetLocalEntries001 + * @tc.desc: Test GetEntries interface for the single ver database. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerGetLocalEntries001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("concurrentPutTest", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Put one data whose key has prefix 'p' into the local zone. + */ + Entry entry1 = {{'p'}, {'q'}}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry1.key, entry1.value), OK); + + /** + * @tc.steps:step3. Get batch data whose key has prefix 'k' from the local zone. + * @tc.expected: step3. Get results NOT_FOUND. + */ + std::vector entries; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries({'k'}, entries), NOT_FOUND); + + /** + * @tc.steps:step4. Put two data whose key have prefix 'k' into the local zone. + */ + Entry entry2 = {{'k', '1'}, {'d'}}; + Entry entry3 = {{'k', '2'}, {'d'}}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry2.key, entry2.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry3.key, entry3.value), OK); + + /** + * @tc.steps:step5. Get batch data whose key has prefix 'k' from the local zone. + * @tc.expected: step5. Get results OK, and the entries size is 2. + */ + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries({'k'}, entries), OK); + EXPECT_EQ(entries.size(), 2UL); + + /** + * @tc.steps:step6. Get batch data whose key has empty prefix from the local zone. + * @tc.expected: step6. Get results OK, and the entries size is 3. + */ + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries((Key){}, entries), OK); + EXPECT_EQ(entries.size(), 3UL); + + /** + * @tc.steps:step7. Delete one data whose key has prefix 'k' from the local zone. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Delete(entry3.key), OK); + + /** + * @tc.steps:step8. Get batch data whose key has prefix 'k' from the local zone. + * @tc.expected: step8. Get results OK, and the entries size is 1. + */ + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries({'k'}, entries), OK); + EXPECT_EQ(entries.size(), 1UL); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("concurrentPutTest"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: ResultSetTest001 + * @tc.desc: Test the NbDelegate for result set function. + * @tc.type: FUNC + * @tc.require: AR000D08KT + * @tc.author: wumin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, ResultSetTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. initialize result set. + * @tc.expected: step1. Success. + */ + g_mgr.GetKvStore("distributed_nb_delegate_result_set_test", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + InitResultSet(); + + /** + * @tc.steps: step2. get entries using result set. + * @tc.expected: step2. Success. + */ + KvStoreResultSet *readResultSet = nullptr; + Key keyPrefix = { g_keyPrefix }; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(keyPrefix, readResultSet), OK); + ASSERT_TRUE(readResultSet != nullptr); + EXPECT_EQ(readResultSet->GetCount(), RESULT_SET_COUNT); + + /** + * @tc.steps: step3. result function check. + * @tc.expected: step3. Success. + */ + CheckResultSetValue(readResultSet, NOT_FOUND, RESULT_SET_INIT_POS); + // index from 0 to 8(first to last) + ReadResultSet(readResultSet); + // change index to 9(after last) + EXPECT_TRUE(!readResultSet->MoveToNext()); + CheckResultSetValue(readResultSet, NOT_FOUND, RESULT_SET_COUNT); + // change index to 8(last) + EXPECT_TRUE(readResultSet->MoveToPrevious()); + CheckResultSetValue(readResultSet, OK, RESULT_SET_COUNT - 1); + // change index to 0(first) + EXPECT_TRUE(readResultSet->MoveToFirst()); + CheckResultSetValue(readResultSet, OK, RESULT_SET_INIT_POS + 1); + // change index to 8(last) + EXPECT_TRUE(readResultSet->MoveToLast()); + CheckResultSetValue(readResultSet, OK, RESULT_SET_COUNT - 1); + // move to -4: change index to -1 + EXPECT_TRUE(!readResultSet->MoveToPosition(RESULT_SET_INIT_POS - 3)); + CheckResultSetValue(readResultSet, NOT_FOUND, RESULT_SET_INIT_POS); + // move to 10: change index to 9 + EXPECT_TRUE(!readResultSet->MoveToPosition(RESULT_SET_COUNT + 1)); + CheckResultSetValue(readResultSet, NOT_FOUND, RESULT_SET_COUNT); + // change index to 2 + EXPECT_TRUE(readResultSet->MoveToPosition(RESULT_SET_INIT_POS + 3)); + CheckResultSetValue(readResultSet, OK, RESULT_SET_INIT_POS + 3); + // move 0: change index to 2 + EXPECT_TRUE(readResultSet->Move(0)); + CheckResultSetValue(readResultSet, OK, RESULT_SET_INIT_POS + 3); + // change index to 6 + EXPECT_TRUE(readResultSet->Move(RESULT_SET_INIT_POS + 5)); + CheckResultSetValue(readResultSet, OK, RESULT_SET_INIT_POS + 7); + // change index to 3 + EXPECT_TRUE(readResultSet->Move(RESULT_SET_INIT_POS - 2)); + CheckResultSetValue(readResultSet, OK, RESULT_SET_INIT_POS + 4); + // move -5: change index to -1 + EXPECT_TRUE(!readResultSet->Move(-5)); + CheckResultSetValue(readResultSet, NOT_FOUND, RESULT_SET_INIT_POS); + + // move INT_MIN: change index to -1 + EXPECT_TRUE(!readResultSet->Move(INT_MIN)); + CheckResultSetValue(readResultSet, NOT_FOUND, RESULT_SET_INIT_POS); + + EXPECT_TRUE(readResultSet->Move(5)); + EXPECT_TRUE(!readResultSet->Move(INT_MAX)); + CheckResultSetValue(readResultSet, NOT_FOUND, RESULT_SET_COUNT); + + /** + * @tc.steps: step4. clear the result set resource. + * @tc.expected: step4. Success. + */ + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(readResultSet), OK); + EXPECT_TRUE(readResultSet == nullptr); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_nb_delegate_result_set_test"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: PutBatchVerify001 + * @tc.desc: This test case use to verify the putBatch interface function + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wumin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, PutBatchVerify001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Get singleVer kvStore by GetKvStore. + * @tc.expected: step1. Get database success. + */ + g_mgr.GetKvStore("distributed_PutBatchVerify_001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step2. Insert 10 records into database. + * @tc.expected: step2. Insert successfully. + */ + vector entries; + for (int i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back(i); + entries.push_back(entry); + } + + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entries), OK); + + for (int i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + Key key; + key.push_back(i); + Value value; + g_kvNbDelegatePtr->Get(key, value); + EXPECT_EQ(key, value); + } + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerPutBatch001 + * @tc.desc: Check for illegal parameters + * @tc.type: FUNC + * @tc.require: AR000DPTQ8 + * @tc.author: sunpeng + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatch001, TestSize.Level1) +{ + /** + * @tc.steps: step1. + * Create and construct three sets of vector , each set of three data contains records: + * (K1, V1) It is illegal for K1 to be greater than 1K, and V1 is 1K in size + * (K2, V2) K2 is legal, V2 is greater than 4M + * (K3, V3) are not legal. + */ + Key illegalKey; + DistributedDBToolsUnitTest::GetRandomKeyValue(illegalKey, DBConstant::MAX_KEY_SIZE + 1); // 1K + 1 + Value illegalValue; + DistributedDBToolsUnitTest::GetRandomKeyValue(illegalValue, DBConstant::MAX_VALUE_SIZE + 1); // 4M + 1 + vector entrysKeyIllegal = {KV_ENTRY_1, KV_ENTRY_2, {illegalKey, VALUE_3}}; + vector entrysValueIllegal = {KV_ENTRY_1, KV_ENTRY_2, {KEY_3, illegalValue}}; + vector entrysIllegal = {KV_ENTRY_1, KV_ENTRY_2, {illegalKey, illegalValue}}; + + g_mgr.GetKvStore("distributed_SingleVerPutBatch_001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps: step2. PutBatch operates on three sets of data. + * @tc.expected: step2. All three operations return INVALID_ARGS. + */ + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysKeyIllegal), INVALID_ARGS); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysValueIllegal), INVALID_ARGS); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysIllegal), INVALID_ARGS); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatch_001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerPutBatch002 + * @tc.desc: PutBatch normal insert function test. + * @tc.type: FUNC + * @tc.require: AR000DPTQ8 + * @tc.author: sunpeng + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatch002, TestSize.Level1) +{ + g_mgr.GetKvStore("distributed_SingleVerPutBatch_002", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps: step1. + * Create and build 4 groups of vector , which are: + * Vect of empty objects; + * Vect1 of a legal Entry record; + * 128 legal Entry records Vect2; + * 129 legal Entry records Vect3; + */ + vector entrysMaxNumber; + for (size_t i = 0; i < DBConstant::MAX_BATCH_SIZE; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back(i); + entrysMaxNumber.push_back(entry); + } + Key keyTemp = {'1', '1'}; + Value valueTemp; + Entry entryTemp = {keyTemp, VALUE_1}; + vector entrysOneRecord = {entryTemp}; + vector entrysOverSize = entrysMaxNumber; + entrysOverSize.push_back(entryTemp); + + /** + * @tc.steps: step2. PutBatch operates on four sets of data. and use get check the result of Vect3. + * @tc.expected: step2. Returns INVALID_ARGS for 129 records, and returns OK for the rest. all get return NOT_FOUND. + */ + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysOverSize), INVALID_ARGS); + for (size_t i = 0; i < entrysOverSize.size(); i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysOverSize[i].key, valueTemp), NOT_FOUND); + } + + /** + * @tc.steps: step3. Use get check the result of Vect2. + * @tc.expected: step3. Return OK and get the correct value. + */ + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysOneRecord), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Get(keyTemp, valueTemp), OK); + EXPECT_EQ(valueTemp, VALUE_1); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysMaxNumber), OK); + /** + * @tc.steps: step4. Use get check the result of Vect3. + * @tc.expected: step4. Return OK and get the correct value. + */ + for (size_t i = 0; i < entrysMaxNumber.size(); i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysMaxNumber[i].key, valueTemp), OK); + EXPECT_EQ(valueTemp, entrysMaxNumber[i].value); + } + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatch_002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerPutBatch003 + * @tc.desc: Check interface atomicity + * @tc.type: FUNC + * @tc.require: AR000DPTQ8 + * @tc.author: sunpeng + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatch003, TestSize.Level1) +{ + g_mgr.GetKvStore("distributed_SingleVerPutBatch_003", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps: step1. Create and construct a set of vector with a total of 128 data, + * including one illegal data. And call PutBatch interface to insert. + */ + vector entrysMaxNumber; + for (size_t i = 0; i < DBConstant::MAX_BATCH_SIZE; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back(i); + entrysMaxNumber.push_back(entry); + } + Key illegalKey; + Value valueTemp; + DistributedDBToolsUnitTest::GetRandomKeyValue(illegalKey, DBConstant::MAX_KEY_SIZE + 1); // 1K + 1 + entrysMaxNumber[0].key = illegalKey; + + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysMaxNumber), INVALID_ARGS); + /** + * @tc.steps: step2. Use Get interface to query 128 corresponding key values. + * @tc.expected: step2. All Get interface return NOT_FOUND. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysMaxNumber[0].key, valueTemp), INVALID_ARGS); + for (size_t i = 1; i < entrysMaxNumber.size(); i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysMaxNumber[i].key, valueTemp), NOT_FOUND); + } + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatch_003"), OK); + g_kvNbDelegatePtr = nullptr; +} + +static void PreparePutBatch004(vector &entrys1, vector &entrys2, vector &entrys3) +{ + g_mgr.GetKvStore("distributed_SingleVerPutBatch_004", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + for (int i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back(i); + entrys1.push_back(entry); + } + + for (int i = 0; i < DIVIDE_BATCH_PRESET_SIZE; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back(i + VALUE_OFFSET); + entrys2.push_back(entry); + } + + for (int i = DIVIDE_BATCH_PRESET_SIZE; i < BATCH_PRESET_SIZE_TEST; i++) { + Entry entry; + entry.key.push_back(i); + entry.value.push_back(i - VALUE_OFFSET); + entrys3.push_back(entry); + } +} + +/** + * @tc.name: SingleVerPutBatch004 + * @tc.desc: Check interface data insertion and update functions. + * @tc.type: FUNC + * @tc.require: AR000DPTQ8 + * @tc.author: sunpeng + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatch004, TestSize.Level1) +{ + /** + * @tc.steps: step1. + * Construct three groups of three vector : + * (1) entrys1: key1 ~ 10, corresponding to Value1 ~ 10; + * (2) entrys2: key1 ~ 5, corresponding to Value6 ~ 10; + * (3) entrys3: key6 ~ 10, corresponding to Value1 ~ 5; + */ + vector entrys1; + vector entrys2; + vector entrys3; + PreparePutBatch004(entrys1, entrys2, entrys3); + /** + * @tc.steps: step2. PutBatch entrys2. + * @tc.expected: step2. PutBatch return OK. + */ + Value valueRead; + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys2), OK); + /** + * @tc.steps: step3. Check PutBatch result. + * @tc.expected: step3. Get correct value of key1~5. Key6~10 return NOT_FOUND. + */ + for (int i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + Key keyTemp; + keyTemp.push_back(i); + if (i < DIVIDE_BATCH_PRESET_SIZE) { + Value valueTemp; + valueTemp.push_back(i + VALUE_OFFSET); + EXPECT_EQ(g_kvNbDelegatePtr->Get(keyTemp, valueRead), OK); + EXPECT_EQ(valueRead, valueTemp); + continue; + } + EXPECT_EQ(g_kvNbDelegatePtr->Get(keyTemp, valueRead), NOT_FOUND); + } + /** + * @tc.steps: step4. PutBatch entrys1. + * @tc.expected: step4. PutBatch return OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys1), OK); + /** + * @tc.steps: step5. Check PutBatch result. + * @tc.expected: step5. Update and insert value of key1~10 to value1~10. + */ + for (int i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + Key keyTemp; + keyTemp.push_back(i); + if (i < DIVIDE_BATCH_PRESET_SIZE) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(keyTemp, valueRead), OK); + EXPECT_EQ(valueRead, keyTemp); + continue; + } + EXPECT_EQ(g_kvNbDelegatePtr->Get(keyTemp, valueRead), OK); + EXPECT_EQ(valueRead, keyTemp); + } + /** + * @tc.steps: step6. PutBatch entrys3. + * @tc.expected: step6. PutBatch return OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys3), OK); + /** + * @tc.steps: step7. Check PutBatch result of key1~10. + * @tc.expected: step7. Update value of key5~10 to value1~5. + */ + for (int i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + Key keyTemp; + keyTemp.push_back(i); + if (i < DIVIDE_BATCH_PRESET_SIZE) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(keyTemp, valueRead), OK); + EXPECT_EQ(valueRead, keyTemp); + continue; + } + Value valueTemp; + valueTemp.push_back(i - VALUE_OFFSET); + EXPECT_EQ(g_kvNbDelegatePtr->Get(keyTemp, valueRead), OK); + EXPECT_EQ(valueRead, valueTemp); + } + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatch_004"), OK); + g_kvNbDelegatePtr = nullptr; +} + +static void CreatEntrys(int recordSize, vector &keys, vector &values, vector &entries) +{ + keys.clear(); + values.clear(); + entries.clear(); + for (int i = 0; i < recordSize; i++) { + string temp = to_string(i); + Entry entry; + Key keyTemp; + Value valueTemp; + for (auto &iter : temp) { + entry.key.push_back(iter); + entry.value.push_back(iter); + keyTemp.push_back(iter); + valueTemp.push_back(iter); + } + keys.push_back(keyTemp); + values.push_back(valueTemp); + entries.push_back(entry); + } +} + +/** + * @tc.name: SingleVerDeleteBatch001 + * @tc.desc: Check for illegal parameters. + * @tc.type: FUNC + * @tc.require: AR000DPTQ8 + * @tc.author: sunpeng + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerDeleteBatch001, TestSize.Level1) +{ + g_mgr.GetKvStore("distributed_SingleVerDeleteBatch_001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps: step1. Create and construct a set of vector , containing a total of 10 data keys1 ~ 10, + * Value1 ~ 10, and call Putbatch interface to insert data. + * @tc.expected: step1. PutBatch successfully. + */ + vector entries; + vector keys; + vector values; + Value valueRead; + CreatEntrys(BATCH_PRESET_SIZE_TEST, keys, values, entries); + vector entrysBase = entries; + vector keysBase = keys; + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysBase), OK); + /** + * @tc.steps: step2. Use Get to check data in database. + * @tc.expected: step2. Get value1~10 by key1~10 successfully. + */ + for (size_t i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysBase[i].key, valueRead), OK); + } + /** + * @tc.steps: step3. Use DeleteBatch interface to transfer 10 + 119 extra keys (total 129). + * @tc.expected: step3. Return INVALID_ARGS. + */ + CreatEntrys(DBConstant::MAX_BATCH_SIZE + 1, keys, values, entries); + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keys), INVALID_ARGS); + /** + * @tc.steps: step4. Use Get to check data in database. + * @tc.expected: step4. Key1~10 still in database. + */ + for (size_t i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysBase[i].key, valueRead), OK); + } + /** + * @tc.steps: step5. Use the DeleteBatch interface to pass in 10 included + * keys6 ~ 10 + 123 additional key values ​​(128 in total). + * @tc.expected: step5. DeleteBatch OK. + */ + CreatEntrys(DBConstant::MAX_BATCH_SIZE + DIVIDE_BATCH_PRESET_SIZE, keys, values, entries); + keys.erase(keys.begin(), keys.begin() + DIVIDE_BATCH_PRESET_SIZE); + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keys), OK); + /** + * @tc.steps: step6. Use Get to check key1~10 in database. + * @tc.expected: step6. Key1~5 in database, key6~10 have been deleted. + */ + for (size_t i = 0; i < DIVIDE_BATCH_PRESET_SIZE; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysBase[i].key, valueRead), OK); + } + for (size_t i = DIVIDE_BATCH_PRESET_SIZE; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysBase[i].key, valueRead), NOT_FOUND); + } + /** + * @tc.steps: step7. Repeat Putbatch key1~10, value1~10. + * @tc.expected: step7. Return OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysBase), OK); + + Key illegalKey; + DistributedDBToolsUnitTest::GetRandomKeyValue(illegalKey, DBConstant::MAX_KEY_SIZE + 1); // 1K + 1 + keysBase.push_back(illegalKey); + /** + * @tc.steps: step8. Use DeleteBatch interface to pass in 10 + 1(larger than 1K) keys. + * @tc.expected: step8. Return INVALID_ARGS. + */ + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keysBase), INVALID_ARGS); + /** + * @tc.steps: step9. Use Get to check key1~10 in database. + * @tc.expected: step9. Delete those data failed. + */ + for (size_t i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysBase[i].key, valueRead), OK); + } + /** + * @tc.steps: step10. Use DeleteBatch interface to pass in 10(in database) + 1 valid keys. + * @tc.expected: step10. Delete those data successfully. + */ + keysBase.back().erase(keysBase.back().begin(), keysBase.back().begin() + 1); + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keysBase), OK); + /** + * @tc.steps: step11. Check data. + * @tc.expected: step11. DeleteBatch successfully. + */ + for (size_t i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(entrysBase[i].key, valueRead), NOT_FOUND); + } + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerDeleteBatch_001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerDeleteBatch002 + * @tc.desc: Check normal delete batch ability. + * @tc.type: FUNC + * @tc.require: AR000DPTQ8 + * @tc.author: sunpeng + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerDeleteBatch002, TestSize.Level1) +{ + g_mgr.GetKvStore("distributed_SingleVerPutBatch_002", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + /** + * @tc.steps: step1. Create a group of vector , containing a total of 10 data keys1 ~ 10, Value1 ~ 10, + * call the Putbatch interface to insert data. + * @tc.expected: step1. Insert to database successfully. + */ + vector entries; + vector keysBase; + vector values; + CreatEntrys(BATCH_PRESET_SIZE_TEST, keysBase, values, entries); + + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entries), OK); + /** + * @tc.steps: step2. Check data. + * @tc.expected: step2. Get key1~10 successfully. + */ + Value valueRead; + for (size_t i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(keysBase[i], valueRead), OK); + } + /** + * @tc.steps: step3. DeleteBatch key1~5. + * @tc.expected: step3. Return OK. + */ + vector keys(keysBase.begin(), keysBase.begin() + DIVIDE_BATCH_PRESET_SIZE); + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keys), OK); + /** + * @tc.steps: step4. Check key1~10. + * @tc.expected: step4. Key1~5 deleted, key6~10 existed. + */ + for (size_t i = 0; i < DIVIDE_BATCH_PRESET_SIZE; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(keysBase[i], valueRead), NOT_FOUND); + } + for (size_t i = DIVIDE_BATCH_PRESET_SIZE; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(keysBase[i], valueRead), OK); + } + /** + * @tc.steps: step5. DeleteBatch key1~10. + * @tc.expected: step5. Return OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keysBase), OK); + /** + * @tc.steps: step6. Check key1~10. + * @tc.expected: step6. Key1~10 deleted successfully. + */ + for (size_t i = 0; i < BATCH_PRESET_SIZE_TEST; i++) { + EXPECT_EQ(g_kvNbDelegatePtr->Get(keysBase[i], valueRead), NOT_FOUND); + } + /** + * @tc.steps: step7. DeleteBatch key1~10 once again. + * @tc.expected: step7. Return OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keysBase), OK); + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatch_002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerPutBatchObserver001 + * @tc.desc: Test the observer function of PutBatch() interface. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: wumin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatchObserver001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("distributed_SingleVerPutBatchObserver_001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; + ASSERT_TRUE(observer != nullptr); + /** + * @tc.steps:step2. Register the non-null observer for the special key. + * @tc.expected: step2. Register results OK. + */ + Key key; + EXPECT_EQ(g_kvNbDelegatePtr->RegisterObserver(key, OBSERVER_CHANGES_NATIVE, observer), OK); + // register same observer twice will return already_set + EXPECT_EQ(g_kvNbDelegatePtr->RegisterObserver(key, OBSERVER_CHANGES_NATIVE, observer), ALREADY_SET); + /** + * @tc.steps:step3. Put batch data. + * @tc.expected: step3. Returns OK. + */ + vector entrysBase; + vector keysBase; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST + 1, entrysBase, keysBase); + + vector entries(entrysBase.begin(), entrysBase.end() - 1); + EXPECT_EQ(entries.size(), 10UL); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entries), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entries, observer->GetEntriesInserted())); + /** + * @tc.steps:step4. Delete the batch data. + * @tc.expected: step4. Returns OK. + */ + vector keys(keysBase.begin() + 5, keysBase.end()); + EXPECT_EQ(keys.size(), 6UL); + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keys), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + vector entrysDel(entrysBase.begin() + 5, entrysBase.end() - 1); + EXPECT_EQ(entrysDel.size(), 5UL); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entrysDel, observer->GetEntriesDeleted())); + /** + * @tc.steps:step5. UnRegister the observer. + * @tc.expected: step5. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UnRegisterObserver(observer), OK); + delete observer; + observer = nullptr; + /** + * @tc.steps:step6. Close the kv store. + * @tc.expected: step6. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatchObserver_001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerPutBatchObserver002 + * @tc.desc: Test the observer function of PutBatch() for invalid input. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: wumin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatchObserver002, TestSize.Level4) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("distributed_SingleVerPutBatchObserver_002", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; + ASSERT_TRUE(observer != nullptr); + /** + * @tc.steps:step2. Register the non-null observer for the special key. + * @tc.expected: step2. Register results OK. + */ + Key key; + EXPECT_EQ(g_kvNbDelegatePtr->RegisterObserver(key, OBSERVER_CHANGES_NATIVE, observer), OK); + /** + * @tc.steps:step3. Put 129 batch data. + * @tc.expected: step3. Returns INVALID_ARGS. + */ + vector entrys1; + vector keys1; + DistributedDBUnitTest::GenerateRecords(DBConstant::MAX_BATCH_SIZE + 1, entrys1, keys1); + + EXPECT_EQ(entrys1.size(), 129UL); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys1), INVALID_ARGS); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(observer->GetEntriesInserted().empty()); + /** + * @tc.steps:step4. Put invalid batch data. + * @tc.expected: step4. Returns INVALID_ARGS. + */ + vector entrys2; + vector keys2; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrys2, keys2); + EXPECT_EQ(entrys2.size(), 10UL); + + vector entrysInvalid; + vector keysInvalid; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrysInvalid, keysInvalid, + DBConstant::MAX_KEY_SIZE + 10); + EXPECT_EQ(entrysInvalid.size(), 10UL); + entrys2[0].key = entrysInvalid[0].key; + + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys2), INVALID_ARGS); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(observer->GetEntriesInserted().empty()); + /** + * @tc.steps:step5. Put MAX valid value batch data. + * @tc.expected: step5. Returns OK. + */ + vector entrys3; + vector keys3; + + DistributedDBUnitTest::GenerateRecords(DBConstant::MAX_BATCH_SIZE, entrys3, keys3); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys3), OK); + LOGD("sleep begin"); + // sleep 20 seconds + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME * 10)); + LOGD("sleep end"); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entrys3, observer->GetEntriesInserted())); + /** + * @tc.steps:step6. UnRegister the observer. + * @tc.expected: step6. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UnRegisterObserver(observer), OK); + delete observer; + observer = nullptr; + /** + * @tc.steps:step7. Close the kv store. + * @tc.expected: step7. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatchObserver_002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerPutBatchObserver003 + * @tc.desc: Test the observer function of PutBatch() update function. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: wumin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatchObserver003, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("distributed_SingleVerPutBatchObserver_003", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; + ASSERT_TRUE(observer != nullptr); + /** + * @tc.steps:step2. Register the non-null observer for the special key. + * @tc.expected: step2. Register results OK. + */ + Key key; + EXPECT_EQ(g_kvNbDelegatePtr->RegisterObserver(key, OBSERVER_CHANGES_NATIVE, observer), OK); + /** + * @tc.steps:step3. Put batch data. + * @tc.expected: step3. Returns OK. + */ + vector entrysAdd; + vector keysAdd; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrysAdd, keysAdd); + + EXPECT_EQ(entrysAdd.size(), 10UL); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysAdd), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entrysAdd, observer->GetEntriesInserted())); + /** + * @tc.steps:step4. Update the batch data. + * @tc.expected: step4. Returns OK. + */ + vector entrysUpdate; + vector keysUpdate; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrysUpdate, keysUpdate, DEFAULT_KEY_VALUE_SIZE, + DEFAULT_KEY_VALUE_SIZE + 10); + + EXPECT_EQ(entrysUpdate.size(), 10UL); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrysUpdate), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entrysUpdate, observer->GetEntriesUpdated())); + /** + * @tc.steps:step5. UnRegister the observer. + * @tc.expected: step5. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UnRegisterObserver(observer), OK); + delete observer; + observer = nullptr; + /** + * @tc.steps:step6. Close the kv store. + * @tc.expected: step6. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatchObserver_003"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerPutBatchObserver004 + * @tc.desc: Test the observer function of PutBatch(), same keys handle. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: wumin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerPutBatchObserver004, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("distributed_SingleVerPutBatchObserver_004", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; + ASSERT_TRUE(observer != nullptr); + /** + * @tc.steps:step2. Register the non-null observer for the special key. + * @tc.expected: step2. Register results OK. + */ + Key key; + EXPECT_EQ(g_kvNbDelegatePtr->RegisterObserver(key, OBSERVER_CHANGES_NATIVE, observer), OK); + /** + * @tc.steps:step3. Put batch data. + * @tc.expected: step3. Returns OK. + */ + vector entrys1; + vector keys1; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrys1, keys1); + vector entrys2; + vector keys2; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrys2, keys2, DEFAULT_KEY_VALUE_SIZE, + DEFAULT_KEY_VALUE_SIZE + 10); + entrys1.insert(entrys1.end(), entrys2.begin(), entrys2.end()); + + EXPECT_EQ(entrys1.size(), 20UL); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys1), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entrys2, observer->GetEntriesInserted())); + EXPECT_EQ(observer->GetEntriesUpdated().size(), 0UL); + + vector entrys3; + vector keys3; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrys3, keys3, DEFAULT_KEY_VALUE_SIZE, + DEFAULT_KEY_VALUE_SIZE + 20); + vector entrys4; + vector keys4; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entrys4, keys4, DEFAULT_KEY_VALUE_SIZE, + DEFAULT_KEY_VALUE_SIZE + 30); + entrys3.insert(entrys3.end(), entrys4.begin(), entrys4.end()); + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entrys3), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entrys4, observer->GetEntriesUpdated())); + EXPECT_EQ(observer->GetEntriesInserted().size(), 0UL); + + /** + * @tc.steps:step4. UnRegister the observer. + * @tc.expected: step4. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UnRegisterObserver(observer), OK); + delete observer; + observer = nullptr; + /** + * @tc.steps:step5. Close the kv store. + * @tc.expected: step5. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerPutBatchObserver_004"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerDeleteBatchObserver001 + * @tc.desc: Test the observer function of DeleteBatch() interface. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: wumin + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerDeleteBatchObserver001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("distributed_SingleVerDeleteBatchObserver_001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + KvStoreObserverUnitTest *observer = new (std::nothrow) KvStoreObserverUnitTest; + ASSERT_TRUE(observer != nullptr); + /** + * @tc.steps:step2. Register the non-null observer for the special key. + * @tc.expected: step2. Register results OK. + */ + Key key; + EXPECT_EQ(g_kvNbDelegatePtr->RegisterObserver(key, OBSERVER_CHANGES_NATIVE, observer), OK); + /** + * @tc.steps:step3. Put batch data. + * @tc.expected: step3. Returns OK. + */ + vector entries; + vector keys; + DistributedDBUnitTest::GenerateRecords(BATCH_PRESET_SIZE_TEST, entries, keys); + EXPECT_EQ(entries.size(), 10UL); + + EXPECT_EQ(g_kvNbDelegatePtr->PutBatch(entries), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entries, observer->GetEntriesInserted())); + /** + * @tc.steps:step4. Delete the batch data. + * @tc.expected: step4. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->DeleteBatch(keys), OK); + std::this_thread::sleep_for(std::chrono::milliseconds(OBSERVER_SLEEP_TIME)); + EXPECT_TRUE(DistributedDBToolsUnitTest::CheckObserverResult(entries, observer->GetEntriesDeleted())); + /** + * @tc.steps:step5. UnRegister the observer. + * @tc.expected: step5. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->UnRegisterObserver(observer), OK); + delete observer; + observer = nullptr; + /** + * @tc.steps:step6. Close the kv store. + * @tc.expected: step6. Results OK and delete successfully. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("distributed_SingleVerDeleteBatchObserver_001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: SingleVerGetSecurityOption001 + * @tc.desc: Test GetSecurityOption interface for the single ver database. + * @tc.type: FUNC + * @tc.require: AR000EV1G2 + * @tc.author: liuwenkai + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerGetSecurityOption001, TestSize.Level1) +{ + SecurityOption savedOption; + std::shared_ptr adapter = std::make_shared(); + EXPECT_TRUE(adapter); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + + /** + * @tc.steps:step1. Create databases without securityOption. + * @tc.expected: step2. Returns a non-null kvstore but can not get SecurityOption. + */ + g_mgr.GetKvStore("SingleVerGetSecurityOption001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + EXPECT_TRUE(g_kvNbDelegatePtr->GetSecurityOption(savedOption) == OK); + EXPECT_TRUE(savedOption.securityLabel == 0); + EXPECT_TRUE(savedOption.securityFlag == 0); + KvStoreNbDelegate *kvNbDelegatePtr1 = g_kvNbDelegatePtr; + + /** + * @tc.steps:step2. Create databases with new securityOption(Check ignore the new option). + * @tc.expected: step2. Returns non-null kvstore. + */ + option.secOption.securityLabel = S3; + option.secOption.securityFlag = 1; + g_mgr.GetKvStore("SingleVerGetSecurityOption001", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + EXPECT_TRUE(g_kvNbDelegatePtr->GetSecurityOption(savedOption) == OK); + EXPECT_TRUE(savedOption.securityLabel == 0); + EXPECT_TRUE(savedOption.securityFlag == 0); + + EXPECT_EQ(g_mgr.CloseKvStore(kvNbDelegatePtr1), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_TRUE(g_mgr.DeleteKvStore("SingleVerGetSecurityOption001") == OK); +} + +/** + * @tc.name: SingleVerGetSecurityOption002 + * @tc.desc: Test GetSecurityOption interface for the single ver database. + * @tc.type: FUNC + * @tc.require: AR000EV1G2 + * @tc.author: liuwenkai + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, SingleVerGetSecurityOption002, TestSize.Level1) +{ + SecurityOption savedOption; + std::shared_ptr adapter = std::make_shared(); + EXPECT_TRUE(adapter != nullptr); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); + KvStoreNbDelegate::Option option; + option.storageEngineType = GAUSSDB_RD; + + /** + * @tc.steps:step1. Create databases with securityOption. + * @tc.expected: step2. Returns a non-null kvstore and get right SecurityOption. + */ + option.secOption.securityLabel = S3; + option.secOption.securityFlag = 1; + g_mgr.GetKvStore("SingleVerGetSecurityOption002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + EXPECT_TRUE(g_kvNbDelegatePtr->GetSecurityOption(savedOption) == OK); + EXPECT_TRUE(savedOption.securityLabel == S3); + EXPECT_TRUE(savedOption.securityFlag == 1); + KvStoreNbDelegate *kvNbDelegatePtr1 = g_kvNbDelegatePtr; + + /** + * @tc.steps:step2. Create databases without securityOption. + * @tc.expected: step2. Returns a non-null kvstore and get right SecurityOption. + */ + option.secOption.securityLabel = 0; + option.secOption.securityFlag = 0; + g_mgr.GetKvStore("SingleVerGetSecurityOption002", option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + EXPECT_TRUE(g_kvNbDelegatePtr->GetSecurityOption(savedOption) == OK); + EXPECT_TRUE(savedOption.securityLabel == S3); + EXPECT_TRUE(savedOption.securityFlag == 1); + + EXPECT_EQ(g_mgr.CloseKvStore(kvNbDelegatePtr1), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_TRUE(g_mgr.DeleteKvStore("SingleVerGetSecurityOption002") == OK); +} + +/** + * @tc.name: MaxLogSize001 + * @tc.desc: Test the pragma cmd of the max log size limit. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, MaxLogSize001, TestSize.Level2) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + g_mgr.GetKvStore("MaxLogSize001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Setting the max log limit for the valid value. + * @tc.expected: step2. Returns NOT_SUPPORT. + */ + uint64_t logSize = DBConstant::MAX_LOG_SIZE_HIGH; + PragmaData pragLimit = static_cast(&logSize); + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_LOG_LIMIT, pragLimit), NOT_SUPPORT); + + logSize = DBConstant::MAX_LOG_SIZE_LOW; + pragLimit = static_cast(&logSize); + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_LOG_LIMIT, pragLimit), NOT_SUPPORT); + + logSize = 10 * 1024 * 1024; // 10M + pragLimit = static_cast(&logSize); + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_LOG_LIMIT, pragLimit), NOT_SUPPORT); + + /** + * @tc.steps:step3. Setting the max log limit for the invalid value. + * @tc.expected: step3. Returns INLIVAD_ARGS. + */ + logSize = DBConstant::MAX_LOG_SIZE_HIGH + 1; + pragLimit = static_cast(&logSize); + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_LOG_LIMIT, pragLimit), NOT_SUPPORT); + + logSize = DBConstant::MAX_LOG_SIZE_LOW - 1; + pragLimit = static_cast(&logSize); + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_LOG_LIMIT, pragLimit), NOT_SUPPORT); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + EXPECT_TRUE(g_mgr.DeleteKvStore("MaxLogSize001") == OK); +} + +/** + * @tc.name: ForceCheckpoint002 + * @tc.desc: Test the checkpoint of the database. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, MaxLogSize002, TestSize.Level2) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + g_mgr.GetKvStore("MaxLogSize002", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Put the random entry into the database. + * @tc.expected: step2. Returns OK. + */ + Key key; + Value value; + DistributedDBToolsUnitTest::GetRandomKeyValue(key, 30); // for 30B random key + DistributedDBToolsUnitTest::GetRandomKeyValue(value, 1024); // 1M value + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); + DistributedDBToolsUnitTest::GetRandomKeyValue(key, 40); // for 40B random key + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); + + DistributedDBToolsUnitTest::GetRandomKeyValue(key, 20); // for 20B random key + DistributedDBToolsUnitTest::GetRandomKeyValue(value, 30); // 30B + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); + + /** + * @tc.steps:step3. Get the resultset. + * @tc.expected: step3. Returns OK. + */ + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(Key{}, resultSet), OK); + ASSERT_NE(resultSet, nullptr); + EXPECT_EQ(resultSet->GetCount(), 3); // size of all the entries is 3 + EXPECT_EQ(resultSet->MoveToFirst(), true); + + /** + * @tc.steps:step4. Put more data into the database. + * @tc.expected: step4. Returns OK. + */ + uint64_t logSize = 6 * 1024 * 1024; // 6M for initial test. + PragmaData pragLimit = static_cast(&logSize); + // rd pragma only support checkpoint only + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(SET_MAX_LOG_LIMIT, pragLimit), NOT_SUPPORT); + + g_kvNbDelegatePtr->CloseResultSet(resultSet); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("MaxLogSize002"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: MaxLogCheckPoint001 + * @tc.desc: Pragma the checkpoint command. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, MaxLogCheckPoint001, TestSize.Level2) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + g_mgr.GetKvStore("MaxLogCheckPoint001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Put the random entry into the database. + * @tc.expected: step2. Returns OK. + */ + Key key; + Value value; + DistributedDBToolsUnitTest::GetRandomKeyValue(key, 30); // for 30B random key(different size) + DistributedDBToolsUnitTest::GetRandomKeyValue(value, 1 * 1024); // 1M + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Delete(key), OK); + + /** + * @tc.steps:step3. Get the disk file size, execute the checkpoint and get the disk file size. + * @tc.expected: step3. Returns DB_ERROR because of Getting file size is not currently supported + */ + int param = 0; + PragmaData paraData = static_cast(¶m); + EXPECT_EQ(g_kvNbDelegatePtr->Pragma(EXEC_CHECKPOINT, paraData), OK); + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("MaxLogCheckPoint001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @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(DistributedDBInterfacesNBDelegateRdTest, 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)); + + mgr1.GetKvStore(STORE_ID_1, g_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, g_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); +} + +/** + * @tc.name: GetKeys001 + * @tc.desc: Test get keys from the database. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, GetKeys001, TestSize.Level1) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + g_mgr.GetKvStore("GetKeys001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Put the all keys into the database. + * @tc.expected: step2. Returns OK. + */ + std::vector expectKeys = { + {'k', '1', '1'}, + {'k', '2'}, + {'k', '3'}, + {'k', '4'} + }; + for (const auto &key : expectKeys) { + EXPECT_EQ(g_kvNbDelegatePtr->Put(key, key), OK); + } + EXPECT_EQ(g_kvNbDelegatePtr->Put({'k', '2'}, {'k', '2'}), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Delete({'k', '4'}), OK); + + /** + * @tc.steps:step3. Get the all keys. + * @tc.expected: step3. Returns OK. + */ + Key keyPrefix = {'k', '1'}; + std::vector actualKeys; + EXPECT_EQ(g_kvNbDelegatePtr->GetKeys(keyPrefix, actualKeys), NOT_SUPPORT); + EXPECT_EQ(actualKeys.size(), 0u); // get the k11, but now not support, so it is 0 for now + for (const auto &key : actualKeys) { + EXPECT_EQ(key, expectKeys[0]); + } + keyPrefix.clear(); + EXPECT_EQ(g_kvNbDelegatePtr->GetKeys(keyPrefix, actualKeys), NOT_SUPPORT); + EXPECT_EQ(actualKeys.size(), 0u); // size of all the key is 3, but now not support, so it is 0 for now + + keyPrefix = {'k', '4'}; + EXPECT_EQ(g_kvNbDelegatePtr->GetKeys(keyPrefix, actualKeys), NOT_SUPPORT); + EXPECT_EQ(actualKeys.size(), 0u); // not found key and size is 0 + + DistributedDBToolsUnitTest::GetRandomKeyValue(keyPrefix, 2048); // for 2048B random key + EXPECT_EQ(g_kvNbDelegatePtr->GetKeys(keyPrefix, actualKeys), NOT_SUPPORT); + EXPECT_EQ(actualKeys.size(), 0u); // invalid prefix key and size is 0 + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("GetKeys001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +#ifdef DB_DEBUG_ENV +/** + * @tc.name: TimeChangeWithCloseStoreTest001 + * @tc.desc: Test close store with time changed + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, TimeChangeWithCloseStoreTest001, TestSize.Level3) +{ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + + std::atomic isFinished(false); + + std::vector slowThreads; + for (int i = 0; i < 10; i++) { // 10: thread to slow donw system + std::thread th([&isFinished]() { + while (!isFinished) { + // pass + } + }); + slowThreads.emplace_back(std::move(th)); + } + + std::thread th([&isFinished]() { + int timeChangedCnt = 0; + while (!isFinished.load()) { + OS::SetOffsetBySecond(100 - timeChangedCnt++ * 2); // 100 2 : fake system time change + std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100: wait for a while + } + }); + + for (int i = 0; i < 100; i++) { // run 100 times + mgr.GetKvStore(STORE_ID_1, g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 1000: wait for a while + isFinished.store(true); + th.join(); + for (auto &it : slowThreads) { + it.join(); + } + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); +} + +/** + * @tc.name: TimeChangeWithCloseStoreTest002 + * @tc.desc: Test close store with time changed + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, TimeChangeWithCloseStoreTest002, TestSize.Level3) +{ + KvStoreDelegateManager mgr(APP_ID, USER_ID); + mgr.SetKvStoreConfig(g_config); + + mgr.GetKvStore(STORE_ID_1, g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_EQ(g_kvDelegateStatus, OK); + const int threadPoolMax = 10; + for (int i = 0; i < threadPoolMax; ++i) { + (void) RuntimeContext::GetInstance()->ScheduleTask([]() { + std::this_thread::sleep_for(std::chrono::seconds(10)); // sleep 10s for block thread pool + }); + } + OS::SetOffsetBySecond(100); // 100 2 : fake system time change + std::this_thread::sleep_for(std::chrono::seconds(1)); // sleep 1s for time tick + + EXPECT_EQ(mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + g_kvNbDelegatePtr = nullptr; + + EXPECT_EQ(mgr.DeleteKvStore(STORE_ID_1), OK); + RuntimeContext::GetInstance()->StopTaskPool(); // stop all async task +} + +/** + * @tc.name: TimeChangeWithCloseStoreTest003 + * @tc.desc: Test store close with timechange listener + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, TimeChangeWithCloseStoreTest003, TestSize.Level3) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + g_mgr.GetKvStore("TimeChangeWithCloseStoreTest003", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + std::shared_ptr timeChange = std::make_shared(false); + int errCode = E_OK; + auto *listener = RuntimeContext::GetInstance()->RegisterTimeChangedLister([timeChange](void *) { + std::this_thread::sleep_for(std::chrono::seconds(10)); // block close store 10s + *timeChange = true; + }, nullptr, errCode); + /** + * @tc.steps:step2. Block time change 10s and trigger time change. + * @tc.expected: step2. close store cost time > 5s. + */ + ASSERT_EQ(errCode, E_OK); + OS::SetOffsetBySecond(100); // 100 : fake system time change + std::this_thread::sleep_for(std::chrono::seconds(1)); // wait 1s for time change + Timestamp beginTime; + (void)OS::GetCurrentSysTimeInMicrosecond(beginTime); + ASSERT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + Timestamp endTime; + (void)OS::GetCurrentSysTimeInMicrosecond(endTime); + if (*timeChange) { + EXPECT_GE(static_cast(endTime - beginTime), 5 * 1000 * 1000); // 5 * 1000 * 1000 = 5s + } + listener->Drop(true); + OS::SetOffsetBySecond(-100); // -100 : fake system time change + g_kvNbDelegatePtr = nullptr; + EXPECT_EQ(g_mgr.DeleteKvStore("TimeChangeWithCloseStoreTest003"), OK); +} + +/** + * @tc.name: ResultSetLimitTest001 + * @tc.desc: Get result set over limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, ResultSetLimitTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create database. + * @tc.expected: step1. Returns a non-null kvstore. + */ + g_mgr.GetKvStore("ResultSetLimitTest001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps:step2. Put the random entry into the database. + * @tc.expected: step2. Returns OK. + */ + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_1, VALUE_1), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_2, VALUE_2), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_3, VALUE_3), OK); + + /** + * @tc.steps:step3. Get the resultset overlimit. + * @tc.expected: step3. In limit returns OK, else return OVER_MAX_LIMITS. + */ + std::vector dataResultSet; + for (int i = 0; i < 8; i++) { // 8: max result set count + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(Key{}, resultSet), OK); + dataResultSet.push_back(resultSet); + EXPECT_NE(resultSet, nullptr); + } + + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(Key{}, resultSet), OVER_MAX_LIMITS); + EXPECT_EQ(resultSet, nullptr); + if (resultSet != nullptr) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(resultSet), OK); + } + + /** + * @tc.steps:step4. Close result set and store. + * @tc.expected: step4. Returns OK. + */ + for (auto it : dataResultSet) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(it), OK); + } + + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("ResultSetLimitTest001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +void GetDataFromDatabase() +{ + int successTime = 0; + for (size_t i = 0; i < 1000; i++) { // cycle 1000 times. + Value value; + EXPECT_EQ(g_kvNbDelegatePtr->Get(KEY_1, value), OK); + EXPECT_EQ(value, VALUE_1); + successTime += 1; + } + LOGD("Succeed times is %d", successTime); +} + +void FreqGet001() +{ + /** + * @tc.steps:step1. Get KV store connection as well as putting an entry (KEY_1, VALUE_1) + * @tc.expected: step1. Returns OK. + */ + g_mgr.GetKvStore("FreqGet001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(KEY_1, VALUE_1), OK); + /** + * @tc.steps:step2. multiple threads tring to get the entry + * @tc.expected: step2. Returns OK. + */ + std::thread t1(GetDataFromDatabase); + std::thread t2(GetDataFromDatabase); + std::thread t3(GetDataFromDatabase); + std::thread t4(GetDataFromDatabase); + t1.join(); + t2.join(); + t3.join(); + t4.join(); + /** + * @tc.steps:step3. Close and delete KV store + * @tc.expected: step3. Returns OK. + */ + EXPECT_EQ(g_mgr.CloseKvStore(g_kvNbDelegatePtr), OK); + EXPECT_EQ(g_mgr.DeleteKvStore("FreqGet001"), OK); + g_kvNbDelegatePtr = nullptr; +} + +/** + * @tc.name: FreqGet001 + * @tc.desc: Open and close the kv store concurrently. + * @tc.type: FUNC + * @tc.require: + * @tc.author: wanyi + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, FreqGet001, TestSize.Level2) +{ + ASSERT_NO_FATAL_FAILURE(FreqGet001()); +} + +/** + * @tc.name: RdRangeQuery001 + * @tc.desc: Test GetEntries and the out of the parameter is entries. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("RdRangeQuery001", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step1. + * @tc.expected: step1. + */ + Entry entry0 = {{'0'}, {'0'}}; + Entry entry1 = {{'1'}, {'1'}}; + Entry entry2 = {{'2'}, {'2'}}; + Entry entry3 = {{'3'}, {'3'}}; + Entry entry4 = {{'4'}, {'4'}}; + Entry entry5 = {{'5'}, {'5'}}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry0.key, entry0.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry1.key, entry1.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry2.key, entry2.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry3.key, entry3.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry4.key, entry4.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry5.key, entry5.value), OK); + + + /** + * @tc.steps: step2. + * @tc.expected: step2. + */ + Query query1 = Query::Select().Range({'2'}, {'4'}); + std::vector entries; + int ret = g_kvNbDelegatePtr->GetEntries(query1, entries); + EXPECT_EQ(entries.size(), 3u); + int count1 = 2; + for(auto item : entries) { + std::string keyStr(item.key.begin(), item.key.end()); + EXPECT_EQ(to_string(count1), keyStr); + count1++; + } + + /** + * @tc.steps: step3. + * @tc.expected: step3. + */ + Query query2 = Query::Select().Range({}, {'4'}); + ret = g_kvNbDelegatePtr->GetEntries(query2, entries); + EXPECT_EQ(entries.size(), 5u); + int count2 = 0; + for(auto item : entries) { + std::string keyStr(item.key.begin(), item.key.end()); + EXPECT_EQ(to_string(count2), keyStr); + count2++; + } + + /** + * @tc.steps: step4. + * @tc.expected: step4. + */ + Query query3 = Query::Select().Range({'2'}, {}); + ret = g_kvNbDelegatePtr->GetEntries(query3, entries); + EXPECT_EQ(entries.size(), 4u); + int count3 = 2; + for(auto item : entries) { + std::string keyStr(item.key.begin(), item.key.end()); + EXPECT_EQ(to_string(count3), keyStr); + count3++; + } +} + +/** + * @tc.name: RdRangeQuery002 + * @tc.desc:Test GetEntries and the out of the parameter is resultSet. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("RdRangeQuery002", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step1. + * @tc.expected: step1. + */ + Entry entry0 = {{'0'}, {'0'}}; + Entry entry1 = {{'1'}, {'1'}}; + Entry entry2 = {{'2'}, {'2'}}; + Entry entry3 = {{'3'}, {'3'}}; + Entry entry4 = {{'4'}, {'4'}}; + Entry entry5 = {{'5'}, {'5'}}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry0.key, entry0.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry1.key, entry1.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry2.key, entry2.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry3.key, entry3.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry4.key, entry4.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry5.key, entry5.value), OK); + + + /** + * @tc.steps: step2. + * @tc.expected: step2. 2, 3, 4 + */ + Query fullQuery = Query::Select().Range({'2'}, {'4'}); + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + int count1 = 1; + while (resultSet->MoveToNext()) { + count1++; + Entry entryValue; + EXPECT_EQ(resultSet->GetEntry(entryValue), OK); + std::string keyStr(entryValue.value.begin(), entryValue.value.end()); + EXPECT_EQ(to_string(count1), keyStr); + } + EXPECT_EQ(count1, 4); + EXPECT_EQ(resultSet->MoveToNext(), false); + Entry entryValue; + EXPECT_EQ(resultSet->GetEntry(entryValue), NOT_FOUND); + std::string keyStr(entryValue.value.begin(), entryValue.value.end()); + + /** + * @tc.steps: step3. + * @tc.expected: step3. 0, 1 ,2 ,3 ,4 + */ + Query fullQuery2 = Query::Select().Range({}, {'4'}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery2, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + int count2 = 0; + while (resultSet->MoveToNext()) { + Entry entryValue; + EXPECT_EQ(resultSet->GetEntry(entryValue), OK); + std::string keyStr(entryValue.value.begin(), entryValue.value.end()); + EXPECT_EQ(to_string(count2), keyStr); + count2++; + } + EXPECT_EQ(count2, 5); + EXPECT_EQ(resultSet->MoveToNext(), false); + + /** + * @tc.steps: step4. + * @tc.expected: step4. 2, 3 ,4 ,5 + */ + Query fullQuery3 = Query::Select().Range({'2'}, {}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery3, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + int count3 = 2; + while (resultSet->MoveToNext()) { + Entry entryValue; + EXPECT_EQ(resultSet->GetEntry(entryValue), OK); + std::string keyStr(entryValue.value.begin(), entryValue.value.end()); + EXPECT_EQ(to_string(count3), keyStr); + count3++; + } + EXPECT_EQ(count3, 6); + EXPECT_EQ(resultSet->MoveToNext(), false); + if (resultSet != nullptr) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(resultSet), OK); + } + + /** + * @tc.steps: step4. + * @tc.expected: step4. 0, 1, 2, 3 ,4 ,5 + */ + Query fullQuery4 = Query::Select().Range({}, {}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery4, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + int count4 = 0; + while (resultSet->MoveToNext()) { + Entry entryValue; + EXPECT_EQ(resultSet->GetEntry(entryValue), OK); + std::string keyStr(entryValue.value.begin(), entryValue.value.end()); + EXPECT_EQ(to_string(count4), keyStr); + count4++; + } + EXPECT_EQ(count4, 6); + EXPECT_EQ(resultSet->MoveToNext(), false); + if (resultSet != nullptr) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(resultSet), OK); + } +} + +/** + * @tc.name: RdRangeQuery003 + * @tc.desc: Test GetEntries and the in put paramter is invalid. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery003, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + std::vector entries; + g_mgr.GetKvStore("RdRangeQuery003", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step2. + * @tc.expected: step2. + */ + KvStoreResultSet *resultSet = nullptr; + Query inValidQuery = Query::Select().Range({'2'}, {'4'}).Range({'1'}, {'6'}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, resultSet), INVALID_ARGS); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery, entries), INVALID_ARGS); + + /** + * @tc.steps: step3. + * @tc.expected: step3. + */ + Query inValidQuery2 = Query::Select().Range({'2'}, {'4'}).And(); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery2, resultSet), INVALID_ARGS); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery2, entries), INVALID_ARGS); + + /** + * @tc.steps: step4. + * @tc.expected: step4. + */ + Key keyCan(1024, 'a'); + Query ValidQuery3 = Query::Select().Range(keyCan, {'4'}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(ValidQuery3, resultSet), OK); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(ValidQuery3, entries), NOT_FOUND); + + Key keyInvalid(1025, 'a'); + Query inValidQuery4 = Query::Select().Range(keyInvalid, {'4'}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery4, resultSet), INVALID_ARGS); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(inValidQuery4, entries), INVALID_ARGS); +} + +/** + * @tc.name: RdRangeQuery004 + * @tc.desc: Test resultSet fuction. + * @tc.type: FUNC + * @tc.require: AR000DPTTA + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery004, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("RdRangeQuery004", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step1. + * @tc.expected: step1. + */ + Entry entry0 = {{'0'}, {'0'}}; + Entry entry1 = {{'1'}, {'1'}}; + Entry entry2 = {{'2'}, {'2'}}; + Entry entry3 = {{'3'}, {'3'}}; + Entry entry4 = {{'4'}, {'4'}}; + Entry entry5 = {{'5'}, {'5'}}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry0.key, entry0.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry1.key, entry1.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry2.key, entry2.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry3.key, entry3.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry4.key, entry4.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry5.key, entry5.value), OK); + + + /** + * @tc.steps: step2. + * @tc.expected: step2. + */ + Query fullQuery = Query::Select().Range({'2'}, {'4'}); + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + + resultSet->MoveToLast(); + Entry entryValue; + EXPECT_EQ(resultSet->GetEntry(entryValue), OK); + std::string keyStr(entryValue.value.begin(), entryValue.value.end()); + int count1 = 4; + EXPECT_EQ(to_string(count1), keyStr); + EXPECT_EQ(count1, 4); + + int count2 = 3; + while (resultSet->MoveToPrevious()) { + Entry entryValue2; + EXPECT_EQ(resultSet->GetEntry(entryValue2), OK); + std::string keyStr2(entryValue2.value.begin(), entryValue2.value.end()); + EXPECT_EQ(to_string(count2), keyStr2); + count2--; + } + EXPECT_EQ(count2, 1); + EXPECT_EQ(resultSet->MoveToPrevious(), false); + + + /** + * @tc.steps: step2. Getentries by query, query is full-set; + * @tc.expected: step2. Getentries return OK; + */ + Query fullQuery2 = Query::Select().Range({}, {'4'}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery2, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + + resultSet->MoveToLast(); + Entry entryValue3; + EXPECT_EQ(resultSet->GetEntry(entryValue3), OK); + std::string keyStr3(entryValue3.value.begin(), entryValue3.value.end()); + int count3 = 4; + EXPECT_EQ(to_string(count3), keyStr3); + + int count4 = 3; + while (resultSet->MoveToPrevious()) { + Entry entryValue4; + EXPECT_EQ(resultSet->GetEntry(entryValue4), OK); + std::string keyStr4(entryValue4.value.begin(), entryValue4.value.end()); + EXPECT_EQ(to_string(count4), keyStr4); + count4--; + } + EXPECT_EQ(count4, -1); + EXPECT_EQ(resultSet->MoveToPrevious(), false); + + /** + * @tc.steps: step2. Getentries by query, query is full-set; + * @tc.expected: step2. Getentries return OK; + */ + Query fullQuery3 = Query::Select().Range({'2'}, {}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery3, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + + resultSet->MoveToLast(); + Entry entryValue5; + EXPECT_EQ(resultSet->GetEntry(entryValue5), OK); + std::string keyStr5(entryValue5.value.begin(), entryValue5.value.end()); + int count5 = 5; + EXPECT_EQ(to_string(count5), keyStr5); + EXPECT_EQ(count5, 5); + + int count6 = 4; + while (resultSet->MoveToPrevious()) { + Entry entryValue6; + EXPECT_EQ(resultSet->GetEntry(entryValue6), OK); + std::string keyStr6(entryValue6.value.begin(), entryValue6.value.end()); + EXPECT_EQ(to_string(count6), keyStr6); + count6--; + } + EXPECT_EQ(count2, 1); + EXPECT_EQ(resultSet->MoveToPrevious(), false); + if (resultSet != nullptr) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(resultSet), OK); + } +} + +/** + * @tc.name: RdRangeQuery005 + * @tc.desc:Test resultSet fuction, end key is bigger or equal than the biggest data in DB. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DistributedDBInterfacesNBDelegateRdTest, RdRangeQuery005, TestSize.Level0) +{ + /** + * @tc.steps:step1. Get the nb delegate. + * @tc.expected: step1. Get results OK and non-null delegate. + */ + g_mgr.GetKvStore("RdRangeQuery005", g_option, g_kvNbDelegateCallback); + ASSERT_TRUE(g_kvNbDelegatePtr != nullptr); + EXPECT_TRUE(g_kvDelegateStatus == OK); + + /** + * @tc.steps: step1. + * @tc.expected: step1. + */ + Entry entry0 = {{'0'}, {'0'}}; + Entry entry1 = {{'1'}, {'1'}}; + Entry entry2 = {{'2'}, {'2'}}; + Entry entry3 = {{'3'}, {'3'}}; + Entry entry4 = {{'4'}, {'4'}}; + Entry entry5 = {{'5'}, {'5'}}; + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry0.key, entry0.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry1.key, entry1.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry2.key, entry2.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry3.key, entry3.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry4.key, entry4.value), OK); + EXPECT_EQ(g_kvNbDelegatePtr->Put(entry5.key, entry5.value), OK); + + + /** + * @tc.steps: step2. + * @tc.expected: step2. 2, 3, 4 + */ + Query fullQuery = Query::Select().Range({'2'}, {'5'}); + KvStoreResultSet *resultSet = nullptr; + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + int count1 = 0; + while (resultSet->MoveToNext()) { + count1++; + } + EXPECT_EQ(count1, 4); + EXPECT_EQ(resultSet->MoveToNext(), false); + + /** + * @tc.steps: step3. + * @tc.expected: step3. 0, 1 ,2 ,3 ,4 + */ + Query fullQuery2 = Query::Select().Range({'2'}, {'8'}); + EXPECT_EQ(g_kvNbDelegatePtr->GetEntries(fullQuery2, resultSet), OK); + EXPECT_NE(resultSet, nullptr); + int count2 = 0; + while (resultSet->MoveToNext()) { + count2++; + } + EXPECT_EQ(count2, 4); + EXPECT_EQ(resultSet->MoveToNext(), false); + if (resultSet != nullptr) { + EXPECT_EQ(g_kvNbDelegatePtr->CloseResultSet(resultSet), OK); + } +} +#endif // DB_DEBUG_ENV +} +#endif // USE_RD_KERNEL diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp index 1eaeb19674b7586d28ef3fa45b31f1bb20c7c80e..1d0e47d02bab47692964364b6f68e29cc077872a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_sync_test.cpp @@ -552,7 +552,7 @@ HWTEST_F(DistributedDBInterfacesRelationalSyncTest, UpgradeTriggerTest001, TestS " flag=0x03 WHERE hash_key=calc_hash(OLD.'id', 0) AND flag&0x02=0x02;\n" "\t INSERT OR REPLACE INTO naturalbase_rdb_aux_student_1_log VALUES (NEW._rowid_, '', '', get_sys_time(0), " "get_last_time(), CASE WHEN (calc_hash(NEW.'id', 0) != calc_hash(NEW.'id', 0)) " \ - "THEN 0x02 ELSE 0x22 END, calc_hash(NEW.'id', 0), '');\n" + "THEN 0x02 ELSE 0x22 END, calc_hash(NEW.'id', 0), '', '', '', '');\n" "END"; EXPECT_TRUE(resultTrigger == expectTrigger); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp index 1c02095ec25b0e2238e2261c7c8c3e50359ed9fe..2db1315bf4c73ab82d34a93714d4bad701f8e23c 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_test.cpp @@ -26,6 +26,9 @@ #include "relational_store_sqlite_ext.h" #include "relational_virtual_device.h" #include "runtime_config.h" +#ifdef DB_DEBUG_ENV +#include "system_time.h" +#endif // DB_DEBUG_ENV #include "virtual_relational_ver_sync_db_interface.h" using namespace testing::ext; @@ -1884,4 +1887,105 @@ HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest003, T EXPECT_EQ(status, OK); delegate = nullptr; } + +/** + * @tc.name: CreateDistributedTableTest004 + * @tc.desc: Test create distributed table will violate the constraint when table contains "_rowid_" column + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest004, TestSize.Level0) +{ + /** + * @tc.steps:step1. Prepare db and table + */ + 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); + std::string t1 = "t1"; + std::string sql = "create table " + t1 + "(key text, _rowid_ int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + std::string t2 = "t2"; + sql = "create table " + t2 + "(rowid int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + std::string t3 = "t3"; + sql = "create table " + t3 + "(oid int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + std::string t4 = "t4"; + sql = "create table " + t4 + "(rowid int, oid int, _rowid_ text);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + std::string t5 = "t5"; + sql = "create table " + t5 + "(_RoWiD_ int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + + /** + * @tc.steps:step2. open relational store, create distributed table + */ + RelationalStoreDelegate *delegate = nullptr; + EXPECT_EQ(g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate), OK); + ASSERT_NE(delegate, nullptr); + EXPECT_EQ(delegate->CreateDistributedTable(t1), NOT_SUPPORT); + EXPECT_EQ(delegate->CreateDistributedTable(t1, DistributedDB::CLOUD_COOPERATION), NOT_SUPPORT); + EXPECT_EQ(delegate->CreateDistributedTable(t2), OK); + EXPECT_EQ(delegate->CreateDistributedTable(t3), OK); + EXPECT_EQ(delegate->CreateDistributedTable(t4), NOT_SUPPORT); + EXPECT_EQ(delegate->CreateDistributedTable(t5), NOT_SUPPORT); + + EXPECT_EQ(g_mgr.CloseStore(delegate), OK); + delegate = nullptr; +} + +/** + * @tc.name: CreateDistributedTableTest005 + * @tc.desc: Test create distributed table again will return ok when rebuild table(miss one field) + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBInterfacesRelationalTest, CreateDistributedTableTest005, TestSize.Level1) +{ + /** + * @tc.steps:step1. Prepare db and table + * @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); + std::string t1 = "t1"; + std::string sql = "create table " + t1 + "(key int, value text);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + + /** + * @tc.steps:step2. open relational store, create distributed table with default mode + * @tc.expected: step2. Return OK. + */ + RelationalStoreDelegate *delegate = nullptr; + EXPECT_EQ(g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate), OK); + ASSERT_NE(delegate, nullptr); + EXPECT_EQ(delegate->CreateDistributedTable("t1"), OK); + + /** + * @tc.steps:step3. drop t1, rebuild t1(miss one column), then reopen store, create distributed table + * @tc.expected: step3. Return OK. + */ + sql = "drop table " + t1; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + sql = "create table " + t1 + "(key int);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + EXPECT_EQ(g_mgr.CloseStore(delegate), OK); + delegate = nullptr; + EXPECT_EQ(g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, delegate), OK); + ASSERT_NE(delegate, nullptr); + EXPECT_EQ(delegate->CreateDistributedTable("t1"), OK); + + /** + * @tc.steps:step4. close store + * @tc.expected: step4. Return OK. + */ + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + EXPECT_EQ(g_mgr.CloseStore(delegate), OK); + delegate = nullptr; +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b08b923bc6c48e52e5b5fff82a1df5d50dd06fde --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_relational_tracker_table_test.cpp @@ -0,0 +1,1788 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#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" +#include "relational_store_sqlite_ext.h" +#include "relational_virtual_device.h" +#include "runtime_config.h" +#include "virtual_relational_ver_sync_db_interface.h" +#include "cloud_db_types.h" +#include "cloud_db_sync_utils_test.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_tracker"; + constexpr const char *STORE_ID2 = "Relational_Store_tracker2"; + std::string g_testDir; + std::string g_dbDir; + const string TABLE_NAME1 = "worKer1"; + const string TABLE_NAME2 = "worKer2"; + const string TABLE_NAME3 = "worKer3"; + DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); + RelationalStoreDelegate *g_delegate = nullptr; + sqlite3 *g_db = nullptr; + const int HALF = 2; + + const std::string CREATE_LOCAL_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS " + TABLE_NAME1 + "(" \ + "name TEXT PRIMARY KEY," \ + "height REAL ," \ + "married BOOLEAN ," \ + "photo BLOB NOT NULL," \ + "assert BLOB," \ + "age INT);"; + + const std::string CREATE_LOCAL_PK_TABLE_SQL = + "CREATE TABLE IF NOT EXISTS " + TABLE_NAME2 + "(" \ + "id INTEGER PRIMARY KEY AUTOINCREMENT," \ + "name TEXT ," \ + "height REAL ," \ + "photo BLOB ," \ + "asserts BLOB," \ + "age INT);"; + + const std::string CREATE_LOCAL_PK_TABLE_SQL2 = + "CREATE TABLE IF NOT EXISTS " + TABLE_NAME3 + "(" \ + "id INTEGER PRIMARY KEY," \ + "name asseT ," \ + "age ASSETs);"; + + const std::string EXTEND_COL_NAME1 = "xxx"; + const std::string EXTEND_COL_NAME2 = "name"; + const std::string EXTEND_COL_NAME3 = "age"; + const std::set LOCAL_TABLE_TRACKER_NAME_SET1 = { "name1" }; + const std::set LOCAL_TABLE_TRACKER_NAME_SET2 = { "name" }; + const std::set LOCAL_TABLE_TRACKER_NAME_SET3 = { "height" }; + const std::set LOCAL_TABLE_TRACKER_NAME_SET4 = { "height", "name" }; + const std::set LOCAL_TABLE_TRACKER_NAME_SET5 = { "name", "" }; + TrackerSchema g_normalSchema1 = { + .tableName = TABLE_NAME2, .extendColName = EXTEND_COL_NAME2, .trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2 + }; + TrackerSchema g_normalSchema2 = { + .tableName = TABLE_NAME2, .extendColName = EXTEND_COL_NAME3, .trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2 + }; + TrackerSchema g_normalSchema3 = { + .tableName = TABLE_NAME2, .extendColName = EXTEND_COL_NAME3, .trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET4 + }; + + void CreateMultiTable() + { + g_db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(g_db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, CREATE_LOCAL_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, CREATE_LOCAL_PK_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, CREATE_LOCAL_PK_TABLE_SQL2), SQLITE_OK); + } + + void BatchInsertTableName2Data(uint64_t num) + { + for (size_t i = 0; i < num; i++) { + string sql = "INSERT INTO " + TABLE_NAME2 + + " (name, height, photo, asserts, age) VALUES ('Local" + std::to_string(i) + + "', '175.8', 175.88888888888, 'x', '18');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, sql), SQLITE_OK); + } + } + + void BatchUpdateTableName2Data(uint64_t num, const std::set &colNames) + { + std::string sql = "UPDATE " + TABLE_NAME2 + " SET "; + for (const auto &col: colNames) { + sql += col + " = '1',"; + } + sql.pop_back(); + sql += " where id = "; + for (size_t i = 1; i <= num; i++) { + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, sql + std::to_string(i)), SQLITE_OK); + } + } + + void BatchDeleteTableName2Data(uint64_t num) + { + std::string sql = "DELETE FROM " + TABLE_NAME2 + " WHERE id <= " + std::to_string(num); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, sql), SQLITE_OK); + } + + void BatchOperatorTableName2Data(uint64_t num, const std::set &colNames) + { + BatchInsertTableName2Data(num); + BatchInsertTableName2Data(num); + BatchUpdateTableName2Data(num, colNames); + BatchDeleteTableName2Data(num); + } + + void CheckExtendAndCursor(uint64_t num, int start) + { + int index = 0; + string querySql = "select extend_field, cursor from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log" + + " where data_key <= " + std::to_string(num); + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(g_db, querySql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string extendVal; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 0, extendVal), E_OK); + EXPECT_EQ(extendVal, "Local" + std::to_string(index % num)); + std::string cursorVal; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, cursorVal), E_OK); + EXPECT_EQ(cursorVal, std::to_string(num + (++index) + start)); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + + void OpenStore() + { + if (g_db == nullptr) { + g_db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + ASSERT_NE(g_db, nullptr); + } + DBStatus status = g_mgr.OpenStore(g_dbDir + STORE_ID + DB_SUFFIX, STORE_ID, {}, g_delegate); + EXPECT_EQ(status, OK); + ASSERT_NE(g_delegate, nullptr); + } + + void CloseStore() + { + if (g_db != nullptr) { + EXPECT_EQ(sqlite3_close_v2(g_db), SQLITE_OK); + g_db = nullptr; + } + if (g_delegate != nullptr) { + EXPECT_EQ(g_mgr.CloseStore(g_delegate), DBStatus::OK); + g_delegate = nullptr; + } + } + + void CheckDropTableAndReopenDb(bool isDistributed) + { + /** + * @tc.steps:step1. SetTrackerTable, init data and drop table + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + if (isDistributed) { + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + } + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + std::string sql = "drop table if exists " + TABLE_NAME2; + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, sql), SQLITE_OK); + CloseStore(); + + /** + * @tc.steps:step2. reopen db, check log table + * @tc.expected: step2. Return OK. + */ + OpenStore(); + sql = "select count(*) from sqlite_master where name = '" + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + + "_log'"; + EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0), nullptr), SQLITE_OK); + + /** + * @tc.steps:step3. check tracker schema + * @tc.expected: step3. Return OK. + */ + const Key schemaKey(DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.begin(), + DBConstant::RELATIONAL_TRACKER_SCHEMA_KEY.end()); + sql = "SELECT value FROM " + DBConstant::RELATIONAL_PREFIX + "metadata WHERE key=?;"; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(g_db, sql, stmt), E_OK); + EXPECT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, schemaKey, false), E_OK); + Value schemaVal; + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + SQLiteUtils::GetColumnBlobValue(stmt, 0, schemaVal); + } + EXPECT_TRUE(schemaVal.size() != 0); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + std::string schemaStr; + DBCommon::VectorToString(schemaVal, schemaStr); + RelationalSchemaObject schemaObject; + EXPECT_EQ(schemaObject.ParseFromTrackerSchemaString(schemaStr), E_OK); + EXPECT_EQ(schemaObject.GetTrackerTable(TABLE_NAME2).IsEmpty(), true); + CloseStore(); + } + + class DistributedDBInterfacesRelationalTrackerTableTest : public testing::Test { + public: + static void SetUpTestCase(void); + + static void TearDownTestCase(void); + + void SetUp(); + + void TearDown(); + }; + + void DistributedDBInterfacesRelationalTrackerTableTest::SetUpTestCase(void) + { + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + g_dbDir = g_testDir + "/"; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + } + + void DistributedDBInterfacesRelationalTrackerTableTest::TearDownTestCase(void) + { + } + + void DistributedDBInterfacesRelationalTrackerTableTest::SetUp(void) + { + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error."); + } + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + } + + void DistributedDBInterfacesRelationalTrackerTableTest::TearDown(void) + { + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir); + } + +void SetTrackerTableTest(const TrackerSchema &schema, DBStatus expect) +{ + CreateMultiTable(); + OpenStore(); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), expect); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest001 + * @tc.desc: Test set tracker table with invalid table name + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest001, TestSize.Level0) +{ + CreateMultiTable(); + OpenStore(); + /** + * @tc.steps:step1. table name is empty + * @tc.expected: step1. Return INVALID_ARGS. + */ + TrackerSchema schema; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), INVALID_ARGS); + + /** + * @tc.steps:step2. table name is no exist + * @tc.expected: step2. Return NOT_FOUND. + */ + schema.tableName = "xx"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + + /** + * @tc.steps:step3. table name is illegal table name + * @tc.expected: step3. Return INVALID_ARGS. + */ + schema.tableName = DBConstant::SYSTEM_TABLE_PREFIX + "_1"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), INVALID_ARGS); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest002 + * @tc.desc: Test set tracker table with empty colNames + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. trackerColNames is empty + * @tc.expected: step1. Return OK. + */ + TrackerSchema schema; + schema.tableName = TABLE_NAME1; + SetTrackerTableTest(schema, OK); + + /** + * @tc.steps:step2. trackerColNames is empty but extendColName is no exist + * @tc.expected: step2. Return OK. + */ + schema.extendColName = EXTEND_COL_NAME1; + SetTrackerTableTest(schema, OK); + + /** + * @tc.steps:step1. param valid but extend name is empty + * @tc.expected: step1. Return OK. + */ + schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2; + schema.extendColName = {}; + SetTrackerTableTest(schema, OK); +} + +/** + * @tc.name: TrackerTableTest003 + * @tc.desc: Test set tracker table with invalid col name + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest003, TestSize.Level0) +{ + /** + * @tc.steps:step1. tracker col name is no exist + * @tc.expected: step1. Return SCHEMA_MISMATCH. + */ + TrackerSchema schema; + schema.tableName = TABLE_NAME1; + schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET1; + SetTrackerTableTest(schema, SCHEMA_MISMATCH); + + /** + * @tc.steps:step2. tracker col names contains empty name + * @tc.expected: step2. Return INVALID_ARGS. + */ + schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET5; + SetTrackerTableTest(schema, INVALID_ARGS); + + /** + * @tc.steps:step3. extend name is no exist + * @tc.expected: step3. Return SCHEMA_MISMATCH. + */ + schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2; + schema.extendColName = EXTEND_COL_NAME1; + SetTrackerTableTest(schema, SCHEMA_MISMATCH); +} + +/** + * @tc.name: TrackerTableTest005 + * @tc.desc: Test set tracker table in same delegate + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest005, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable twice in same delegate + * @tc.expected: step1. Return OK. + */ + TrackerSchema schema = g_normalSchema1; + CreateMultiTable(); + OpenStore(); + uint64_t num = 10; + BatchInsertTableName2Data(num); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + + /** + * @tc.steps:step2. SetTrackerTable again with different schema + * @tc.expected: step2. Return OK. + */ + schema = g_normalSchema3; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + + /** + * @tc.steps:step3. SetTrackerTable again with different table + * @tc.expected: step3. Return OK. + */ + schema.tableName = TABLE_NAME1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step4. unSetTrackerTable + * @tc.expected: step4. Return OK. + */ + schema.tableName = TABLE_NAME2; + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest006 + * @tc.desc: Test set tracker table in diff delegate + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest006, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable + * @tc.expected: step1. Return OK. + */ + TrackerSchema schema = g_normalSchema1; + CreateMultiTable(); + OpenStore(); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + uint64_t num = 10; + BatchInsertTableName2Data(num); + CloseStore(); + + /** + * @tc.steps:step2. reopen db and SetTrackerTable + * @tc.expected: step2. Return OK. + */ + OpenStore(); + schema = g_normalSchema2; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + CloseStore(); + + /** + * @tc.steps:step3. reopen db and SetTrackerTable with diff table + * @tc.expected: step3. Return OK. + */ + OpenStore(); + schema.tableName = TABLE_NAME1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + CloseStore(); + + /** + * @tc.steps:step4. reopen db and unSetTrackerTable + * @tc.expected: step4. Return OK. + */ + OpenStore(); + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest007 + * @tc.desc: Test set tracker table to upgrade inventory data + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest007, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable when the db exist data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + TrackerSchema schema = g_normalSchema3; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. SetTrackerTable again with diff tracker schema + * @tc.expected: step2. Return OK. + */ + schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step3. check extend_field and cursor + * @tc.expected: step3. Return OK. + */ + CheckExtendAndCursor(num, 0); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest008 + * @tc.desc: Test set tracker table to check extend_field and cursor + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest008, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. Update non tracker columns,then check extend_field and cursor + * @tc.expected: step2. Return OK. + */ + uint64_t updateNum = 2; + BatchUpdateTableName2Data(updateNum, LOCAL_TABLE_TRACKER_NAME_SET3); + int index = 0; + string querySql = "select extend_field, cursor from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log" + + " where data_key <= " + std::to_string(updateNum); + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(g_db, querySql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string extendVal; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 0, extendVal), E_OK); + EXPECT_EQ(extendVal, "Local" + std::to_string(index % num)); + std::string cursorVal; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, cursorVal), E_OK); + EXPECT_EQ(cursorVal, std::to_string(++index + num)); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + + /** + * @tc.steps:step3. Update tracker columns,then check extend_field and cursor + * @tc.expected: step3. Return OK. + */ + BatchUpdateTableName2Data(updateNum, LOCAL_TABLE_TRACKER_NAME_SET2); + stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(g_db, querySql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string extendVal; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 0, extendVal), E_OK); + EXPECT_EQ(extendVal, "1"); + std::string cursorVal; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 1, cursorVal), E_OK); + EXPECT_EQ(cursorVal, std::to_string(num + (++index))); + } + SQLiteUtils::ResetStatement(stmt, true, errCode); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest009 + * @tc.desc: Test set tracker table to check extend_field and cursor after delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest009, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. select extend_field and cursor after delete + * @tc.expected: step2. Return OK. + */ + BatchDeleteTableName2Data(num); + CheckExtendAndCursor(num, 0); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest010 + * @tc.desc: Test set tracker table after unSetTrackerTable + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest010, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. unSetTrackerTable + * @tc.expected: step2. Return OK. + */ + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step3. SetTrackerTable again + * @tc.expected: step3. Return OK. + */ + schema.trackerColNames = LOCAL_TABLE_TRACKER_NAME_SET2; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step4. operator data + * @tc.expected: step4. Return OK. + */ + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest011 + * @tc.desc: Test CreateDistributedTable after set tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest011, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. CreateDistributedTable on table2 and insert data + * @tc.expected: step2. Return OK. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + uint64_t num = 10; + BatchInsertTableName2Data(num); + + /** + * @tc.steps:step3. CreateDistributedTable on table2 again, but schema not change + * @tc.expected: step3. Return OK. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + CheckExtendAndCursor(num, -num); + + /** + * @tc.steps:step4. operator data on table2 + * @tc.expected: step4. Return OK. + */ + std::string sql = "ALTER TABLE " + TABLE_NAME2 + " ADD COLUMN xxx INT"; + EXPECT_EQ(SQLiteUtils::ExecuteRawSQL(g_db, sql), E_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + CheckExtendAndCursor(num, 0); + + /** + * @tc.steps:step5. unSetTrackerTable + * @tc.expected: step5. Return OK. + */ + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step6. operator data on table2 + * @tc.expected: step6. Return OK. + */ + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest012 + * @tc.desc: Test CreateDistributedTable after set tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest012, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. CreateDistributedTable on table2 without data + * @tc.expected: step2. Return OK. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step3. CreateDistributedTable on table1 + * @tc.expected: step3. Return OK. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME1, CLOUD_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step4. operator data on table2 + * @tc.expected: step4. Return OK. + */ + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + + /** + * @tc.steps:step5. unSetTrackerTable + * @tc.expected: step5. Return OK. + */ + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step6. operator data on table2 + * @tc.expected: step6. Return OK. + */ + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest013 + * @tc.desc: Test CreateDistributedTable after clean table data + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest013, TestSize.Level0) +{ + /** + * @tc.steps:step1. init data and SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. CreateDistributedTable on table2 + * @tc.expected: step2. Return NOT_SUPPORT. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::NOT_SUPPORT); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::NOT_SUPPORT); + + /** + * @tc.steps:step3. delete all data but keep the log , then CreateDistributedTable + * @tc.expected: step3. Return OK. + */ + BatchDeleteTableName2Data(num); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), OK); + BatchInsertTableName2Data(num); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest014 + * @tc.desc: Test SetTrackerTable after CreateDistributedTable + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest014, TestSize.Level0) +{ + /** + * @tc.steps:step1. CreateDistributedTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step2. SetTrackerTable on table2 + * @tc.expected: step2. Return OK. + */ + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step3. operator data and check extend_filed and cursor + * @tc.expected: step3. Return OK. + */ + uint64_t num = 10; + int begin = -10; + BatchInsertTableName2Data(num); + CheckExtendAndCursor(num, begin); + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + + /** + * @tc.steps:step4. unSetTrackerTable + * @tc.expected: step4. Return OK. + */ + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest015 + * @tc.desc: Test operator data on Distributed tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest015, TestSize.Level0) +{ + /** + * @tc.steps:step1. CreateDistributedTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step2. operator data + * @tc.expected: step2. Return OK. + */ + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + + /** + * @tc.steps:step3. SetTrackerTable on table2 + * @tc.expected: step3. Return OK. + */ + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step4. operator data + * @tc.expected: step4. Return OK. + */ + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest016 + * @tc.desc: Test operator data on tracker Distributed table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest016, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. reopen store and create distributed table + * @tc.expected: step2. Return OK. + */ + CloseStore(); + OpenStore(); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step3. operator data + * @tc.expected: step3. Return OK. + */ + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET2); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest017 + * @tc.desc: Test set tracker table with DEVICE_COOPERATION mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest017, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. Create DEVICE_COOPERATION DistributedTable + * @tc.expected: step2. Return NOT_SUPPORT. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, DEVICE_COOPERATION), DBStatus::NOT_SUPPORT); + + /** + * @tc.steps:step3. operator data on table2 + * @tc.expected: step3. Return OK. + */ + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + + /** + * @tc.steps:step4. unSetTrackerTable + * @tc.expected: step4. Return OK. + */ + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step5. There is still data in the table + * @tc.expected: step5. Return NOT_SUPPORT. + */ + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, DEVICE_COOPERATION), DBStatus::NOT_SUPPORT); + + /** + * @tc.steps:step6. clear all data and create DEVICE_COOPERATION table + * @tc.expected: step6. Return OK. + */ + BatchDeleteTableName2Data(num + num); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, DEVICE_COOPERATION), OK); + + /** + * @tc.steps:step7. operator data on table2 + * @tc.expected: step7. Return OK. + */ + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest018 + * @tc.desc: Test set tracker table with DEVICE_COOPERATION mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest018, TestSize.Level0) +{ + /** + * @tc.steps:step1. Create DEVICE_COOPERATION DistributedTable + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, DEVICE_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step2. SetTrackerTable on table2 + * @tc.expected: step2. Return NOT_SUPPORT. + */ + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_SUPPORT); + + /** + * @tc.steps:step3. operator data on table2 + * @tc.expected: step3. Return OK. + */ + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + + /** + * @tc.steps:step4. unSetTrackerTable + * @tc.expected: step4. Return NOT_SUPPORT. + */ + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_SUPPORT); + + /** + * @tc.steps:step5. operator data on table2 + * @tc.expected: step5. Return OK. + */ + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest019 + * @tc.desc: Test set tracker table with DEVICE_COOPERATION mode + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest019, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. CleanTrackerData with table name no exist + * @tc.expected: step2. Return DB_ERROR. + */ + uint64_t num = 10; + BatchInsertTableName2Data(num); + BatchDeleteTableName2Data(num / HALF); + EXPECT_EQ(g_delegate->CleanTrackerData("xx", num), DB_ERROR); + + /** + * @tc.steps:step3. CleanTrackerData with empty table name + * @tc.expected: step3. Return INVALID_ARGS. + */ + EXPECT_EQ(g_delegate->CleanTrackerData("", num), INVALID_ARGS); + + /** + * @tc.steps:step4. CleanTrackerData + * @tc.expected: step4. Return OK. + */ + EXPECT_EQ(g_delegate->CleanTrackerData(TABLE_NAME2, num + (num / HALF)), OK); + std::string sql = "select count(*) from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log" + + " where extend_field is NULL;"; + EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num / HALF), nullptr), SQLITE_OK); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest020 + * @tc.desc: Test drop and rebuild table in same delegate + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest020, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable and init data + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + + /** + * @tc.steps:step2. drop and rebuild table, then SetTrackerTable + * @tc.expected: step2. Return OK. + */ + std::string sql = "drop table if exists " + TABLE_NAME2; + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, sql), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, CREATE_LOCAL_PK_TABLE_SQL), SQLITE_OK); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step3. check the extend_field and cursor is null + * @tc.expected: step3. Return OK. + */ + sql = "select count(*) from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log where extend_field is NULL " + + " AND cursor is NULL"; + EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(0), nullptr), SQLITE_OK); + + /** + * @tc.steps:step4. set diff schema, check the extend_field and cursor is null + * @tc.expected: step4. Return OK. + */ + schema.extendColName = EXTEND_COL_NAME3; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + sql = "select count(*) from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log where extend_field is NULL " + + " AND cursor is NULL"; + EXPECT_EQ(sqlite3_exec(g_db, sql.c_str(), CloudDBSyncUtilsTest::QueryCountCallback, + reinterpret_cast(num + num), nullptr), SQLITE_OK); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest021 + * @tc.desc: Test non distributed table delete table and reopen db + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest021, TestSize.Level0) +{ + CheckDropTableAndReopenDb(false); +} + +/** + * @tc.name: TrackerTableTest022 + * @tc.desc: Test distributed table delete table and reopen db + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest022, TestSize.Level0) +{ + CheckDropTableAndReopenDb(true); +} + +/** + * @tc.name: TrackerTableTest023 + * @tc.desc: Test drop and rebuild table,then insert data and set tracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest023, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable and init data + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + uint64_t num = 10; + BatchInsertTableName2Data(num); + BatchDeleteTableName2Data(num); + + /** + * @tc.steps:step2. drop and rebuild table,then insert data and set tracker table + * @tc.expected: step2. Return OK. + */ + std::string sql = "drop table if exists " + TABLE_NAME2; + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, sql), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, CREATE_LOCAL_PK_TABLE_SQL), SQLITE_OK); + BatchInsertTableName2Data(num); + schema = g_normalSchema2; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step3. query cursor + * @tc.expected: step3. Return OK. + */ + string querySql = "select cursor from " + DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log"; + sqlite3_stmt *stmt = nullptr; + int index = 0; + EXPECT_EQ(SQLiteUtils::GetStatement(g_db, querySql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + std::string cursorVal; + EXPECT_EQ(SQLiteUtils::GetColumnTextValue(stmt, 0, cursorVal), E_OK); + EXPECT_EQ(cursorVal, std::to_string(++index)); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest024 + * @tc.desc: Test set tracker table and set extend col as the asset type + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest024, TestSize.Level0) +{ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema; + schema.tableName = TABLE_NAME3; + schema.extendColName = EXTEND_COL_NAME3; + schema.trackerColNames = { EXTEND_COL_NAME3 }; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), INVALID_ARGS); + CloseStore(); +} + +/** + * @tc.name: ExecuteSql001 + * @tc.desc: Test ExecuteSql with invalid param + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql001, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + + /** + * @tc.steps:step2. sql is empty + * @tc.expected: step2. Return INVALID_ARGS. + */ + SqlCondition condition; + std::vector records; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), INVALID_ARGS); + + /** + * @tc.steps:step3. SQL does not have placeholders but there are bind args present + * @tc.expected: step3. Return INVALID_ARGS. + */ + std::string querySql = "select * from " + TABLE_NAME2 + " where id = 1;"; + condition.sql = querySql; + condition.bindArgs = {"1"}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), INVALID_ARGS); + + /** + * @tc.steps:step4. More SQL binding parameters than SQL placeholders + * @tc.expected: step4. Return INVALID_ARGS. + */ + querySql = "select * from " + TABLE_NAME2 + " where id > ?;"; + condition.sql = querySql; + condition.bindArgs = {}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), INVALID_ARGS); + + /** + * @tc.steps:step5. More SQL placeholders than SQL binding parameters + * @tc.expected: step5. Return INVALID_ARGS. + */ + condition.bindArgs = {"1", "2"}; + condition.sql = querySql; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), INVALID_ARGS); + CloseStore(); +} + +/** + * @tc.name: ExecuteSql002 + * @tc.desc: Test ExecuteSql and check query result + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql002, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + + /** + * @tc.steps:step2. execute query sql and check result + * @tc.expected: step2. Return OK. + */ + int64_t beginId = 1; + SqlCondition condition; + std::vector records; + std::string querySql = "select * from " + TABLE_NAME2 + " where id > ?;"; + condition.sql = querySql; + condition.bindArgs = {beginId}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), static_cast(num - beginId)); + for (const VBucket &item: records) { + auto iter = item.find("id"); + ASSERT_NE(iter, item.end()); + ASSERT_TRUE(iter->second.index() == TYPE_INDEX); + EXPECT_EQ(std::get(iter->second), beginId + 1); + + iter = item.find("name"); + ASSERT_NE(iter, item.end()); + ASSERT_TRUE(iter->second.index() == TYPE_INDEX); + EXPECT_EQ(std::get(iter->second), "Local" + std::to_string(beginId)); + + iter = item.find("height"); + ASSERT_NE(iter, item.end()); + ASSERT_TRUE(iter->second.index() == TYPE_INDEX); + EXPECT_EQ(std::get(iter->second), 175.8); + + iter = item.find("photo"); + ASSERT_NE(iter, item.end()); + ASSERT_TRUE(iter->second.index() == TYPE_INDEX); + EXPECT_EQ(std::get(iter->second), 175.88888888888); + + iter = item.find("asserts"); + ASSERT_NE(iter, item.end()); + ASSERT_TRUE(iter->second.index() == TYPE_INDEX); + EXPECT_EQ(std::get(iter->second), "x"); + beginId++; + } + CloseStore(); +} + +/** + * @tc.name: ExecuteSql003 + * @tc.desc: Test ExecuteSql and check update and delete result + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql003, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + + /** + * @tc.steps:step2. update sql + * @tc.expected: step2. Return OK. + */ + int64_t beginId = 1; + SqlCondition condition; + std::vector records; + std::string updateSql = "update " + TABLE_NAME2 + " set age = 3 where id = ?;"; + condition.sql = updateSql; + condition.bindArgs = {beginId}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), 0u); + + std::string delSql = "delete from " + TABLE_NAME2 + " where id = ?;"; + condition.sql = delSql; + condition.bindArgs = {beginId + 1}; + std::vector records2; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records2), OK); + EXPECT_EQ(records2.size(), 0u); + + string insSql = "INSERT INTO " + TABLE_NAME2 + + " (name, height, photo, asserts, age) VALUES ('Local" + std::to_string(num + 1) + + "', '175.8', '0', 'x', ?);"; + condition.sql = insSql; + condition.bindArgs = {beginId}; + std::vector records3; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records3), OK); + EXPECT_EQ(records3.size(), 0u); + CloseStore(); +} + +/** + * @tc.name: ExecuteSql004 + * @tc.desc: Test ExecuteSql after SetTrackerTable + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql004, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. batch insert + * @tc.expected: step2. Return OK. + */ + uint64_t num = 10; + BatchInsertTableName2Data(num); + + /** + * @tc.steps:step3. execute query sql and check result + * @tc.expected: step3. Return OK. + */ + int64_t begin = 0; + SqlCondition condition; + std::vector records; + std::string querySql = "select " + TABLE_NAME2 + ".* from " + TABLE_NAME2 + " join "; + querySql += DBConstant::RELATIONAL_PREFIX + TABLE_NAME2 + "_log" + " as a on " + TABLE_NAME2 + "._rowid_ = "; + querySql += "a.data_key where a.cursor > ?;"; + condition.sql = querySql; + condition.bindArgs = {begin}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), num); + + /** + * @tc.steps:step4. update + * @tc.expected: step4. Return OK. + */ + std::string updateSql = "update " + TABLE_NAME2 + " set name = '3' where _rowid_ <= 5;"; + condition.sql = updateSql; + condition.bindArgs = {}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + + /** + * @tc.steps:step5. query after updating + * @tc.expected: step5. Return OK. + */ + records.clear(); + begin = 10; + condition.sql = querySql; + condition.bindArgs = {begin}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), 5u); // 5 is the num of update + CloseStore(); +} + +/** + * @tc.name: ExecuteSql005 + * @tc.desc: Test ExecuteSql interface only takes effect on the first SQL + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql005, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + + /** + * @tc.steps:step2. execute query sql but the table is no exist + * @tc.expected: step2. Return DB_ERROR. + */ + int64_t beginId = 1; + SqlCondition condition; + std::vector records; + std::string querySql = "select * from " + TABLE_NAME2 + " where id > 1;"; + querySql += "select _rowid_ from " + TABLE_NAME2 + " where id = 1;"; + condition.sql = querySql; + condition.bindArgs = {}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), static_cast(num - beginId)); + + /** + * @tc.steps:step3. execute multi query sql and the num of bindArgs is greater than the first sql + * @tc.expected: step3. Return INVALID_ARGS. + */ + records = {}; + std::string querySql2 = "select * from " + TABLE_NAME2 + " where id > ?;"; + querySql2 += "select _rowid_ from " + TABLE_NAME2 + " where id = ?;"; + condition.sql = querySql2; + condition.bindArgs = {beginId, beginId}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), INVALID_ARGS); + EXPECT_EQ(records.size(), 0u); + + /** + * @tc.steps:step4. execute multi query sql and the num of bindArgs is equal to the first sql + * @tc.expected: step4. Return OK. + */ + records = {}; + condition.bindArgs = {beginId}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), static_cast(num - beginId)); + CloseStore(); +} + +/** + * @tc.name: ExecuteSql006 + * @tc.desc: Test ExecuteSql interface only takes effect on the first SQL + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql006, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + + /** + * @tc.steps:step2. execute multi update sql + * @tc.expected: step2. Return OK. + */ + SqlCondition condition; + std::vector records; + std::string updateSql = "update " + TABLE_NAME2 + " SET age = 100; "; + updateSql += "update " + TABLE_NAME2 + " SET age = 50;"; + condition.sql = updateSql; + condition.bindArgs = {}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + + /** + * @tc.steps:step3. execute query sql where age is 100 + * @tc.expected: step3. Return OK. + */ + records = {}; + std::string querySql = "select * from " + TABLE_NAME2 + " where age = 100;"; + condition.sql = querySql; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), num); + + /** + * @tc.steps:step4. execute update sql and query sql + * @tc.expected: step4. Return OK. + */ + updateSql = "update " + TABLE_NAME2 + " SET age = 88; "; + updateSql += "select * from " + TABLE_NAME2; + condition.sql = updateSql; + condition.bindArgs = {}; + records = {}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), 0u); + + /** + * @tc.steps:step5. execute multi delete sql + * @tc.expected: step5. Return OK. + */ + records = {}; + std::string delSql = "DELETE FROM " + TABLE_NAME2 + " WHERE age = 100; "; + delSql += "DELETE FROM " + TABLE_NAME2 + " WHERE age = 88;"; + condition.sql = delSql; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + + /** + * @tc.steps:step6. execute query sql where age is 100 + * @tc.expected: step6. Return OK. + */ + records = {}; + condition.sql = "select * from " + TABLE_NAME2 + " where age = 88;"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), num); + CloseStore(); +} + +/** + * @tc.name: ExecuteSql006 + * @tc.desc: Test ExecuteSql interface only takes effect on the first SQL + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql007, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + BatchInsertTableName2Data(num); + OpenStore(); + + /** + * @tc.steps:step2. ExecuteSql with transaction + * @tc.expected: step2. Return OK. + */ + SqlCondition condition; + std::vector records; + condition.sql = "BEGIN"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "COMMIT;"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "BEGIN"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "ROLLBACK;"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "BEGIN TRANSACTION;"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "END TRANSACTION;"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "BEGIN IMMEDIATE TRANSACTION;"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "COMMIT;"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + + /** + * @tc.steps:step3. ExecuteSql with attach and detach + * @tc.expected: step3. Return OK. + */ + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID2 + DB_SUFFIX); + EXPECT_NE(db, nullptr); + condition.sql = "ATTACH DATABASE '" + g_dbDir + STORE_ID2 + DB_SUFFIX + "' AS TEST"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "DETACH DATABASE TEST"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); + db = nullptr; + CloseStore(); +} + +/** + * @tc.name: ExecuteSql008 + * @tc.desc: Test the ExecSql interface for bool type results + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql008, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + uint64_t num = 10; + for (size_t i = 0; i < num; i++) { + string sql = "INSERT OR REPLACE INTO " + TABLE_NAME1 + + " (name, height, married, photo, assert, age) VALUES ('Tom" + std::to_string(i) + + "', '175.8', '0', '', '' , '18');"; + EXPECT_EQ(RelationalTestUtils::ExecSql(g_db, sql), SQLITE_OK); + } + + /** + * @tc.steps:step2. check if the result is of bool type + * @tc.expected: step2. Return OK. + */ + SqlCondition condition; + condition.sql = "select * from " + TABLE_NAME1; + std::vector records; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), num); + EXPECT_NE(records[0].find("married"), records[0].end()); + if (records[0].find("married") != records[0].end()) { + Type married = records[0].find("married")->second; + EXPECT_TRUE(married.index() == TYPE_INDEX); + } + CloseStore(); +} + +/** + * @tc.name: ExecuteSql010 + * @tc.desc: Test ExecuteSql with temp table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, ExecuteSql010, TestSize.Level0) +{ + /** + * @tc.steps:step1. init db data + * @tc.expected: step1. Return OK. + */ + uint64_t num = 10; + CreateMultiTable(); + OpenStore(); + SqlCondition condition; + Bytes photo = { 1, 2, 3, 4 }; + std::vector records; + for (size_t i = 0; i < num; i++) { + condition.sql = "INSERT INTO " + TABLE_NAME2 + + " (name, height, photo, asserts, age) VALUES ('Local" + std::to_string(i) + + "', '175.8', ?, 'x', '18');"; + condition.bindArgs = {photo}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + } + + /** + * @tc.steps:step2. ExecuteSql with transaction + * @tc.expected: step2. Return OK. + */ + condition.sql = "create temp table AA as select * from " + TABLE_NAME2; + condition.bindArgs = {}; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + condition.sql = "select * from AA"; + EXPECT_EQ(g_delegate->ExecuteSql(condition, records), OK); + EXPECT_EQ(records.size(), num); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest026 + * @tc.desc: Test tracker table with case sensitive table name + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest026, TestSize.Level0) +{ + /** + * @tc.steps:step1. SetTrackerTable on table2 + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + + /** + * @tc.steps:step2. SetTrackerTable on table2 with case different + * @tc.expected: step2. Return NOT_FOUND. + */ + schema.tableName = "worker2"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + schema.tableName = "workeR2"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + schema.trackerColNames = {}; + schema.tableName = "WorkeR2"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + + schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + CloseStore(); +} + +/** + * @tc.name: TrackerTableTest027 + * @tc.desc: Test tracker table with case sensitive distributed table name + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBInterfacesRelationalTrackerTableTest, TrackerTableTest027, TestSize.Level0) +{ + /** + * @tc.steps:step1. create distributed table on table2 with case different + * @tc.expected: step1. Return OK. + */ + CreateMultiTable(); + OpenStore(); + EXPECT_EQ(g_delegate->CreateDistributedTable(TABLE_NAME2, CLOUD_COOPERATION), DBStatus::OK); + TrackerSchema schema = g_normalSchema1; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + EXPECT_EQ(g_delegate->CreateDistributedTable("worker2", CLOUD_COOPERATION), DBStatus::OK); + + /** + * @tc.steps:step2. SetTrackerTable on table2 with case different + * @tc.expected: step2. Return NOT_FOUND. + */ + schema.tableName = "Worker2"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + uint64_t num = 10; + BatchOperatorTableName2Data(num, LOCAL_TABLE_TRACKER_NAME_SET3); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + schema.tableName = "WOrker2"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + schema.tableName = "Worker2"; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + + /** + * @tc.steps:step3. SetTrackerTable with "worKer2" + * @tc.expected: step3. Return NOT_FOUND. + */ + schema.tableName = g_normalSchema1.tableName; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), NOT_FOUND); + + /** + * @tc.steps:step4. SetTrackerTable with "worKer2" after reopening db + * @tc.expected: step4. Return OK. + */ + CloseStore(); + OpenStore(); + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + schema.trackerColNames = {}; + EXPECT_EQ(g_delegate->SetTrackerTable(schema), OK); + CloseStore(); +} +} \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp index a4bd33648244fcbcb7590d42ff8342dd0a0ae609..0813b176293752b7a1556a4cffe963c93d9ba9ba 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/distributeddb_interfaces_single_version_result_set_test.cpp @@ -104,7 +104,7 @@ void DistributedDBInterfacesSingleVersionResultSetTest::SetUp(void) property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); g_store = new (std::nothrow) SQLiteSingleVerNaturalStore; ASSERT_NE(g_store, nullptr); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp index 92b14a3333605c64f8d2c065e6941275ae561553..1c14b65c9da93bf87cb807f9bc3fc63d3584e46e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/interfaces/runtime_context_process_system_api_adapter_impl_test.cpp @@ -86,7 +86,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSecurityOption001, Te * @tc.expected: step1. function return E_NOT_SUPPORT */ RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(nullptr); - int errCode = RuntimeContext::GetInstance()->SetSecurityOption(DATA_FILE_PATH, g_option); + int errCode = RuntimeContext::GetInstance()->SetSecurityOption(g_testDir, g_option); EXPECT_TRUE(errCode == -E_NOT_SUPPORT); /** @@ -95,7 +95,7 @@ HWTEST_F(RuntimeContextProcessSystemApiAdapterImplTest, SetSecurityOption001, Te */ EXPECT_TRUE(g_adapter != nullptr); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); - errCode = RuntimeContext::GetInstance()->SetSecurityOption(DATA_FILE_PATH, g_option); + errCode = RuntimeContext::GetInstance()->SetSecurityOption(g_testDir, g_option); EXPECT_EQ(errCode, E_OK); } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8d6459072102c79f26a68cccb29e297d4a0de310 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_assets_operation_sync_test.cpp @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef RELATIONAL_STORE +#include +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_db_types.h" +#include "distributeddb_data_generate_unit_test.h" +#include "log_print.h" +#include "relational_store_delegate.h" +#include "relational_store_manager.h" +#include "runtime_config.h" +#include "time_helper.h" +#include "virtual_asset_loader.h" +#include "virtual_cloud_data_translate.h" +#include "virtual_cloud_db.h" +#include "sqlite_relational_utils.h" +#include "cloud/cloud_storage_utils.h" + +namespace { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +const char *g_createSQL = + "CREATE TABLE IF NOT EXISTS DistributedDBCloudAssetsOperationSyncTest(" \ + "id TEXT PRIMARY KEY," \ + "name TEXT," \ + "height REAL ," \ + "photo BLOB," \ + "asset ASSET," \ + "assets ASSETS," \ + "age INT);"; +const int64_t g_syncWaitTime = 60; +const Asset g_localAsset = { + .version = 2, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/cloud/sync", + .modifyTime = "123456", .createTime = "0", .size = "1024", .hash = "DEC" +}; + +void CreateUserDBAndTable(sqlite3 *&db) +{ + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, g_createSQL), SQLITE_OK); +} + +void BlockSync(const Query &query, RelationalStoreDelegate *delegate) +{ + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + auto callback = [&cv, &dataMutex, &finish](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard autoLock(dataMutex); + finish = true; + } + cv.notify_one(); + } + } + }; + LOGW("begin call sync"); + ASSERT_EQ(delegate->Sync({ "CLOUD" }, SYNC_MODE_CLOUD_MERGE, query, callback, g_syncWaitTime), OK); + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { + return finish; + }); + LOGW("end call sync"); +} + +class DistributedDBCloudAssetsOperationSyncTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +protected: + void InitTestDir(); + DataBaseSchema GetSchema(); + void CloseDb(); + void InsertUserTableRecord(const std::string &tableName, int64_t begin, int64_t count, int64_t photoSize, + bool assetIsNull); + void CheckAssetsCount(const std::vector &expectCount); + void UpdateCloudTableRecord(int64_t begin, int64_t count, bool assetIsNull); + std::string testDir_; + std::string storePath_; + sqlite3 *db_ = nullptr; + RelationalStoreDelegate *delegate_ = nullptr; + std::shared_ptr virtualCloudDb_ = nullptr; + std::shared_ptr virtualAssetLoader_ = nullptr; + std::shared_ptr virtualTranslator_ = nullptr; + std::shared_ptr mgr_ = nullptr; + std::string tableName_ = "DistributedDBCloudAssetsOperationSyncTest"; +}; + +void DistributedDBCloudAssetsOperationSyncTest::SetUpTestCase() +{ + RuntimeConfig::SetCloudTranslate(std::make_shared()); +} + +void DistributedDBCloudAssetsOperationSyncTest::TearDownTestCase() +{} + +void DistributedDBCloudAssetsOperationSyncTest::SetUp() +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + InitTestDir(); + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != 0) { + LOGE("rm test db files error."); + } + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + LOGD("Test dir is %s", testDir_.c_str()); + db_ = RelationalTestUtils::CreateDataBase(storePath_); + ASSERT_NE(db_, nullptr); + CreateUserDBAndTable(db_); + mgr_ = std::make_shared(APP_ID, USER_ID); + RelationalStoreDelegate::Option option; + ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); + ASSERT_NE(delegate_, nullptr); + ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK); + virtualCloudDb_ = std::make_shared(); + virtualAssetLoader_ = std::make_shared(); + ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); + ASSERT_EQ(delegate_->SetIAssetLoader(virtualAssetLoader_), DBStatus::OK); + virtualTranslator_ = std::make_shared(); + DataBaseSchema dataBaseSchema = GetSchema(); + ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); +} + +void DistributedDBCloudAssetsOperationSyncTest::TearDown() +{ + CloseDb(); + EXPECT_EQ(sqlite3_close_v2(db_), SQLITE_OK); + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) { + LOGE("rm test db files error."); + } +} + +void DistributedDBCloudAssetsOperationSyncTest::InitTestDir() +{ + if (!testDir_.empty()) { + return; + } + DistributedDBToolsUnitTest::TestDirInit(testDir_); + storePath_ = testDir_ + "/" + STORE_ID_1 + ".db"; + LOGI("The test db is:%s", testDir_.c_str()); +} + +DataBaseSchema DistributedDBCloudAssetsOperationSyncTest::GetSchema() +{ + DataBaseSchema schema; + TableSchema tableSchema; + tableSchema.name = tableName_; + tableSchema.fields = { + {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, {"height", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"asset", TYPE_INDEX}, {"assets", TYPE_INDEX}, + {"age", TYPE_INDEX} + }; + schema.tables.push_back(tableSchema); + return schema; +} + +void DistributedDBCloudAssetsOperationSyncTest::CloseDb() +{ + virtualCloudDb_->ForkUpload(nullptr); + virtualCloudDb_ = nullptr; + EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK); + delegate_ = nullptr; + mgr_ = nullptr; +} + +void DistributedDBCloudAssetsOperationSyncTest::InsertUserTableRecord(const std::string &tableName, int64_t begin, + int64_t count, int64_t photoSize, bool assetIsNull) +{ + std::string photo(photoSize, 'v'); + int errCode; + std::vector assetBlob; + std::vector assetsBlob; + for (int64_t i = begin; i < begin + count; ++i) { + std::string name = g_localAsset.name + std::to_string(i); + Asset asset = g_localAsset; + asset.name = name; + RuntimeContext::GetInstance()->AssetToBlob(asset, assetBlob); + std::vector assets; + asset.name = name + "_1"; + assets.push_back(asset); + asset.name = name + "_2"; + assets.push_back(asset); + string sql = "INSERT OR REPLACE INTO " + tableName + + " (id, name, height, photo, asset, assets, age) VALUES ('" + std::to_string(i) + + "', 'local', '178.0', '" + photo + "', ?, ?, '18');"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + RuntimeContext::GetInstance()->AssetsToBlob(assets, assetsBlob); + if (assetIsNull) { + ASSERT_EQ(sqlite3_bind_null(stmt, 1), SQLITE_OK); // 1 is bind asset + ASSERT_EQ(sqlite3_bind_null(stmt, 2), SQLITE_OK); // 2 is bind assets + } else { + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); // 1 is bind asset + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 2, assetsBlob, false), E_OK); // 2 is bind assets + } + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(stmt, true, errCode); + } +} + +void DistributedDBCloudAssetsOperationSyncTest::UpdateCloudTableRecord(int64_t begin, int64_t count, bool assetIsNull) +{ + std::vector record; + std::vector extend; + Timestamp now = TimeHelper::GetSysCurrentTime(); + for (int64_t i = begin; i < (begin + count); ++i) { + VBucket data; + data.insert_or_assign("id", std::to_string(i)); + data.insert_or_assign("name", "Cloud" + std::to_string(i)); + Assets assets; + for (int j = 1; j <= 2; ++j) { // add 2 asset in assets col + Asset asset; + asset.name = "Phone_" + std::to_string(j); + asset.assetId = std::to_string(j); + asset.status = AssetStatus::UPDATE; + } + record.push_back(data); + VBucket log; + log.insert_or_assign(CloudDbConstant::CREATE_FIELD, static_cast( + now / CloudDbConstant::TEN_THOUSAND)); + log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, static_cast( + now / CloudDbConstant::TEN_THOUSAND)); + log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); + log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i)); + extend.push_back(log); + } + + ASSERT_EQ(virtualCloudDb_->BatchUpdate(tableName_, std::move(record), extend), DBStatus::OK); +} + +void DistributedDBCloudAssetsOperationSyncTest::CheckAssetsCount(const std::vector &expectCount) +{ + std::vector allData; + auto dbSchema = GetSchema(); + ASSERT_GT(dbSchema.tables.size(), 0u); + ASSERT_EQ(RelationalTestUtils::SelectData(db_, dbSchema.tables[0], allData), E_OK); + int index = 0; + ASSERT_EQ(allData.size(), expectCount.size()); + for (const auto &data : allData) { + auto colIter = data.find("assets"); + EXPECT_NE(colIter, data.end()); + if (colIter == data.end()) { + index++; + continue; + } + Type colValue = data.at("assets"); + auto translate = std::dynamic_pointer_cast(virtualTranslator_); + auto assets = RelationalTestUtils::GetAssets(colValue, translate); + LOGI("[DistributedDBCloudAssetsOperationSyncTest] Check data index %d", index); + EXPECT_EQ(assets.size(), expectCount[index]); + index++; + } +} + +/** + * @tc.name: SyncWithAssetOperation001 + * @tc.desc: Delete Assets When Download + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation001, TestSize.Level0) +{ + const int actualCount = 10; + const int photoSize = 10; + const int deleteDataCount = 5; + const int deleteAssetsCount = 4; + InsertUserTableRecord(tableName_, 0, photoSize, actualCount, false); + std::string tableName = tableName_; + virtualCloudDb_->ForkUpload([this, deleteDataCount, deleteAssetsCount](const std::string &, VBucket &) { + for (int64_t i = 0; i < deleteDataCount; i++) { + std::string sql = "DELETE FROM " + tableName_ + " WHERE id = " + std::to_string(i) + ";"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, sql), SQLITE_OK); + } + for (int64_t i = deleteDataCount; i < deleteDataCount + deleteAssetsCount; i++) { + std::string sql = "UPDATE " + tableName_ + " SET asset = NULL, assets = NULL WHERE id = " + + std::to_string(i) + ";"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, sql), SQLITE_OK); + } + }); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + virtualCloudDb_->ForkUpload(nullptr); + std::vector expectCount(actualCount - deleteDataCount, 0); + expectCount[expectCount.size() - 1] = 2; // default one row has 2 assets + CheckAssetsCount(expectCount); +} + +/** + * @tc.name: SyncWithAssetOperation002 + * @tc.desc: Download Assets When local assets was removed + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation002, TestSize.Level0) +{ + const int actualCount = 1; + InsertUserTableRecord(tableName_, 0, actualCount, 10, false); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + int downLoadCount = 0; + virtualAssetLoader_->ForkDownload([this, &downLoadCount](std::map &assets) { + downLoadCount++; + if (downLoadCount == 1) { + std::string sql = "UPDATE " + tableName_ + " SET assets = NULL WHERE id = 0;"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, sql), SQLITE_OK); + } + }); + int removeCount = 0; + virtualAssetLoader_->ForkRemoveLocalAssets([&removeCount](const std::vector &assets) { + EXPECT_EQ(assets.size(), 2u); + removeCount++; + }); + UpdateCloudTableRecord(0, actualCount, false); + BlockSync(query, delegate_); + EXPECT_EQ(downLoadCount, 3); // local asset was removed should download 3 times + EXPECT_EQ(removeCount, 1); + virtualAssetLoader_->ForkDownload(nullptr); + virtualAssetLoader_->ForkRemoveLocalAssets(nullptr); + + std::vector expectCount = { 0 }; + CheckAssetsCount(expectCount); +} + +/** + * @tc.name: SyncWithAssetOperation003 + * @tc.desc: Delete Assets When Download + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudAssetsOperationSyncTest, SyncWithAssetOperation003, TestSize.Level0) +{ + InsertUserTableRecord(tableName_, 0, 1, 10, false); // 1 is size, 10 is count + int uploadCount = 0; + virtualCloudDb_->ForkUpload([this, &uploadCount](const std::string &, VBucket &) { + if (uploadCount > 0) { + return; + } + SqlCondition condition; + condition.sql = "UPDATE " + tableName_ + " SET age = '666' WHERE id = 0;"; + std::vector records; + EXPECT_EQ(delegate_->ExecuteSql(condition, records), OK); + uploadCount++; + }); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + virtualCloudDb_->ForkUpload(nullptr); + + std::string sql = "SELECT assets from " + tableName_ + " where id = 0;"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_BLOB); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + std::vector assetsBlob; + Assets assets; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, assetsBlob), E_OK); + ASSERT_EQ(RuntimeContext::GetInstance()->BlobToAssets(assetsBlob, assets), E_OK); + ASSERT_EQ(assets.size(), 2u); // 2 is asset num + for (size_t i = 0; i < assets.size(); ++i) { + EXPECT_EQ(assets[i].status, AssetStatus::NORMAL); + } + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} +} +#endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp index c870fb959d1d6fc8dd6a02eac2f64ceeaa38dacc..4ed7ed3d35cc2305f39ec5ed29993c9cb948c3d3 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_check_sync_test.cpp @@ -14,8 +14,9 @@ */ #ifdef RELATIONAL_STORE #include -#include "cloud_db_constant.h" -#include "cloud_db_types.h" +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_db_types.h" +#include "db_common.h" #include "distributeddb_data_generate_unit_test.h" #include "log_print.h" #include "relational_store_delegate.h" @@ -36,6 +37,13 @@ const char *g_createSQL = "height REAL ," \ "photo BLOB," \ "age INT);"; +const char *g_createNonPrimaryKeySQL = + "CREATE TABLE IF NOT EXISTS NonPrimaryKeyTable(" \ + "id TEXT," \ + "name TEXT," \ + "height REAL ," \ + "photo BLOB," \ + "age INT);"; const int64_t g_syncWaitTime = 60; const Asset g_cloudAsset = { @@ -47,6 +55,16 @@ void CreateUserDBAndTable(sqlite3 *&db) { EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); EXPECT_EQ(RelationalTestUtils::ExecSql(db, g_createSQL), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, g_createNonPrimaryKeySQL), SQLITE_OK); +} + +void PrepareOption(CloudSyncOption &option, const Query &query, bool isPriorityTask) +{ + option.devices = { "CLOUD" }; + option.mode = SYNC_MODE_CLOUD_MERGE; + option.query = query; + option.waitTime = g_syncWaitTime; + option.priorityTask = isPriorityTask; } void BlockSync(const Query &query, RelationalStoreDelegate *delegate) @@ -72,6 +90,50 @@ void BlockSync(const Query &query, RelationalStoreDelegate *delegate) }); } +void BlockPrioritySync(const Query &query, RelationalStoreDelegate *delegate, bool isPriority, DBStatus expectResult) +{ + std::mutex dataMutex; + std::condition_variable cv; + bool finish = false; + auto callback = [&cv, &dataMutex, &finish](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard autoLock(dataMutex); + finish = true; + } + cv.notify_one(); + } + } + }; + CloudSyncOption option; + PrepareOption(option, query, isPriority); + ASSERT_EQ(delegate->Sync(option, callback), expectResult); + if (expectResult == OK) { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { + return finish; + }); + } +} + +int QueryCountCallback(void *data, int count, char **colValue, char **colName) +{ + if (count != 1) { + return 0; + } + auto expectCount = reinterpret_cast(data); + EXPECT_EQ(strtol(colValue[0], nullptr, 10), expectCount); // 10: decimal + return 0; +} + +void CheckUserTableResult(sqlite3 *&db, const std::string &tableName, int64_t expectCount) +{ + string query = "select count(*) from " + tableName + ";"; + EXPECT_EQ(sqlite3_exec(db, query.c_str(), QueryCountCallback, + reinterpret_cast(expectCount), nullptr), SQLITE_OK); +} + class DistributedDBCloudCheckSyncTest : public testing::Test { public: static void SetUpTestCase(); @@ -82,10 +144,19 @@ protected: void InitTestDir(); DataBaseSchema GetSchema(); void CloseDb(); - void InsertUserTableRecord(int64_t recordCounts, int64_t begin = 0); + void InsertUserTableRecord(const std::string &tableName, int64_t recordCounts, int64_t begin = 0); void InsertCloudTableRecord(int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull); void DeleteUserTableRecord(int64_t id); void DeleteCloudTableRecord(int64_t gid); + void CheckCloudTableCount(const std::string &tableName, int64_t expectCount); + void PriorityAndNormalSync(const Query &normalQuery, const Query &priorityQuery, + RelationalStoreDelegate *delegate); + void DeleteCloudDBData(int64_t begin, int64_t count); + void SetForkQueryForCloudPrioritySyncTest007(std::atomic &count); + void SetForkQueryForCloudPrioritySyncTest008(std::atomic &count); + void InitLogicDeleteDataEnv(int64_t dataCount); + void CheckLocalCount(int64_t expectCount); + void CheckLogCleaned(int64_t expectCount); std::string testDir_; std::string storePath_; sqlite3 *db_ = nullptr; @@ -94,6 +165,7 @@ protected: std::shared_ptr virtualAssetLoader_ = nullptr; std::shared_ptr mgr_ = nullptr; std::string tableName_ = "DistributedDBCloudCheckSyncTest"; + std::string tableWithoutPrimaryName_ = "NonPrimaryKeyTable"; }; void DistributedDBCloudCheckSyncTest::SetUpTestCase() @@ -121,6 +193,7 @@ void DistributedDBCloudCheckSyncTest::SetUp() ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); ASSERT_NE(delegate_, nullptr); ASSERT_EQ(delegate_->CreateDistributedTable(tableName_, CLOUD_COOPERATION), DBStatus::OK); + ASSERT_EQ(delegate_->CreateDistributedTable(tableWithoutPrimaryName_, CLOUD_COOPERATION), DBStatus::OK); virtualCloudDb_ = std::make_shared(); virtualAssetLoader_ = std::make_shared(); ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); @@ -131,9 +204,10 @@ void DistributedDBCloudCheckSyncTest::SetUp() void DistributedDBCloudCheckSyncTest::TearDown() { + virtualCloudDb_->ForkQuery(nullptr); CloseDb(); EXPECT_EQ(sqlite3_close_v2(db_), SQLITE_OK); - if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != 0) { + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) { LOGE("rm test db files error."); } } @@ -157,7 +231,14 @@ DataBaseSchema DistributedDBCloudCheckSyncTest::GetSchema() {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, {"height", TYPE_INDEX}, {"photo", TYPE_INDEX}, {"age", TYPE_INDEX} }; + TableSchema tableWithoutPrimaryKeySchema; + tableWithoutPrimaryKeySchema.name = tableWithoutPrimaryName_; + tableWithoutPrimaryKeySchema.fields = { + {"id", TYPE_INDEX}, {"name", TYPE_INDEX}, {"height", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"age", TYPE_INDEX} + }; schema.tables.push_back(tableSchema); + schema.tables.push_back(tableWithoutPrimaryKeySchema); return schema; } @@ -169,11 +250,12 @@ void DistributedDBCloudCheckSyncTest::CloseDb() mgr_ = nullptr; } -void DistributedDBCloudCheckSyncTest::InsertUserTableRecord(int64_t recordCounts, int64_t begin) +void DistributedDBCloudCheckSyncTest::InsertUserTableRecord(const std::string &tableName, + int64_t recordCounts, int64_t begin) { ASSERT_NE(db_, nullptr); for (int64_t i = begin; i < recordCounts; ++i) { - string sql = "INSERT OR REPLACE INTO " + tableName_ + string sql = "INSERT OR REPLACE INTO " + tableName + " (id, name, height, photo, age) VALUES ('" + std::to_string(i) + "', 'Local" + std::to_string(i) + "', '155.10', 'text', '21');"; ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK); @@ -239,6 +321,152 @@ void DistributedDBCloudCheckSyncTest::DeleteCloudTableRecord(int64_t gid) ASSERT_EQ(virtualCloudDb_->DeleteByGid(tableName_, idMap), DBStatus::OK); } +void DistributedDBCloudCheckSyncTest::CheckCloudTableCount(const std::string &tableName, int64_t expectCount) +{ + VBucket extend; + extend[CloudDbConstant::CURSOR_FIELD] = std::to_string(0); + int64_t realCount = 0; + std::vector data; + virtualCloudDb_->Query(tableName, extend, data); + for (size_t j = 0; j < data.size(); ++j) { + auto entry = data[j].find(CloudDbConstant::DELETE_FIELD); + if (entry != data[j].end() && std::get(entry->second)) { + continue; + } + realCount++; + } + EXPECT_EQ(realCount, expectCount); // ExpectCount represents the total amount of cloud data. +} + +void DistributedDBCloudCheckSyncTest::PriorityAndNormalSync(const Query &normalQuery, const Query &priorityQuery, + RelationalStoreDelegate *delegate) +{ + std::mutex dataMutex; + std::condition_variable cv; + bool normalFinish = false; + bool priorityFinish = false; + auto normalCallback = [&cv, &dataMutex, &normalFinish, &priorityFinish]( + const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard autoLock(dataMutex); + normalFinish = true; + } + ASSERT_EQ(priorityFinish, true); + cv.notify_one(); + } + } + }; + auto priorityCallback = [&priorityFinish](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + priorityFinish = true; + } + } + }; + CloudSyncOption option; + PrepareOption(option, normalQuery, false); + virtualCloudDb_->SetBlockTime(500); // 500 ms + ASSERT_EQ(delegate->Sync(option, normalCallback), OK); + PrepareOption(option, priorityQuery, true); + ASSERT_EQ(delegate->Sync(option, priorityCallback), OK); + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&normalFinish]() { + return normalFinish; + }); +} + +void DistributedDBCloudCheckSyncTest::DeleteCloudDBData(int64_t begin, int64_t count) +{ + for (int64_t i = begin; i < begin + count; i++) { + VBucket idMap; + idMap.insert_or_assign("#_gid", std::to_string(i)); + ASSERT_EQ(virtualCloudDb_->DeleteByGid(tableName_, idMap), DBStatus::OK); + } +} + +void DistributedDBCloudCheckSyncTest::SetForkQueryForCloudPrioritySyncTest007(std::atomic &count) +{ + virtualCloudDb_->ForkQuery([this, &count](const std::string &, VBucket &) { + count++; + if (count == 1) { // taskid1 + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if (count == 2) { // 2 means taskid3 because CheckCloudTableCount will query then count++ + CheckCloudTableCount(tableName_, 1); // 1 is count of cloud records after last sync + } + if (count == 4) { // 4 means taskid2 because CheckCloudTableCount will query then count++ + CheckCloudTableCount(tableName_, 2); // 2 is count of cloud records after last sync + } + if (count == 6) { // 6 means taskid4 because CheckCloudTableCount will query then count++ + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records after last sync + } + }); +} + +void DistributedDBCloudCheckSyncTest::SetForkQueryForCloudPrioritySyncTest008(std::atomic &count) +{ + virtualCloudDb_->ForkQuery([this, &count](const std::string &, VBucket &) { + count++; + if (count == 1) { // taskid1 + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if (count == 2) { // 2 means taskid3 because CheckCloudTableCount will query then count++ + CheckCloudTableCount(tableName_, 1); // 1 is count of cloud records after last sync + } + if (count == 4) { // 4 means taskid2 because CheckCloudTableCount will query then count++ + CheckCloudTableCount(tableName_, 1); // 1 is count of cloud records after last sync + } + if (count == 6) { // 6 means taskid4 because CheckCloudTableCount will query then count++ + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records after last sync + } + }); +} + +void DistributedDBCloudCheckSyncTest::InitLogicDeleteDataEnv(int64_t dataCount) +{ + // prepare data + InsertUserTableRecord(tableName_, dataCount); + // sync + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + // delete cloud data + for (int i = 0; i < dataCount; ++i) { + DeleteCloudTableRecord(i); + } + // sync again + BlockSync(query, delegate_); +} + +void DistributedDBCloudCheckSyncTest::CheckLocalCount(int64_t expectCount) +{ + // check local data + int dataCnt = -1; + std::string checkLogSql = "SELECT count(*) FROM " + tableName_; + RelationalTestUtils::ExecSql(db_, checkLogSql, nullptr, [&dataCnt](sqlite3_stmt *stmt) { + dataCnt = sqlite3_column_int(stmt, 0); + return E_OK; + }); + EXPECT_EQ(dataCnt, expectCount); +} + +void DistributedDBCloudCheckSyncTest::CheckLogCleaned(int64_t expectCount) +{ + std::string sql1 = "select count(*) from " + DBCommon::GetLogTableName(tableName_) + + " where device = 'cloud';"; + EXPECT_EQ(sqlite3_exec(db_, sql1.c_str(), QueryCountCallback, + reinterpret_cast(expectCount), nullptr), SQLITE_OK); + std::string sql2 = "select count(*) from " + DBCommon::GetLogTableName(tableName_) + " where cloud_gid " + " is not null and cloud_gid != '';"; + EXPECT_EQ(sqlite3_exec(db_, sql2.c_str(), QueryCountCallback, + reinterpret_cast(expectCount), nullptr), SQLITE_OK); + std::string sql3 = "select count(*) from " + DBCommon::GetLogTableName(tableName_) + + " where flag & 0x02 = 0;"; + EXPECT_EQ(sqlite3_exec(db_, sql3.c_str(), QueryCountCallback, + reinterpret_cast(expectCount), nullptr), SQLITE_OK); +} + /** * @tc.name: CloudSyncTest001 * @tc.desc: sync with device sync query @@ -250,7 +478,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest001, TestSize.Level0) { // prepare data const int actualCount = 10; - InsertUserTableRecord(actualCount); + InsertUserTableRecord(tableName_, actualCount); // sync twice Query query = Query::Select().FromTable({ tableName_ }); BlockSync(query, delegate_); @@ -278,7 +506,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level0) { // prepare data const int actualCount = 1; - InsertUserTableRecord(actualCount); + InsertUserTableRecord(tableName_, actualCount); // sync twice Query query = Query::Select().FromTable({ tableName_ }); BlockSync(query, delegate_); @@ -291,7 +519,28 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level0) bool deleteStatus = true; EXPECT_EQ(virtualCloudDb_->GetDataStatus("1", deleteStatus), OK); EXPECT_EQ(deleteStatus, false); - // check local data +} + +/** + * @tc.name: CloudSyncTest003 + * @tc.desc: local data is delete before sync, then sync, cloud data will insert into local + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangshijie + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest003, TestSize.Level0) +{ + // prepare data + const int actualCount = 1; + InsertUserTableRecord(tableName_, actualCount); + + InsertCloudTableRecord(0, actualCount, 0, false); + // delete local data + DeleteUserTableRecord(0); + Query query = Query::Select().FromTable({ tableName_ }); + BlockSync(query, delegate_); + + // check local data, cloud date will insert into local int dataCnt = -1; std::string checkLogSql = "SELECT count(*) FROM " + tableName_; RelationalTestUtils::ExecSql(db_, checkLogSql, nullptr, [&dataCnt](sqlite3_stmt *stmt) { @@ -301,6 +550,33 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest002, TestSize.Level0) EXPECT_EQ(dataCnt, actualCount); } +/** + * @tc.name: CloudSyncTest004 + * @tc.desc: sync after insert failed + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncTest004, TestSize.Level0) +{ + // prepare data + const int actualCount = 1; + InsertUserTableRecord(tableName_, actualCount); + // sync twice + Query query = Query::Select().FromTable({ tableName_ }); + LOGW("Block Sync"); + virtualCloudDb_->SetInsertFailed(1); + BlockSync(query, delegate_); + // delete local data + DeleteUserTableRecord(0); // 0 is id + LOGW("Block Sync"); + // sync again and this record with be synced to cloud + BlockSync(query, delegate_); + bool deleteStatus = true; + EXPECT_EQ(virtualCloudDb_->GetDataStatus("0", deleteStatus), OK); + EXPECT_EQ(deleteStatus, true); +} + /** * @tc.name: CloudSyncObserverTest001 * @tc.desc: test cloud sync multi observer @@ -312,7 +588,7 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Lev { // prepare data const int actualCount = 10; - InsertUserTableRecord(actualCount); + InsertUserTableRecord(tableName_, actualCount); /** * @tc.steps:step1. open two delegate with two observer. @@ -373,5 +649,853 @@ HWTEST_F(DistributedDBCloudCheckSyncTest, CloudSyncObserverTest001, TestSize.Lev observer2 = nullptr; EXPECT_EQ(mgr_->CloseStore(delegate2), DBStatus::OK); } + +/** + * @tc.name: CloudPrioritySyncTest001 + * @tc.desc: use priority sync interface when query in or from table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record and query in 3 records, then priority sync. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableName_, actualCount); + std::vector idValue = {"0", "1", "2"}; + Query query = Query::Select().From(tableName_).In("id", idValue); + + /** + * @tc.steps:step2. check ParserQueryNodes + * @tc.expected: step2. ok. + */ + virtualCloudDb_->ForkQuery([this, &idValue](const std::string &tableName, VBucket &extend) { + EXPECT_EQ(tableName_, tableName); + if (extend.find(CloudDbConstant::QUERY_FIELD) == extend.end()) { + return; + } + Bytes bytes = std::get(extend[CloudDbConstant::QUERY_FIELD]); + DBStatus status = OK; + auto queryNodes = RelationalStoreManager::ParserQueryNodes(bytes, status); + EXPECT_EQ(status, OK); + ASSERT_EQ(queryNodes.size(), 1u); + EXPECT_EQ(queryNodes[0].type, QueryNodeType::IN); + EXPECT_EQ(queryNodes[0].fieldName, "id"); + ASSERT_EQ(queryNodes[0].fieldValue.size(), idValue.size()); + for (size_t i = 0u; i < idValue.size(); i++) { + std::string val = std::get(queryNodes[0].fieldValue[i]); + EXPECT_EQ(val, idValue[i]); + } + }); + BlockPrioritySync(query, delegate_, true, OK); + virtualCloudDb_->ForkQuery(nullptr); + CheckCloudTableCount(tableName_, 3); // 3 is count of cloud records + + /** + * @tc.steps:step3. use priority sync interface but not priority. + * @tc.expected: step3. ok. + */ + query = Query::Select().FromTable({ tableName_ }); + BlockPrioritySync(query, delegate_, false, OK); + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records + + /** + * @tc.steps:step4. insert user table record and query from table, then priority sync. + * @tc.expected: step4. ok. + */ + InsertUserTableRecord(tableName_, actualCount, actualCount); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records +} + + +/** + * @tc.name: CloudPrioritySyncTest002 + * @tc.desc: priority sync in some abnormal query situations + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 1; // 1 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. query select tablename then priority sync. + * @tc.expected: step2. invalid. + */ + Query query = Query::Select(tableName_); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step3. query select without from then priority sync. + * @tc.expected: step3. invalid. + */ + query = Query::Select(); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step4. query select and from without in then priority sync. + * @tc.expected: step4. invalid. + */ + query = Query::Select().From(tableName_); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step5. query select and fromtable then priority sync. + * @tc.expected: step5. not support. + */ + query = Query::Select().From(tableName_).FromTable({tableName_}); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step6. query select and from with other predicates then priority sync. + * @tc.expected: step6. not support. + */ + query = Query::Select().From(tableName_).IsNotNull("id"); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step7. query select and from with in and other predicates then priority sync. + * @tc.expected: step7 not support. + */ + std::vector idValue = {"0"}; + query = Query::Select().From(tableName_).IsNotNull("id").In("id", idValue); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step8. query select and from with in non-primary key then priority sync. + * @tc.expected: step8. not support. + */ + std::vector heightValue = {"155.10"}; + query = Query::Select().From(tableName_).In("height", heightValue); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step9. query in count greater than 100. + * @tc.expected: step9. over max limits. + */ + idValue.resize(101); // 101 > 100 + query = Query::Select().From(tableName_).In("id", idValue); + BlockPrioritySync(query, delegate_, true, OVER_MAX_LIMITS); + CheckCloudTableCount(tableName_, 0); +} + +/** + * @tc.name: CloudPrioritySyncTest003 + * @tc.desc: priority sync when normal syncing + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest003, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. begin normal sync and priority sync. + * @tc.expected: step2. ok. + */ + Query normalQuery = Query::Select().FromTable({tableName_}); + std::vector idValue = {"0", "1", "2"}; + Query priorityQuery = Query::Select().From(tableName_).In("id", idValue); + PriorityAndNormalSync(normalQuery, priorityQuery, delegate_); + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records + EXPECT_EQ(virtualCloudDb_->GetLockCount(), 2); + virtualCloudDb_->Reset(); + EXPECT_EQ(virtualCloudDb_->GetLockCount(), 0); +} + +/** + * @tc.name: CloudPrioritySyncTest004 + * @tc.desc: non-primarykey table priority sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest004, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user non-primarykey table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableWithoutPrimaryName_, actualCount); + + /** + * @tc.steps:step2. begin priority sync. + * @tc.expected: step2. not support. + */ + std::vector idValue = {"0", "1", "2"}; + Query query = Query::Select().From(tableWithoutPrimaryName_).In("id", idValue); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableWithoutPrimaryName_, 0); + + /** + * @tc.steps:step3. begin priority sync when in rowid. + * @tc.expected: step3. invalid. + */ + std::vector rowidValue = {0, 1, 2}; // 0,1,2 are rowid value + query = Query::Select().From(tableWithoutPrimaryName_).In("rowid", rowidValue); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableWithoutPrimaryName_, 0); +} + +/** + * @tc.name: CloudPrioritySyncTest005 + * @tc.desc: priority sync but don't have records + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest005, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user non-primarykey table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableWithoutPrimaryName_, actualCount); + + /** + * @tc.steps:step2. begin DistributedDBCloudCheckSyncTest priority sync and check records. + * @tc.expected: step2. ok. + */ + std::vector idValue = {"0", "1", "2"}; + Query query = Query::Select().From(tableName_).In("id", idValue); + BlockPrioritySync(query, delegate_, true, OK); + CheckCloudTableCount(tableWithoutPrimaryName_, 0); + CheckCloudTableCount(tableName_, 0); +} + +/** + * @tc.name: CloudPrioritySyncTest006 + * @tc.desc: priority sync tasks greater than limit + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest006, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. begin 32 priority sync tasks and then begin 1 priority sync task. + * @tc.expected: step2. ok. + */ + std::vector idValue = {"0", "1", "2"}; + Query query = Query::Select().From(tableName_).In("id", idValue); + std::mutex dataMutex; + std::condition_variable cv; + std::mutex callbackMutex; + std::condition_variable callbackCv; + bool finish = false; + size_t finishCount = 0u; + virtualCloudDb_->ForkQuery([&cv, &finish, &dataMutex](const std::string &tableName, VBucket &extend) { + std::unique_lock uniqueLock(dataMutex); + cv.wait(uniqueLock, [&finish]() { + return finish; + }); + }); + auto callback = [&callbackCv, &callbackMutex, &finishCount](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard callbackAutoLock(callbackMutex); + finishCount++; + } + callbackCv.notify_one(); + } + } + }; + CloudSyncOption option; + PrepareOption(option, query, true); + for (int i = 0; i < 32; i++) { // 32 is count of sync tasks + ASSERT_EQ(delegate_->Sync(option, callback), OK); + } + ASSERT_EQ(delegate_->Sync(option, nullptr), BUSY); + { + std::lock_guard autoLock(dataMutex); + finish = true; + } + cv.notify_all(); + virtualCloudDb_->ForkQuery(nullptr); + std::unique_lock callbackLock(callbackMutex); + callbackCv.wait(callbackLock, [&finishCount]() { + return (finishCount == 32u); // 32 is count of finished sync tasks + }); + CheckCloudTableCount(tableName_, 3); // 3 is count of cloud records +} + +/** + * @tc.name: CloudPrioritySyncTest007 + * @tc.desc: priority normal priority normal when different query + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest007, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. set callback to check during sync. + * @tc.expected: step2. ok. + */ + std::atomic count = 0; + SetForkQueryForCloudPrioritySyncTest007(count); + + /** + * @tc.steps:step3. perform priority normal priority normal sync. + * @tc.expected: step3. ok. + */ + std::vector idValue = {"0"}; + Query priorytyQuery = Query::Select().From(tableName_).In("id", idValue); + CloudSyncOption option; + PrepareOption(option, priorytyQuery, true); + std::mutex callbackMutex; + std::condition_variable callbackCv; + size_t finishCount = 0u; + auto callback = [&callbackCv, &callbackMutex, &finishCount](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard callbackAutoLock(callbackMutex); + finishCount++; + } + callbackCv.notify_one(); + } + } + }; + ASSERT_EQ(delegate_->Sync(option, callback), OK); + Query normalQuery = Query::Select().FromTable({tableName_}); + PrepareOption(option, normalQuery, false); + ASSERT_EQ(delegate_->Sync(option, callback), OK); + idValue = {"1"}; + priorytyQuery = Query::Select().From(tableName_).In("id", idValue); + PrepareOption(option, priorytyQuery, true); + ASSERT_EQ(delegate_->Sync(option, callback), OK); + PrepareOption(option, normalQuery, false); + ASSERT_EQ(delegate_->Sync(option, callback), OK); + std::unique_lock callbackLock(callbackMutex); + callbackCv.wait(callbackLock, [&finishCount]() { + return (finishCount == 4u); // 4 is count of finished sync tasks + }); + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records +} + +/** + * @tc.name: CloudPrioritySyncTest008 + * @tc.desc: priority normal priority normal when different query + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest008, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. set callback to check during sync. + * @tc.expected: step2. ok. + */ + std::atomic count = 0; + SetForkQueryForCloudPrioritySyncTest008(count); + + /** + * @tc.steps:step3. perform priority normal priority normal sync. + * @tc.expected: step3. ok. + */ + std::vector idValue = {"0"}; + Query priorytyQuery = Query::Select().From(tableName_).In("id", idValue); + CloudSyncOption option; + PrepareOption(option, priorytyQuery, true); + std::mutex callbackMutex; + std::condition_variable callbackCv; + size_t finishCount = 0u; + auto callback = [&callbackCv, &callbackMutex, &finishCount](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard callbackAutoLock(callbackMutex); + finishCount++; + } + callbackCv.notify_one(); + } + } + }; + ASSERT_EQ(delegate_->Sync(option, callback), OK); + Query normalQuery = Query::Select().FromTable({tableName_}); + PrepareOption(option, normalQuery, false); + ASSERT_EQ(delegate_->Sync(option, callback), OK); + priorytyQuery = Query::Select().From(tableName_).In("id", idValue); + PrepareOption(option, priorytyQuery, true); + ASSERT_EQ(delegate_->Sync(option, callback), OK); + PrepareOption(option, normalQuery, false); + ASSERT_EQ(delegate_->Sync(option, callback), OK); + std::unique_lock callbackLock(callbackMutex); + callbackCv.wait(callbackLock, [&finishCount]() { + return (finishCount == 4u); // 4 is count of finished sync tasks + }); + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records +} + +/** + * @tc.name: CloudPrioritySyncTest009 + * @tc.desc: use priority sync interface when query equal to from table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest009, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record and query in 3 records, then priority sync. + * @tc.expected: step1. ok. + */ + const int actualCount = 5; // 5 is count of records + InsertUserTableRecord(tableName_, actualCount); + Query query = Query::Select().From(tableName_).BeginGroup().EqualTo("id", "0").Or().EqualTo("id", "1").EndGroup(); + + /** + * @tc.steps:step2. check ParserQueryNodes + * @tc.expected: step2. ok. + */ + virtualCloudDb_->ForkQuery([this](const std::string &tableName, VBucket &extend) { + EXPECT_EQ(tableName_, tableName); + Bytes bytes = std::get(extend[CloudDbConstant::QUERY_FIELD]); + DBStatus status = OK; + auto queryNodes = RelationalStoreManager::ParserQueryNodes(bytes, status); + EXPECT_EQ(status, OK); + ASSERT_EQ(queryNodes.size(), 5u); // 5 is query nodes count + }); + BlockPrioritySync(query, delegate_, true, OK); + virtualCloudDb_->ForkQuery(nullptr); + CheckCloudTableCount(tableName_, 2); // 2 is count of cloud records +} + +/** + * @tc.name: CloudPrioritySyncTest010 + * @tc.desc: priority sync after cloud delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest010, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. normal sync and then delete cloud records. + * @tc.expected: step2. ok. + */ + Query query = Query::Select().FromTable({tableName_}); + BlockSync(query, delegate_); + CheckCloudTableCount(tableName_, 10); // 10 is count of cloud records after sync + DeleteCloudDBData(0, 3); // delete 0 1 2 record in cloud + CheckCloudTableCount(tableName_, 7); // 7 is count of cloud records after delete + CheckUserTableResult(db_, tableName_, 10); // 10 is count of user records + + /** + * @tc.steps:step3. priory sync and set query then check user table records. + * @tc.expected: step3. ok. + */ + std::vector idValue = {"3", "4", "5"}; + query = Query::Select().From(tableName_).In("id", idValue); + BlockPrioritySync(query, delegate_, true, OK); + CheckUserTableResult(db_, tableName_, 10); // 10 is count of user records after sync + idValue = {"0", "1", "2"}; + query = Query::Select().From(tableName_).In("id", idValue); + BlockPrioritySync(query, delegate_, true, OK); + CheckUserTableResult(db_, tableName_, 7); // 7 is count of user records after sync +} + +/** + * @tc.name: CloudPrioritySyncTest011 + * @tc.desc: priority sync after cloud insert + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest011, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert cloud table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertCloudTableRecord(0, actualCount, actualCount, false); + std::vector idValue = {"0", "1", "2"}; + Query query = Query::Select().From(tableName_).In("id", idValue); + std::atomic count = 0; + + /** + * @tc.steps:step2. check user records when query. + * @tc.expected: step1. ok. + */ + virtualCloudDb_->ForkQuery([this, &count](const std::string &, VBucket &) { + count++; + if (count == 1) { // taskid1 + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + if (count == 2) { // taskid2 + CheckUserTableResult(db_, tableName_, 3); // 3 is count of user records after first sync + } + }); + CloudSyncOption option; + PrepareOption(option, query, true); + std::mutex callbackMutex; + std::condition_variable callbackCv; + size_t finishCount = 0u; + auto callback = [&callbackCv, &callbackMutex, &finishCount](const std::map &process) { + for (const auto &item: process) { + if (item.second.process == DistributedDB::FINISHED) { + { + std::lock_guard callbackAutoLock(callbackMutex); + finishCount++; + } + callbackCv.notify_one(); + } + } + }; + + /** + * @tc.steps:step3. begin sync and check user record. + * @tc.expected: step3. ok. + */ + ASSERT_EQ(delegate_->Sync(option, callback), OK); + idValue = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; + query = Query::Select().From(tableName_).In("id", idValue); + PrepareOption(option, query, true); + ASSERT_EQ(delegate_->Sync(option, callback), OK); + std::unique_lock callbackLock(callbackMutex); + callbackCv.wait(callbackLock, [&finishCount]() { + return (finishCount == 2u); // 2 is count of finished sync tasks + }); + CheckUserTableResult(db_, tableName_, 10); // 10 is count of user records +} + +/** + * @tc.name: CloudPrioritySyncTest012 + * @tc.desc: priority or normal sync when waittime > 300s or < -1 + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest012, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert cloud table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 10; // 10 is count of records + InsertCloudTableRecord(0, actualCount, actualCount, false); + std::vector idValue = {"0", "1", "2"}; + Query query = Query::Select().From(tableName_).In("id", idValue); + + /** + * @tc.steps:step2. set waittime < -1 then begin sync. + * @tc.expected: step2. invalid. + */ + CloudSyncOption option; + PrepareOption(option, query, true); + option.waitTime = -2; // -2 < -1; + ASSERT_EQ(delegate_->Sync(option, nullptr), INVALID_ARGS); + CheckUserTableResult(db_, tableName_, 0); // 0 is count of user records + + /** + * @tc.steps:step3. set waittime > 300s then begin sync. + * @tc.expected: step3. invalid. + */ + + option.waitTime = 300001; // 300001 > 300s + ASSERT_EQ(delegate_->Sync(option, nullptr), INVALID_ARGS); + CheckUserTableResult(db_, tableName_, 0); // 0 is count of user records +} + +/** + * @tc.name: CloudPrioritySyncTest013 + * @tc.desc: priority sync in some abnormal composite pk query situations + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, CloudPrioritySyncTest013, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert user table record. + * @tc.expected: step1. ok. + */ + const int actualCount = 1; // 1 is count of records + InsertUserTableRecord(tableName_, actualCount); + + /** + * @tc.steps:step2. query only begingroup then priority sync. + * @tc.expected: step2. invalid. + */ + Query query = Query::Select().From(tableName_).BeginGroup(); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step3. query only endgroup then priority sync. + * @tc.expected: step3. invalid. + */ + query = Query::Select().From(tableName_).EndGroup(); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step4. query only begingroup and endgroup then priority sync. + * @tc.expected: step4. invalid. + */ + query = Query::Select().From(tableName_).BeginGroup().EndGroup(); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step5. query and from table then priority sync. + * @tc.expected: step5. invalid. + */ + query = Query::Select().And().From(tableName_); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step6. query or from table then priority sync. + * @tc.expected: step6. invalid. + */ + query = Query::Select().Or().From(tableName_); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step7. query begingroup from table then priority sync. + * @tc.expected: step7 invalid. + */ + query = Query::Select().BeginGroup().From(tableName_); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step8. query endgroup from table then priority sync. + * @tc.expected: step8 invalid. + */ + query = Query::Select().EndGroup().From(tableName_); + BlockPrioritySync(query, delegate_, true, NOT_SUPPORT); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step9. query and in then priority sync. + * @tc.expected: step9. invalid. + */ + std::vector idValue = {"0"}; + query = Query::Select().From(tableName_).And().In("id", idValue); + BlockPrioritySync(query, delegate_, true, INVALID_ARGS); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step10. query when the table name does not exit then priority sync. + * @tc.expected: step10. schema mismatch. + */ + query = Query::Select().From("tableName").And().In("id", idValue); + BlockPrioritySync(query, delegate_, true, SCHEMA_MISMATCH); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step11. query when the table name does not exit then priority sync. + * @tc.expected: step11. schema mismatch. + */ + query = Query::Select().From("tableName").In("id", idValue); + BlockPrioritySync(query, delegate_, true, SCHEMA_MISMATCH); + CheckCloudTableCount(tableName_, 0); + + /** + * @tc.steps:step12. query when the table name does not exit then sync. + * @tc.expected: step12. schema mismatch. + */ + query = Query::Select().FromTable({"tableName"}); + BlockPrioritySync(query, delegate_, false, SCHEMA_MISMATCH); + CheckCloudTableCount(tableName_, 0); +} + +/** + * @tc.name: LogicDeleteSyncTest001 + * @tc.desc: sync with logic delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest001, TestSize.Level0) +{ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + delegate_->Pragma(LOGIC_DELETE_SYNC_DATA, data); + int actualCount = 10; + InitLogicDeleteDataEnv(actualCount); + CheckLocalCount(actualCount); + std::string device = ""; + ASSERT_EQ(delegate_->RemoveDeviceData(device, DistributedDB::FLAG_AND_DATA), DBStatus::OK); + CheckLocalCount(0); +} + +/** + * @tc.name: LogicDeleteSyncTest002 + * @tc.desc: sync without logic delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest002, TestSize.Level0) +{ + bool logicDelete = false; + auto data = static_cast(&logicDelete); + delegate_->Pragma(LOGIC_DELETE_SYNC_DATA, data); + int actualCount = 10; + InitLogicDeleteDataEnv(actualCount); + CheckLocalCount(0); +} + +/** + * @tc.name: LogicDeleteSyncTest003 + * @tc.desc: sync with logic delete and check observer + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest003, TestSize.Level0) +{ + /** + * @tc.steps:step1. register observer. + * @tc.expected: step1. ok. + */ + RelationalStoreDelegate::Option option; + auto observer = new (std::nothrow) RelationalStoreObserverUnitTest(); + ASSERT_NE(observer, nullptr); + observer->SetCallbackDetailsType(static_cast(CallbackDetailsType::DETAILED)); + EXPECT_EQ(delegate_->RegisterObserver(observer), OK); + ChangedData expectData; + expectData.tableName = tableName_; + expectData.type = ChangedDataType::DATA; + expectData.field.push_back(std::string("id")); + const int count = 10; + for (int64_t i = 0; i < count; ++i) { + expectData.primaryData[ChangeType::OP_DELETE].push_back({std::to_string(i)}); + } + expectData.properties = { .isTrackedDataChange = true }; + observer->SetExpectedResult(expectData); + + /** + * @tc.steps:step2. set tracker table + * @tc.expected: step2. ok. + */ + TrackerSchema trackerSchema; + trackerSchema.tableName = tableName_; + trackerSchema.trackerColNames = { "id" }; + EXPECT_EQ(delegate_->SetTrackerTable(trackerSchema), OK); + + /** + * @tc.steps:step3. set logic delete and sync + * @tc.expected: step3. ok. + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + delegate_->Pragma(LOGIC_DELETE_SYNC_DATA, data); + int actualCount = 10; + InitLogicDeleteDataEnv(actualCount); + CheckLocalCount(actualCount); + EXPECT_EQ(observer->IsAllChangedDataEq(), true); + observer->ClearChangedData(); + + /** + * @tc.steps:step4. unSetTrackerTable and sync + * @tc.expected: step4. ok. + */ + expectData.properties = { .isTrackedDataChange = false }; + observer->SetExpectedResult(expectData); + trackerSchema.trackerColNames = {}; + EXPECT_EQ(delegate_->SetTrackerTable(trackerSchema), OK); + InsertUserTableRecord(tableName_, actualCount); + BlockSync(Query::Select().FromTable({ tableName_ }), delegate_); + for (int i = 0; i < actualCount + actualCount; ++i) { + DeleteCloudTableRecord(i); + } + BlockSync(Query::Select().FromTable({ tableName_ }), delegate_); + EXPECT_EQ(observer->IsAllChangedDataEq(), true); + + EXPECT_EQ(delegate_->UnRegisterObserver(observer), OK); + delete observer; + observer = nullptr; +} + +/** + * @tc.name: LogicDeleteSyncTest004 + * @tc.desc: test removedevicedata in mode FLAG_ONLY when sync with logic delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudCheckSyncTest, LogicDeleteSyncTest004, TestSize.Level0) +{ + /** + * @tc.steps:step1. set logic delete + * @tc.expected: step1. ok. + */ + bool logicDelete = true; + auto data = static_cast(&logicDelete); + delegate_->Pragma(LOGIC_DELETE_SYNC_DATA, data); + + /** + * @tc.steps:step2. cloud delete data then sync, check removedevicedata + * @tc.expected: step2. ok. + */ + int actualCount = 10; + InitLogicDeleteDataEnv(actualCount); + CheckLocalCount(actualCount); + std::string device = ""; + ASSERT_EQ(delegate_->RemoveDeviceData(device, DistributedDB::FLAG_ONLY), DBStatus::OK); + CheckLocalCount(actualCount); + CheckLogCleaned(0); +} } #endif \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp index 4e211c6950c4efcfbef3e5bd562e1c0ebdfab1f1..65e438c7db0332aeaea1c21f5d9b4df8ed977dad 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_interfaces_relational_sync_test.cpp @@ -16,7 +16,7 @@ #include #include #include "cloud/cloud_storage_utils.h" -#include "cloud_db_constant.h" +#include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "process_system_api_adapter_impl.h" @@ -300,6 +300,7 @@ namespace { asset.name = "Phone" + std::to_string(rowid - cloudCount - 1); if (opType == AssetOpType::UPDATE) { asset.uri = "/data/test"; + asset.hash = ""; } else if (opType == AssetOpType::INSERT) { asset.name = "Test10"; } @@ -326,6 +327,7 @@ namespace { if (opType == AssetOpType::UPDATE) { assets.push_back(asset1); asset2.uri = "/data/test"; + asset2.hash = ""; asset2.status = static_cast(CloudStorageUtils::FlagToStatus(opType)); assets.push_back(asset2); } else if (opType == AssetOpType::INSERT) { @@ -559,18 +561,22 @@ namespace { { TableSchema tableSchema1 = { .name = g_tableName1, + .sharedTableName = "", .fields = g_cloudFiled1 }; TableSchema tableSchema2 = { .name = g_tableName2, + .sharedTableName = "", .fields = g_cloudFiled2 }; TableSchema tableSchemaWithOutPrimaryKey = { .name = g_tableName3, + .sharedTableName = "", .fields = g_cloudFiledWithOutPrimaryKey3 }; TableSchema tableSchema4 = { .name = g_tableName4, + .sharedTableName = "", .fields = g_cloudFiled2 }; dataBaseSchema.tables.push_back(tableSchema1); @@ -584,10 +590,12 @@ namespace { { TableSchema tableSchema1 = { .name = g_tableName1, + .sharedTableName = "", .fields = g_invalidCloudFiled1 }; TableSchema tableSchema2 = { - .name = g_tableName1, + .name = g_tableName2, + .sharedTableName = "", .fields = g_cloudFiled2 }; dataBaseSchema.tables.push_back(tableSchema1); @@ -983,11 +991,7 @@ namespace { Asset asset; ASSERT_EQ(RuntimeContext::GetInstance()->BlobToAsset(blobValue, asset), E_OK); EXPECT_EQ(asset.version, g_cloudAsset.version); - if (index % 6u == 0) { // 6 is AssetStatus type num, include invalid type - EXPECT_EQ(asset.status, static_cast(AssetStatus::NORMAL)); - } else { - EXPECT_EQ(asset.status, static_cast(AssetStatus::ABNORMAL)); - } + EXPECT_EQ(asset.status, static_cast(AssetStatus::ABNORMAL)); index++; } int errCode; @@ -1059,7 +1063,8 @@ namespace { LOGD("Download GID:%s", gid.c_str()); for (auto &item: assets) { for (auto &asset: item.second) { - EXPECT_EQ(asset.status, static_cast(AssetStatus::DOWNLOADING)); + EXPECT_EQ(AssetOperationUtils::EraseBitMask(asset.status), + static_cast(AssetStatus::DOWNLOADING)); LOGD("asset [name]:%s, [status]:%u, [flag]:%u", asset.name.c_str(), asset.status, asset.flag); asset.status = (index++) % 6u; // 6 is AssetStatus type num, include invalid type } @@ -2087,7 +2092,6 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest007, CloseDb(); } - /** * @tc.name: DownloadAssetTest001 * @tc.desc: Test the sync of different Asset status out of parameters when the download is successful @@ -2179,6 +2183,30 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest008, CloseDb(); } +/* + * @tc.name: CloudSyncAssetTest009 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudSyncAssetTest009, TestSize.Level0) +{ + // insert 3 data with asset 3 data without asset into local + // sync them to cloud + int64_t paddingSize = 10; + int localCount = 3; + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + InsertUserTableRecord(db, localCount, localCount, paddingSize, true); + callSync(g_tables, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + // update these data and sync again + InsertUserTableRecord(db, 0, localCount, paddingSize, false); + InsertUserTableRecord(db, localCount, localCount, paddingSize, true); + callSync(g_tables, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + EXPECT_EQ(g_syncProcess.errCode, DBStatus::OK); + CloseDb(); +} + /** * @tc.name: DownloadAssetTest002 * @tc.desc: Test the sync of different Asset status out of parameters when the download is failed @@ -2344,11 +2372,46 @@ HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, SchemaTest002, TestSize ASSERT_EQ(g_delegate->CreateDistributedTable(g_tableName4, DEVICE_COOPERATION), DBStatus::OK); /** * @tc.steps:step1. do sync - * @tc.expected: step1. return ok. + * @tc.expected: step1. return NOT_SUPPORT. */ callSync({g_tableName4}, SYNC_MODE_CLOUD_MERGE, DBStatus::NOT_SUPPORT); CloseDb(); } +/** + * @tc.name: CloudCursorTest001 + * @tc.desc: Init different asset name between local and cloud, then sync to test download + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudInterfacesRelationalSyncTest, CloudCursorTest001, TestSize.Level0) +{ + /** + * @tc.steps:step1. Init data and sync + * @tc.expected: step1. return ok. + */ + int64_t paddingSize = 1; + int localCount = 10; + InsertUserTableRecord(db, 0, localCount, paddingSize, true); + InsertCloudTableRecord(0, localCount, paddingSize, true); + callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + + /** + * @tc.steps:step2. the cursor does not increase during upload, the cursor will increase during download + * although it is unTrackerTable + * @tc.expected: step2. return ok. + */ + string sql = "select cursor from " + DBConstant::RELATIONAL_PREFIX + g_tableName1 + "_log"; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + int64_t index = 0; + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + EXPECT_EQ(static_cast(sqlite3_column_int64(stmt, 0)), ++index); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + CloseDb(); +} } #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bade69e983af880bf31f770625fc98821afd8c4e --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_reference_sync_test.cpp @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef RELATIONAL_STORE +#include +#include "cloud/cloud_storage_utils.h" +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_db_types.h" +#include "db_common.h" +#include "distributeddb_data_generate_unit_test.h" +#include "log_print.h" +#include "relational_store_delegate.h" +#include "relational_store_manager.h" +#include "runtime_config.h" +#include "sqlite_relational_utils.h" +#include "time_helper.h" +#include "virtual_asset_loader.h" +#include "virtual_cloud_data_translate.h" +#include "virtual_cloud_db.h" + +namespace { +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +class DistributedDBCloudReferenceSyncTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +protected: + void InitTestDir(); + DataBaseSchema GetSchema(); + void CloseDb(); + void SetReference(); + void InsertUserTableRecord(const std::string &tableName, int64_t recordCounts, bool isShared = false, + int64_t begin = 0, std::string owner = ""); + void UpdateUserTableRecord(const std::string &tableName, int64_t begin, int64_t count); + void DeleteUserTableRecord(const std::string &tableName, int64_t begin, int64_t count); + void InsertCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull); + void UpdateCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize, bool assetIsNull); + void DeleteCloudSharedTableRecordByGid(int64_t begin, int64_t count); + void CheckCloudData(const std::string &tableName, bool hasRef, const std::vector &refData); + void CheckDistributedSharedData(const std::vector &expect); + void CheckSharedDataAfterUpdated(const std::vector &expect); + DataBaseSchema GetSchema(const std::vector &tableNames); + std::vector InitMultiTable(int count); + static void InitWalModeAndTable(sqlite3 *db, const std::vector &tableName); + std::string testDir_; + std::string storePath_; + sqlite3 *db_ = nullptr; + RelationalStoreDelegate *delegate_ = nullptr; + std::shared_ptr virtualCloudDb_ = nullptr; + std::shared_ptr mgr_ = nullptr; + const std::string parentTableName_ = "parent"; + const std::string sharedParentTableName_ = "parent_shared"; + const std::string childTableName_ = "child"; + const std::string sharedChildTableName_ = "child_shared"; + const std::vector sharedTables_ = { sharedParentTableName_, sharedChildTableName_ }; + const Asset cloudAsset1_ = { + .version = 2, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/cloud/sync", + .modifyTime = "123456", .createTime = "0", .size = "1024", .hash = "DEC" + }; + const Asset cloudAsset2_ = { + .version = 2, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/cloud/sync", + .modifyTime = "123456", .createTime = "0", .size = "1024", .hash = "UPDATE" + }; +}; + +void DistributedDBCloudReferenceSyncTest::SetUpTestCase() +{ + RuntimeConfig::SetCloudTranslate(std::make_shared()); +} + +void DistributedDBCloudReferenceSyncTest::TearDownTestCase() +{} + +void DistributedDBCloudReferenceSyncTest::SetUp() +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + InitTestDir(); + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != 0) { + LOGE("rm test db files error."); + } + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + LOGD("Test dir is %s", testDir_.c_str()); + db_ = RelationalTestUtils::CreateDataBase(storePath_); + ASSERT_NE(db_, nullptr); + InitWalModeAndTable(db_, { parentTableName_, childTableName_ }); + mgr_ = std::make_shared(APP_ID, USER_ID); + RelationalStoreDelegate::Option option; + ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); + ASSERT_NE(delegate_, nullptr); + virtualCloudDb_ = std::make_shared(); + ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); + ASSERT_EQ(delegate_->SetIAssetLoader(std::make_shared()), DBStatus::OK); + ASSERT_EQ(delegate_->CreateDistributedTable(parentTableName_, CLOUD_COOPERATION), DBStatus::OK); + ASSERT_EQ(delegate_->CreateDistributedTable(childTableName_, CLOUD_COOPERATION), DBStatus::OK); + SetReference(); + DataBaseSchema dataBaseSchema = GetSchema(); + ASSERT_EQ(delegate_->SetCloudDbSchema(dataBaseSchema), DBStatus::OK); +} + +void DistributedDBCloudReferenceSyncTest::TearDown() +{ + virtualCloudDb_->ForkQuery(nullptr); + CloseDb(); + EXPECT_EQ(sqlite3_close_v2(db_), SQLITE_OK); + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(testDir_) != E_OK) { + LOGE("rm test db files error."); + } +} + +void DistributedDBCloudReferenceSyncTest::InitTestDir() +{ + if (!testDir_.empty()) { + return; + } + DistributedDBToolsUnitTest::TestDirInit(testDir_); + storePath_ = testDir_ + "/" + STORE_ID_1 + ".db"; + LOGI("The test db is:%s", testDir_.c_str()); +} + +DataBaseSchema DistributedDBCloudReferenceSyncTest::GetSchema() +{ + DataBaseSchema schema; + TableSchema tableSchema; + tableSchema.name = parentTableName_; + tableSchema.sharedTableName = sharedParentTableName_; + tableSchema.fields = { + {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, {"height", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"age", TYPE_INDEX} + }; + TableSchema childSchema; + childSchema.name = childTableName_; + childSchema.sharedTableName = sharedChildTableName_; + childSchema.fields = { + {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, {"height", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"age", TYPE_INDEX} + }; + schema.tables.push_back(tableSchema); + schema.tables.push_back(childSchema); + return schema; +} + +DataBaseSchema DistributedDBCloudReferenceSyncTest::GetSchema(const std::vector &tableNames) +{ + DataBaseSchema schema; + for (const auto &table : tableNames) { + TableSchema tableSchema; + tableSchema.name = table; + tableSchema.fields = { + {"id", TYPE_INDEX, true}, {"name", TYPE_INDEX}, {"height", TYPE_INDEX}, + {"photo", TYPE_INDEX}, {"age", TYPE_INDEX} + }; + schema.tables.push_back(tableSchema); + } + return schema; +} + +void DistributedDBCloudReferenceSyncTest::CloseDb() +{ + virtualCloudDb_ = nullptr; + EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK); + delegate_ = nullptr; + mgr_ = nullptr; +} + +void DistributedDBCloudReferenceSyncTest::SetReference() +{ + std::vector tableReferenceProperty; + TableReferenceProperty property; + property.sourceTableName = childTableName_; + property.targetTableName = parentTableName_; + property.columns["name"] = "name"; + tableReferenceProperty.push_back(property); + delegate_->SetReference(tableReferenceProperty); +} + +void DistributedDBCloudReferenceSyncTest::InitWalModeAndTable(sqlite3 *db, const std::vector &tableName) +{ + ASSERT_NE(db, nullptr); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); + static constexpr const char *createSQLBegin = "CREATE TABLE IF NOT EXISTS "; + static constexpr const char *createSQLEnd = " (" \ + "id TEXT PRIMARY KEY," \ + "name TEXT," \ + "height REAL ," \ + "photo BLOB," \ + "age INT);"; + for (const auto &table : tableName) { + std::string createSQL = createSQLBegin + table + createSQLEnd; + LOGD("[DistributedDBCloudReferenceSyncTest] create sql is %s", createSQL.c_str()); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, createSQL), SQLITE_OK); + } +} + +void DistributedDBCloudReferenceSyncTest::InsertUserTableRecord(const std::string &tableName, + int64_t recordCounts, bool isShared, int64_t begin, std::string owner) +{ + ASSERT_NE(db_, nullptr); + for (int64_t i = begin; i < recordCounts; ++i) { + string sql = "INSERT OR REPLACE INTO " + tableName + " ("; + if (isShared) { + sql += " cloud_owner, cloud_privilege,"; + } + sql += " id, name, height, photo, age) VALUES ("; + if (isShared) { + if (owner.empty()) { + sql += "'mock_owner', 'true', "; + } else { + sql += "'" + owner + "', 'true', "; + } + } + sql += "'" + std::to_string(i) + "', 'Local"; + sql += std::to_string(i) + "', '155.10', 'text', '21');"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db_, sql), E_OK); + } +} + +void DistributedDBCloudReferenceSyncTest::UpdateUserTableRecord(const std::string &tableName, int64_t begin, + int64_t count) +{ + string updateAge = "UPDATE " + tableName + " SET age = '99' where id in ("; + for (int64_t j = begin; j < begin + count; ++j) { + updateAge += "'" + std::to_string(j) + "',"; + } + updateAge.pop_back(); + updateAge += ");"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateAge), SQLITE_OK); +} + +void DistributedDBCloudReferenceSyncTest::DeleteUserTableRecord(const std::string &tableName, int64_t begin, + int64_t count) +{ + for (int64_t i = begin; i < begin + count; i++) { + string sql = "Delete from " + tableName + " where id = " + std::to_string(i) + ";"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, sql), SQLITE_OK); + } +} + +void DistributedDBCloudReferenceSyncTest::InsertCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize, + bool assetIsNull) +{ + std::vector photo(photoSize, 'v'); + std::vector record1; + std::vector record2; + std::vector extend1; + std::vector extend2; + Timestamp now = TimeHelper::GetSysCurrentTime(); + for (int64_t i = begin; i < begin + count; ++i) { + VBucket data; + data.insert_or_assign(std::string("id"), std::to_string(i)); + data.insert_or_assign(std::string("name"), std::string("Cloud") + std::to_string(i)); + data.insert_or_assign(std::string("height"), 166.0); // 166.0 is random double value + data.insert_or_assign(std::string("photo"), photo); + data.insert_or_assign(std::string("age"), 13L); // 13 is random int64_t value + data.insert_or_assign(std::string("cloud_owner"), std::string("a_owner")); + data.insert_or_assign(std::string("cloud_privilege"), std::string("true")); + Asset asset = cloudAsset1_; + asset.name = asset.name + std::to_string(i); + assetIsNull ? data.insert_or_assign(std::string("asset"), Nil()) : + data.insert_or_assign(std::string("asset"), asset); + record1.push_back(data); + record2.push_back(data); + VBucket log; + log.insert_or_assign(CloudDbConstant::CREATE_FIELD, + static_cast(now / CloudDbConstant::TEN_THOUSAND + i)); + log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, + static_cast(now / CloudDbConstant::TEN_THOUSAND + i)); + log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); + extend1.push_back(log); + extend2.push_back(log); + } + ASSERT_EQ(virtualCloudDb_->BatchInsert(sharedParentTableName_, std::move(record1), extend1), DBStatus::OK); + ASSERT_EQ(virtualCloudDb_->BatchInsert(sharedChildTableName_, std::move(record2), extend2), DBStatus::OK); + std::this_thread::sleep_for(std::chrono::milliseconds(count)); +} + +void DistributedDBCloudReferenceSyncTest::UpdateCloudSharedTableRecord(int64_t begin, int64_t count, int64_t photoSize, + bool assetIsNull) +{ + std::vector photo(photoSize, 'v'); + std::vector record1; + std::vector record2; + std::vector extend1; + std::vector extend2; + Timestamp now = TimeHelper::GetSysCurrentTime(); + for (int64_t i = begin; i < begin + 2 * count; ++i) { // 2 is two tables shared only one gid + VBucket data; + data.insert_or_assign("id", std::to_string(i)); + data.insert_or_assign("name", std::string("Cloud") + std::to_string(i)); + data.insert_or_assign("height", 188.0); // 188.0 is random double value + data.insert_or_assign("photo", photo); + data.insert_or_assign("age", 13L); // 13 is random int64_t value + data.insert_or_assign("cloud_owner", std::string("b_owner")); + data.insert_or_assign("cloud_privilege", std::string("true")); + Asset asset = cloudAsset2_; + asset.name = asset.name + std::to_string(i); + assetIsNull ? data.insert_or_assign("asset", Nil()) : data.insert_or_assign("asset", asset); + record1.push_back(data); + record2.push_back(data); + VBucket log; + log.insert_or_assign(CloudDbConstant::CREATE_FIELD, + static_cast(now / CloudDbConstant::TEN_THOUSAND + i)); + log.insert_or_assign(CloudDbConstant::MODIFY_FIELD, + static_cast(now / CloudDbConstant::TEN_THOUSAND + i)); + log.insert_or_assign(CloudDbConstant::DELETE_FIELD, false); + log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(i)); + extend1.push_back(log); + log.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(++i)); + extend2.push_back(log); + } + ASSERT_EQ(virtualCloudDb_->BatchUpdate(sharedParentTableName_, std::move(record1), extend1), DBStatus::OK); + ASSERT_EQ(virtualCloudDb_->BatchUpdate(sharedChildTableName_, std::move(record2), extend2), DBStatus::OK); + std::this_thread::sleep_for(std::chrono::milliseconds(count)); +} + +void DistributedDBCloudReferenceSyncTest::DeleteCloudSharedTableRecordByGid(int64_t begin, int64_t count) +{ + for (size_t i = 0; i < sharedTables_.size(); i++) { + for (int64_t j = begin; j < begin + count; ++j) { + VBucket data; + data.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(j)); + ASSERT_EQ(virtualCloudDb_->DeleteByGid(sharedTables_[i], data), DBStatus::OK); + } + } + std::this_thread::sleep_for(std::chrono::milliseconds(count)); +} + +void DistributedDBCloudReferenceSyncTest::CheckCloudData(const std::string &tableName, bool hasRef, + const std::vector &refData) +{ + VBucket extend; + extend[CloudDbConstant::CURSOR_FIELD] = std::string(); + std::vector queryRes; + (void) virtualCloudDb_->Query(tableName, extend, queryRes); + if (hasRef) { + ASSERT_EQ(refData.size(), queryRes.size()); + } + int index = 0; + for (const auto &data : queryRes) { + if (!hasRef) { + EXPECT_EQ(data.find(CloudDbConstant::REFERENCE_FIELD), data.end()); + continue; + } + ASSERT_NE(data.find(CloudDbConstant::REFERENCE_FIELD), data.end()); + Entries entries = std::get(data.at(CloudDbConstant::REFERENCE_FIELD)); + EXPECT_EQ(refData[index], entries); + index++; + } +} + +void DistributedDBCloudReferenceSyncTest::CheckDistributedSharedData(const std::vector &expect) +{ + for (size_t i = 0; i < sharedTables_.size(); i++) { + std::string sql = "SELECT version FROM " + DBCommon::GetLogTableName(sharedTables_[i]) + " WHERE rowid = 1;"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_TEXT); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + std::string versionValue; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, versionValue), E_OK); + ASSERT_EQ(versionValue, expect[i]); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } +} + +void DistributedDBCloudReferenceSyncTest::CheckSharedDataAfterUpdated(const std::vector &expect) +{ + for (size_t i = 0; i < sharedTables_.size(); i++) { + std::string sql = "SELECT height FROM " + sharedTables_[i] + " WHERE _rowid_ = 1;"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_FLOAT); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + double heightValue; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, heightValue), E_OK); + EXPECT_EQ(heightValue, expect[i]); + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + } +} + +std::vector DistributedDBCloudReferenceSyncTest::InitMultiTable(int count) +{ + std::vector tableName; + for (int i = 0; i < count; ++i) { + std::string table = "table_"; + table += static_cast(static_cast('a') + i); + tableName.push_back(table); + } + InitWalModeAndTable(db_, tableName); + for (const auto &table : tableName) { + EXPECT_EQ(delegate_->CreateDistributedTable(table, CLOUD_COOPERATION), DBStatus::OK); + LOGW("table %s", table.c_str()); + } + return tableName; +} + +/** + * @tc.name: CloudSyncTest001 + * @tc.desc: sync table with reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest001, TestSize.Level0) +{ + std::vector tableNames = { parentTableName_, childTableName_ }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + + InsertUserTableRecord(parentTableName_, 1); + InsertUserTableRecord(childTableName_, 1); + RelationalTestUtils::CloudBlockSync(query, delegate_); + LOGD("check parent table"); + CheckCloudData(parentTableName_, false, {}); + LOGD("check child table"); + std::vector expectEntries; + Entries entries; + entries[parentTableName_] = "0"; + expectEntries.push_back(entries); + CheckCloudData(childTableName_, true, expectEntries); +} + +/** + * @tc.name: CloudSyncTest002 + * @tc.desc: sync shared table with reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest002, TestSize.Level0) +{ + std::vector tableNames = { sharedParentTableName_, sharedChildTableName_ }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + + InsertUserTableRecord(sharedParentTableName_, 1, true); + InsertUserTableRecord(sharedChildTableName_, 1, true); + RelationalTestUtils::CloudBlockSync(query, delegate_); + LOGD("check parent table"); + CheckCloudData(sharedParentTableName_, false, {}); + LOGD("check child table"); + std::vector expectEntries; + Entries entries; + entries[sharedParentTableName_] = "0"; + expectEntries.push_back(entries); + CheckCloudData(sharedChildTableName_, true, expectEntries); +} + +/** + * @tc.name: CloudSyncTest003 + * @tc.desc: sync with invalid table reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest003, TestSize.Level0) +{ + std::vector tableNames = { childTableName_, parentTableName_ }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::INVALID_ARGS); + + tableNames = { sharedChildTableName_, sharedParentTableName_ }; + query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::INVALID_ARGS); + + tableNames = { sharedChildTableName_, parentTableName_ }; + query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::OK); + + tableNames = { childTableName_, sharedParentTableName_ }; + query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::OK); +} + +/** + * @tc.name: CloudSyncTest004 + * @tc.desc: sync shared table and check version, cloud insert, local update, local delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest004, TestSize.Level0) +{ + /** + * @tc.steps: step1. cloud insert records then sync, check distributed shared table + * @tc.expected: OK. + */ + int64_t num = 200; + std::vector tableNames = { sharedParentTableName_, sharedChildTableName_ }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + InsertCloudSharedTableRecord(0, num, 10240, true); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckDistributedSharedData({"0", "200"}); + + /** + * @tc.steps: step2. user update records then sync, check distributed shared table + * @tc.expected: OK. + */ + UpdateUserTableRecord(sharedParentTableName_, 0, num); + UpdateUserTableRecord(sharedChildTableName_, 0, num); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckDistributedSharedData({"400", "600"}); + CheckCloudData(sharedParentTableName_, false, {}); + std::vector expectEntries; + Entries entries; + for (size_t i = 0; i < 100; i++) { // 100 is max cloud query num + entries[sharedParentTableName_] = std::to_string(i); + expectEntries.push_back(entries); + } + CheckCloudData(sharedChildTableName_, true, expectEntries); + + /** + * @tc.steps: step3. user delete records then sync, check distributed shared table + * @tc.expected: OK. + */ + DeleteUserTableRecord(sharedParentTableName_, 0, 1); + DeleteUserTableRecord(sharedChildTableName_, 0, 1); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckDistributedSharedData({"400", "600"}); +} + +/** + * @tc.name: CloudSyncTest005 + * @tc.desc: sync shared table and check version, local insert, cloud delete, local update + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest005, TestSize.Level0) +{ + /** + * @tc.steps: step1. user insert records then sync, check distributed shared table + * @tc.expected: OK. + */ + std::vector tableNames = { sharedParentTableName_, sharedChildTableName_ }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + InsertUserTableRecord(sharedParentTableName_, 1, true, 0); + InsertUserTableRecord(sharedChildTableName_, 1, true, 0); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckDistributedSharedData({"0", "1"}); + + /** + * @tc.steps: step2. user update records then sync, check distributed shared table + * @tc.expected: OK. + */ + DeleteCloudSharedTableRecordByGid(0, 2); + UpdateUserTableRecord(sharedParentTableName_, 0, 1); + UpdateUserTableRecord(sharedChildTableName_, 0, 1); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckDistributedSharedData({"2", "3"}); + CheckCloudData(sharedParentTableName_, false, {}); + std::vector expectEntries; + Entries entries; + entries[sharedParentTableName_] = "0"; + expectEntries.push_back(entries); + entries = {}; + entries[sharedParentTableName_] = "2"; + expectEntries.push_back(entries); + CheckCloudData(sharedChildTableName_, true, expectEntries); +} + +/** + * @tc.name: CloudSyncTest006 + * @tc.desc: sync shared table and check version, cloud insert, cloud update + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest006, TestSize.Level0) +{ + /** + * @tc.steps: step1. user insert records then sync, check distributed shared table + * @tc.expected: OK. + */ + std::vector tableNames = { sharedParentTableName_, sharedChildTableName_ }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + InsertCloudSharedTableRecord(0, 1, 1, true); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckDistributedSharedData({"0", "1"}); + + /** + * @tc.steps: step2. cloud update records then sync, check distributed shared table + * @tc.expected: OK. + */ + UpdateCloudSharedTableRecord(0, 1, 1, true); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckDistributedSharedData({"2", "3"}); +} + +/** + * @tc.name: CloudSyncTest007 + * @tc.desc: there is no gid locally, shared table sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, CloudSyncTest007, TestSize.Level0) +{ + /** + * @tc.steps: step1. user insert records then sync, check distributed shared table + * @tc.expected: OK. + */ + std::vector tableNames = { sharedParentTableName_, sharedChildTableName_ }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + InsertUserTableRecord(sharedParentTableName_, 1, true, 0, "a_owner"); + InsertUserTableRecord(sharedChildTableName_, 1, true, 0, "a_owner"); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + InsertCloudSharedTableRecord(0, 1, 1, true); + RelationalTestUtils::CloudBlockSync(query, delegate_); + CheckSharedDataAfterUpdated({166.0, 166.0}); // 166.0 is the height col val on the cloud +} + +void ComplexReferenceCheck001SetReference(RelationalStoreDelegate *delegate) +{ + // the reference like this + // h <- a + // b c + // d e f g + std::vector tableReferenceProperty; + TableReferenceProperty property; + property.sourceTableName = "table_d"; + property.targetTableName = "table_b"; + property.columns["name"] = "name"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_e"; + property.targetTableName = "table_b"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_f"; + property.targetTableName = "table_c"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_g"; + property.targetTableName = "table_c"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_b"; + property.targetTableName = "table_a"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_b"; + property.targetTableName = "table_h"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_c"; + property.targetTableName = "table_a"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_a"; + property.targetTableName = "table_h"; + tableReferenceProperty.push_back(property); + delegate->SetReference(tableReferenceProperty); +} + +/** + * @tc.name: ComplexReferenceCheck001 + * @tc.desc: sync with complex table reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck001, TestSize.Level0) +{ + auto tableName = InitMultiTable(8); // 8 table + ComplexReferenceCheck001SetReference(delegate_); + ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); + + std::vector tableNames = { "table_a", "table_b", "table_d" }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + + tableNames = { "table_a", "table_b", "table_c", "table_h" }; + query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_, INVALID_ARGS); + + tableNames = { "table_h", "table_e" }; + query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + + tableNames = { "table_e" }; + query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); +} + +void ComplexReferenceCheck002SetReference(RelationalStoreDelegate *delegate) +{ + // the reference like this + // a -> b -> c -> d -> e + std::vector tableReferenceProperty; + TableReferenceProperty property; + property.sourceTableName = "table_a"; + property.targetTableName = "table_b"; + property.columns["name"] = "name"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_c"; + property.targetTableName = "table_d"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_d"; + property.targetTableName = "table_e"; + tableReferenceProperty.push_back(property); + + property.sourceTableName = "table_b"; + property.targetTableName = "table_c"; + tableReferenceProperty.push_back(property); + + delegate->SetReference(tableReferenceProperty); +} + +/** + * @tc.name: ComplexReferenceCheck002 + * @tc.desc: sync with complex table reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck002, TestSize.Level0) +{ + auto tableName = InitMultiTable(5); // 5 table + ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); + ComplexReferenceCheck002SetReference(delegate_); + + std::vector tableNames = { "table_a", "table_e" }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_, DistributedDB::INVALID_ARGS); + + tableNames = { "table_e", "table_a" }; + query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + + tableNames = { "table_a", "table_a_shared" }; + query = Query::Select().FromTable(tableNames); + std::vector actualTables; + std::set addTables; + virtualCloudDb_->ForkQuery([&addTables, &actualTables](const std::string &table, VBucket &) { + if (addTables.find(table) != addTables.end()) { + return ; + } + actualTables.push_back(table); + addTables.insert(table); + }); + RelationalTestUtils::CloudBlockSync(query, delegate_); + virtualCloudDb_->ForkQuery(nullptr); + for (const auto &item : actualTables) { + LOGW("table is %s", item.c_str()); + } + ASSERT_EQ(actualTables.size(), tableName.size() * 2); // 2 is table size + shared table size + // expect res table is table_e table_d ... table_e_shared table_a_shared + for (size_t i = 0; i < tableName.size(); ++i) { + size_t expectIndex = tableName.size() - 1 - i; + size_t expectSharedIndex = expectIndex + tableName.size(); + const std::string actualTable = actualTables[expectIndex]; + const std::string actualSharedTable = actualTables[expectSharedIndex]; + bool equal = (actualTable == tableName[i]); + equal &= (actualSharedTable == (tableName[i] + "_shared")); + LOGW("index %zu expectIndex %zu expectSharedIndex %zu actualTable %s actualSharedTable %s", + i, expectIndex, expectSharedIndex, actualTable.c_str(), actualSharedTable.c_str()); + EXPECT_TRUE(equal); + } +} + +/** + * @tc.name: ComplexReferenceCheck003 + * @tc.desc: sync with complex table reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck003, TestSize.Level0) +{ + /** + * @tc.steps: step1. init reference table, and reopen db + * @tc.expected: OK. + */ + auto tableName = InitMultiTable(8); // 8 table + ComplexReferenceCheck001SetReference(delegate_); + ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); + virtualCloudDb_ = nullptr; + EXPECT_EQ(mgr_->CloseStore(delegate_), DBStatus::OK); + delegate_ = nullptr; + RelationalStoreDelegate::Option option; + ASSERT_EQ(mgr_->OpenStore(storePath_, STORE_ID_1, option, delegate_), DBStatus::OK); + ASSERT_NE(delegate_, nullptr); + virtualCloudDb_ = std::make_shared(); + ASSERT_EQ(delegate_->SetCloudDB(virtualCloudDb_), DBStatus::OK); + ASSERT_EQ(delegate_->SetIAssetLoader(std::make_shared()), DBStatus::OK); + ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); + tableName = InitMultiTable(8); + + /** + * @tc.steps: step2. init local data, sync + * @tc.expected: OK. + */ + int64_t num = 10; + InsertUserTableRecord("table_a", num); + InsertUserTableRecord("table_b", num); + InsertUserTableRecord("table_c", num); + std::vector tableNames = { "table_a", "table_b", "table_c" }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + + /** + * @tc.steps: step3. operator target table, check source table timeStamp + * @tc.expected: OK. + */ + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT max(timestamp) FROM " + DBCommon::GetLogTableName("table_c"), + stmt), E_OK); + ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + int64_t timeStamp = static_cast(sqlite3_column_int64(stmt, 0)); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + std::string updateSql = "UPDATE table_a SET name = '99' where id = 1"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK); + std::string deleteSql = "DELETE FROM table_a where id = 2"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, deleteSql), SQLITE_OK); + updateSql = "UPDATE table_a SET age = '99' where id = 3"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK); + stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT count(*) FROM " + DBCommon::GetLogTableName("table_c") + + " WHERE timestamp > '" + std::to_string(timeStamp) + "';", stmt), E_OK); + ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + int64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + SQLiteUtils::ResetStatement(stmt, true, errCode); + EXPECT_EQ(count, 2L); // 2 is changed log num + RelationalTestUtils::CloudBlockSync(query, delegate_); +} + +/** + * @tc.name: ComplexReferenceCheck004 + * @tc.desc: sync with complex table reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck004, TestSize.Level0) +{ + /** + * @tc.steps: step1. init table and set reference twice + * @tc.expected: OK. + */ + auto tableName = InitMultiTable(8); // 8 table + ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); + ComplexReferenceCheck001SetReference(delegate_); + ComplexReferenceCheck001SetReference(delegate_); + + /** + * @tc.steps: step2. init local data, sync + * @tc.expected: OK. + */ + InsertUserTableRecord("table_b", 10); + InsertUserTableRecord("table_d", 10); + InsertUserTableRecord("table_e", 10); + std::vector tableNames = { "table_b", "table_d", "table_e" }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); + + /** + * @tc.steps: step3. operator target table, check source table timeStamp + * @tc.expected: OK. + */ + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT max(timestamp) FROM " + DBCommon::GetLogTableName("table_d"), + stmt), E_OK); + ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + int64_t timeStamp = static_cast(sqlite3_column_int64(stmt, 0)); + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); + std::string updateSql = "UPDATE table_b SET name = '99' where id = 4"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK); + std::string deleteSql = "DELETE FROM table_b where id = 6"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, deleteSql), SQLITE_OK); + updateSql = "UPDATE table_b SET age = '99' where id = 7"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db_, updateSql), SQLITE_OK); + stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db_, "SELECT count(*) FROM " + DBCommon::GetLogTableName("table_d") + + " WHERE timestamp > '" + std::to_string(timeStamp) + "';", stmt), E_OK); + ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); + int64_t count = static_cast(sqlite3_column_int64(stmt, 0)); + SQLiteUtils::ResetStatement(stmt, true, errCode); + EXPECT_EQ(count, 2L); + RelationalTestUtils::CloudBlockSync(query, delegate_); +} + +/** + * @tc.name: ComplexReferenceCheck005 + * @tc.desc: sync with complex table reference + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, ComplexReferenceCheck005, TestSize.Level1) +{ + auto tableName = InitMultiTable(26); // 26 table is alphabet count + ASSERT_EQ(delegate_->SetCloudDbSchema(GetSchema(tableName)), DBStatus::OK); + std::vector tableReferenceProperty; + TableReferenceProperty property; + property.columns["name"] = "name"; + for (size_t i = 0; i < tableName.size() - 1; ++i) { + property.sourceTableName = tableName[i]; + property.targetTableName = tableName[i + 1]; + tableReferenceProperty.push_back(property); + } + delegate_->SetReference(tableReferenceProperty); + + std::vector tableNames = { "table_e" }; + Query query = Query::Select().FromTable(tableNames); + RelationalTestUtils::CloudBlockSync(query, delegate_); +} + +/** + * @tc.name: SetSharedReference001 + * @tc.desc: test set shared table + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudReferenceSyncTest, SetSharedReference001, TestSize.Level0) +{ + std::vector tableReferenceProperty; + TableReferenceProperty property; + property.columns["name"] = "name"; + property.sourceTableName = childTableName_; + property.targetTableName = sharedParentTableName_; + tableReferenceProperty.push_back(property); + EXPECT_EQ(delegate_->SetReference(tableReferenceProperty), NOT_SUPPORT); + + property.sourceTableName = sharedChildTableName_; + property.targetTableName = parentTableName_; + tableReferenceProperty.clear(); + tableReferenceProperty.push_back(property); + EXPECT_EQ(delegate_->SetReference(tableReferenceProperty), NOT_SUPPORT); + + property.sourceTableName = sharedChildTableName_; + property.targetTableName = sharedParentTableName_; + tableReferenceProperty.clear(); + tableReferenceProperty.push_back(property); + EXPECT_EQ(delegate_->SetReference(tableReferenceProperty), NOT_SUPPORT); +} +} +#endif // RELATIONAL_STORE \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp index c8b53608e1be07a803db62fc6e8024483add07d3..f6c10da7f66fe1a3ce459649fb40999da0a5be46 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/distributeddb_cloud_save_cloud_data_test.cpp @@ -21,14 +21,14 @@ #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "icloud_sync_storage_interface.h" +#include "mock_relational_sync_able_storage.h" #include "relational_store_instance.h" #include "relational_store_manager.h" #include "relational_sync_able_storage.h" +#include "runtime_config.h" #include "sqlite_relational_store.h" #include "storage_proxy.h" #include "virtual_cloud_data_translate.h" -#include "runtime_config.h" - using namespace testing::ext; using namespace DistributedDB; @@ -79,7 +79,7 @@ namespace { EXPECT_EQ(sqlite3_close_v2(db), E_OK); } - void SetCloudSchema(PrimaryKeyType pkType, bool nullable) + void SetCloudSchema(PrimaryKeyType pkType, bool nullable, bool asset = false) { TableSchema tableSchema; bool isIdPk = pkType == PrimaryKeyType::SINGLE_PRIMARY_KEY || pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY; @@ -87,12 +87,19 @@ namespace { Field field2 = { "name", TYPE_INDEX, pkType == PrimaryKeyType::COMPOSITE_PRIMARY_KEY, true }; Field field3 = { "age", TYPE_INDEX, false, true }; Field field4 = { "sex", TYPE_INDEX, false, nullable }; - Field field5 = { "image", TYPE_INDEX, false, true }; - tableSchema = { g_tableName, { field1, field2, field3, field4, field5} }; - + Field field5; + if (asset) { + field5 = { "image", TYPE_INDEX, false, true }; + } else { + field5 = { "image", TYPE_INDEX, false, true }; + } + tableSchema = { g_tableName, "", { field1, field2, field3, field4, field5} }; DataBaseSchema dbSchema; - dbSchema.tables = { tableSchema }; - g_cloudStore->SetCloudDbSchema(dbSchema); + dbSchema.tables.push_back(tableSchema); + tableSchema = { g_assetTableName, "", { field1, field2, field3, field4, field5} }; + dbSchema.tables.push_back(tableSchema); + + g_delegate->SetCloudDbSchema(dbSchema); } void PrepareDataBase(const std::string &tableName, PrimaryKeyType pkType, bool nullable = true) @@ -159,6 +166,32 @@ namespace { SetCloudSchema(pkType, nullable); } + void PrepareDataBaseForAsset(const std::string &tableName, bool nullable = true) + { + sqlite3 *db = RelationalTestUtils::CreateDataBase(g_dbDir + STORE_ID + DB_SUFFIX); + EXPECT_NE(db, nullptr); + std::string sql = + "create table " + tableName + "(id int, name TEXT, age REAL, sex INTEGER, image BLOB);"; + EXPECT_EQ(RelationalTestUtils::ExecSql(db, sql), E_OK); + EXPECT_EQ(g_delegate->CreateDistributedTable(tableName, DistributedDB::CLOUD_COOPERATION), OK); + + sql = "insert into " + tableName + "(id, name, image) values(1, 'zhangsan1', ?);"; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), SQLITE_OK); + Asset asset; + asset.name = "123"; + asset.status = static_cast(AssetStatus::ABNORMAL); + VirtualCloudDataTranslate translate; + Bytes bytes = translate.AssetToBlob(asset); + EXPECT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, bytes), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + int errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, errCode); + + EXPECT_EQ(sqlite3_close_v2(db), E_OK); + SetCloudSchema(PrimaryKeyType::NO_PRIMARY_KEY, nullable, true); + } + void InitStoreProp(const std::string &storePath, const std::string &appId, const std::string &userId, RelationalDBProperties &properties) { @@ -465,11 +498,11 @@ namespace { TableSchema tableSchema; Field field1 = { "name", TYPE_INDEX, true, false }; Field field2 = { "age", TYPE_INDEX, ageIsPrimaryKey, false }; - tableSchema = { g_tableName, { field1, field2 } }; + tableSchema = { g_tableName, "", { field1, field2 } }; DataBaseSchema dbSchema; dbSchema.tables = { tableSchema }; - g_cloudStore->SetCloudDbSchema(dbSchema); + g_delegate->SetCloudDbSchema(dbSchema); } void PrimaryKeyCollateTest(const std::string &createSql, const std::string &insertSql, @@ -1333,4 +1366,110 @@ namespace { EXPECT_EQ(count, 1); EXPECT_EQ(sqlite3_close_v2(db), E_OK); } + + /** + * @tc.name: GetDataWithAsset001 + * @tc.desc: Test get data with abnormal asset + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, GetDataWithAsset001, TestSize.Level0) + { + /** + * @tc.steps:step1. create db, create table, prepare data. + * @tc.expected: step1. success. + */ + PrepareDataBaseForAsset(g_assetTableName, true); + RuntimeConfig::SetCloudTranslate(std::make_shared()); + std::shared_ptr storageProxy = GetStorageProxy(g_cloudStore); + ASSERT_NE(storageProxy, nullptr); + int errCode = storageProxy->StartTransaction(); + EXPECT_EQ(errCode, E_OK); + /** + * @tc.steps:step2. create db, create table, prepare data. + * @tc.expected: step2. success. + */ + ContinueToken token = nullptr; + CloudSyncData data(g_assetTableName); + errCode = storageProxy->GetCloudData(g_assetTableName, 0u, token, data); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(data.ignoredCount, 1); + + EXPECT_EQ(storageProxy->Commit(), E_OK); + EXPECT_EQ(token, nullptr); + RuntimeConfig::SetCloudTranslate(nullptr); + } + + void CheckCloudBatchData(CloudSyncBatch &batchData, bool existRef) + { + for (size_t i = 0u; i < batchData.rowid.size(); ++i) { + int64_t rowid = batchData.rowid[i]; + auto &extend = batchData.extend[i]; + ASSERT_EQ(extend.find(CloudDbConstant::REFERENCE_FIELD) != extend.end(), existRef); + if (!existRef) { + continue; + } + Entries entries = std::get(extend[CloudDbConstant::REFERENCE_FIELD]); + EXPECT_EQ(std::to_string(rowid), entries["targetTable"]); + } + } + + /** + * @tc.name: FillReferenceGid001 + * @tc.desc: Test fill gid data with normal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, FillReferenceGid001, TestSize.Level0) + { + auto storage = new(std::nothrow) MockRelationalSyncAbleStorage(); + CloudSyncData syncData("FillReferenceGid001"); + EXPECT_CALL(*storage, GetReferenceGid).WillRepeatedly([&syncData](const std::string &tableName, + const CloudSyncBatch &syncBatch, std::map &referenceGid) { + EXPECT_EQ(syncData.tableName, tableName); + EXPECT_EQ(syncBatch.rowid.size(), 1u); // has 1 record + for (auto rowid : syncBatch.rowid) { + Entries entries; + entries["targetTable"] = std::to_string(rowid); + referenceGid[rowid] = entries; + } + return E_OK; + }); + syncData.insData.rowid.push_back(1); // rowid is 1 + syncData.insData.extend.resize(1); // has 1 record + syncData.updData.rowid.push_back(2); // rowid is 2 + syncData.updData.extend.resize(1); // has 1 record + syncData.delData.rowid.push_back(3); // rowid is 3 + syncData.delData.extend.resize(1); // has 1 record + EXPECT_EQ(storage->CallFillReferenceData(syncData), E_OK); + CheckCloudBatchData(syncData.insData, true); + CheckCloudBatchData(syncData.updData, true); + CheckCloudBatchData(syncData.delData, false); + RefObject::KillAndDecObjRef(storage); + } + + /** + * @tc.name: FillReferenceGid002 + * @tc.desc: Test fill gid data with abnormal + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ + HWTEST_F(DistributedDBCloudSaveCloudDataTest, FillReferenceGid002, TestSize.Level0) + { + auto storage = new(std::nothrow) MockRelationalSyncAbleStorage(); + CloudSyncData syncData("FillReferenceGid002"); + syncData.insData.rowid.push_back(1); // rowid is 1 + EXPECT_CALL(*storage, GetReferenceGid).WillRepeatedly([](const std::string &, + const CloudSyncBatch &, std::map &referenceGid) { + referenceGid[0] = {}; // create default + return E_OK; + }); + EXPECT_EQ(storage->CallFillReferenceData(syncData), -E_UNEXPECTED_DATA); + syncData.insData.extend.resize(1); // rowid is 1 + EXPECT_EQ(storage->CallFillReferenceData(syncData), E_OK); + RefObject::KillAndDecObjRef(storage); + } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/mock_relational_sync_able_storage.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/mock_relational_sync_able_storage.h new file mode 100644 index 0000000000000000000000000000000000000000..fd2306d79822e8431b042ce8d6824a618eb64bd0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/cloud/mock_relational_sync_able_storage.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MOCK_RELATIONAL_SYNC_ABLE_STORAGE_H +#define MOCK_RELATIONAL_SYNC_ABLE_STORAGE_H +#include +#include "relational_sync_able_storage.h" + +namespace DistributedDB { +class MockRelationalSyncAbleStorage : public RelationalSyncAbleStorage { +public: + MockRelationalSyncAbleStorage() : RelationalSyncAbleStorage(nullptr) + { + } + + int CallFillReferenceData(CloudSyncData &syncData) + { + return RelationalSyncAbleStorage::FillReferenceData(syncData); + } + + MOCK_METHOD3(GetReferenceGid, int(const std::string &, const CloudSyncBatch &, std::map &)); +}; +} +#endif // MOCK_RELATIONAL_SYNC_ABLE_STORAGE_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp index 53089db134690ae237a4bf1035187d0b4bc59ca0..d0a0216ac4da393e843d1a790ef33a53f9662781 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_cloud_schema_mgr_test.cpp @@ -74,6 +74,7 @@ DataBaseSchema g_schema = { .tables = { { .name = TABLE_NAME_1, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -91,6 +92,7 @@ DataBaseSchema g_schema = { }, { .name = TABLE_NAME_2, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -108,6 +110,7 @@ DataBaseSchema g_schema = { }, { .name = TABLE_NAME_3, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -131,6 +134,7 @@ DataBaseSchema g_schema = { }, { .name = TABLE_NAME_4, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -159,6 +163,7 @@ DataBaseSchema g_schema2 = { .tables = { { .name = TABLE_NAME_2, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -176,6 +181,7 @@ DataBaseSchema g_schema2 = { }, { .name = TABLE_NAME_3, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -193,6 +199,7 @@ DataBaseSchema g_schema2 = { }, { .name = TABLE_NAME_4, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -215,6 +222,7 @@ DataBaseSchema g_schema3 = { .tables = { { .name = TABLE_NAME_1, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_1, @@ -232,6 +240,7 @@ DataBaseSchema g_schema3 = { }, { .name = TABLE_NAME_2, + .sharedTableName = "", .fields = { { .colName = FIELD_NAME_4, diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp index eabfbabd6c7bcb074812fd065581a1bac1d17393..1d2c9fceeaaf022e18fd8d2051b9289f0e4974b0 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_query_object_helper_test.cpp @@ -15,10 +15,14 @@ #include +#include "cloud_db_types.h" #include "db_errno.h" #include "get_query_info.h" #include "log_print.h" #include "query_object.h" +#include "query_sync_object.h" +#include "relational_store_manager.h" +#include "version.h" using namespace testing::ext; using namespace DistributedDB; @@ -40,7 +44,7 @@ const std::string VALID_SCHEMA_FULL_DEFINE = "{\"SCHEMA_VERSION\":\"1.0\"," "\"SCHEMA_INDEXES\":[\"$.field_name1\", \"$.field_name2.field_name6\"]}"; const std::string TEST_FIELD_NAME = "$.field_name2.field_name6"; -static void GetQuerySql(const Query &query) +void GetQuerySql(const Query &query) { QueryObject queryObj(query); @@ -56,6 +60,26 @@ static void GetQuerySql(const Query &query) helper.GetQuerySql(sql, false); LOGD("[UNITTEST][sql] = [%s]", sql.c_str()); } + +void CheckType(const Type &expectType, const Type &actualType) +{ + ASSERT_EQ(expectType.index(), actualType.index()); + if (expectType.index() != TYPE_INDEX) { + return; + } + std::string expectStr = std::get(expectType); + std::string actualStr = std::get(actualType); + EXPECT_EQ(expectStr, actualStr); +} + +void CheckQueryNode(const QueryNode &expectNode, const QueryNode &actualNode) +{ + EXPECT_EQ(expectNode.type, actualNode.type); + EXPECT_EQ(expectNode.fieldName, actualNode.fieldName); + ASSERT_EQ(expectNode.fieldValue.size(), actualNode.fieldValue.size()); + for (size_t i = 0; i < expectNode.fieldValue.size(); ++i) { + CheckType(expectNode.fieldValue[i], actualNode.fieldValue[i]); + } } class DistributedDBQueryObjectHelperTest : public testing::Test { @@ -179,4 +203,111 @@ HWTEST_F(DistributedDBQueryObjectHelperTest, Query003, TestSize.Level1) Query query1 = Query::Select().GreaterThan(TEST_FIELD_NAME, 1).OrderBy(TEST_FIELD_NAME); GetQuerySql(query1); +} + +std::vector> Query004GetExpectNode() +{ + std::vector> expectNode; + expectNode.push_back({ + QueryNode { + .type = QueryNodeType::BEGIN_GROUP, + .fieldName = "", + .fieldValue = {} + }, QueryNode { + .type = QueryNodeType::EQUAL_TO, + .fieldName = "field1", + .fieldValue = {std::string("1")} + }, QueryNode { + .type = QueryNodeType::AND, + .fieldName = "", + .fieldValue = {} + }, QueryNode { + .type = QueryNodeType::EQUAL_TO, + .fieldName = "field2", + .fieldValue = {std::string("2")} + }, QueryNode { + .type = QueryNodeType::END_GROUP, + .fieldName = "", + .fieldValue = {} + }, QueryNode { + .type = QueryNodeType::OR, + .fieldName = "", + .fieldValue = {} + }, QueryNode { + .type = QueryNodeType::BEGIN_GROUP, + .fieldName = "", + .fieldValue = {} + }, QueryNode { + .type = QueryNodeType::EQUAL_TO, + .fieldName = "field1", + .fieldValue = {std::string("2")} + }, QueryNode { + .type = QueryNodeType::AND, + .fieldName = "", + .fieldValue = {} + }, QueryNode { + .type = QueryNodeType::EQUAL_TO, + .fieldName = "field2", + .fieldValue = {std::string("1")} + }, QueryNode { + .type = QueryNodeType::END_GROUP, + .fieldName = "", + .fieldValue = {} + }}); + return expectNode; +} + +std::vector Query004GetTable2ExpectNode() +{ + return { + QueryNode { + .type = QueryNodeType::IN, + .fieldName = "field3", + .fieldValue = {std::string("1"), std::string("2"), std::string("3")} + } + }; +} + +/** + * @tc.name: Query004 + * @tc.desc: Check query transform in serialize func + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBQueryObjectHelperTest, Query004, TestSize.Level1) +{ + std::vector inVal = {"1", "2", "3"}; + Query query = Query::Select().From("table1").BeginGroup(). + EqualTo("field1", "1").And().EqualTo("field2", "2"). + EndGroup().Or().BeginGroup().EqualTo("field1", "2").And().EqualTo("field2", "1").EndGroup(). + From("table2").In("field3", inVal); + + std::vector objectList = QuerySyncObject::GetQuerySyncObject(query); + ASSERT_EQ(objectList.size(), 2u); // 2 tables + + std::vector> expectNode = Query004GetExpectNode(); + expectNode.emplace_back(Query004GetTable2ExpectNode()); + std::vector> actualNode; + for (auto &object: objectList) { + ASSERT_TRUE(object.IsContainQueryNodes()); + Bytes bytes; + bytes.resize(object.CalculateParcelLen(SOFTWARE_VERSION_CURRENT)); + Parcel parcel(bytes.data(), bytes.size()); + EXPECT_EQ(object.SerializeData(parcel, SOFTWARE_VERSION_CURRENT), E_OK); + DBStatus status; + auto nodeList = RelationalStoreManager::ParserQueryNodes(bytes, status); + EXPECT_EQ(status, OK); + actualNode.emplace_back(nodeList); + } + + ASSERT_EQ(actualNode.size(), expectNode.size()); + for (size_t i = 0; i < actualNode.size(); ++i) { + for (size_t j = 0; j < actualNode[i].size(); ++j) { + ASSERT_EQ(actualNode[i].size(), expectNode[i].size()); + LOGD("check %zu table %zu node", i, j); + CheckQueryNode(expectNode[i][j], actualNode[i][j]); + } + } +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp index e494e9c2776ffc1f675f1b2e6ffcc15d68efc2ef..18b934e4fb1ba0bed4df45972d484c0fbcafbdac 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_relational_cloud_syncable_storage_test.cpp @@ -15,7 +15,7 @@ #ifdef RELATIONAL_STORE #include -#include "cloud_db_constant.h" +#include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "log_table_manager_factory.h" @@ -25,6 +25,7 @@ #include "relational_sync_able_storage.h" #include "runtime_config.h" #include "sqlite_relational_store.h" +#include "virtual_asset_loader.h" #include "virtual_cloud_data_translate.h" @@ -57,9 +58,10 @@ const std::vector g_cloudFiled = { {"assert", TYPE_INDEX}, {"asserts", TYPE_INDEX} }; const Asset g_localAsset = { - .version = 1, .name = "Phone", .uri = "/local/sync", .modifyTime = "123456", .createTime = "", - .size = "256", .hash = " ", .flag = static_cast(AssetOpType::NO_CHANGE), - .status = static_cast(AssetStatus::NORMAL), .timestamp = 0L + .version = 1, .name = "Phone", .assetId = "0", .subpath = "/local/sync", .uri = "/local/sync", + .modifyTime = "123456", .createTime = "", .size = "256", .hash = " ", + .flag = static_cast(AssetOpType::NO_CHANGE), .status = static_cast(AssetStatus::NORMAL), + .timestamp = 0L }; DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreDelegate *g_delegate = nullptr; @@ -98,7 +100,7 @@ void CreateLogTable() sqlite3_close(db); } -void CreateAndInitUserTable(int64_t count, int64_t photoSize) +void CreateAndInitUserTable(int64_t count, int64_t photoSize, const Asset &expect) { sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); @@ -107,15 +109,15 @@ void CreateAndInitUserTable(int64_t count, int64_t photoSize) std::string photo(photoSize, 'v'); std::vector assetBlob; std::vector assetsBlob; - Asset asset = g_localAsset; + Asset asset = expect; int id = 0; Assets assets; - asset.name = g_localAsset.name + std::to_string(id++); + asset.name = expect.name + std::to_string(id++); assets.push_back(asset); - asset.name = g_localAsset.name + std::to_string(id++); + asset.name = expect.name + std::to_string(id++); assets.push_back(asset); int errCode; - ASSERT_EQ(RuntimeContext::GetInstance()->AssetToBlob(g_localAsset, assetBlob), E_OK); + ASSERT_EQ(RuntimeContext::GetInstance()->AssetToBlob(expect, assetBlob), E_OK); ASSERT_EQ(RuntimeContext::GetInstance()->AssetsToBlob(assets, assetsBlob), E_OK); for (int i = 1; i <= count; ++i) { string sql = "INSERT OR REPLACE INTO " + g_tableName + @@ -142,24 +144,31 @@ void InitLogData(int64_t insCount, int64_t updCount, int64_t delCount, int64_t e std::string flag; std::string cloudGid; for (int64_t i = 1; i <= insCount + updCount + delCount + excludeCount; ++i) { + std::string index = std::to_string(i); if (i <= insCount) { flag = std::to_string(g_localFlag); cloudGid = "''"; } else if (i > insCount && i <= insCount + updCount) { flag = std::to_string(g_localFlag); - cloudGid = "'" + g_storeID + std::to_string(i) + "'"; + cloudGid = "'" + g_storeID + index + "'"; } else if (i > (insCount + updCount) && i <= (insCount + updCount + delCount)) { flag = std::to_string(g_localFlag | g_deleteFlag); - cloudGid = "'" + g_storeID + std::to_string(i) + "'"; + cloudGid = "'" + g_storeID + index + "'"; } else { flag = std::to_string(g_localFlag | g_deleteFlag); cloudGid = "''"; } + Bytes hashKey(index.begin(), index.end()); string sql = "INSERT OR REPLACE INTO " + g_logTblName + " (data_key, device, ori_device, timestamp, wtimestamp, flag, hash_key, cloud_gid)" + " VALUES ('" + std::to_string(i) + "', '', '', '" + std::to_string(g_startTime + i) + "', '" + - std::to_string(g_startTime + i) + "','" + flag + "','" + std::to_string(i) + "', " + cloudGid + ");"; - ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + std::to_string(g_startTime + i) + "','" + flag + "', ? , " + cloudGid + ");"; + sqlite3_stmt *stmt = nullptr; + int errCode = E_OK; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + EXPECT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, hashKey, false), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(stmt, true, errCode); } sqlite3_close(db); } @@ -176,9 +185,52 @@ void InitLogGid(int64_t count) sqlite3_close(db); } -void ConstructMultiDownloadData(int64_t count, DownloadData &downloadData) +void UpdateLogGidAndHashKey(int64_t count) +{ + sqlite3 *db = nullptr; + int errCode; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + for (int i = 1; i <= count; i++) { + std::string id = std::to_string(i); + string sql = "update " + g_logTblName + " set cloud_gid = '" + id + + "' , hash_key = ? where data_key = " + id; + sqlite3_stmt *stmt = nullptr; + EXPECT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + Bytes hashKey(id.begin(), id.end()); + EXPECT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, hashKey, false), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(stmt, true, errCode); + } + sqlite3_close(db); +} + +void CheckGetAsset(VBucket &assets, uint32_t status) { - for (int i = 1; i <= 5; i++) { // 5 is random num + EXPECT_EQ(assets.size(), 2u); + ASSERT_TRUE(assets["assert"].index() == TYPE_INDEX); + ASSERT_TRUE(assets["asserts"].index() == TYPE_INDEX); + Asset data1 = std::get(assets["assert"]); + ASSERT_EQ(data1.status, status); + Assets data2 = std::get(assets["asserts"]); + ASSERT_GT(data2.size(), 0u); + ASSERT_EQ(data2[0].status, static_cast(AssetStatus::NORMAL)); +} + +void InitLogicDelete(int64_t count) +{ + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + for (int i = 1; i <= count; i++) { + string sql = "update " + g_logTblName + " set flag = flag | 0x09" + " where data_key = " + std::to_string(i); + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + } + sqlite3_close(db); +} + +void ConstructMultiDownloadData(int64_t count, DownloadData &downloadData, std::vector &opTypes) +{ + for (size_t i = 1; i <= opTypes.size(); i++) { Asset asset = g_localAsset; Assets assets; VBucket vBucket; @@ -207,25 +259,38 @@ void ConstructMultiDownloadData(int64_t count, DownloadData &downloadData) vBucket[CloudDbConstant::CREATE_FIELD] = mTime; downloadData.data.push_back(vBucket); } - downloadData.opType = { OpType::DELETE, OpType::INSERT, OpType::UPDATE, - OpType::UPDATE, OpType::NOT_HANDLE }; + downloadData.opType = opTypes; +} + +void AddVersionToDownloadData(DownloadData &downloadData) +{ + for (size_t i = 0; i < downloadData.data.size(); i++) { + downloadData.data[i].insert_or_assign(CloudDbConstant::VERSION_FIELD, std::string("11")); + } +} + +void AddCloudOwnerToDownloadData(DownloadData &downloadData) +{ + for (size_t i = 0; i < downloadData.data.size(); i++) { + downloadData.data[i].insert_or_assign(CloudDbConstant::CLOUD_OWNER, std::to_string(i)); + } } void SetDbSchema(const TableSchema &tableSchema) { DataBaseSchema dataBaseSchema; dataBaseSchema.tables.push_back(tableSchema); - EXPECT_EQ(g_cloudStore->SetCloudDbSchema(dataBaseSchema), E_OK); + EXPECT_EQ(g_delegate->SetCloudDbSchema(dataBaseSchema), E_OK); } -void InitUserDataForAssetTest(int64_t insCount, int64_t photoSize) +void InitUserDataForAssetTest(int64_t insCount, int64_t photoSize, const Asset &expect) { sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db, CREATE_LOCAL_TABLE_SQL), E_OK); sqlite3_close(db); EXPECT_EQ(g_delegate->CreateDistributedTable(g_tableName, DistributedDB::CLOUD_COOPERATION), OK); - CreateAndInitUserTable(insCount, photoSize); + CreateAndInitUserTable(insCount, photoSize, expect); SetDbSchema(g_tableSchema); } @@ -348,6 +413,7 @@ void DistributedDBRelationalCloudSyncableStorageTest::SetUp(void) ASSERT_NE(g_cloudStore, nullptr); g_storageProxy = GetStorageProxy(g_cloudStore); ASSERT_NE(g_storageProxy, nullptr); + ASSERT_EQ(g_delegate->SetIAssetLoader(std::make_shared()), DBStatus::OK); } void DistributedDBRelationalCloudSyncableStorageTest::TearDown(void) @@ -369,7 +435,7 @@ void DistributedDBRelationalCloudSyncableStorageTest::TearDown(void) * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest001, TestSize.Level0) { EXPECT_EQ(g_cloudStore->PutMetaData(KEY_1, VALUE_2), E_OK); EXPECT_EQ(g_cloudStore->PutMetaData(KEY_1, VALUE_3), E_OK); @@ -386,7 +452,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest001, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest002, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest002, TestSize.Level0) { const string str(DBConstant::MAX_KEY_SIZE, 'k'); const Key key(str.begin(), str.end()); @@ -408,7 +474,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, MetaDataTest002, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest001, TestSize.Level0) { /** * @tc.steps: allow get or put meta in read transaction @@ -436,7 +502,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest001, Te * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest002, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest002, TestSize.Level0) { Timestamp cloudTime = 666888; Timestamp localTime; @@ -480,7 +546,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest002, Te * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest003, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest003, TestSize.Level0) { EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); @@ -514,7 +580,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest003, Te * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest004, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest004, TestSize.Level0) { /** * @tc.steps: transaction is not allowed after closing the proxy @@ -545,7 +611,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, TransactionTest004, Te * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, TestSize.Level0) { /** * @tc.steps: Table does not exist @@ -558,7 +624,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, Tes CreateLogTable(); int64_t insCount = 100; - CreateAndInitUserTable(insCount, insCount); + CreateAndInitUserTable(insCount, insCount, g_localAsset); InitLogData(insCount, insCount, insCount, insCount); EXPECT_EQ(g_cloudStore->GetUploadCount(query, g_startTime, false, resCount), E_OK); EXPECT_EQ(resCount, insCount + insCount + insCount); @@ -579,12 +645,12 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount001, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, TestSize.Level0) { CreateLogTable(); int64_t insCount = 100; InitLogData(insCount, insCount, 0, insCount); - CreateAndInitUserTable(insCount, insCount); + CreateAndInitUserTable(insCount, insCount, g_localAsset); int64_t resCount = 0; /** @@ -616,11 +682,11 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount002, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, TestSize.Level0) { CreateLogTable(); int64_t insCount = 100; - CreateAndInitUserTable(insCount, insCount); + CreateAndInitUserTable(insCount, insCount, g_localAsset); InitLogData(0, 0, insCount, insCount); int64_t resCount = 0; @@ -643,18 +709,19 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetUploadCount003, Tes * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestSize.Level0) { CreateLogTable(); int64_t insCount = 100; InitLogData(insCount, 0, insCount, insCount); - CloudSyncData syncData; + CloudSyncData syncData(g_tableName); + SetDbSchema(g_tableSchema); /** * @tc.steps: rowid set is empty * @tc.expected: return -E_INVALID_ARGS. */ - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), -E_INVALID_ARGS); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_INVALID_ARGS); syncData.insData.rowid.push_back(1); syncData.insData.rowid.push_back(2); // 2 is random id @@ -662,7 +729,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS * @tc.steps: insData set is empty * @tc.expected: return -E_INVALID_ARGS. */ - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), -E_INVALID_ARGS); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_INVALID_ARGS); VBucket bucket1; bucket1.insert_or_assign(g_tableName, g_tableName); bucket1.insert_or_assign(CloudDbConstant::GID_FIELD, 1L); @@ -672,7 +739,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS * @tc.steps: the size of rowid and insData is not equal * @tc.expected: return -E_INVALID_ARGS. */ - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), -E_INVALID_ARGS); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_INVALID_ARGS); /** * @tc.steps: table name is empty @@ -681,14 +748,15 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS VBucket bucket2; bucket2.insert_or_assign(CloudDbConstant::CREATE_FIELD, 2L); // 2L is random field syncData.insData.extend.push_back(bucket2); - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), -SQLITE_ERROR); + syncData.tableName = ""; + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_NOT_FOUND); /** * @tc.steps: the field type does not match * @tc.expected: return -E_INVALID_DATA. */ syncData.tableName = g_tableName; - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), -E_INVALID_DATA); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_INVALID_DATA); /** * @tc.steps: missing field GID_FIELD @@ -699,114 +767,19 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid001, TestS bucket2.insert_or_assign(CloudDbConstant::CREATE_FIELD, std::string("2")); syncData.insData.extend.push_back(bucket1); syncData.insData.extend.push_back(bucket2); - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), -E_INVALID_ARGS); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_INVALID_ARGS); syncData.insData.extend.pop_back(); bucket2.insert_or_assign(CloudDbConstant::GID_FIELD, std::string("2")); syncData.insData.extend.push_back(bucket2); - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), E_OK); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), E_OK); /** * @tc.steps: table name is not exists * @tc.expected: return -SQLITE_ERROR. */ syncData.tableName = "noneTable"; - EXPECT_EQ(g_cloudStore->FillCloudGid(syncData), -SQLITE_ERROR); -} - -/** - * @tc.name: FillCloudGid002 - * @tc.desc: Test whether the num of gid after fill are correct - * @tc.type: FUNC - * @tc.require: - * @tc.author: bty - */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid002, TestSize.Level1) -{ - CreateLogTable(); - int64_t insCount = 100; - int64_t updCount = 50; - int64_t delCount = 50; - InitLogData(insCount, updCount, delCount, insCount); - - CloudSyncData syncData(g_tableName); - for (int64_t i = 1; i <= 3 * insCount; ++i) { // 3 is insert,update and delete type data - syncData.insData.rowid.push_back(i); - VBucket bucket1; - bucket1.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(g_startTime + i)); - syncData.insData.extend.push_back(bucket1); - } - EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); - EXPECT_EQ(g_storageProxy->FillCloudGid(syncData), E_OK); - EXPECT_EQ(g_storageProxy->Commit(), E_OK); - - sqlite3 *db = nullptr; - ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); - std::string querySql = "SELECT COUNT(*) FROM " + g_logTblName + " WHERE cloud_gid in ("; - for (int64_t i = 1; i <= (insCount + updCount + delCount); ++i) { - querySql += "'" + std::to_string(g_startTime + i) + "',"; - } - querySql.pop_back(); - querySql += ");"; - EXPECT_EQ(sqlite3_exec(db, querySql.c_str(), - QueryCountCallback, reinterpret_cast(insCount + updCount + delCount), nullptr), SQLITE_OK); - sqlite3_close(db); -} - -/** - * @tc.name: FillCloudGid003 - * @tc.desc: Test FillCloudGid after in write transaction - * @tc.type: FUNC - * @tc.require: - * @tc.author: bty - */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid003, TestSize.Level1) -{ - CreateLogTable(); - int64_t insCount = 10; - InitLogData(insCount, insCount, insCount, insCount); - CloudSyncData syncData(g_tableName); - for (int64_t i = 1; i <= (insCount + insCount + insCount); ++i) { - syncData.insData.rowid.push_back(i); - VBucket bucket1; - bucket1.insert_or_assign(CloudDbConstant::GID_FIELD, std::to_string(g_startTime + i)); - syncData.insData.extend.push_back(bucket1); - } - - /** - * @tc.steps: FillCloudGid is not allowed after starting write transaction - * @tc.expected: return -E_BUSY. - */ - EXPECT_EQ(g_storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); - EXPECT_EQ(g_storageProxy->FillCloudGid(syncData), -E_BUSY); - EXPECT_EQ(g_storageProxy->Commit(), E_OK); -} - -/** - * @tc.name: FillCloudGid004 - * @tc.desc: Test FillCloudGid when gid is empty - * @tc.type: FUNC - * @tc.require: - * @tc.author: bty - */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid004, TestSize.Level1) -{ - CreateLogTable(); - int64_t insCount = 2; - InitLogData(insCount, insCount, insCount, insCount); - CloudSyncData syncData(g_tableName); - syncData.insData.rowid.push_back(0); - VBucket bucket1; - bucket1.insert_or_assign(CloudDbConstant::GID_FIELD, std::string("")); - syncData.insData.extend.push_back(bucket1); - - /** - * @tc.steps: FillCloudGid is not allowed when gid is empty - * @tc.expected: return -E_CLOUD_ERROR. - */ - EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); - EXPECT_EQ(g_storageProxy->FillCloudGid(syncData), -E_CLOUD_ERROR); - EXPECT_EQ(g_storageProxy->Commit(), E_OK); + EXPECT_EQ(g_cloudStore->FillCloudLogAndAsset(OpType::INSERT, syncData, false, false), -E_NOT_FOUND); } /** @@ -816,7 +789,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudGid004, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData001, TestSize.Level0) { CreateLogTable(); int64_t insCount = 100; @@ -824,10 +797,10 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData001, TestS int64_t delCount = 25; int64_t photoSize = 10; InitLogData(insCount, updCount, delCount, insCount); - CreateAndInitUserTable(3 * insCount, photoSize); // 3 is insert,update and delete type data + CreateAndInitUserTable(3 * insCount, photoSize, g_localAsset); // 3 is insert,update and delete type data ContinueToken token = nullptr; - CloudSyncData cloudSyncData; + CloudSyncData cloudSyncData(g_tableName); SetDbSchema(g_tableSchema); /** @@ -851,15 +824,6 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData001, TestS EXPECT_EQ(cloudSyncData.insData.record[0].find(CloudDbConstant::GID_FIELD), cloudSyncData.insData.record[0].end()); EXPECT_NE(cloudSyncData.updData.record[0].find(CloudDbConstant::GID_FIELD), cloudSyncData.insData.record[0].end()); EXPECT_NE(cloudSyncData.delData.record[0].find(CloudDbConstant::GID_FIELD), cloudSyncData.insData.record[0].end()); - - - /** - * @tc.steps: GetCloudData also can be called under write transaction - * @tc.expected: return E_OK. - */ - EXPECT_EQ(g_storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); - EXPECT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime + timeOffset, token, cloudSyncData), E_OK); - EXPECT_EQ(g_storageProxy->Commit(), E_OK); } /** @@ -869,13 +833,13 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData001, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData002, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData002, TestSize.Level0) { CreateLogTable(); int64_t insCount = 1024; int64_t photoSize = 512 * 3; InitLogData(insCount, insCount, insCount, insCount); - CreateAndInitUserTable(3 * insCount, photoSize); // 3 is insert,update and delete type data + CreateAndInitUserTable(3 * insCount, photoSize, g_localAsset); // 3 is insert,update and delete type data /** @@ -884,7 +848,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData002, TestS */ SetDbSchema(g_tableSchema); ContinueToken token = nullptr; - CloudSyncData cloudSyncData1; + CloudSyncData cloudSyncData1(g_tableName); int timeOffset = 10; EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); EXPECT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime + timeOffset, token, cloudSyncData1), @@ -893,12 +857,12 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData002, TestS cloudSyncData1.delData.record.size(), static_cast(insCount)); EXPECT_EQ(cloudSyncData1.delData.record.size(), 0u); - CloudSyncData cloudSyncData2; + CloudSyncData cloudSyncData2(g_tableName); EXPECT_EQ(g_storageProxy->GetCloudDataNext(token, cloudSyncData2), -E_UNFINISHED); EXPECT_LT(cloudSyncData2.insData.record.size() + cloudSyncData2.updData.record.size() + cloudSyncData2.delData.record.size(), static_cast(insCount)); - CloudSyncData cloudSyncData3; + CloudSyncData cloudSyncData3(g_tableName); EXPECT_EQ(g_storageProxy->GetCloudDataNext(token, cloudSyncData3), E_OK); EXPECT_GT(cloudSyncData3.insData.record.size() + cloudSyncData3.updData.record.size() + cloudSyncData3.delData.record.size(), static_cast(insCount)); @@ -919,17 +883,17 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData002, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestSize.Level0) { CreateLogTable(); int64_t insCount = 1024; int64_t photoSize = 1024 * 8; InitLogData(insCount, insCount, insCount, insCount); - CreateAndInitUserTable(2 * insCount, photoSize); // 2 is insert,update type data + CreateAndInitUserTable(2 * insCount, photoSize, g_localAsset); // 2 is insert,update type data SetDbSchema(g_tableSchema); ContinueToken token = nullptr; - CloudSyncData cloudSyncData; + CloudSyncData cloudSyncData(g_tableName); EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); EXPECT_EQ(g_storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), -E_UNFINISHED); @@ -951,13 +915,13 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData003, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestSize.Level0) { CreateLogTable(); int64_t insCount = 10; int64_t photoSize = 10; InitLogData(insCount, insCount, insCount, insCount); - CreateAndInitUserTable(3 * insCount, photoSize); // 3 is insert,update and delete type data + CreateAndInitUserTable(3 * insCount, photoSize, g_localAsset); // 3 is insert,update and delete type data SetDbSchema(g_tableSchema); sqlite3 *db = nullptr; @@ -965,7 +929,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestS ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db, "UPDATE " + g_tableName + " SET assert = NULL, asserts = NULL;"), E_OK); sqlite3_close(db); ContinueToken token = nullptr; - CloudSyncData cloudSyncData; + CloudSyncData cloudSyncData(g_tableName); EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); EXPECT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), E_OK); EXPECT_NE(cloudSyncData.insData.record.size(), 0u); @@ -987,17 +951,17 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData004, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestSize.Level0) { CreateLogTable(); int64_t insCount = 1024; int64_t photoSize = 1024 * 8; InitLogData(insCount, insCount, insCount, insCount); - CreateAndInitUserTable(2 * insCount, photoSize); // 2 is insert,update type data + CreateAndInitUserTable(2 * insCount, photoSize, g_localAsset); // 2 is insert,update type data SetDbSchema(g_tableSchema); ContinueToken token = nullptr; - CloudSyncData cloudSyncData; + CloudSyncData cloudSyncData(g_tableName); EXPECT_EQ(g_storageProxy->ReleaseContinueToken(token), E_OK); EXPECT_EQ(g_storageProxy->StartTransaction(TransactType::IMMEDIATE), E_OK); ASSERT_EQ(g_storageProxy->GetCloudData(g_tableName, g_startTime, token, cloudSyncData), -E_UNFINISHED); @@ -1017,7 +981,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData005, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestSize.Level0) { /** * @tc.steps:step1. Init data and set asset status to invalid num @@ -1027,7 +991,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestS int64_t insCount = 1024; int64_t photoSize = 1024; InitLogData(insCount, insCount, insCount, insCount); - CreateAndInitUserTable(2 * insCount, photoSize); // 2 is insert,update type data + CreateAndInitUserTable(2 * insCount, photoSize, g_localAsset); // 2 is insert,update type data Asset asset = g_localAsset; asset.status = static_cast(AssetStatus::UPDATE) + 1; UpdateLocalAsset(g_tableName, asset, 2L); // 2 is rowid @@ -1051,11 +1015,11 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetCloudData006, TestS * @tc.require: * @tc.author: bty */ -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrGid001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrGid001, TestSize.Level0) { int64_t insCount = 100; int64_t photoSize = 10; - InitUserDataForAssetTest(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); InitLogGid(insCount); EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); @@ -1081,15 +1045,45 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrG EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, TestSize.Level1) +/** + * @tc.name: GetInfoByPrimaryKeyOrGid002 + * @tc.desc: Test the query of the GetInfoByPrimaryKeyOrGid interface to obtain assets. + * @tc.type: FUNC + * @tc.require: + * @tc.author: zqq + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, GetInfoByPrimaryKeyOrGid002, TestSize.Level0) +{ + int64_t insCount = 5; + int64_t photoSize = 1; + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); + InitLogGid(insCount); + InitLogicDelete(insCount); + + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + for (int i = 1; i <= insCount; i++) { + VBucket vBucket; + vBucket[CloudDbConstant::GID_FIELD] = std::to_string(i); + VBucket assetInfo; + DataInfoWithLog dataInfo; + ASSERT_EQ(g_storageProxy->GetInfoByPrimaryKeyOrGid(g_tableName, vBucket, dataInfo, assetInfo), E_OK); + ASSERT_EQ(dataInfo.logInfo.cloudGid, std::to_string(i)); + EXPECT_EQ(assetInfo.size(), 0u); + } + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} + +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, TestSize.Level0) { int64_t insCount = 10; int64_t photoSize = 10; - InitUserDataForAssetTest(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); InitLogGid(insCount); DownloadData downloadData; - ConstructMultiDownloadData(insCount, downloadData); + std::vector opTypes = { OpType::DELETE, OpType::INSERT, OpType::UPDATE, + OpType::UPDATE, OpType::NOT_HANDLE }; + ConstructMultiDownloadData(insCount, downloadData, opTypes); EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); EXPECT_EQ(g_storageProxy->PutCloudSyncData(g_tableName, downloadData), E_OK); ContinueToken token = nullptr; @@ -1098,11 +1092,11 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncData001, T EXPECT_EQ(g_storageProxy->Commit(), E_OK); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, TestSize.Level0) { int64_t insCount = 10; int64_t photoSize = 10; - InitUserDataForAssetTest(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); InitLogGid(insCount); fillCloudAssetTest(insCount, AssetStatus::NORMAL, false); fillCloudAssetTest(insCount, AssetStatus::DOWNLOADING, false); @@ -1112,40 +1106,49 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset001, Tes fillCloudAssetTest(insCount, AssetStatus::ABNORMAL, true); } -HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, TestSize.Level1) +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset002, TestSize.Level0) { int64_t insCount = 10; int64_t photoSize = 10; - InitUserDataForAssetTest(insCount, photoSize); + Asset asset1 = g_localAsset; + asset1.status = static_cast(AssetStatus::DELETE | AssetStatus::UPLOADING); + InitUserDataForAssetTest(insCount, photoSize, asset1); InitLogGid(insCount); sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); sqlite3_stmt *stmt = nullptr; - ASSERT_EQ(SQLiteUtils::GetStatement(db, "SELECT timestamp FROM " + DBCommon::GetLogTableName(g_tableName) + ASSERT_EQ(SQLiteUtils::GetStatement(db, "SELECT timestamp, hash_key FROM " + DBCommon::GetLogTableName(g_tableName) + " WHERE data_key = 1;", stmt), E_OK); ASSERT_EQ(SQLiteUtils::StepWithRetry(stmt, false), SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)); int64_t timeStamp = static_cast(sqlite3_column_int64(stmt, 0)); - int errCode; + Bytes hashKey; + int errCode = SQLiteUtils::GetColumnBlobValue(stmt, 1, hashKey); // 1 is hash_key index + EXPECT_EQ(errCode, E_OK); SQLiteUtils::ResetStatement(stmt, true, errCode); CloudSyncData syncData(g_tableName); EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); - ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::UPDATE, syncData), E_OK); + ASSERT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::UPDATE, syncData), E_OK); syncData.updData.rowid.push_back(1L); VBucket bucket1; Asset asset = g_localAsset; asset.size = "888"; asset.flag = static_cast(AssetOpType::NO_CHANGE); - asset.status = static_cast(AssetStatus::DELETE); + asset.status = static_cast(AssetStatus::DELETE | AssetStatus::UPLOADING); bucket1.insert_or_assign("assert", asset); + int id = 0; Assets assets; + asset.name = asset1.name + std::to_string(id++); assets.push_back(asset); + asset.name = asset1.name + std::to_string(id++); assets.push_back(asset); bucket1.insert_or_assign("asserts", assets); syncData.updData.assets.push_back(bucket1); + syncData.updData.extend.push_back(bucket1); syncData.updData.timestamp.push_back(timeStamp); - ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::UPDATE, syncData), E_OK); + syncData.updData.hashKey.push_back(hashKey); + ASSERT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::UPDATE, syncData), E_OK); EXPECT_EQ(g_storageProxy->Commit(), E_OK); ASSERT_EQ(SQLiteUtils::GetStatement(db, "SELECT assert, asserts FROM " + g_tableName + " WHERE rowid = 1;", @@ -1168,7 +1171,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, Tes { int64_t insCount = 2; int64_t photoSize = 10; - InitUserDataForAssetTest(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); InitLogGid(insCount); sqlite3 *db = nullptr; @@ -1198,10 +1201,14 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset003, Tes bucket2.insert_or_assign("asserts", assets); syncData.updData.assets.push_back(bucket1); syncData.updData.assets.push_back(bucket2); + syncData.updData.extend.push_back(bucket1); + syncData.updData.extend.push_back(bucket2); syncData.updData.timestamp.push_back(timeStamp1); syncData.updData.timestamp.push_back(timeStamp2); + syncData.updData.hashKey.push_back({ 1 }); + syncData.updData.hashKey.push_back({ 2 }); EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); - ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::UPDATE, syncData), E_OK); + ASSERT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::UPDATE, syncData), E_OK); EXPECT_EQ(g_storageProxy->Commit(), E_OK); } @@ -1216,7 +1223,7 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset004, Tes { int64_t insCount = 2; int64_t photoSize = 10; - InitUserDataForAssetTest(insCount, photoSize); + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); sqlite3 *db = nullptr; ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); @@ -1248,9 +1255,10 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudAsset004, Tes bucket2.insert_or_assign("asserts", assets); syncData.insData.assets.push_back(bucket2); syncData.insData.timestamp.push_back(timeVector[i - 1]); + syncData.insData.hashKey.push_back({ 1 }); } EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); - ASSERT_EQ(g_storageProxy->FillCloudGidAndAsset(OpType::INSERT, syncData), E_OK); + ASSERT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::INSERT, syncData), E_OK); EXPECT_EQ(g_storageProxy->Commit(), E_OK); } @@ -1364,5 +1372,245 @@ HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, CalPrimaryKeyHash002, SQLiteUtils::ResetStatement(statement, true, errCode); sqlite3_close(db); } + +/* + * @tc.name: FillCloudVersion001 + * @tc.desc: Test FillCloudLogAndAsset interface when opType is UPDATE_VERSION + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, FillCloudVersion001, TestSize.Level0) +{ + /** + * @tc.steps: step1. init data + * @tc.expected: OK. + */ + int64_t insCount = 100; + int64_t photoSize = 10; + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); + + /** + * @tc.steps: step2. FillCloudLogAndAsset which isShared is false, but extend val is empty + * @tc.expected: OK. + */ + CloudSyncData syncData(g_tableName); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + EXPECT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::UPDATE_VERSION, syncData), E_OK); + + /** + * @tc.steps: step3. FillCloudLogAndAsset which isShared is true, but extend val is empty + * @tc.expected: OK. + */ + syncData.isShared = true; + EXPECT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::UPDATE_VERSION, syncData), E_OK); + + /** + * @tc.steps: step4. the extend size is not equal to the hashKey size + * @tc.expected: -E_INVALID_ARGS. + */ + VBucket extend1; + extend1.insert_or_assign(CloudDbConstant::VERSION_FIELD, std::string("1")); + syncData.delData.extend.push_back(extend1); + syncData.updData.extend.push_back(extend1); + syncData.insData.extend.push_back(extend1); + EXPECT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::UPDATE_VERSION, syncData), -E_INVALID_ARGS); + + /** + * @tc.steps: step5. the extend size is equal to the hashKey size + * @tc.expected: OK. + */ + std::string hashKeyStr = "1"; + Bytes hashKey(hashKeyStr.begin(), hashKeyStr.end()); + syncData.delData.hashKey.push_back(hashKey); + syncData.updData.hashKey.push_back(hashKey); + syncData.insData.hashKey.push_back(hashKey); + EXPECT_EQ(g_storageProxy->FillCloudLogAndAsset(OpType::UPDATE_VERSION, syncData), E_OK); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} + +/* + * @tc.name: PutCloudSyncVersion001 + * @tc.desc: Test PutCloudSyncData interface that table is share + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion001, TestSize.Level0) +{ + /** + * @tc.steps: step1. table type is shareTable, but downloadData is not contains version + * @tc.expected: -E_CLOUD_ERROR. + */ + int64_t insCount = 10; + int64_t photoSize = 10; + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); + InitLogGid(insCount); + DownloadData downloadData; + std::vector opTypes = { OpType::INSERT, OpType::INSERT, OpType::DELETE, OpType::UPDATE, + OpType::ONLY_UPDATE_GID, OpType::NOT_HANDLE }; + ConstructMultiDownloadData(insCount, downloadData, opTypes); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + EXPECT_EQ(g_storageProxy->PutCloudSyncData(g_tableName + CloudDbConstant::SHARED, downloadData), -E_CLOUD_ERROR); + EXPECT_EQ(g_storageProxy->Rollback(), E_OK); + + /** + * @tc.steps: step2. PutCloudSyncData and check table row num + * @tc.expected: E_OK. + */ + AddVersionToDownloadData(downloadData); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + EXPECT_EQ(g_storageProxy->PutCloudSyncData(g_tableName + CloudDbConstant::SHARED, downloadData), E_OK); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); + sqlite3 *db = nullptr; + ASSERT_EQ(sqlite3_open(g_storePath.c_str(), &db), SQLITE_OK); + std::string querySql = "SELECT COUNT(*) FROM " + DBConstant::RELATIONAL_PREFIX + g_tableName + + CloudDbConstant::SHARED + "_log"; + EXPECT_EQ(sqlite3_exec(db, querySql.c_str(), + QueryCountCallback, reinterpret_cast(2L), nullptr), SQLITE_OK); + sqlite3_close(db); +} + +/* + * @tc.name: PutCloudSyncVersion002 + * @tc.desc: Test PutCloudSyncData interface that download data is not contains version + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, PutCloudSyncVersion002, TestSize.Level0) +{ + /** + * @tc.steps: step1. table type is shareTable, but downloadData is not contains version + * @tc.expected: E_OK. + */ + int64_t insCount = 10; + int64_t photoSize = 10; + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); + InitLogGid(insCount); + DownloadData downloadData; + std::vector opTypes = { OpType::INSERT, OpType::INSERT, OpType::INSERT }; + ConstructMultiDownloadData(insCount, downloadData, opTypes); + AddVersionToDownloadData(downloadData); + AddCloudOwnerToDownloadData(downloadData); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + EXPECT_EQ(g_storageProxy->PutCloudSyncData(g_tableName + CloudDbConstant::SHARED, downloadData), E_OK); + + /** + * @tc.steps: step2. test opType of DELETE,UPDATE_TIMESTAMP,and CLEAR_GID without version field + * @tc.expected: E_OK. + */ + downloadData.opType = { OpType::DELETE, OpType::UPDATE_TIMESTAMP, OpType::CLEAR_GID }; + for (size_t i = 0; i < downloadData.data.size(); i++) { + downloadData.data[i].erase(CloudDbConstant::VERSION_FIELD); + } + EXPECT_EQ(g_storageProxy->PutCloudSyncData(g_tableName + CloudDbConstant::SHARED, downloadData), E_OK); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} + +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset001, TestSize.Level0) +{ + /** + * @tc.steps: step1. both gid and hashKey are empty + * @tc.expected: -E_INVALID_ARGS. + */ + int64_t insCount = 10; + int64_t photoSize = 10; + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); + UpdateLogGidAndHashKey(insCount); + VBucket assets; + std::string gid; + Bytes hashKey; + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), -E_INVALID_ARGS); + EXPECT_EQ(assets.size(), 0u); + + /** + * @tc.steps: step2. gid is empty, but hashKey is 2 + * @tc.expected: E_OK. + */ + Asset asset = g_localAsset; + asset.status = static_cast(AssetStatus::UPDATE); + UpdateLocalAsset(g_tableName, asset, 2L); // 2 is rowid + std::string pk = "2"; + hashKey.assign(pk.begin(), pk.end()); + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), E_OK); + CheckGetAsset(assets, static_cast(AssetStatus::UPDATE)); + + /** + * @tc.steps: step3. gid is empty, but hashKey out of range + * @tc.expected: -E_NOT_FOUND. + */ + assets = {}; + pk = "11"; + hashKey.assign(pk.begin(), pk.end()); + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), -E_NOT_FOUND); + EXPECT_EQ(assets.size(), 0u); + + /** + * @tc.steps: step4. hashKey is empty, but gid is 4 + * @tc.expected: E_OK. + */ + gid = "2"; + pk = {}; + assets = {}; + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), E_OK); + CheckGetAsset(assets, static_cast(AssetStatus::UPDATE)); + + /** + * @tc.steps: step5. hashKey is empty, but gid is out of range + * @tc.expected: -E_NOT_FOUND. + */ + gid = "11"; + assets = {}; + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), -E_NOT_FOUND); + EXPECT_EQ(assets.size(), 0u); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} + +HWTEST_F(DistributedDBRelationalCloudSyncableStorageTest, getAsset002, TestSize.Level0) +{ + /** + * @tc.steps: step1. hashKey is 2, or gid is 4 + * @tc.expected: E_OK. + */ + int64_t insCount = 10; + int64_t photoSize = 10; + InitUserDataForAssetTest(insCount, photoSize, g_localAsset); + UpdateLogGidAndHashKey(insCount); + VBucket assets; + Bytes hashKey; + Asset asset = g_localAsset; + asset.status = static_cast(AssetStatus::INSERT); + UpdateLocalAsset(g_tableName, asset, 4L); // 4 is rowid + std::string gid = "4"; + std::string pk = "2"; + hashKey.assign(pk.begin(), pk.end()); + EXPECT_EQ(g_storageProxy->StartTransaction(), E_OK); + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), E_OK); + CheckGetAsset(assets, static_cast(AssetStatus::INSERT)); + + /** + * @tc.steps: step2. hashKey is 1, or gid is 11 + * @tc.expected: E_OK. + */ + assets = {}; + gid = "11"; + pk = "1"; + hashKey.assign(pk.begin(), pk.end()); + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), E_OK); + CheckGetAsset(assets, static_cast(AssetStatus::NORMAL)); + + /** + * @tc.steps: step3. hashKey is 12, or gid is 11 + * @tc.expected: -E_NOT_FOUND. + */ + assets = {}; + pk = "12"; + hashKey.assign(pk.begin(), pk.end()); + EXPECT_EQ(g_storageProxy->GetAssetsByGidOrHashKey(g_tableName, gid, hashKey, assets), -E_NOT_FOUND); + EXPECT_EQ(assets.size(), 0u); + EXPECT_EQ(g_storageProxy->Commit(), E_OK); +} } #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_connection_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_connection_test.cpp index 346a5e828e98009e7db35612004049c50b377204..105f8a28ee7f1454a8e36884ad2a9f9d26978312 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_connection_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_connection_test.cpp @@ -97,7 +97,7 @@ void DistributedDBStorageDataConnectionTest::SetUp(void) DistributedDBToolsUnitTest::PrintTestCaseInfo(); KvDBProperties properties; properties.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); - properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); properties.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); properties.SetStringProp(KvDBProperties::STORE_ID, "test"); properties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "test"); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp index 0b69464c2dc1d5a035e64b909a1ce67eeb3483bf..36dd34d7970569a7e2d18d95f4bf17a60dd6eaa9 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_data_operation_test.cpp @@ -107,7 +107,7 @@ void DistributedDBStorageDataOperationTest::SetUp(void) DistributedDBToolsUnitTest::PrintTestCaseInfo(); KvDBProperties properties; properties.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); - properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE); + properties.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::LOCAL_TYPE_SQLITE); properties.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); properties.SetStringProp(KvDBProperties::STORE_ID, "test"); properties.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "test"); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp index 77805452792af6cd27bedefee9bfc16292a5b903..79bb4ed993c5b5dde85366bf4abae359d77a219e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_index_optimize_test.cpp @@ -68,7 +68,7 @@ namespace { string hashIdentifierName = DBCommon::TransferHashString(identifier); string identifierName = DBCommon::TransferStringToHex(hashIdentifierName); string filePath = g_testDir + "/" + identifierName + "/" + DBConstant::SINGLE_SUB_DIR + "/main/"; - filePath += DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + filePath += DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; return filePath; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_rd_single_ver_naturall_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_rd_single_ver_naturall_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9163a9efebfb6364e7f294d2ed06a94c6e7a1fe0 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_rd_single_ver_naturall_store_test.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021 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. + */ +#ifdef USE_RD_KERNEL + +#include + +#include "db_constant.h" +#include "distributeddb_storage_rd_single_ver_natural_store_testcase.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + DistributedDB::KvStoreConfig g_config; + std::string g_testDir; + const std::string MEM_URL = "file:31?mode=memory&cache=shared"; + DistributedDB::RdSingleVerNaturalStore *g_store = nullptr; + DistributedDB::RdSingleVerNaturalStoreConnection *g_connection = nullptr; +} + +class DistributedDBStorageMemoryRdSingleVerNaturalStoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("Test dir is %s", g_testDir.c_str()); + // IDENTIFIER_DIR is 31 + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/31/" + DBConstant::SINGLE_SUB_DIR); +} + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::TearDownTestCase(void) {} + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + KvDBProperties property; + property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNB"); + property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "31"); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); + g_store = new (std::nothrow) RdSingleVerNaturalStore; + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->Open(property), E_OK); + + int erroCode = E_OK; + g_connection = static_cast(g_store->GetDBConnection(erroCode)); + ASSERT_NE(g_connection, nullptr); + g_store->DecObjRef(g_store); + EXPECT_EQ(erroCode, E_OK); +} + +void DistributedDBStorageMemoryRdSingleVerNaturalStoreTest::TearDown(void) +{ + if (g_connection != nullptr) { + g_connection->Close(); + } + + g_store = nullptr; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/31/" + DBConstant::SINGLE_SUB_DIR); +} + +/** + * @tc.name: SyncDatabaseOperate001 + * @tc.desc: To test the function of inserting data of the local device in the synchronization database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate001, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Set Ioption to the local data and insert a record of key1 and value1. + * @tc.expected: step1/2. Return OK. + */ + /** + * @tc.steps: step3. Set Ioption to the local data and obtain the value of key1. + * Check whether the value is the same as the value of value1. + * @tc.expected: step3. The obtained value and value2 are the same. + */ + /** + * @tc.steps: step4. Ioption Set this parameter to the local data. Insert key1. + * The value cannot be empty. value2(!=value1) + * @tc.expected: step4. Return OK. + */ + /** + * @tc.steps: step5. Set Ioption to the local data, GetMetaData to obtain the value of key1, + * and check whether the value is the same as the value of value2. + * @tc.expected: step5. The obtained value and value2 are the same. + */ + /** + * @tc.steps: step6. The Ioption parameter is set to the local data. + * The data record whose key is empty and value is not empty is inserted. + * @tc.expected: step6. Return E_INVALID_DATA. + */ + /** + * @tc.steps: step7. Set Ioption to the local data, insert data + * whose key2(!=key1) is not empty, and value is empty. + * @tc.expected: step7. Return OK. + */ + /** + * @tc.steps: step8. Set option to local data, obtain the value of key2, + * and check whether the value is empty. + * @tc.expected: step8. Return OK, value is empty. + */ + /** + * @tc.steps: step9. Ioption Set the local data. + * Insert the data whose key size is 1024 and value size is 4Mb. + * @tc.expected: step9. Return OK. + */ + /** + * @tc.steps: step10/11. Set Ioption to the local data and insert data items + * whose value is greater than 4Mb or key is bigger than 1Kb + * @tc.expected: step10/11. Return E_INVALID_ARGS. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate003 + * @tc.desc: test the delete operation in sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate003, TestSize.Level1) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and delete the data whose key is key1. + * @tc.expected: step5. Return E_OK. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value of Key1. + * @tc.expected: step5. Return E_NOT_FOUND. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate005 + * @tc.desc: test the reading for sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate005, TestSize.Level1) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value data of Key1. + * Check whether the value is the same as the value of value2. + * @tc.expected: step4. Return E_OK, and the value is the same as the value of value2. + */ + /** + * @tc.steps: step5. The Ioption is set to the local. + * The data of the key1 and value2(!=value1) is inserted. + * @tc.expected: step4. Return E_OK. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate006 + * @tc.desc: test the get entries for sync database + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageMemoryRdSingleVerNaturalStoreTest, SyncDatabaseOperate006, TestSize.Level1) +{ + /** + * @tc.steps: step2/3/4. Set Ioption to synchronous data. + * Insert the data of key=keyPrefix + 'a', value1. + * Insert the data of key=keyPrefix + 'c', value2. + * Insert the data of key length=keyPrefix length - 1, value3. + * @tc.expected: step2/3/4. Return E_NOT_FOUND. + */ + /** + * @tc.steps: step5. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step5. Return OK. The number of obtained data records is 2. + */ + /** + * @tc.steps: step6. Obtain all data whose prefixKey is empty. + * @tc.expected: step6. Return OK. The number of obtained data records is 3. + */ + /** + * @tc.steps: step7. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step7. Return E_NOT_SUPPORT. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(g_store, g_connection); +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_single_ver_naturall_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_single_ver_naturall_store_test.cpp index 3d7eb017f6a953d0a0733bf2eac1daefc80affcc..bb83c54475765e6c17ba99785fea12184a953fd2 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_single_ver_naturall_store_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_memory_single_ver_naturall_store_test.cpp @@ -56,7 +56,7 @@ void DistributedDBStorageMemorySingleVerNaturalStoreTest::SetUp(void) property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNB"); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "31"); property.SetBoolProp(KvDBProperties::MEMORY_MODE, true); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); g_store = new (std::nothrow) SQLiteSingleVerNaturalStore; ASSERT_NE(g_store, nullptr); ASSERT_EQ(g_store->Open(property), E_OK); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp index 6179933b57a22d0b6cdac714c020fc77f4464fd2..3db6c1b2e356eb8c3fc627adcd8f942624699255 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_query_sync_test.cpp @@ -138,7 +138,7 @@ void DistributedDBStorageQuerySyncTest::SetUp(void) property.SetStringProp(KvDBProperties::STORE_ID, "31"); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "TestQuerySync"); property.SetBoolProp(KvDBProperties::MEMORY_MODE, false); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); property.SetIntProp(KvDBProperties::CONFLICT_RESOLVE_POLICY, ConflictResolvePolicy::DEVICE_COLLABORATION); g_store = new (std::nothrow) SQLiteSingleVerNaturalStore; ASSERT_NE(g_store, nullptr); @@ -1422,7 +1422,7 @@ HWTEST_F(DistributedDBStorageQuerySyncTest, QueryObject005, TestSize.Level1) property.SetStringProp(KvDBProperties::STORE_ID, "31"); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "TestQuerySync"); property.SetBoolProp(KvDBProperties::MEMORY_MODE, false); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); property.SetIntProp(KvDBProperties::CONFLICT_RESOLVE_POLICY, ConflictResolvePolicy::DEVICE_COLLABORATION); int errCode = E_OK; SQLiteSingleVerStorageEngine *storageEngine = diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0c329d5e18dca1c74f10e18dd2eacf71b02fbb5a --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_register_observer_test.cpp @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2021 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. + */ +#ifdef USE_RD_KERNEL +#include +#include +#include "db_common.h" +#include "db_constant.h" +#include "db_errno.h" +#include "default_factory.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "ikvdb_factory.h" +#include "log_print.h" +#include "rd_single_ver_natural_store.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + string g_testDir; + + RdSingleVerNaturalStore *g_singleVerNaturaStore = nullptr; + IKvDBConnection *g_singleVerNaturaStoreConnection = nullptr; + bool g_createFactory = false; + const int OBSERVER_SLEEP_TIME = 80; + + Key g_emptyKey; + string g_keyStr1 = "key_1"; + string g_keyStr2 = "key_2"; + string g_keyStr3 = "key_3"; + string g_keyStr4 = "key_4"; + string g_keyStr5 = "key_5"; + string g_keyStr6 = "key_6"; + + string g_valueStr1 = "value_1"; + string g_valueStr2 = "value_2"; + string g_valueStr3 = "value_3"; + string g_valueStr4 = "value_4"; + string g_valueStr5 = "value_5"; + string g_valueStr6 = "value_6"; + string g_oldValueStr3 = "old_value_3"; + string g_oldValueStr4 = "old_value_4"; + + list g_emptyEntries; + Entry g_entry0; + Entry g_entry1; + Entry g_entry2; + Entry g_entry3; + Entry g_entry4; + Entry g_entry5; + Entry g_entry6; + Entry g_oldEntry3; + Entry g_oldEntry4; + + bool g_testFuncCalled = false; + list g_insertedEntries; + list g_updatedEntries; + list g_deletedEntries; + + Entry TransferStrToKyEntry(const string &key, const string &value) + { + Entry entry; + entry.key.resize(key.size()); + entry.key.assign(key.begin(), key.end()); + entry.value.resize(value.size()); + entry.value.assign(value.begin(), value.end()); + return entry; + } + + void TestFunc(const KvDBCommitNotifyData &data) + { + g_testFuncCalled = true; + int errCode; + g_insertedEntries = data.GetInsertedEntries(errCode); + ASSERT_EQ(errCode, E_OK); + g_updatedEntries = data.GetUpdatedEntries(errCode); + ASSERT_EQ(errCode, E_OK); + g_deletedEntries = data.GetDeletedEntries(errCode); + ASSERT_EQ(errCode, E_OK); + LOGI("Insert:%zu, update:%zu, delete:%zu", g_insertedEntries.size(), g_updatedEntries.size(), + g_deletedEntries.size()); + return; + } +} + +class DistributedDBStorageRdRegisterObserverTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageRdRegisterObserverTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + if (IKvDBFactory::GetCurrent() == nullptr) { + IKvDBFactory *factory = new (std::nothrow) DefaultFactory(); + ASSERT_NE(factory, nullptr); + if (factory == nullptr) { + LOGE("failed to new DefaultFactory!"); + return; + } + IKvDBFactory::Register(factory); + g_createFactory = true; + } + // prepare test entries + g_entry1 = TransferStrToKyEntry(g_keyStr1, g_valueStr1); + g_entry2 = TransferStrToKyEntry(g_keyStr2, g_valueStr2); + g_entry3 = TransferStrToKyEntry(g_keyStr3, g_valueStr3); + g_entry4 = TransferStrToKyEntry(g_keyStr4, g_valueStr4); + g_entry5 = TransferStrToKyEntry(g_keyStr5, g_valueStr5); + g_entry6 = TransferStrToKyEntry(g_keyStr6, g_valueStr6); + g_oldEntry3 = TransferStrToKyEntry(g_keyStr3, g_oldValueStr3); + g_oldEntry4 = TransferStrToKyEntry(g_keyStr4, g_oldValueStr4); +} + +void DistributedDBStorageRdRegisterObserverTest::TearDownTestCase(void) +{ + if (g_createFactory) { + if (IKvDBFactory::GetCurrent() != nullptr) { + delete IKvDBFactory::GetCurrent(); + IKvDBFactory::Register(nullptr); + } + } + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } +} + +void DistributedDBStorageRdRegisterObserverTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + IKvDBFactory *factory = IKvDBFactory::GetCurrent(); + ASSERT_NE(factory, nullptr); + if (factory == nullptr) { + LOGE("failed to get DefaultFactory!"); + return; + } + + g_singleVerNaturaStore = new (std::nothrow) RdSingleVerNaturalStore(); + ASSERT_NE(g_singleVerNaturaStore, nullptr); + if (g_singleVerNaturaStore == nullptr) { + return; + } + + KvDBProperties property; + property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNB"); + property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "TestGeneralNB"); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); + int errCode = g_singleVerNaturaStore->Open(property); + ASSERT_EQ(errCode, E_OK); + if (errCode != E_OK) { + g_singleVerNaturaStore = nullptr; + return; + } + + g_singleVerNaturaStoreConnection = g_singleVerNaturaStore->GetDBConnection(errCode); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(g_singleVerNaturaStoreConnection, nullptr); +} + +void DistributedDBStorageRdRegisterObserverTest::TearDown(void) +{ + if (g_singleVerNaturaStoreConnection != nullptr) { + g_singleVerNaturaStoreConnection->Close(); + } + std::string identifierName; + g_singleVerNaturaStore->DecObjRef(g_singleVerNaturaStore); + identifierName = DBCommon::TransferStringToHex("TestGeneralNB"); + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/" + identifierName + "/" + DBConstant::SINGLE_SUB_DIR); +} + +/** + * @tc.name: RegisterObserver001 + * @tc.desc: Register a NULL pointer as an observer + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: liujialei + */ +HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver001, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Register a null pointer to subscribe to the database. + * Check whether the registration is successful. + * @tc.expected: step1/2. Returns INVALID_ARGS. + */ + int result; + KvDBObserverHandle* handle = g_singleVerNaturaStoreConnection->RegisterObserver( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT), g_entry1.key, + nullptr, result); + EXPECT_EQ(result, -E_INVALID_ARGS); + EXPECT_EQ(handle, nullptr); + + /** + * @tc.steps: step3/4. UnRegister a null pointer to subscribe to the database. + * Check whether the unregistration is successful. + * @tc.expected: step3/4. Returns INVALID_ARGS. + */ + result = g_singleVerNaturaStoreConnection->UnRegisterObserver(nullptr); + EXPECT_EQ(result, -E_INVALID_ARGS); + return; +} + +/** + * @tc.name: RegisterObserver010 + * @tc.desc: Register an observer for the local sync database change and the local database change of a specified key. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: liujialei + */ +HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver010, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Register an observer for the local sync database change + * and the local database change of a specified key. Check register result. + * @tc.expected: step1/2. Returns E_NOT_SUPPORT. + */ + int result; + KvDBObserverHandle* handle = g_singleVerNaturaStoreConnection->RegisterObserver( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT) | + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_LOCAL_PUT_EVENT), + g_entry1.key, TestFunc, result); + EXPECT_EQ(result, -E_NOT_SUPPORT); + EXPECT_EQ(handle, nullptr); + return; +} + +/** + * @tc.name: RegisterObserver011 + * @tc.desc: Register an observer for the remote sync database change and the local database change of a specified key + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: liujialei + */ +HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver011, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Register an observer for the remote sync database change + * and the local database change of a specified key. Check register result. + * @tc.expected: step1/2. Returns E_NOT_SUPPORT. + */ + int result; + KvDBObserverHandle* handle = g_singleVerNaturaStoreConnection->RegisterObserver( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_SYNC_EVENT) | + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_LOCAL_PUT_EVENT), + g_entry1.key, TestFunc, result); + EXPECT_EQ(result, -E_NOT_SUPPORT); + EXPECT_EQ(handle, nullptr); + return; +} + +/** + * @tc.name: RegisterObserver012 + * @tc.desc: Register an observer for the local sync database change and the local database change of any key. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: liujialei + */ +HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver012, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Register an observer for the local sync database change + * and the local database change of any key. Check register result. + * @tc.expected: step1/2. Returns E_NOT_SUPPORT. + */ + int result; + KvDBObserverHandle* handle = g_singleVerNaturaStoreConnection->RegisterObserver( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_PUT_EVENT) | + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_LOCAL_PUT_EVENT), + g_emptyKey, TestFunc, result); + EXPECT_EQ(result, -E_NOT_SUPPORT); + EXPECT_EQ(handle, nullptr); + return; +} + +/** + * @tc.name: RegisterObserver013 + * @tc.desc: Register an observer for the remote sync database change and the local database change of any key. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: liujialei + */ +HWTEST_F(DistributedDBStorageRdRegisterObserverTest, RegisterObserver013, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Register an observer for the remote sync database change + * and the local database change of any key. Check register result. + * @tc.expected: step1/2. Returns E_NOT_SUPPORT. + */ + int result; + KvDBObserverHandle* handle = g_singleVerNaturaStoreConnection->RegisterObserver( + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_SYNC_EVENT) | + static_cast(SQLiteGeneralNSNotificationEventType::SQLITE_GENERAL_NS_LOCAL_PUT_EVENT), + g_emptyKey, TestFunc, result); + EXPECT_EQ(result, -E_NOT_SUPPORT); + EXPECT_EQ(handle, nullptr); + return; +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_resultset_and_json_optimize.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_resultset_and_json_optimize.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1c43617087e851456df067a4800b984df6749f63 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_resultset_and_json_optimize.cpp @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef USE_RD_KERNEL +#ifndef OMIT_JSON +#include + +#include "db_common.h" +#include "db_constant.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "kvdb_manager.h" +#include "log_print.h" +#include "platform_specific.h" +#include "res_finalizer.h" +#include "rd_single_ver_natural_store_connection.h" +#include "rd_single_ver_result_set.h" +#include "store_types.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { + const int INSERT_NUMBER = 10; + const Key EMPTY_KEY; + + string g_testDir; + string g_identifier; + RdSingleVerNaturalStore *g_store = nullptr; + RdSingleVerNaturalStoreConnection *g_connection = nullptr; + KvDBProperties g_Property; + const string STORE_ID = STORE_ID_SYNC; +} +class DistributedDBStorageRdResultAndJsonOptimizeTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageRdResultAndJsonOptimizeTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + std::string origIdentifier = USER_ID + "-" + APP_ID + "-" + STORE_ID; + std::string identifier = DBCommon::TransferHashString(origIdentifier); + g_identifier = DBCommon::TransferStringToHex(identifier); + std::string dir = g_testDir + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR; + DIR *dirTmp = opendir(dir.c_str()); + if (dirTmp == nullptr) { + OS::MakeDBDirectory(dir); + } else { + closedir(dirTmp); + } + g_Property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + g_Property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID); + g_Property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); + g_Property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); +} + +void DistributedDBStorageRdResultAndJsonOptimizeTest::TearDownTestCase(void) +{ + if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { + LOGE("rm test db files error!"); + } +} + +void DistributedDBStorageRdResultAndJsonOptimizeTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + /** + * @tc.setup: 1. Create a RdSingleVerNaturalStore. + * 2. Set the ResultSet cache mode to CACHE_ENTRY_ID_ONLY. + * 3. Put 10 records. + */ + g_store = new (std::nothrow) RdSingleVerNaturalStore; + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->Open(g_Property), E_OK); + + int errCode = E_OK; + g_connection = static_cast(g_store->GetDBConnection(errCode)); + ASSERT_NE(g_connection, nullptr); + g_store->DecObjRef(g_store); + EXPECT_EQ(errCode, E_OK); + + IOption option; + option.dataType = IOption::SYNC_DATA; + g_connection->Clear(option); + Key insertKey; + ASSERT_EQ(g_connection->StartTransaction(), -E_NOT_SUPPORT); + for (int i = 1; i < INSERT_NUMBER + 1; i++) { + insertKey.clear(); + insertKey.push_back(i); + ASSERT_EQ(g_connection->Put(option, insertKey, VALUE_1), OK); + } + ASSERT_EQ(g_connection->Commit(), -E_NOT_SUPPORT); +} + +void DistributedDBStorageRdResultAndJsonOptimizeTest::TearDown(void) +{ + /** + * @tc.teardown: Release the RdSingleVerNaturalStore. + */ + if (g_connection != nullptr) { + g_connection->Close(); + g_connection = nullptr; + } + + g_store = nullptr; + KvDBManager::RemoveDatabase(g_Property); +} + +/** + * @tc.name: ResultSetOpen001 + * @tc.desc: Test the RdSingleVerResultSet Open function + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetOpen001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet1 = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open with parameter true. + * @tc.expected: step2. Expect return E_OK. + */ + EXPECT_EQ(resultSet1->Open(false), E_OK); + + /** + * @tc.steps: step3. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet2 = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step4. Call RdSingleVerResultSet.Open with parameter false. + * @tc.expected: step4. Expect return E_OK. + */ + EXPECT_EQ(resultSet2->Open(false), E_OK); + + /** + * @tc.steps: step5. Close all ResultSet. + */ + resultSet1->Close(); + resultSet2->Close(); +} + +/** + * @tc.name: ResultSetGetCount001 + * @tc.desc: Test the RdSingleVerResultSet GetCount function. + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetCount001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open + * @tc.expected: step2. Expect return E_OK.Gits + */ + EXPECT_EQ(resultSet->Open(false), E_OK); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.GetCount + * @tc.expected: step2. Expect return INSERT_NUMBER. + */ + EXPECT_EQ(resultSet->GetCount(), INSERT_NUMBER); + + /** + * @tc.steps: step3. Close the ResultSet. + */ + resultSet->Close(); +} + +/** + * @tc.name: ResultSetMoveTo001 + * @tc.desc: Test the RdSingleVerResultSet MoveTo And GetPosition function. + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetMoveTo001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open. + * @tc.expected: step2. Expect return E_OK. + */ + EXPECT_EQ(resultSet->Open(false), E_OK); + + /** + * @tc.steps: step3. Call RdSingleVerResultSet MoveTo INSERT_NUMBER - 1 + * @tc.expected: step3. Expect return E_OK. + */ + EXPECT_EQ(resultSet->MoveTo(INSERT_NUMBER - 1), E_OK); + + /** + * @tc.steps: step4. Call RdSingleVerResultSet GetPosition + * @tc.expected: step5. Expect return INSERT_NUMBER - 1. + */ + EXPECT_EQ(resultSet->GetPosition(), INSERT_NUMBER - 1); + + /** + * @tc.steps: step5. Call RdSingleVerResultSet MoveTo INSERT_NUMBER + * @tc.expected: step5. Expect return -E_INVALID_ARGS. + */ + EXPECT_EQ(resultSet->MoveTo(INSERT_NUMBER), -E_INVALID_ARGS); + + /** + * @tc.steps: step6. Call RdSingleVerResultSet GetPosition + * @tc.expected: step6. Expect return INSERT_NUMBER. + */ + EXPECT_EQ(resultSet->GetPosition(), INSERT_NUMBER); + + /** + * @tc.steps: step7. Call RdSingleVerResultSet MoveTo -1 + * @tc.expected: step7. Expect return E_INVALID_ARGS. + */ + EXPECT_EQ(resultSet->MoveTo(-1), -E_INVALID_ARGS); + + /** + * @tc.steps: step8. Call RdSingleVerResultSet GetPosition + * @tc.expected: step8. Expect return 0. + */ + EXPECT_EQ(resultSet->GetPosition(), -1); + + /** + * @tc.steps: step9. Call RdSingleVerResultSet MoveTo 0 + * @tc.expected: step9. Expect return E_OK. + */ + EXPECT_EQ(resultSet->MoveTo(0), E_OK); + + /** + * @tc.steps: step10. Call RdSingleVerResultSet GetPosition + * @tc.expected: step10. Expect return 0. + */ + EXPECT_EQ(resultSet->GetPosition(), 0); + + /** + * @tc.steps: step11. Close the ResultSet. + */ + resultSet->Close(); +} + +/** + * @tc.name: ResultSetGetEntry001 + * @tc.desc: Test the RdSingleVerResultSet GetEntry function. + * @tc.type: FUNC + * @tc.require: AR000F3OP0 + * @tc.author: xushaohua + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetGetEntry001, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create a RdSingleVerResultSet. + */ + std::unique_ptr resultSet = + std::make_unique(g_store, EMPTY_KEY); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet.Open + * @tc.expected: step2. Expect return E_OK. + */ + EXPECT_EQ(resultSet->Open(false), E_OK); + + /** + * @tc.steps: step2. Call RdSingleVerResultSet MoveTo 0 And GetEntry + * @tc.expected: step2. Expect return E_OK. + */ + Entry entry; + ASSERT_EQ(resultSet->MoveTo(0), E_OK); + EXPECT_EQ(resultSet->GetEntry(entry), E_OK); + + /** + * @tc.expected: step2. Expect return Key == { 1 }, value == VALUE_1. + */ + const Key key = { 1 }; + EXPECT_EQ(entry.key, key); + EXPECT_EQ(entry.value, VALUE_1); + + /** + * @tc.steps: step3. Close the ResultSet. + */ + resultSet->Close(); +} + +/** + * @tc.name: ResultSetTest002 + * @tc.desc: Check the resultSet move,then get + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdResultAndJsonOptimizeTest, ResultSetTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. Check resultSet MoveTo when resultSet is not opened + * @tc.expected: step1. Expect return -E_RESULT_SET_STATUS_INVALID. + */ + std::unique_ptr resultSet1 = + std::make_unique(g_store, EMPTY_KEY); + ASSERT_NE(resultSet1, nullptr); + EXPECT_EQ(resultSet1->MoveTo(INSERT_NUMBER - 1), -E_RESULT_SET_STATUS_INVALID); + + /** + * @tc.steps: step2. Then get the Entry + * @tc.expected: step2. Expect return -E_NO_SUCH_ENTRY. + */ + EXPECT_EQ(resultSet1->Open(false), E_OK); + Entry entry; + EXPECT_EQ(resultSet1->GetEntry(entry), -E_NO_SUCH_ENTRY); + resultSet1->Close(); + + /** + * @tc.steps: step3. Check resultSet MoveTo when db is empty + * @tc.expected: step3. Expect return -E_RESULT_SET_EMPTY. + */ + std::unique_ptr resultSet2 = + std::make_unique(g_store, EMPTY_KEY); + ASSERT_NE(resultSet2, nullptr); + IOption option; + option.dataType = IOption::SYNC_DATA; + Key insertKey; + ASSERT_EQ(g_connection->StartTransaction(), -E_NOT_SUPPORT); + for (int i = 1; i < INSERT_NUMBER + 1; i++) { + insertKey.clear(); + insertKey.push_back(i); + ASSERT_EQ(g_connection->Delete(option, insertKey), OK); + } + ASSERT_EQ(g_connection->Commit(), -E_NOT_SUPPORT); + resultSet2->Open(false); + EXPECT_EQ(resultSet2->MoveTo(INSERT_NUMBER - 1), -E_RESULT_SET_EMPTY); + + /** + * @tc.steps: step4. Get resultSet Entry when db is empty + * @tc.expected: step4. Expect return -E_NO_SUCH_ENTRY. + */ + EXPECT_EQ(resultSet2->GetEntry(entry), -E_NO_SUCH_ENTRY); + resultSet2->Close(); +} +#endif +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_executor_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_executor_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..89a84decb43da71a6de17aec893ab39ff0d69afa --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_executor_test.cpp @@ -0,0 +1,613 @@ +/* + * 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. + */ +#ifdef USE_RD_KERNEL +#include +#include + +#include "db_constant.h" +#include "db_common.h" +#include "distributeddb_storage_single_ver_natural_store_testcase.h" +#include "rd_single_ver_natural_store.h" +#include "rd_single_ver_natural_store_connection.h" +#include "kvdb_pragma.h" +#include "storage_engine_manager.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + string g_testDir; + string g_databaseName; + string g_identifier; + KvDBProperties g_property; + + RdSingleVerNaturalStore *g_store = nullptr; + RdSingleVerNaturalStoreConnection *g_connection = nullptr; + RdSingleVerStorageExecutor *g_handle = nullptr; + RdSingleVerStorageExecutor *g_nullHandle = nullptr; + + const char * const ADD_SYNC = "ALTER TABLE sync_data ADD column version INT"; + const char * const ADD_LOCAL = "ALTER TABLE local_data ADD column flag INT"; + const char * const INSERT_SQL = "INSERT INTO sync_data VALUES('a', 'b', 1, 2, '', '', 'efdef', 100 , 1);"; + const int SQL_STATE_ERR = -1; +} + +class DistributedDBStorageRdSingleVerNaturalExecutorTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageRdSingleVerNaturalExecutorTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGI("DistributedDBStorageRdSingleVerNaturalExecutorTest dir is %s", g_testDir.c_str()); + std::string oriIdentifier = APP_ID + "-" + USER_ID + "-" + "TestGeneralNBExecutor"; + std::string identifier = DBCommon::TransferHashString(oriIdentifier); + g_identifier = DBCommon::TransferStringToHex(identifier); + + g_databaseName = "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + g_property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + g_property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNBExecutor"); + g_property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); + g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); +} + +void DistributedDBStorageRdSingleVerNaturalExecutorTest::TearDownTestCase(void) +{ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR); +} + +void DistributedDBStorageRdSingleVerNaturalExecutorTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR); + g_store = new (std::nothrow) RdSingleVerNaturalStore; + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->Open(g_property), E_OK); + + int erroCode = E_OK; + g_connection = static_cast(g_store->GetDBConnection(erroCode)); + ASSERT_NE(g_connection, nullptr); + g_store->DecObjRef(g_store); + EXPECT_EQ(erroCode, E_OK); + + g_handle = static_cast( + g_store->GetHandle(true, erroCode, OperatePerm::NORMAL_PERM)); + ASSERT_EQ(erroCode, E_OK); + ASSERT_NE(g_handle, nullptr); + + g_nullHandle = new (nothrow) RdSingleVerStorageExecutor(nullptr, false); + ASSERT_NE(g_nullHandle, nullptr); +} + +void DistributedDBStorageRdSingleVerNaturalExecutorTest::TearDown(void) +{ + if (g_nullHandle != nullptr) { + delete g_nullHandle; + g_nullHandle = nullptr; + } + if (g_store != nullptr) { + g_store->ReleaseHandle(g_handle); + } + if (g_connection != nullptr) { + g_connection->Close(); + g_connection = nullptr; + } + g_store = nullptr; + g_handle = nullptr; +} + +/** + * @tc.name: InvalidParam001 + * @tc.desc: Get Kv Data with Invalid condition + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, InvalidParam001, TestSize.Level1) +{ + /** + * @tc.steps: step1. The Data type is invalid + * @tc.expected: step1. Expect -E_INVALID_ARGS + */ + Timestamp timestamp = 0; + Key key; + Value value; + int type = static_cast(SingleVerDataType::SYNC_TYPE); + EXPECT_EQ(g_nullHandle->GetKvData(SingleVerDataType(type + 1), key, value, timestamp), -E_INVALID_ARGS); + + /** + * @tc.steps: step2. The key is empty + * @tc.expected: step2. Expect -E_INVALID_ARGS + */ + EXPECT_EQ(g_handle->GetKvData(SingleVerDataType(type), key, value, timestamp), -E_INVALID_ARGS); + + /** + * @tc.steps: step3. The db is null + * @tc.expected: step3. Expect -E_INVALID_DB + */ + EXPECT_EQ(g_nullHandle->GetKvData(SingleVerDataType(type), KEY_1, value, timestamp), -E_INVALID_DB); +} + +/** + * @tc.name: InvalidParam002 + * @tc.desc: Put Kv Data check + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, InvalidParam002, TestSize.Level1) +{ + /** + * @tc.steps: step1. rd unsupport put kv data + * @tc.expected: step1. Expect -E_NOT_SUPPORT + */ + Value value; + EXPECT_EQ(g_nullHandle->PutKvData(SingleVerDataType::SYNC_TYPE, KEY_1, value, 0, nullptr), -E_NOT_SUPPORT); + + /** + * @tc.steps: step2. rd unsupport put kv data + * @tc.expected: step2. Expect -E_NOT_SUPPORT + */ + EXPECT_EQ(g_nullHandle->PutKvData(SingleVerDataType::META_TYPE, KEY_1, value, 0, nullptr), -E_NOT_SUPPORT); +} + +/** + * @tc.name: InvalidParam003 + * @tc.desc: Get entries with Invalid condition + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, InvalidParam003, TestSize.Level1) +{ + /** + * @tc.steps: step1. The Data type is invalid + * @tc.expected: step1. Expect -E_INVALID_ARGS + */ + vector entries; + EXPECT_EQ(g_nullHandle->GetEntries(false, SingleVerDataType::META_TYPE, KEY_1, entries), -E_INVALID_ARGS); + EXPECT_EQ(g_nullHandle->GetEntries(false, SingleVerDataType::LOCAL_TYPE_SQLITE, KEY_1, entries), -E_INVALID_ARGS); + /** + * @tc.steps: step2. The db is null + * @tc.expected: step2.. Expect -E_INVALID_DB + */ + EXPECT_EQ(g_nullHandle->GetEntries(false, SingleVerDataType::SYNC_TYPE, KEY_1, entries), -E_INVALID_DB); + + /** + * @tc.steps: step3. This key does not exist + * @tc.expected: step3. Expect -E_NOT_FOUND + */ + Key key; + EXPECT_EQ(g_handle->GetEntries(false, SingleVerDataType::SYNC_TYPE, KEY_1, entries), -E_NOT_FOUND); +} + +/** + * @tc.name: InvalidParam005 + * @tc.desc: Test timestamp with Invalid condition (rd not support timestamp) + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, InvalidParam005, TestSize.Level1) +{ + /** + * @tc.steps: step1. The db is null + * @tc.expected: step1. Expect return 0 + */ + Timestamp timestamp = 0; + g_nullHandle->InitCurrentMaxStamp(timestamp); + EXPECT_EQ(timestamp, 0u); + + /** + * @tc.steps: step2. Get timestamp when The db is null + * @tc.expected: step2. Expect -E_NOT_SUPPORT + */ + std::vector dataItems; + Timestamp begin = 0; + Timestamp end = INT64_MAX; + DataSizeSpecInfo info; + EXPECT_EQ(g_nullHandle->GetSyncDataByTimestamp(dataItems, sizeof("time"), begin, end, info), -E_NOT_SUPPORT); + EXPECT_EQ(g_nullHandle->GetDeletedSyncDataByTimestamp(dataItems, sizeof("time"), begin, end, info), + -E_NOT_SUPPORT); +} + +/** + * @tc.name: InvalidParam008 + * @tc.desc: Test transaction with Invalid condition (rd not support transcaction yet) + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, InvalidParam008, TestSize.Level1) +{ + EXPECT_EQ(g_nullHandle->StartTransaction(TransactType::DEFERRED), E_OK); // -E_INVALID_DB + EXPECT_EQ(g_nullHandle->Commit(), E_OK); // -E_INVALID_DB + EXPECT_EQ(g_nullHandle->Rollback(), E_OK); // -E_INVALID_DB + + EXPECT_EQ(g_handle->StartTransaction(TransactType::DEFERRED), E_OK); + EXPECT_EQ(g_handle->Reset(), -E_NOT_SUPPORT); +} + +/** + * @tc.name: InvalidParam009 + * @tc.desc: Get identifier with Invalid condition (rd not support) + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, InvalidParam009, TestSize.Level1) +{ + /** + * @tc.steps: step1. The parameter is null + * @tc.expected: step1. Expect -E_INVALID_ARGS + */ + EXPECT_EQ(g_nullHandle->GetDeviceIdentifier(nullptr), -E_NOT_SUPPORT); + + /** + * @tc.steps: step2. The db is null + * @tc.expected: step2. Expect -E_INVALID_DB + */ + PragmaEntryDeviceIdentifier identifier; + EXPECT_EQ(g_nullHandle->GetDeviceIdentifier(&identifier), -E_NOT_SUPPORT); + + /** + * @tc.steps: step3. The identifier is empty + * @tc.expected: step3. Expect -E_INVALID_ARGS + */ + EXPECT_EQ(g_handle->GetDeviceIdentifier(&identifier), -E_NOT_SUPPORT); +} + +/** + * @tc.name: InvalidParam010 + * @tc.desc: Fail to call function with Invalid condition + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, InvalidParam010, TestSize.Level1) +{ + vector keys; + EXPECT_EQ(g_nullHandle->GetAllMetaKeys(keys), -E_NOT_SUPPORT); + string devName; + vector entries; + EXPECT_EQ(g_nullHandle->GetAllSyncedEntries(devName, entries), -E_NOT_SUPPORT); + EXPECT_EQ(g_nullHandle->ForceCheckPoint(), -E_INVALID_DB); + EXPECT_EQ(g_nullHandle->CheckIntegrity(), -E_NOT_SUPPORT); +} + +/** + * @tc.name: ConnectionTest001 + * @tc.desc: Failed to get the keys (rd not support yet) + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, ConnectionTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. the dataType is error + * @tc.expected: step1. Expect -E_INVALID_ARGS + */ + IOption option; + option.dataType = IOption::SYNC_DATA + 1; + vector keys; + EXPECT_EQ(g_connection->GetKeys(option, KEY_1, keys), -E_NOT_SUPPORT); + + /** + * @tc.steps: step2. Get keys in cacheDB state + * @tc.expected: step2. Expect -E_EKEYREVOKED + */ + int errCode = E_OK; + RdSingleVerStorageEngine *storageEngine = + static_cast(StorageEngineManager::GetStorageEngine(g_property, errCode)); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(storageEngine, nullptr); + storageEngine->SetEngineState(EngineState::CACHEDB); + option.dataType = IOption::LOCAL_DATA; + EXPECT_EQ(g_connection->GetKeys(option, KEY_1, keys), -E_NOT_SUPPORT); + storageEngine->Release(); + + /** + * @tc.steps: step3. Get keys in null db connection + * @tc.expected: step3. Expect -E_NOT_INIT + */ + std::unique_ptr emptyConn = + std::make_unique(nullptr); + ASSERT_NE(emptyConn, nullptr); + EXPECT_EQ(emptyConn->GetKeys(option, KEY_1, keys), -E_NOT_SUPPORT); +} + +/** + * @tc.name: ConnectionTest002 + * @tc.desc: Push and delete on empty connect + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, ConnectionTest002, TestSize.Level1) +{ + std::unique_ptr emptyConn = + std::make_unique(nullptr); + IOption option = {IOption::SYNC_DATA}; + std::vector entries; + EXPECT_EQ(emptyConn->PutBatch(option, entries), -E_INVALID_DB); + std::vector keys; + EXPECT_EQ(emptyConn->DeleteBatch(option, keys), -E_INVALID_DB); + option.dataType = IOption::SYNC_DATA; + EXPECT_EQ(emptyConn->PutBatch(option, entries), -E_INVALID_DB); + EXPECT_EQ(emptyConn->DeleteBatch(option, keys), -E_INVALID_DB); + option.dataType = IOption::SYNC_DATA + 1; + EXPECT_EQ(emptyConn->PutBatch(option, entries), -E_NOT_SUPPORT); +} + +/** + * @tc.name: PragmaTest001 + * @tc.desc: Calling Pragma incorrectly + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, PragmaTest001, TestSize.Level1) +{ + /** + * @tc.steps: step1. the parameter is null + * @tc.expected: step1. Expect -E_INVALID_ARGS + */ + // Rd Pragma only support check point for now + EXPECT_EQ(g_connection->Pragma(PRAGMA_RESULT_SET_CACHE_MAX_SIZE, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_RESULT_SET_CACHE_MODE, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_AUTO_LIFE_CYCLE, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_UNPUBLISH_SYNC, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_PUBLISH_LOCAL, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_GET_DEVICE_IDENTIFIER_OF_ENTRY, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, nullptr), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_GET_IDENTIFIER_OF_DEVICE, nullptr), -E_NOT_SUPPORT); + + /** + * @tc.steps: step2. the option is invalid + * @tc.expected: step2. Expect -E_INVALID_ARGS + */ + std::unique_ptr emptyConn = + std::make_unique(nullptr); + ASSERT_NE(emptyConn, nullptr); + SecurityOption option = {S3, SECE}; + EXPECT_EQ(emptyConn->Pragma(PRAGMA_TRIGGER_TO_MIGRATE_DATA, &option), -E_NOT_SUPPORT); + + /** + * @tc.steps: step3. the size is invalid + * @tc.expected: step3. Expect -E_INVALID_ARGS + */ + int size = 0; + EXPECT_EQ(emptyConn->Pragma(PRAGMA_RESULT_SET_CACHE_MAX_SIZE, &size), -E_NOT_SUPPORT); + size = 1; + EXPECT_EQ(emptyConn->Pragma(PRAGMA_RESULT_SET_CACHE_MAX_SIZE, &size), -E_NOT_SUPPORT); + + /** + * @tc.steps: step4. the mode is invalid + * @tc.expected: step4. Expect -E_INVALID_ARGS + */ + ResultSetCacheMode mode = ResultSetCacheMode(2); // 2 is invalid mode + EXPECT_EQ(emptyConn->Pragma(PRAGMA_RESULT_SET_CACHE_MODE, &mode), -E_NOT_SUPPORT); + + /** + * @tc.steps: step5. the db is null + * @tc.expected: step5. Expect -E_INVALID_DB + */ + int time = 6000; // 6000 is random + EXPECT_EQ(emptyConn->Pragma(PRAGMA_SET_AUTO_LIFE_CYCLE, &time), -E_NOT_SUPPORT); +} + +/** + * @tc.name: PragmaTest002 + * @tc.desc: Incorrect publishing and unPublishing + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, PragmaTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. the db is null + * @tc.expected: step1. Expect -E_INVALID_DB + */ + std::unique_ptr emptyConn = + std::make_unique(nullptr); + PragmaPublishInfo info; + EXPECT_EQ(emptyConn->Pragma(PRAGMA_PUBLISH_LOCAL, &info), -E_NOT_SUPPORT); + EXPECT_EQ(emptyConn->Pragma(PRAGMA_UNPUBLISH_SYNC, &info), -E_NOT_SUPPORT); + + /** + * @tc.steps: step2. publish in transaction + * @tc.expected: step2. Expect -E_NOT_SUPPORT + */ + g_store->ReleaseHandle(g_handle); + g_connection->StartTransaction(); + EXPECT_EQ(g_connection->Pragma(PRAGMA_PUBLISH_LOCAL, &info), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_UNPUBLISH_SYNC, &info), -E_NOT_SUPPORT); + g_connection->RollBack(); + + /** + * @tc.steps: step3. publish in cacheDB + * @tc.expected: step3. Expect -E_EKEYREVOKED + */ + int errCode = E_OK; + RdSingleVerStorageEngine *storageEngine = + static_cast(StorageEngineManager::GetStorageEngine(g_property, errCode)); + ASSERT_EQ(errCode, E_OK); + ASSERT_NE(storageEngine, nullptr); + storageEngine->SetEngineState(EngineState::CACHEDB); + EXPECT_EQ(g_connection->Pragma(PRAGMA_PUBLISH_LOCAL, &info), -E_NOT_SUPPORT); + EXPECT_EQ(g_connection->Pragma(PRAGMA_UNPUBLISH_SYNC, &info), -E_NOT_SUPPORT); + g_connection->StartTransaction(); + g_connection->Commit(); + storageEngine->Release(); +} + +/** + * @tc.name: PragmaTest003 + * @tc.desc: Failed to call function with empty connection + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, PragmaTest003, TestSize.Level1) +{ + auto emptyConn = std::make_unique(nullptr); + PragmaEntryDeviceIdentifier identifier = {.key = KEY_1}; + EXPECT_EQ(emptyConn->Pragma(PRAGMA_GET_DEVICE_IDENTIFIER_OF_ENTRY, &identifier), -E_NOT_SUPPORT); + EXPECT_EQ(emptyConn->Pragma(PRAGMA_EXEC_CHECKPOINT, nullptr), -E_NOT_INIT); + EXPECT_EQ(emptyConn->CheckIntegrity(), -E_NOT_INIT); + + int limit = 0; + EXPECT_EQ(emptyConn->Pragma(PRAGMA_SET_MAX_LOG_LIMIT, &limit), -E_NOT_SUPPORT); + EXPECT_EQ(emptyConn->Pragma(PRAGMA_RM_DEVICE_DATA, nullptr), -E_NOT_SUPPORT); + CipherPassword pw; + EXPECT_EQ(emptyConn->Import("/a.b", pw), -E_NOT_SUPPORT); + EXPECT_EQ(emptyConn->Export("/a.b", pw), -E_NOT_SUPPORT); + DatabaseLifeCycleNotifier notifier; + EXPECT_EQ(emptyConn->RegisterLifeCycleCallback(notifier), -E_NOT_SUPPORT); + + EXPECT_EQ(emptyConn->SetConflictNotifier(0, nullptr), -E_NOT_SUPPORT); + KvDBConflictAction func = [&](const KvDBCommitNotifyData &data) {}; + EXPECT_EQ(emptyConn->SetConflictNotifier(0, func), -E_NOT_SUPPORT); + IKvDBSnapshot *shot; + EXPECT_EQ(emptyConn->GetSnapshot(shot), -E_NOT_SUPPORT); +} + +/** + * @tc.name: ExecutorCache001 + * @tc.desc: Fail to operate data + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, ExecutorCache001, TestSize.Level1) +{ + g_handle->SetAttachMetaMode(true); + std::set devices; + EXPECT_EQ(g_handle->GetExistsDevicesFromMeta(devices), -E_NOT_SUPPORT); + EXPECT_EQ(g_handle->DeleteMetaDataByPrefixKey(KEY_1), -E_NOT_SUPPORT); + std::vector keys; + EXPECT_EQ(g_handle->DeleteMetaData(keys), -E_NOT_SUPPORT); + EXPECT_EQ(g_handle->PrepareForSavingCacheData(SingleVerDataType::LOCAL_TYPE_SQLITE), -E_NOT_SUPPORT); + std::string hashDev = DBCommon::TransferHashString("device1"); + EXPECT_EQ(g_handle->RemoveDeviceDataInCacheMode(hashDev, true, 0u), -E_NOT_SUPPORT); + Timestamp timestamp; + EXPECT_EQ(g_handle->GetMaxTimestampDuringMigrating(timestamp), -E_NOT_SUPPORT); + EXPECT_EQ(g_handle->ResetForSavingCacheData(SingleVerDataType::LOCAL_TYPE_SQLITE), -E_NOT_SUPPORT); +} + +/** + * @tc.name: ExecutorCache003 + * @tc.desc: Test different condition to attach db + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, ExecutorCache003, TestSize.Level1) +{ + /** + * @tc.steps: step1. Copy empty db, then attach + */ + string cacheDir = g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + + "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; + EXPECT_EQ(DBCommon::CopyFile(g_testDir + g_databaseName, cacheDir), E_OK); + CipherPassword password; + EXPECT_EQ(g_nullHandle->AttachMainDbAndCacheDb( + CipherType::DEFAULT, password, cacheDir, EngineState::INVALID), -E_NOT_SUPPORT); + EXPECT_EQ(g_nullHandle->AttachMainDbAndCacheDb( + CipherType::DEFAULT, password, cacheDir, EngineState::CACHEDB), -E_NOT_SUPPORT); + EXPECT_EQ(g_nullHandle->AttachMainDbAndCacheDb( + CipherType::DEFAULT, password, cacheDir, EngineState::ATTACHING), -E_NOT_SUPPORT); + EXPECT_EQ(g_handle->AttachMainDbAndCacheDb( + CipherType::DEFAULT, password, cacheDir, EngineState::MAINDB), -E_NOT_SUPPORT); + + /** + * @tc.steps: step2. Try migrate data after attaching cache + * @tc.expected: step2. Expect SQL_STATE_ERR + */ + NotifyMigrateSyncData syncData; + DataItem dataItem; + std::vector items; + items.push_back(dataItem); + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); +} + +/** + * @tc.name: ExecutorCache004 + * @tc.desc: Test migrate after attaching + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalExecutorTest, ExecutorCache004, TestSize.Level1) +{ + /** + * @tc.steps: step1. Copy normal db, attach cache + * @tc.expected: step1. Expect E_OK + */ + string cacheDir = g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + + "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; + EXPECT_EQ(g_handle->ForceCheckPoint(), E_OK); + EXPECT_EQ(DBCommon::CopyFile(g_testDir + g_databaseName, cacheDir), E_OK); + CipherPassword password; + EXPECT_EQ(g_handle->AttachMainDbAndCacheDb( + CipherType::DEFAULT, password, cacheDir, EngineState::MAINDB), -E_NOT_SUPPORT); + + /** + * @tc.steps: step2. Migrate sync data but param incomplete + */ + NotifyMigrateSyncData syncData; + DataItem dataItem; + std::vector items; + items.push_back(dataItem); + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); + Timestamp timestamp; + EXPECT_EQ(g_handle->GetMaxTimestampDuringMigrating(timestamp), -E_NOT_SUPPORT); + items.front().neglect = true; + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); + items.front().neglect = false; + items.front().flag = DataItem::REMOVE_DEVICE_DATA_FLAG; + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); + items.front().key = {'r', 'e', 'm', 'o', 'v', 'e'}; + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); + items.front().flag = DataItem::REMOVE_DEVICE_DATA_NOTIFY_FLAG; + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); + items.front().flag = DataItem::REMOTE_DEVICE_DATA_MISS_QUERY; + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); + string selectSync = "SELECT * FROM sync_data"; + Value value; + value.assign(selectSync.begin(), selectSync.end()); + items.front().value = value; + items.front().flag = DataItem::REMOVE_DEVICE_DATA_NOTIFY_FLAG; + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); + EXPECT_EQ(g_handle->MigrateLocalData(), -E_NOT_SUPPORT); + + /** + * @tc.steps: step3. Attach maindb + */ + EXPECT_EQ(g_handle->AttachMainDbAndCacheDb( + CipherType::DEFAULT, password, cacheDir, EngineState::CACHEDB), -E_NOT_SUPPORT); + EXPECT_EQ(g_handle->MigrateLocalData(), -E_NOT_SUPPORT); + EXPECT_EQ(g_handle->MigrateSyncDataByVersion(0u, syncData, items), -E_NOT_SUPPORT); +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..351a7b2633c6a943860ec6e7661f8860f26dc57f --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_test.cpp @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2021 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. + */ +#ifdef USE_RD_KERNEL +#include + +#include "db_constant.h" +#include "db_common.h" +#include "distributeddb_storage_rd_single_ver_natural_store_testcase.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + DistributedDB::KvStoreConfig g_config; + + std::string g_testDir; + std::string g_databaseName; + std::string g_identifier; + + DistributedDB::RdSingleVerNaturalStore *g_store = nullptr; + DistributedDB::RdSingleVerNaturalStoreConnection *g_connection = nullptr; + +class DistributedDBStorageRdSingleVerNaturalStoreTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageRdSingleVerNaturalStoreTest::SetUpTestCase(void) +{} + +void DistributedDBStorageRdSingleVerNaturalStoreTest::TearDownTestCase(void) {} + +void DistributedDBStorageRdSingleVerNaturalStoreTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGD("DistributedDBStorageRdSingleVerNaturalStoreTest dir is %s", g_testDir.c_str()); + std::string oriIdentifier = APP_ID + "-" + USER_ID + "-" + "TestGeneralNB"; + std::string identifier = DBCommon::TransferHashString(oriIdentifier); + std::string g_identifier = DBCommon::TransferStringToHex(identifier); + + g_databaseName = "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + + DBConstant::SINGLE_VER_DATA_STORE + ".db"; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR); + KvDBProperties property; + property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNB"); + property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); + + g_store = new (std::nothrow) RdSingleVerNaturalStore; + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->Open(property), E_OK); + + int erroCode = E_OK; + g_connection = static_cast(g_store->GetDBConnection(erroCode)); + ASSERT_NE(g_connection, nullptr); + g_store->DecObjRef(g_store); + EXPECT_EQ(erroCode, E_OK); +} + +void DistributedDBStorageRdSingleVerNaturalStoreTest::TearDown(void) +{ + if (g_connection != nullptr) { + g_connection->Close(); + g_connection = nullptr; + } + + g_store = nullptr; + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/" + g_identifier + "/" + + DBConstant::SINGLE_SUB_DIR); +} + +/** + * @tc.name: SyncDatabaseOperate001 + * @tc.desc: To test the function of inserting data of the local device in the synchronization database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate001, TestSize.Level1) +{ + /** + * @tc.steps: step1/2. Set Ioption to the local data and insert a record of key1 and value1. + * @tc.expected: step1/2. Return OK. + */ + /** + * @tc.steps: step3. Set Ioption to the local data and obtain the value of key1. + * Check whether the value is the same as the value of value1. + * @tc.expected: step3. The obtained value and value2 are the same. + */ + /** + * @tc.steps: step4. Ioption Set this parameter to the local data. Insert key1. + * The value cannot be empty. value2(!=value1) + * @tc.expected: step4. Return OK. + */ + /** + * @tc.steps: step5. Set Ioption to the local data, GetMetaData to obtain the value of key1, + * and check whether the value is the same as the value of value2. + * @tc.expected: step5. The obtained and value2 are the same. + */ + /** + * @tc.steps: step6. The Ioption parameter is set to the local data. + * The data record whose key is empty and value is not empty is inserted. + * @tc.expected: step6. Return E_INVALID_DATA. + */ + /** + * @tc.steps: step7. Set Ioption to the local data, insert data + * whose key2(!=key1) is not empty, and value is empty. + * @tc.expected: step7. Return OK. + */ + /** + * @tc.steps: step8. Set option to local data, obtain the value of key2, + * and check whether the value is empty. + * @tc.expected: step8. Return OK, value is empty. + */ + /** + * @tc.steps: step9. Ioption Set the local data. + * Insert the data whose key size is 1024 and value size is 4Mb. + * @tc.expected: step9. Return OK. + */ + /** + * @tc.steps: step10/11. Set Ioption to the local data and insert data items + * whose value is greater than 4Mb or key is bigger than 1Kb + * @tc.expected: step10/11. Return E_INVALID_ARGS. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate003 + * @tc.desc: test the delete operation in sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate003, TestSize.Level1) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and delete the data whose key is key1. + * @tc.expected: step5. Return E_OK. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value of Key1. + * @tc.expected: step5. Return E_NOT_FOUND. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate005 + * @tc.desc: test the reading for sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate005, TestSize.Level1) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value data of Key1. + * Check whether the value is the same as the value of value2. + * @tc.expected: step4. Return E_OK, and the value is the same as the value of value2. + */ + /** + * @tc.steps: step5. The Ioption is set to the local. + * The data of the key1 and value2(!=value1) is inserted. + * @tc.expected: step4. Return E_OK. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(g_store, g_connection); +} + +/** + * @tc.name: SyncDatabaseOperate006 + * @tc.desc: test the get entries for sync database + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: wangbingquan + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, SyncDatabaseOperate006, TestSize.Level1) +{ + /** + * @tc.steps: step2/3/4. Set Ioption to synchronous data. + * Insert the data of key=keyPrefix + 'a', value1. + * Insert the data of key=keyPrefix + 'c', value2. + * Insert the data of key length=keyPrefix length - 1, value3. + * @tc.expected: step2/3/4. Return E_NOT_FOUND. + */ + /** + * @tc.steps: step5. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step5. Return OK. The number of obtained data records is 2. + */ + /** + * @tc.steps: step6. Obtain all data whose prefixKey is empty. + * @tc.expected: step6. Return OK. The number of obtained data records is 3. + */ + /** + * @tc.steps: step7. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step7. Return E_NOT_SUPPORT. + */ + DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(g_store, g_connection); +} + +/** + * @tc.name: ExportBusy001 + * @tc.desc: Test export with busy + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBStorageRdSingleVerNaturalStoreTest, ExportBusy001, TestSize.Level1) +{ + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->TryToDisableConnection(OperatePerm::NORMAL_WRITE), E_OK); + CipherPassword password; + EXPECT_EQ(g_store->Export(g_testDir, password), -E_NOT_SUPPORT); + g_store->ReEnableConnection(OperatePerm::NORMAL_WRITE); +} +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d36fb1c49f5c7c0ecf4dfb7360b3d9f59fa83024 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.cpp @@ -0,0 +1,344 @@ +/* + * Copyright (c) 2021 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. + */ +#ifdef USE_RD_KERNEL +#include "distributeddb_storage_rd_single_ver_natural_store_testcase.h" + +#include "generic_single_ver_kv_entry.h" +#include "runtime_context.h" +#include "time_helper.h" + +using namespace DistributedDB; +using namespace DistributedDBUnitTest; + +namespace { + const int MAX_TEST_KEY_SIZE = 1024; // 1K + const int MAX_TEST_VAL_SIZE = 4194304; // 4M + + // select result index for the item for sync database + const int SYNC_RES_KEY_INDEX = 0; + const int SYNC_RES_VAL_INDEX = 1; + const int SYNC_RES_TIME_INDEX = 2; + const int SYNC_RES_FLAG_INDEX = 3; + const int SYNC_RES_HASH_KEY_INDEX = 6; + + const std::string SYNC_DATA_DEFAULT_SQL = "select * from SYNC_DATA;"; +} + +/** + * @tc.name: SyncDatabaseOperate001 + * @tc.desc: To test the function of inserting data of the local device in the synchronization database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: huangboxin + */ +void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate001(RdSingleVerNaturalStore *&store, + RdSingleVerNaturalStoreConnection *&connection) +{ + IOption option; + option.dataType = IOption::SYNC_DATA; + DataBaseCommonPutOperate(store, connection, option); +} + +/** + * @tc.name: SyncDatabaseOperate003 + * @tc.desc: test the delete operation in sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: huangboxin + */ +void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate003(RdSingleVerNaturalStore *&store, + RdSingleVerNaturalStoreConnection *&connection) +{ + IOption option; + option.dataType = IOption::SYNC_DATA; + DataBaseCommonDeleteOperate(store, connection, option); +} + +/** + * @tc.name: SyncDatabaseOperate005 + * @tc.desc: test the reading for sync database. + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: huangboxin + */ +void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate005(RdSingleVerNaturalStore *&store, + RdSingleVerNaturalStoreConnection *&connection) +{ + IOption option; + option.dataType = IOption::SYNC_DATA; + DataBaseCommonGetOperate(store, connection, option); +} + +/** + * @tc.name: SyncDatabaseOperate006 + * @tc.desc: test the get entries for sync database + * @tc.type: FUNC + * @tc.require: AR000CCPOM + * @tc.author: huangboxin + */ +void DistributedDBStorageRdSingleVerNaturalStoreTestCase::SyncDatabaseOperate006(RdSingleVerNaturalStore *&store, + RdSingleVerNaturalStoreConnection *&connection) +{ + IOption option; + option.dataType = IOption::SYNC_DATA; + Key key1, key2, key3; + Value value1, value2, value3; + + /** + * @tc.steps: step2/3/4. Set Ioption to synchronous data. + * Insert the data of key=keyPrefix + 'a', value1. + * Insert the data of key=keyPrefix + 'c', value2. + * Insert the data of key length=keyPrefix length - 1, value3. + * @tc.expected: step2/3/4. Return E_NOT_FOUND. + */ + DistributedDBToolsUnitTest::GetRandomKeyValue(key1, 30); // 30 as random size + key3 = key2 = key1; + key2.push_back('C'); + key3.pop_back(); + DistributedDBToolsUnitTest::GetRandomKeyValue(value1, 84); // 84 as random size + DistributedDBToolsUnitTest::GetRandomKeyValue(value2, 101); // 101 as random size + DistributedDBToolsUnitTest::GetRandomKeyValue(value3, 37); // 37 as random size + EXPECT_EQ(connection->Put(option, key1, value1), E_OK); + EXPECT_EQ(connection->Put(option, key2, value2), E_OK); + EXPECT_EQ(connection->Put(option, key3, value3), E_OK); + + /** + * @tc.steps: step5. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step5. Return OK. The number of obtained data records is 2. + */ + std::vector entriesRead; + EXPECT_EQ(connection->GetEntries(option, key1, entriesRead), E_OK); + EXPECT_EQ(entriesRead.size(), 2UL); + + /** + * @tc.steps: step6. Obtain all data whose prefixKey is empty. + * @tc.expected: step6. Return OK. The number of obtained data records is 3. + */ + entriesRead.clear(); + Key emptyKey; + EXPECT_EQ(connection->GetEntries(option, emptyKey, entriesRead), E_OK); + EXPECT_EQ(entriesRead.size(), 3UL); + + /** + * @tc.steps: step7. Obtain all data whose prefixKey is keyPrefix. + * @tc.expected: step7. Return -E_NOT_SUPPORT. + */ + option.dataType = IOption::LOCAL_DATA; + EXPECT_EQ(connection->GetEntries(option, emptyKey, entriesRead), -E_NOT_SUPPORT); +} + +// @Real query sync-DATA table by key, judge is exist. +bool DistributedDBStorageRdSingleVerNaturalStoreTestCase::IsSqlinteExistKey(const std::vector &vecSyncData, + const std::vector &key) +{ + for (const auto &iter : vecSyncData) { + if (key == iter.key) { + return true; + } + } + return false; +} + +void DistributedDBStorageRdSingleVerNaturalStoreTestCase::DataBaseCommonPutOperate(RdSingleVerNaturalStore *&store, + RdSingleVerNaturalStoreConnection *&connection, IOption option) +{ + Key key1; + Value value1; + + /** + * @tc.steps: step1/2. Set Ioption to the local data and insert a record of key1 and value1. + * @tc.expected: step1/2. Return OK. + */ + DistributedDBToolsUnitTest::GetRandomKeyValue(key1); + DistributedDBToolsUnitTest::GetRandomKeyValue(value1); + EXPECT_EQ(connection->Put(option, key1, value1), E_OK); + + /** + * @tc.steps: step3. Set Ioption to the local data and obtain the value of key1. + * Check whether the value is the same as the value of value1. + * @tc.expected: step3. The obtained value and value2 are the same. + */ + Value valueRead; + EXPECT_EQ(connection->Get(option, key1, valueRead), E_OK); + EXPECT_EQ(DistributedDBToolsUnitTest::IsValueEqual(valueRead, value1), true); + Value value2; + DistributedDBToolsUnitTest::GetRandomKeyValue(value2, static_cast(value1.size() + 3)); // 3 more for diff + + /** + * @tc.steps: step4. Ioption Set this parameter to the local data. Insert key1. + * The value cannot be empty. value2(!=value1) + * @tc.expected: step4. Return OK. + */ + EXPECT_EQ(connection->Put(option, key1, value2), E_OK); + + /** + * @tc.steps: step5. Set Ioption to the local data, GetMetaData to obtain the value of key1, + * and check whether the value is the same as the value of value2. + * @tc.expected: step5. The obtained value and value2 are the same. + */ + EXPECT_EQ(connection->Get(option, key1, valueRead), E_OK); + EXPECT_EQ(DistributedDBToolsUnitTest::IsValueEqual(valueRead, value2), true); + + /** + * @tc.steps: step6. The Ioption parameter is set to the local data. + * The data record whose key is empty and value is not empty is inserted. + * @tc.expected: step6. Return E_INVALID_DATA. + */ + Key emptyKey; + Value emptyValue; + EXPECT_EQ(connection->Put(option, emptyKey, value1), -E_INVALID_ARGS); + + /** + * @tc.steps: step7. Set Ioption to the local data, insert data + * whose key2(!=key1) is not empty, and value is empty. + * @tc.expected: step7. Return E_OK + */ + Key key2; + DistributedDBToolsUnitTest::GetRandomKeyValue(key2, static_cast(key1.size() + 1)); + EXPECT_EQ(connection->Put(option, key2, emptyValue), E_OK); + + /** + * @tc.steps: step8. Set option to local data, obtain the value of key2, + * and check whether the value is empty. + * @tc.expected: step8. Return E_OK. + */ + EXPECT_EQ(connection->Get(option, key2, valueRead), E_OK); + + /** + * @tc.steps: step9. Ioption Set the local data. + * Insert the data whose key size is 1024 and value size is 4Mb + 1. + * @tc.expected: step9. Return OK. + */ + Key sizeKey; + Value sizeValue; + DistributedDBToolsUnitTest::GetRandomKeyValue(sizeKey, MAX_TEST_KEY_SIZE); + DistributedDBToolsUnitTest::GetRandomKeyValue(sizeValue, MAX_TEST_VAL_SIZE + 1); + EXPECT_EQ(connection->Put(option, sizeKey, sizeValue), -E_INVALID_ARGS); + EXPECT_EQ(connection->Get(option, sizeKey, valueRead), -E_NOT_FOUND); + + /** + * @tc.steps: step10/11. Set Ioption to the local data and insert data items + * whose value is greater than 4Mb or key is bigger than 1Kb + * @tc.expected: step10/11. Return E_INVALID_ARGS. + */ + sizeKey.push_back(std::rand()); // random size + EXPECT_EQ(connection->Put(option, sizeKey, sizeValue), -E_INVALID_ARGS); + sizeKey.pop_back(); + sizeValue.push_back(174); // 174 as random size + EXPECT_EQ(connection->Put(option, sizeKey, sizeValue), -E_INVALID_ARGS); +} + +void DistributedDBStorageRdSingleVerNaturalStoreTestCase::DataBaseCommonDeleteOperate(RdSingleVerNaturalStore *&store, + RdSingleVerNaturalStoreConnection *&connection, IOption option) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + Key key1; + EXPECT_EQ(connection->Delete(option, key1), -E_INVALID_ARGS); + DistributedDBToolsUnitTest::GetRandomKeyValue(key1, MAX_TEST_KEY_SIZE + 1); + EXPECT_EQ(connection->Delete(option, key1), -E_INVALID_ARGS); + DistributedDBToolsUnitTest::GetRandomKeyValue(key1); + EXPECT_EQ(connection->Delete(option, key1), E_OK); + + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + Value value1; + DistributedDBToolsUnitTest::GetRandomKeyValue(value1); + EXPECT_EQ(connection->Put(option, key1, value1), E_OK); + + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + Value valueRead; + EXPECT_EQ(connection->Get(option, key1, valueRead), E_OK); + EXPECT_EQ(DistributedDBToolsUnitTest::IsValueEqual(valueRead, value1), true); + + /** + * @tc.steps: step5. Set Ioption to the local data and delete the data whose key is key1. + * @tc.expected: step5. Return E_OK. + */ + EXPECT_EQ(connection->Delete(option, key1), E_OK); + + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value of Key1. + * @tc.expected: step5. Return E_NOT_FOUND. + */ + EXPECT_EQ(connection->Get(option, key1, valueRead), -E_NOT_FOUND); +} + +void DistributedDBStorageRdSingleVerNaturalStoreTestCase::DataBaseCommonGetOperate(RdSingleVerNaturalStore *&store, + RdSingleVerNaturalStoreConnection *&connection, IOption option) +{ + /** + * @tc.steps: step2. Set Ioption to the local data and delete the data whose key is key1 (empty). + * @tc.expected: step2. Return E_INVALID_ARGS. + */ + Key key1; + Value valueRead; + // empty key + EXPECT_EQ(connection->Get(option, key1, valueRead), -E_INVALID_ARGS); + + // invalid key + DistributedDBToolsUnitTest::GetRandomKeyValue(key1, MAX_TEST_KEY_SIZE + 1); + EXPECT_EQ(connection->Get(option, key1, valueRead), -E_INVALID_ARGS); + + // non-exist key + DistributedDBToolsUnitTest::GetRandomKeyValue(key1, MAX_TEST_KEY_SIZE); + EXPECT_EQ(connection->Get(option, key1, valueRead), -E_NOT_FOUND); + + /** + * @tc.steps: step3. Set Ioption to the local data, insert non-null key1, and non-null value1 data. + * @tc.expected: step3. Return E_OK. + */ + Value value1; + DistributedDBToolsUnitTest::GetRandomKeyValue(value1); + EXPECT_EQ(connection->Put(option, key1, value1), E_OK); + + /** + * @tc.steps: step4. Set Ioption to the local data, obtain the value of key1, + * and check whether the value is the same as that of value1. + * @tc.expected: step4. Return E_OK. The obtained value is the same as the value of value1. + */ + EXPECT_EQ(connection->Get(option, key1, valueRead), E_OK); + EXPECT_EQ(DistributedDBToolsUnitTest::IsValueEqual(valueRead, value1), true); + + Key key2; + DistributedDBToolsUnitTest::GetRandomKeyValue(key2); + EXPECT_EQ(connection->Get(option, key2, valueRead), -E_NOT_FOUND); + + /** + * @tc.steps: step5. Set Ioption to the local data and obtain the value data of Key1. + * Check whether the value is the same as the value of value2. + * @tc.expected: step4. Return E_OK, and the value is the same as the value of value2. + */ + Value value2; + DistributedDBToolsUnitTest::GetRandomKeyValue(value2, value1.size() + 1); + EXPECT_EQ(connection->Put(option, key1, value2), E_OK); + + /** + * @tc.steps: step5. The Ioption is set to the local. + * The data of the key1 and value2(!=value1) is inserted. + * @tc.expected: step4. Return E_OK. + */ + EXPECT_EQ(connection->Get(option, key1, valueRead), E_OK); + EXPECT_EQ(DistributedDBToolsUnitTest::IsValueEqual(valueRead, value2), true); +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.h new file mode 100644 index 0000000000000000000000000000000000000000..2e92001c3b349f2521298ba728e93bba06e49ab5 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_natural_store_testcase.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021 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. + */ +#ifdef USE_RD_KERNEL +#ifndef DISTRIBUTEDDB_STORAGE_SINGLE_VER_NATURAL_STORE_TESTCASE_H +#define DISTRIBUTEDDB_STORAGE_SINGLE_VER_NATURAL_STORE_TESTCASE_H + +#include +#include "db_errno.h" +#include "distributeddb_data_generate_unit_test.h" +#include "distributeddb_tools_unit_test.h" +#include "multi_ver_natural_store.h" +#include "sqlite_local_kvdb.h" +#include "rd_single_ver_natural_store.h" +#include "rd_single_ver_natural_store_connection.h" +#include "sqlite_utils.h" + +struct SyncData { + std::vector hashKey; + std::vector key; + std::vector value; + uint64_t timestamp; + uint64_t flag; + std::string deviceInfo; +}; + +class DistributedDBStorageRdSingleVerNaturalStoreTestCase final { +public: + DistributedDBStorageRdSingleVerNaturalStoreTestCase() {}; + ~DistributedDBStorageRdSingleVerNaturalStoreTestCase() {}; + + static void SyncDatabaseOperate001(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection); + + static void SyncDatabaseOperate003(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection); + + static void SyncDatabaseOperate005(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection); + + static void SyncDatabaseOperate006(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection); + +private: + static bool IsSqlinteExistKey(const std::vector &vecSyncData, const std::vector &key); + + static void TestMetaDataPutAndGet(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection); + + static void TestMetaDataDeleteByPrefixKey(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection); + + static void DataBaseCommonPutOperate(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection, DistributedDB::IOption option); + + static void DataBaseCommonDeleteOperate(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection, DistributedDB::IOption option); + + static void DataBaseCommonGetOperate(DistributedDB::RdSingleVerNaturalStore *&store, + DistributedDB::RdSingleVerNaturalStoreConnection *&connection, DistributedDB::IOption option); +}; +#endif +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_storage_engine_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_storage_engine_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fff42fd543f80b8201370febc964a323aca76c05 --- /dev/null +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_rd_single_ver_storage_engine_test.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifdef USE_RD_KERNEL +#include + +#include "db_common.h" +#include "distributeddb_storage_rd_single_ver_natural_store_testcase.h" +#include "storage_engine_manager.h" + +using namespace testing::ext; +using namespace DistributedDB; +using namespace DistributedDBUnitTest; +using namespace std; + +namespace { + string g_testDir; + string g_databaseName; + string g_identifier; + KvDBProperties g_property; + + RdSingleVerNaturalStore *g_store = nullptr; + RdSingleVerNaturalStoreConnection *g_connection = nullptr; + + const char * const ADD_SYNC = "ALTER TABLE sync_data ADD column version INT"; + const char * const INSERT_SQL = "INSERT INTO sync_data VALUES('a', 'b', 1, 2, '', '', 'efdef', 100 , 1);"; + const int SQL_STATE_ERR = -1; + + void GetStorageEngine(RdSingleVerStorageEngine *&storageEngine) + { + int errCode; + storageEngine = + static_cast(StorageEngineManager::GetStorageEngine(g_property, errCode)); + EXPECT_EQ(errCode, E_OK); + } +} + +class DistributedDBStorageRdSingleVerStorageEngineTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DistributedDBStorageRdSingleVerStorageEngineTest::SetUpTestCase(void) +{ + DistributedDBToolsUnitTest::TestDirInit(g_testDir); + LOGI("DistributedDBStorageRdSingleVerStorageEngineTest dir is %s", g_testDir.c_str()); + std::string oriIdentifier = APP_ID + "-" + USER_ID + "-" + "TestGeneralNBStorageEngine"; + std::string identifier = DBCommon::TransferHashString(oriIdentifier); + g_identifier = DBCommon::TransferStringToHex(identifier); + + g_databaseName = "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; + g_property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); + g_property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNBStorageEngine"); + g_property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); + g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_RD_KERNAL); +} + +void DistributedDBStorageRdSingleVerStorageEngineTest::TearDownTestCase(void) +{ + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR); +} + +void DistributedDBStorageRdSingleVerStorageEngineTest::SetUp(void) +{ + DistributedDBToolsUnitTest::PrintTestCaseInfo(); + DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR); + g_store = new (std::nothrow) RdSingleVerNaturalStore; + ASSERT_NE(g_store, nullptr); + ASSERT_EQ(g_store->Open(g_property), E_OK); + + int erroCode = E_OK; + g_connection = static_cast(g_store->GetDBConnection(erroCode)); + ASSERT_NE(g_connection, nullptr); + g_store->DecObjRef(g_store); + EXPECT_EQ(erroCode, E_OK); +} + +void DistributedDBStorageRdSingleVerStorageEngineTest::TearDown(void) +{ + if (g_connection != nullptr) { + g_connection->Close(); + g_connection = nullptr; + } + g_store = nullptr; +} + +/** + * @tc.name: DataTest001 + * @tc.desc: Change engine state, execute migrate + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBStorageRdSingleVerStorageEngineTest, DataTest001, TestSize.Level1) +{ + RdSingleVerStorageEngine *storageEngine = nullptr; + GetStorageEngine(storageEngine); + ASSERT_NE(storageEngine, nullptr); + + storageEngine->SetEngineState(EngineState::ENGINE_BUSY); + EXPECT_EQ(storageEngine->ExecuteMigrate(), -E_NOT_SUPPORT); + storageEngine->SetEngineState(EngineState::ATTACHING); + EXPECT_EQ(storageEngine->ExecuteMigrate(), -E_NOT_SUPPORT); + storageEngine->SetEngineState(EngineState::MAINDB); + EXPECT_EQ(storageEngine->ExecuteMigrate(), -E_NOT_SUPPORT); + storageEngine->SetEngineState(EngineState::CACHEDB); + EXPECT_EQ(storageEngine->ExecuteMigrate(), -E_NOT_SUPPORT); + storageEngine->Release(); + storageEngine = nullptr; +} +#endif // USE_RD_KERNEL \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp index a7d5f6228c482ac3f14875b9c87e480890e68de7..aa1474581188aa92f89cf71e131ff5016acf5811 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_conflict_test.cpp @@ -182,7 +182,7 @@ void DistributedDBStorageRegisterConflictTest::SetUp(void) property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); g_store = new (std::nothrow) SQLiteSingleVerNaturalStore; ASSERT_NE(g_store, nullptr); ASSERT_EQ(g_store->Open(property), E_OK); @@ -793,7 +793,7 @@ namespace { property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); property.SetIntProp(KvDBProperties::CONFLICT_RESOLVE_POLICY, DENY_OTHER_DEV_AMEND_CUR_DEV_DATA); g_store = new (std::nothrow) SQLiteSingleVerNaturalStore; ASSERT_NE(g_store, nullptr); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp index 554a30cb498cd6e4f1ef3f712b6cf3aac0706fae..b6dadf19522c083809123671aa2b3292d8231b8b 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_register_observer_test.cpp @@ -301,7 +301,7 @@ void DistributedDBStorageRegisterObserverTest::SetUp(void) property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNB"); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, "TestGeneralNB"); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); int errCode = g_singleVerNaturaStore->Open(property); ASSERT_EQ(errCode, E_OK); if (errCode != E_OK) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp index c24d791a44bddc38bcab08ff31cff9c36c2f7b72..475930ecbf2c66a5d2aef536da402f16b06ffa6e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_resultset_and_json_optimize.cpp @@ -68,7 +68,7 @@ void DistributedDBStorageResultAndJsonOptimizeTest::SetUpTestCase(void) g_Property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); g_Property.SetStringProp(KvDBProperties::STORE_ID, STORE_ID); g_Property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - g_Property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + g_Property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); } void DistributedDBStorageResultAndJsonOptimizeTest::TearDownTestCase(void) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp index f6b969111663e6d7b8ce3f3d8a51d2e672c4aa41..18c80e4e889cd303f1fad7cd7fe18a40eb9abd10 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_natural_store_testcase.cpp @@ -1571,7 +1571,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::TestMetaDataPutAndGet(SQ * @tc.steps:step1. Run the PutMetaData command to insert a non-empty key1 non-empty value1 data record. * @tc.expected: step1. Return OK. */ - EXPECT_EQ(store->PutMetaData(key1, value1), E_OK); + EXPECT_EQ(store->PutMetaData(key1, value1, false), E_OK); /** * @tc.steps:step2. Run the PutMetaData command to insert a non-empty key1 non-empty value1 data record. @@ -1588,7 +1588,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::TestMetaDataPutAndGet(SQ * and the value of value2 is different from the value of value1 through the PutMetaData interface. * @tc.expected: step3. Return OK. */ - EXPECT_EQ(store->PutMetaData(key1, value2), E_OK); + EXPECT_EQ(store->PutMetaData(key1, value2, false), E_OK); /** * @tc.steps:step4. Run the GetMetaData command to obtain the value of key1 @@ -1602,7 +1602,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::TestMetaDataPutAndGet(SQ * @tc.steps:step5. Use PutMetaData to insert a record whose key is empty and value is not empty. * @tc.expected: step5. Return E_INVALID_ARGS. */ - EXPECT_EQ(store->PutMetaData(emptyKey, value1), -E_INVALID_ARGS); + EXPECT_EQ(store->PutMetaData(emptyKey, value1, false), -E_INVALID_ARGS); /** * @tc.steps:step6. Use PutMetaData in NaturalStore to insert data whose key2(!=key1) @@ -1611,7 +1611,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::TestMetaDataPutAndGet(SQ */ Key key2; DistributedDBToolsUnitTest::GetRandomKeyValue(key2, static_cast(key1.size() + 1)); - EXPECT_EQ(store->PutMetaData(key2, emptyValue), E_OK); + EXPECT_EQ(store->PutMetaData(key2, emptyValue, false), E_OK); /** * @tc.steps:step7. Obtain the value of key2 and check whether the value is empty. @@ -1629,7 +1629,7 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::TestMetaDataPutAndGet(SQ Value sizeValue; DistributedDBToolsUnitTest::GetRandomKeyValue(sizeKey, MAX_TEST_KEY_SIZE); DistributedDBToolsUnitTest::GetRandomKeyValue(sizeValue, MAX_TEST_VAL_SIZE); - EXPECT_EQ(store->PutMetaData(sizeKey, sizeValue), E_OK); + EXPECT_EQ(store->PutMetaData(sizeKey, sizeValue, false), E_OK); EXPECT_EQ(store->GetMetaData(sizeKey, valueRead), E_OK); EXPECT_EQ(DistributedDBToolsUnitTest::IsValueEqual(valueRead, sizeValue), true); @@ -1639,10 +1639,10 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::TestMetaDataPutAndGet(SQ * @tc.expected: step9/10. Return E_INVALID_ARGS. */ sizeKey.push_back(249); // 249 as random size - EXPECT_EQ(store->PutMetaData(sizeKey, sizeValue), -E_INVALID_ARGS); + EXPECT_EQ(store->PutMetaData(sizeKey, sizeValue, false), -E_INVALID_ARGS); sizeKey.pop_back(); sizeValue.push_back(174); // 174 as random size - EXPECT_EQ(store->PutMetaData(sizeKey, sizeValue), -E_INVALID_ARGS); + EXPECT_EQ(store->PutMetaData(sizeKey, sizeValue, false), -E_INVALID_ARGS); /** * @tc.steps:step11. Delete key1 and key2 successfully. @@ -1853,10 +1853,10 @@ void DistributedDBStorageSingleVerNaturalStoreTestCase::TestMetaDataDeleteByPref * @tc.steps:step1. Put a1, b1, a2, b2. * @tc.expected: step1. Return OK. */ - ASSERT_EQ(store->PutMetaData(Key {'a', '1'}, Value {'a', '1'}), E_OK); - ASSERT_EQ(store->PutMetaData(Key {'b', '1'}, Value {'b', '1'}), E_OK); - ASSERT_EQ(store->PutMetaData(Key {'a', '2'}, Value {'a', '2'}), E_OK); - ASSERT_EQ(store->PutMetaData(Key {'b', '2'}, Value {'b', '2'}), E_OK); + ASSERT_EQ(store->PutMetaData(Key {'a', '1'}, Value {'a', '1'}, false), E_OK); + ASSERT_EQ(store->PutMetaData(Key {'b', '1'}, Value {'b', '1'}, false), E_OK); + ASSERT_EQ(store->PutMetaData(Key {'a', '2'}, Value {'a', '2'}, false), E_OK); + ASSERT_EQ(store->PutMetaData(Key {'b', '2'}, Value {'b', '2'}, false), E_OK); /** * @tc.steps:step2. Delete meta data with prefix key 'b'. diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp index 00c4c33f0670ecafd9b0c5f58e4a42fc3c5a4e36..2555b321ead3da527a669a84c13080634f4b8780 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_single_ver_upgrade_test.cpp @@ -223,8 +223,9 @@ namespace { SecurityOption checkSecOpt; SecurityOption currentMetaSecOpt {SecurityLabel::S2, SecurityFlag::ECE}; int errCode = RuntimeContext::GetInstance()->GetSecurityOption(g_maindbPath, checkSecOpt); - EXPECT_TRUE(currentSecOpt == checkSecOpt); - EXPECT_TRUE(errCode == E_OK); + EXPECT_EQ(currentSecOpt.securityLabel, checkSecOpt.securityLabel); + EXPECT_EQ(currentSecOpt.securityFlag, checkSecOpt.securityFlag); + EXPECT_EQ(errCode, E_OK); if (OS::CheckPathExistence(g_cachedbPath)) { errCode = RuntimeContext::GetInstance()->GetSecurityOption(g_cachedbPath, checkSecOpt); EXPECT_TRUE(currentSecOpt == checkSecOpt); @@ -276,11 +277,11 @@ void DistributedDBStorageSingleVerUpgradeTest::SetUpTestCase(void) g_identifier = DBCommon::TransferHashString(oriIdentifier); std::string identifier = DBCommon::TransferStringToHex(g_identifier); g_databaseName = "/" + identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; g_newDatabaseName = "/" + identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; g_localdatabaseName = "/" + identifier + "/" + DBConstant::LOCAL_SUB_DIR + "/" + - DBConstant::LOCAL_DATABASE_NAME + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::LOCAL_DATABASE_NAME + DBConstant::DB_EXTENSION; const int passwdLen = 5; const int passwdVal = 1; vector passwdBuffer1(passwdLen, passwdVal); @@ -289,11 +290,11 @@ void DistributedDBStorageSingleVerUpgradeTest::SetUpTestCase(void) g_adapter = std::make_shared(); RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(g_adapter); g_maindbPath = g_testDir + "/" + identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + - "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + "/" + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; g_metadbPath = g_testDir + "/" + identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::METADB_DIR + - "/" + DBConstant::SINGLE_VER_META_STORE + DBConstant::SQLITE_DB_EXTENSION; + "/" + DBConstant::SINGLE_VER_META_STORE + DBConstant::DB_EXTENSION; g_cachedbPath = g_testDir + "/" + identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::CACHEDB_DIR + - "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::SQLITE_DB_EXTENSION; + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; } void DistributedDBStorageSingleVerUpgradeTest::TearDownTestCase(void) @@ -346,7 +347,8 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest001, TestSize.Leve */ KvStoreNbDelegate::Option option = {true, false, false}; option.secOption = secopt; - GetKvStoreProcess(option, true, true, SecurityOption()); + // check sec option update to s3 + GetKvStoreProcess(option, true, true, secopt); sqlite3 *db = nullptr; dbPath = g_testDir + g_newDatabaseName; @@ -359,7 +361,8 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest001, TestSize.Leve */ CheckLocalDataV1ToV2(db); CheckSyncDataV1ToV2(db); - CheckDirectoryV2ToV3(true, false); + // sec option update to s3, create cache db + CheckDirectoryV2ToV3(true, true); CheckVersionV3(db); (void)sqlite3_close_v2(db); EXPECT_EQ(g_mgr.DeleteKvStore("TestUpgradeNb"), OK); @@ -389,7 +392,8 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest002, TestSize.Leve */ KvStoreNbDelegate::Option option = {true, false, false}; option.secOption = secopt; - GetKvStoreProcess(option, true, true, SecurityOption()); + // check sec option update to s3 + GetKvStoreProcess(option, true, true, secopt); sqlite3 *db = nullptr; dbPath = g_testDir + g_newDatabaseName; @@ -400,10 +404,12 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest002, TestSize.Leve * @tc.steps:step3. check result is ok. * @tc.expected: dir is ok,version is ok. */ - CheckDirectoryV2ToV3(true, false); + // sec option update to s3, create cache db + CheckDirectoryV2ToV3(true, true); CheckVersionV3(db); (void)sqlite3_close_v2(db); - GetKvStoreProcess(option, false, true, SecurityOption()); + // check sec option update to s3 + GetKvStoreProcess(option, false, true, secopt); EXPECT_EQ(g_mgr.DeleteKvStore("TestUpgradeNb"), OK); } #ifndef OMIT_JSON @@ -450,7 +456,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest003, TestSize.Leve "}" "}," "\"SCHEMA_INDEXES\":[\"$.field_name1\", \"$.field_name2.field_name6\"]}"; - GetKvStoreProcess(option, false, true, SecurityOption()); + GetKvStoreProcess(option, false, true, secopt); sqlite3 *db = nullptr; dbPath = g_testDir + g_newDatabaseName; @@ -461,11 +467,11 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest003, TestSize.Leve * @tc.steps:step3. check result is ok. * @tc.expected: dir is ok,version is ok. */ - CheckDirectoryV2ToV3(true, false); + CheckDirectoryV2ToV3(true, true); CheckVersionV3(db); (void)sqlite3_close_v2(db); - GetKvStoreProcess(option, false, true, SecurityOption()); + GetKvStoreProcess(option, false, true, secopt); EXPECT_EQ(g_mgr.DeleteKvStore("TestUpgradeNb"), OK); } #endif @@ -498,7 +504,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest004, TestSize.Leve EXPECT_TRUE(checkSecOpt.securityLabel == NOT_SET); option.secOption = secopt; - GetKvStoreProcess(option, true, true, SecurityOption()); + GetKvStoreProcess(option, true, true, secopt); sqlite3 *db = nullptr; dbPath = g_testDir + g_newDatabaseName; @@ -509,7 +515,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest004, TestSize.Leve * @tc.steps:step3. check result is ok. * @tc.expected: dir is ok,version is ok. */ - CheckDirectoryV2ToV3(true, false); + CheckDirectoryV2ToV3(true, true); CheckVersionV3(db); (void)sqlite3_close_v2(db); @@ -534,7 +540,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest005, TestSize.Leve */ KvStoreNbDelegate::Option option = {true, false, false}; option.secOption = secopt; - GetKvStoreProcess(option, true, true, SecurityOption()); + GetKvStoreProcess(option, true, true, secopt); sqlite3 *db = nullptr; dbPath = g_testDir + g_newDatabaseName; @@ -569,7 +575,7 @@ HWTEST_F(DistributedDBStorageSingleVerUpgradeTest, UpgradeTest006, TestSize.Leve */ KvStoreNbDelegate::Option option = {true, false, false}; option.secOption = secopt; - GetKvStoreProcess(option, true, true, SecurityOption()); + GetKvStoreProcess(option, true, true, secopt); sqlite3 *db = nullptr; dbPath = g_testDir + g_newDatabaseName; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp index 71805b5f245250c2c7073ee4226629def807fad5..cfd785e704a4cb16ffe5f75f0cec66c5f3592006 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_executor_test.cpp @@ -60,11 +60,11 @@ void DistributedDBStorageSQLiteSingleVerNaturalExecutorTest::SetUpTestCase(void) g_identifier = DBCommon::TransferStringToHex(identifier); g_databaseName = "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; g_property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); g_property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNBExecutor"); g_property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); } void DistributedDBStorageSQLiteSingleVerNaturalExecutorTest::TearDownTestCase(void) @@ -194,14 +194,14 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, InvalidParam003 * @tc.steps: step2. The db is null * @tc.expected: step2.. Expect -E_INVALID_DB */ - EXPECT_EQ(g_nullHandle->GetEntries(false, SingleVerDataType::LOCAL_TYPE, KEY_1, entries), -E_INVALID_DB); + EXPECT_EQ(g_nullHandle->GetEntries(false, SingleVerDataType::LOCAL_TYPE_SQLITE, KEY_1, entries), -E_INVALID_DB); /** * @tc.steps: step3. This key does not exist * @tc.expected: step3. Expect -E_NOT_FOUND */ Key key; - EXPECT_EQ(g_handle->GetEntries(false, SingleVerDataType::LOCAL_TYPE, KEY_1, entries), -E_NOT_FOUND); + EXPECT_EQ(g_handle->GetEntries(false, SingleVerDataType::LOCAL_TYPE_SQLITE, KEY_1, entries), -E_NOT_FOUND); } /** @@ -422,7 +422,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, InvalidParam011 Key key = KEY_1; Value value; Timestamp timestamp = 0; - EXPECT_EQ(g_handle->PutKvData(SingleVerDataType::LOCAL_TYPE, key, value, timestamp, nullptr), E_OK); + EXPECT_EQ(g_handle->PutKvData(SingleVerDataType::LOCAL_TYPE_SQLITE, key, value, timestamp, nullptr), E_OK); /** * @tc.steps: step2. Get sqlite3 handle,then create executor for state CACHE_ATTACH_MAIN @@ -482,7 +482,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, InvalidSync001, * @tc.steps: step2. Try to prepare when the db is null * @tc.expected: step2. Expect -E_INVALID_DB */ - EXPECT_EQ(g_nullHandle->PrepareForSavingData(SingleVerDataType::LOCAL_TYPE), -E_INVALID_DB); + EXPECT_EQ(g_nullHandle->PrepareForSavingData(SingleVerDataType::LOCAL_TYPE_SQLITE), -E_INVALID_DB); /** * @tc.steps: step3. The data item key is empty @@ -878,12 +878,12 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ExecutorCache00 EXPECT_EQ(g_handle->DeleteMetaDataByPrefixKey(KEY_1), SQL_STATE_ERR); std::vector keys; EXPECT_EQ(g_handle->DeleteMetaData(keys), SQL_STATE_ERR); - EXPECT_EQ(g_handle->PrepareForSavingCacheData(SingleVerDataType::LOCAL_TYPE), SQL_STATE_ERR); + EXPECT_EQ(g_handle->PrepareForSavingCacheData(SingleVerDataType::LOCAL_TYPE_SQLITE), SQL_STATE_ERR); std::string hashDev = DBCommon::TransferHashString("device1"); EXPECT_EQ(g_handle->RemoveDeviceDataInCacheMode(hashDev, true, 0u), SQL_STATE_ERR); Timestamp timestamp; EXPECT_EQ(g_handle->GetMaxTimestampDuringMigrating(timestamp), -E_NOT_INIT); - EXPECT_EQ(g_handle->ResetForSavingCacheData(SingleVerDataType::LOCAL_TYPE), E_OK); + EXPECT_EQ(g_handle->ResetForSavingCacheData(SingleVerDataType::LOCAL_TYPE_SQLITE), E_OK); } /** @@ -956,7 +956,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ExecutorCache00 * @tc.steps: step1. Copy empty db, then attach */ string cacheDir = g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + - "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::SQLITE_DB_EXTENSION; + "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; EXPECT_EQ(DBCommon::CopyFile(g_testDir + g_databaseName, cacheDir), E_OK); CipherPassword password; EXPECT_EQ(g_nullHandle->AttachMainDbAndCacheDb( @@ -993,7 +993,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalExecutorTest, ExecutorCache00 * @tc.expected: step1. Expect E_OK */ string cacheDir = g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + - "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::SQLITE_DB_EXTENSION; + "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; EXPECT_EQ(g_handle->ForceCheckPoint(), E_OK); EXPECT_EQ(DBCommon::CopyFile(g_testDir + g_databaseName, cacheDir), E_OK); CipherPassword password; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp index b369cd2a0927367bc415eafb650742503722a279..075e76053d76d441b31aa6ec6170de7b5daa7b10 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_natural_store_test.cpp @@ -64,7 +64,7 @@ void DistributedDBStorageSQLiteSingleVerNaturalStoreTest::SetUp(void) property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNB"); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); g_store = new (std::nothrow) SQLiteSingleVerNaturalStore; ASSERT_NE(g_store, nullptr); @@ -1127,7 +1127,7 @@ HWTEST_F(DistributedDBStorageSQLiteSingleVerNaturalStoreTest, MigrationAndReleas property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNBMigration"); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); int iterCount = 100; for (int i = 0; i < iterCount; i++) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp index a54ef8c01ace6072c68b61c26b2a673f6ebb1883..24d029231d6a073904c6dfdeaa7028d617400086 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_sqlite_single_ver_storage_engine_test.cpp @@ -70,13 +70,13 @@ void DistributedDBStorageSQLiteSingleVerStorageEngineTest::SetUpTestCase(void) g_identifier = DBCommon::TransferStringToHex(identifier); g_databaseName = "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + "/" + DBConstant::MAINDB_DIR + "/" + - DBConstant::SINGLE_VER_DATA_STORE + DBConstant::SQLITE_DB_EXTENSION; + DBConstant::SINGLE_VER_DATA_STORE + DBConstant::DB_EXTENSION; g_property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); g_property.SetStringProp(KvDBProperties::STORE_ID, "TestGeneralNBStorageEngine"); g_property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, g_identifier); - g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + g_property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); g_cacheDir = g_testDir + "/" + g_identifier + "/" + DBConstant::SINGLE_SUB_DIR + - "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::SQLITE_DB_EXTENSION; + "/" + DBConstant::CACHEDB_DIR + "/" + DBConstant::SINGLE_VER_CACHE_STORE + DBConstant::DB_EXTENSION; } void DistributedDBStorageSQLiteSingleVerStorageEngineTest::TearDownTestCase(void) diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp index c485778696ad0c5ab8c817bcbf500241e2cda948..9da40f841c093df2cab53377cc51756917f5888d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/storage/distributeddb_storage_subscribe_query_test.cpp @@ -113,7 +113,7 @@ void CreateAndGetStore(const std::string &storeId, const std::string &schemaStri property.SetStringProp(KvDBProperties::DATA_DIR, g_testDir); property.SetStringProp(KvDBProperties::STORE_ID, storeId); property.SetBoolProp(KvDBProperties::MEMORY_MODE, false); - property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE); + property.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::SINGLE_VER_TYPE_SQLITE); property.SetStringProp(KvDBProperties::IDENTIFIER_DIR, identifierHex); property.SetIntProp(KvDBProperties::CONFLICT_RESOLVE_POLICY, ConflictResolvePolicy::LAST_WIN); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_data_utils.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_data_utils.cpp index f2bab3c0724e722e00c662753cb44ac8960dd2cf..374b49803f744eeb446039b4582b6ee42366ab4a 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_data_utils.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_data_utils.cpp @@ -14,8 +14,8 @@ */ #include "cloud_db_data_utils.h" -#include "cloud_db_constant.h" -#include "cloud_db_types.h" +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_db_types.h" namespace DistributedDB { std::vector CloudDBDataUtils::GenerateRecords(int recordCounts, const TableSchema &schema) { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp index 786d56e60303ab9804f3ea40d5f73fcccf43032f..2a58c41353a34099857537c6febb79022c60addf 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.cpp @@ -45,9 +45,9 @@ namespace DistributedDB { g_storePath = path; } - void CloudDBSyncUtilsTest::InitSyncUtils(std::vector cloudField, RelationalStoreObserverUnitTest *&observer, - std::shared_ptr &virtualCloudDb, std::shared_ptr &virtualAssetLoader, - RelationalStoreDelegate *&delegate) + void CloudDBSyncUtilsTest::InitSyncUtils(const std::vector &cloudField, + RelationalStoreObserverUnitTest *&observer, std::shared_ptr &virtualCloudDb, + std::shared_ptr &virtualAssetLoader, RelationalStoreDelegate *&delegate) { observer = new (std::nothrow) RelationalStoreObserverUnitTest(); ASSERT_NE(observer, nullptr); @@ -151,6 +151,16 @@ namespace DistributedDB { std::this_thread::sleep_for(std::chrono::milliseconds(count)); } + void CloudDBSyncUtilsTest::DeleteUserTableRecord(sqlite3 *&db, int64_t begin, int64_t count) + { + for (size_t i = 0; i < g_tables.size(); i++) { + for (int64_t j = begin; j < begin + count; j++) { + string sql = "Delete from " + g_tables[i] + " where name = 'Cloud" + std::to_string(j) + "';"; + ASSERT_EQ(RelationalTestUtils::ExecSql(db, sql), SQLITE_OK); + } + } + } + void CloudDBSyncUtilsTest::GetCallback(SyncProcess &syncProcess, CloudSyncStatusCallback &callback, std::vector &expectProcess) { @@ -269,7 +279,8 @@ namespace DistributedDB { return 0; } - void CloudDBSyncUtilsTest::CheckDownloadResult(sqlite3 *&db, std::vector expectCounts, std::string keyStr) + void CloudDBSyncUtilsTest::CheckDownloadResult(sqlite3 *&db, std::vector expectCounts, + const std::string &keyStr) { for (size_t i = 0; i < g_tables.size(); ++i) { string queryDownload = "select count(*) from " + g_tables[i] + " where name " + @@ -279,18 +290,19 @@ namespace DistributedDB { } } - void CloudDBSyncUtilsTest::CheckLocalRecordNum(sqlite3 *&db, std::string tableName, int count) + void CloudDBSyncUtilsTest::CheckLocalRecordNum(sqlite3 *&db, const std::string &tableName, int count) { std::string sql = "select count(*) from " + tableName + ";"; EXPECT_EQ(sqlite3_exec(db, sql.c_str(), QueryCountCallback, reinterpret_cast(count), nullptr), SQLITE_OK); } - void CloudDBSyncUtilsTest::GetCloudDbSchema(std::string tableName, std::vector cloudField, + void CloudDBSyncUtilsTest::GetCloudDbSchema(const std::string &tableName, const std::vector &cloudField, DataBaseSchema &dataBaseSchema) { TableSchema tableSchema = { .name = tableName, + .sharedTableName = "", .fields = cloudField }; dataBaseSchema.tables.push_back(tableSchema); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.h index 57026676aa6adbc7bf9e6f89ff33c36bfcd72a04..155b9d965c1541a78e72ca8fdf5d086c0cfdb6a7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_db_sync_utils_test.h @@ -19,7 +19,7 @@ #include #include #include "cloud/cloud_storage_utils.h" -#include "cloud_db_constant.h" +#include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "process_system_api_adapter_impl.h" @@ -42,7 +42,7 @@ class CloudDBSyncUtilsTest { public: static void SetStorePath(const std::string &path); - static void InitSyncUtils(std::vector cloudField, RelationalStoreObserverUnitTest *&observer, + static void InitSyncUtils(const std::vector &cloudField, RelationalStoreObserverUnitTest *&observer, std::shared_ptr &virtualCloudDb, std::shared_ptr &virtualAssetLoader, RelationalStoreDelegate *&delegate); @@ -57,6 +57,8 @@ public: static void DeleteCloudTableRecordByGid(int64_t begin, int64_t count, std::shared_ptr &virtualCloudDb); + static void DeleteUserTableRecord(sqlite3 *&db, int64_t begin, int64_t count); + static void GetCallback(SyncProcess &syncProcess, CloudSyncStatusCallback &callback, std::vector &expectProcess); @@ -73,11 +75,11 @@ public: static int QueryCountCallback(void *data, int count, char **colValue, char **colName); - static void CheckDownloadResult(sqlite3 *&db, std::vector expectCounts, std::string keyStr); + static void CheckDownloadResult(sqlite3 *&db, std::vector expectCounts, const std::string &keyStr); - static void CheckLocalRecordNum(sqlite3 *&db, std::string tableName, int count); + static void CheckLocalRecordNum(sqlite3 *&db, const std::string &tableName, int count); - static void GetCloudDbSchema(std::string tableName, std::vector cloudField, + static void GetCloudDbSchema(const std::string &tableName, const std::vector &cloudField, DataBaseSchema &dataBaseSchema); }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h index c0d4b88ede2ad4e62a9b81fc29ac7bbfa74affe7..d8a2df44140536fcb5b375d52b4c140c17b2fdec 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/cloud_syncer_test.h @@ -23,6 +23,16 @@ namespace DistributedDB { +const Asset ASSET_COPY = { .version = 1, + .name = "Phone", + .assetId = "0", + .subpath = "/local/sync", + .uri = "/local/sync", + .modifyTime = "123456", + .createTime = "", + .size = "256", + .hash = "ASE" }; + class TestStorageProxy : public StorageProxy { public: explicit TestStorageProxy(ICloudSyncStorageInterface *iCloud) : StorageProxy(iCloud) @@ -85,6 +95,8 @@ public: void CallClose() { currentContext_.currentTaskId = 0u; + currentContext_.strategy = nullptr; + currentContext_.notifier = nullptr; Close(); } void SetTimeOut(TaskId taskId, int64_t timeout) @@ -182,12 +194,16 @@ public: void initFullCloudSyncData(CloudSyncData &uploadData, int size) { - VBucket tmp = {std::pair(CloudDbConstant::MODIFY_FIELD, 1), - std::pair(CloudDbConstant::CREATE_FIELD, 1)}; + VBucket tmp = { std::pair(CloudDbConstant::MODIFY_FIELD, 1), + std::pair(CloudDbConstant::CREATE_FIELD, 1), + std::pair(CloudDbConstant::ASSET, ASSET_COPY) }; + VBucket asset = { std::pair(CloudDbConstant::ASSET, ASSET_COPY) }; uploadData.insData.record = std::vector(size, tmp); uploadData.insData.extend = std::vector(size, tmp); + uploadData.insData.assets = std::vector(size, asset); uploadData.updData.record = std::vector(size, tmp); uploadData.updData.extend = std::vector(size, tmp); + uploadData.updData.assets = std::vector(size, asset); uploadData.delData.record = std::vector(size, tmp); uploadData.delData.extend = std::vector(size, tmp); } @@ -237,6 +253,84 @@ public: currentContext_.cloudWaterMarks[tableName] = mark; } + int CallDownloadAssets() + { + InnerProcessInfo info; + std::vector pKColNames; + std::set dupHashKeySet; + ChangedData changedAssets; + return CloudSyncer::DownloadAssets(info, pKColNames, dupHashKeySet, changedAssets); + } + + void SetCurrentContext(TaskId taskId) + { + currentContext_.currentTaskId = taskId; + } + + void SetLastTaskId(TaskId taskId) + { + lastTaskId_ = taskId; + } + + void SetCurrentTaskPause() + { + cloudTaskInfos_[currentContext_.currentTaskId].pause = true; + } + + void SetAssetDownloadList(int downloadCount) + { + for (int i = 0; i < downloadCount; ++i) { + currentContext_.assetDownloadList.push_back({}); + } + } + + void SetQuerySyncObject(TaskId taskId, const QuerySyncObject &query) + { + std::vector queryList; + queryList.push_back(query); + cloudTaskInfos_[taskId].queryList = queryList; + } + + QuerySyncObject CallGetQuerySyncObject(const std::string &tableName) + { + return CloudSyncer::GetQuerySyncObject(tableName); + } + + void CallReloadWaterMarkIfNeed(TaskId taskId, WaterMark &waterMark) + { + CloudSyncer::ReloadWaterMarkIfNeed(taskId, waterMark); + } + + void CallRecordWaterMark(TaskId taskId, Timestamp waterMark) + { + CloudSyncer::RecordWaterMark(taskId, waterMark); + } + + void SetResumeSyncParam(TaskId taskId, const SyncParam &syncParam) + { + resumeTaskInfos_[taskId].syncParam = syncParam; + resumeTaskInfos_[taskId].context.tableName = syncParam.tableName; + } + + void ClearResumeTaskInfo(TaskId taskId) + { + resumeTaskInfos_.erase(taskId); + } + + void SetTaskResume(TaskId taskId, bool resume) + { + cloudTaskInfos_[taskId].resume = resume; + } + + int CallGetSyncParamForDownload(TaskId taskId, SyncParam ¶m) + { + return CloudSyncer::GetSyncParamForDownload(taskId, param); + } + + bool IsResumeTaskUpload(TaskId taskId) + { + return resumeTaskInfos_[taskId].upload; + } CloudTaskInfo taskInfo_; private: std::map process_; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp index e8febffcd35a521d747e7770b0ed549b422ba3b9..544517e0f87a5be7509ba49ce5e40162fc106b7d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_asset_compare_test.cpp @@ -16,6 +16,7 @@ #include +#include "cloud/asset_operation_utils.h" #include "cloud_syncer_test.h" #include "cloud_store_types.h" #include "db_errno.h" @@ -237,10 +238,13 @@ namespace { std::map &expected) { if (target[fieldName].size() != expected[fieldName].size()) { + LOGE("[CheckAssetDownloadList] size is not equal actual %zu expect %zu", target[fieldName].size(), + expected[fieldName].size()); return false; } for (size_t i = 0; i < target[fieldName].size(); i++) { if (!IsAssetEq(target[fieldName][i], expected[fieldName][i])) { + LOGE("[CheckAssetDownloadList] asset not equal fieldName %s index %zu", fieldName.c_str(), i); return false; } } @@ -253,6 +257,11 @@ namespace { asset.status = static_cast(status); } + static AssetStatus GetDownloadWithNullStatus() + { + return static_cast(static_cast(DOWNLOADING) | static_cast(DOWNLOAD_WITH_NULL)); + } + /** * @tc.name: AssetCmpTest001 * @tc.desc: @@ -264,10 +273,10 @@ namespace { { auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_EMPTY); std::map expectedList; - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a1); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a2); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a3); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a4); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a1); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a2); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a3); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4); expectedList[FIELD_HOUSE] = { a1 }; expectedList[FIELD_CARS] = { a2, a3, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); @@ -285,10 +294,10 @@ namespace { { auto assetList = g_cloudSyncer->TestTagAssetsInSingleRecord(DATA_BASELINE, DATA_EMPTY_ASSET); std::map expectedList; - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a1); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a2); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a3); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a4); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a1); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a2); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a3); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4); expectedList[FIELD_HOUSE] = { a1 }; expectedList[FIELD_CARS] = { a2, a3, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); @@ -382,7 +391,7 @@ namespace { DATA_BASELINE, DATA_ASSETS_DIFFERENT_FIELD); std::map expectedList; TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a4); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4); expectedList[FIELD_HOUSE] = {}; expectedList[FIELD_CARS] = { a2, a3, a5, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); @@ -403,7 +412,7 @@ namespace { std::map expectedList; TagAsset(AssetOpType::UPDATE, AssetStatus::DOWNLOADING, a3); TagAsset(AssetOpType::DELETE, AssetStatus::DOWNLOADING, a5); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a4); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4); expectedList[FIELD_HOUSE] = {}; expectedList[FIELD_CARS] = { a2, a3, a5, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); @@ -533,9 +542,9 @@ namespace { DATA_BASELINE, DATA_NULL_ASSETS); std::map expectedList; TagAsset(AssetOpType::NO_CHANGE, AssetStatus::DOWNLOADING, a1); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a2); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a3); - TagAsset(AssetOpType::INSERT, AssetStatus::DOWNLOADING, a4); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a2); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a3); + TagAsset(AssetOpType::INSERT, GetDownloadWithNullStatus(), a4); expectedList[FIELD_HOUSE] = {}; expectedList[FIELD_CARS] = { a2, a3, a4 }; ASSERT_TRUE(CheckAssetDownloadList(FIELD_HOUSE, assetList, expectedList)); @@ -835,4 +844,155 @@ namespace { ASSERT_TRUE(g_cloudSyncer->TestIsDataContainDuplicateAsset(assetFields, DATA_SAME_NAME_ASSETS)); ASSERT_TRUE(g_cloudSyncer->TestIsDataContainDuplicateAsset(assetFields, DATA_BASELINE) == false); } + + /** + * @tc.name: AssetOperation001 + * @tc.desc: Different opType with end download action and assets + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation001, TestSize.Level0) + { + VBucket cacheAssets; + VBucket dbAssets; + Asset asset; + asset.status = AssetStatus::DOWNLOADING; + asset.name = "name"; + cacheAssets["field"] = asset; + dbAssets["field"] = asset; + // check both downloading after download + auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::END_DOWNLOAD); + EXPECT_EQ(res["field"].size(), 1u); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE); + // status mask download with null + asset.status = (static_cast(AssetStatus::DOWNLOADING) | + static_cast(AssetStatus::DOWNLOAD_WITH_NULL)); + cacheAssets["field"] = asset; + dbAssets["field"] = asset; + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::END_DOWNLOAD); + EXPECT_EQ(res["field"].size(), 1u); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE); + // if status not equal, not handle + asset.status = AssetStatus::UPDATE; + dbAssets["field"] = asset; + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::END_DOWNLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + // if asset not exist, not handle + dbAssets.erase("field"); + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::END_DOWNLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + } + + /** + * @tc.name: AssetOperation002 + * @tc.desc: Different opType with start download action and assets + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation002, TestSize.Level0) + { + VBucket cacheAssets; + VBucket dbAssets; + Asset asset; + asset.name = "name"; + asset.status = AssetStatus::DOWNLOADING; + cacheAssets["field"] = asset; + dbAssets["field"] = asset; + // check both downloading before download + auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::START_DOWNLOAD); + EXPECT_EQ(res["field"].size(), 1u); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE); + // if status not equal, not handle + asset.status = AssetStatus::UPDATE; + dbAssets["field"] = asset; + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::START_DOWNLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + // if db asset not exist, not handle + dbAssets.erase("field"); + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::START_DOWNLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + // if db asset not exist but cache is delete, handle + asset.flag = static_cast(AssetOpType::DELETE); + cacheAssets["field"] = asset; + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::START_DOWNLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE); + } + + /** + * @tc.name: AssetOperation003 + * @tc.desc: Different opType with start upload action and assets + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation003, TestSize.Level0) + { + Asset asset; + VBucket cacheAssets; + VBucket dbAssets; + asset.name = "name"; + asset.status = AssetStatus::UPDATE; + cacheAssets["field"] = asset; + dbAssets["field"] = asset; + // check both update before upload + auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::START_UPLOAD); + EXPECT_EQ(res["field"].size(), 1u); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE); + // if status not equal, not handle + asset.status = AssetStatus::DELETE; + dbAssets["field"] = asset; + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::START_UPLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + // if asset not exist, not handle + dbAssets.erase("field"); + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::START_UPLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + } + + /** + * @tc.name: AssetOperation004 + * @tc.desc: Different opType with start upload action and assets + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ + HWTEST_F(DistributedDBCloudAssetCompareTest, AssetOperation004, TestSize.Level0) + { + Asset asset; + VBucket cacheAssets; + VBucket dbAssets; + asset.name = "name"; + asset.status = (static_cast(AssetStatus::UPDATE) | static_cast(AssetStatus::UPLOADING)); + cacheAssets["field"] = asset; + dbAssets["field"] = asset; + // check both UPLOADING after upload + auto res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::END_UPLOAD); + EXPECT_EQ(res["field"].size(), 1u); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::HANDLE); + // if status not equal, not handle + asset.status = AssetStatus::DELETE; + dbAssets["field"] = asset; + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::END_UPLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + // if asset not exist, not handle + dbAssets.erase("field"); + res = AssetOperationUtils::CalAssetOperation(cacheAssets, dbAssets, + AssetOperationUtils::CloudSyncAction::END_UPLOAD); + EXPECT_EQ(res["field"][asset.name], AssetOperationUtils::AssetOpType::NOT_HANDLE); + } } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp index 220b67867e2630e69e289729e3fcbc0eef681667..34c14cf2ebe774bc8636957e83372ee47c64fbdd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_db_proxy_test.cpp @@ -15,10 +15,10 @@ #include #include -#include "cloud_db_constant.h" -#include "cloud_db_data_utils.h" -#include "cloud_db_types.h" -#include "cloud_db_proxy.h" +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_db_data_utils.h" +#include "cloud/cloud_db_types.h" +#include "cloud/cloud_db_proxy.h" #include "distributeddb_tools_unit_test.h" #include "kv_store_errno.h" #include "mock_icloud_sync_storage_interface.h" @@ -185,6 +185,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest002, TestSize.Level0) */ TableSchema schema = { .name = TABLE_NAME, + .sharedTableName = "", .fields = GetFields() }; std::vector expectRecords = CloudDBDataUtils::GenerateRecords(10, schema); // generate 10 records @@ -227,6 +228,7 @@ HWTEST_F(DistributedDBCloudDBProxyTest, CloudDBProxyTest003, TestSize.Level0) { TableSchema schema = { .name = TABLE_NAME, + .sharedTableName = "", .fields = GetFields() }; /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp index 72aa4f03ab5b42bf0da30ad1ff96e0134be21908..0085ebdb3bbe8d23601907af56c28996a106782f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_strategy_test.cpp @@ -159,6 +159,14 @@ HWTEST_F(DistributedDBCloudStrategyTest, TagOpTyeTest001, TestSize.Level0) */ localInfo.cloudGid = ""; EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::NOT_HANDLE); + /** + * @tc.steps: step11. cloud has same timestamp with local, and local has empty gid + * @tc.expected: step11 only update gid + */ + cloudInfo.timestamp = localInfo.timestamp; + cloudInfo.flag = 0; // it means no delete + localInfo.flag = 0; // it means no delete + EXPECT_EQ(strategy->TagSyncDataStatus(true, localInfo, cloudInfo), OpType::ONLY_UPDATE_GID); } /** diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp index afdf9a7adaa3de11ebbcfdd20b484e2e9d5fce10..b0e404af0fd968b6e7e3b00bdf6843aca87e2472 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_assets_test.cpp @@ -13,8 +13,9 @@ * limitations under the License. */ #ifdef RELATIONAL_STORE +#include "cloud/asset_operation_utils.h" #include "cloud/cloud_storage_utils.h" -#include "cloud_db_constant.h" +#include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "mock_asset_loader.h" @@ -40,19 +41,34 @@ namespace { const string STORE_ID = "Relational_Store_SYNC"; const string DB_SUFFIX = ".db"; const string ASSETS_TABLE_NAME = "student"; +const string NO_PRIMARY_TABLE = "teacher"; +const string COMPOUND_PRIMARY_TABLE = "worker1"; const string DEVICE_CLOUD = "cloud_dev"; const string COL_ID = "id"; const string COL_NAME = "name"; const string COL_HEIGHT = "height"; +const string COL_ASSET = "asset"; const string COL_ASSETS = "assets"; const string COL_AGE = "age"; const int64_t SYNC_WAIT_TIME = 600; const std::vector CLOUD_FIELDS = {{COL_ID, TYPE_INDEX, true}, {COL_NAME, TYPE_INDEX}, - {COL_HEIGHT, TYPE_INDEX}, {COL_ASSETS, TYPE_INDEX}, {COL_AGE, TYPE_INDEX}}; + {COL_HEIGHT, TYPE_INDEX}, {COL_ASSET, TYPE_INDEX}, {COL_ASSETS, TYPE_INDEX}, + {COL_AGE, TYPE_INDEX}}; +const std::vector NO_PRIMARY_FIELDS = {{COL_ID, TYPE_INDEX}, {COL_NAME, TYPE_INDEX}, + {COL_HEIGHT, TYPE_INDEX}, {COL_ASSET, TYPE_INDEX}, {COL_ASSETS, TYPE_INDEX}, + {COL_AGE, TYPE_INDEX}}; +const std::vector COMPOUND_PRIMARY_FIELDS = {{COL_ID, TYPE_INDEX, true}, + {COL_NAME, TYPE_INDEX}, {COL_HEIGHT, TYPE_INDEX}, {COL_ASSET, TYPE_INDEX}, + {COL_ASSETS, TYPE_INDEX}, {COL_AGE, TYPE_INDEX, true}}; const string CREATE_SINGLE_PRIMARY_KEY_TABLE = "CREATE TABLE IF NOT EXISTS " + ASSETS_TABLE_NAME + "(" + COL_ID + - " INTEGER PRIMARY KEY," + COL_NAME + " TEXT ," + COL_HEIGHT + " REAL ," + - COL_ASSETS + " BLOB," + COL_AGE + " INT);"; -const string INSERT_SQL = "insert or replace into " + ASSETS_TABLE_NAME + " values (?,?,?,?,?);"; + " INTEGER PRIMARY KEY," + COL_NAME + " TEXT ," + COL_HEIGHT + " REAL ," + COL_ASSET + " ASSET," + + COL_ASSETS + " ASSETS," + COL_AGE + " INT);"; +const string CREATE_NO_PRIMARY_KEY_TABLE = "CREATE TABLE IF NOT EXISTS " + NO_PRIMARY_TABLE + "(" + COL_ID + + " INTEGER," + COL_NAME + " TEXT ," + COL_HEIGHT + " REAL ," + COL_ASSET + " ASSET," + COL_ASSETS + + " ASSETS," + COL_AGE + " INT);"; +const string CREATE_COMPOUND_PRIMARY_KEY_TABLE = "CREATE TABLE IF NOT EXISTS " + COMPOUND_PRIMARY_TABLE + "(" + COL_ID + + " INTEGER," + COL_NAME + " TEXT ," + COL_HEIGHT + " REAL ," + COL_ASSET + " ASSET," + COL_ASSETS + " ASSETS," + + COL_AGE + " INT, PRIMARY KEY (id, age));"; const Asset ASSET_COPY = {.version = 1, .name = "Phone", .assetId = "0", @@ -62,6 +78,16 @@ const Asset ASSET_COPY = {.version = 1, .createTime = "", .size = "256", .hash = "ASE"}; +const Asset ASSET_COPY2 = {.version = 1, + .name = "Phone_copy_2", + .assetId = "0", + .subpath = "/local/sync", + .uri = "/local/sync", + .modifyTime = "123456", + .createTime = "", + .size = "256", + .hash = "ASE"}; +const Assets ASSETS_COPY1 = { ASSET_COPY, ASSET_COPY2 }; string g_storePath; string g_testDir; @@ -70,6 +96,7 @@ DistributedDB::RelationalStoreManager g_mgr(APP_ID, USER_ID); RelationalStoreDelegate *g_delegate = nullptr; std::shared_ptr g_virtualCloudDb; std::shared_ptr g_virtualAssetLoader; +std::shared_ptr g_virtualCloudDataTranslate; SyncProcess g_syncProcess; std::condition_variable g_processCondition; std::mutex g_processMutex; @@ -79,11 +106,17 @@ void InitDatabase(sqlite3 *&db) { EXPECT_EQ(RelationalTestUtils::ExecSql(db, "PRAGMA journal_mode=WAL;"), SQLITE_OK); EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_SINGLE_PRIMARY_KEY_TABLE), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_NO_PRIMARY_KEY_TABLE), SQLITE_OK); + EXPECT_EQ(RelationalTestUtils::ExecSql(db, CREATE_COMPOUND_PRIMARY_KEY_TABLE), SQLITE_OK); } void GetCloudDbSchema(DataBaseSchema &dataBaseSchema) { - TableSchema assetsTableSchema = {.name = ASSETS_TABLE_NAME, .fields = CLOUD_FIELDS}; + TableSchema assetsTableSchema = {.name = ASSETS_TABLE_NAME, .sharedTableName = "", .fields = CLOUD_FIELDS}; + dataBaseSchema.tables.push_back(assetsTableSchema); + assetsTableSchema = {.name = NO_PRIMARY_TABLE, .sharedTableName = "", .fields = NO_PRIMARY_FIELDS}; + dataBaseSchema.tables.push_back(assetsTableSchema); + assetsTableSchema = {.name = COMPOUND_PRIMARY_TABLE, .sharedTableName = "", .fields = COMPOUND_PRIMARY_FIELDS}; dataBaseSchema.tables.push_back(assetsTableSchema); } @@ -95,6 +128,8 @@ void GenerateDataRecords( Asset asset = ASSET_COPY; asset.name = ASSET_COPY.name + std::to_string(i); assets.emplace_back(asset); + asset.name = ASSET_COPY.name + std::to_string(i) + "_copy"; + assets.emplace_back(asset); VBucket data; data.insert_or_assign(COL_ID, i); data.insert_or_assign(COL_NAME, "name" + std::to_string(i)); @@ -113,44 +148,68 @@ void GenerateDataRecords( } } -void InsertLocalData(sqlite3 *&db, int64_t begin, int64_t count) +void InsertLocalData(sqlite3 *&db, int64_t begin, int64_t count, const std::string &tableName) { int errCode; std::vector record; std::vector extend; - std::vector assetBlob; + std::vector assetsBlob; GenerateDataRecords(begin, count, 0, record, extend); + const string sql = "insert or replace into " + tableName + " values (?,?,?,?,?,?);"; for (VBucket vBucket : record) { sqlite3_stmt *stmt = nullptr; - ASSERT_EQ(SQLiteUtils::GetStatement(db, INSERT_SQL, stmt), E_OK); + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); ASSERT_EQ(SQLiteUtils::BindInt64ToStatement(stmt, 1, std::get(vBucket[COL_ID])), E_OK); // 1 is id ASSERT_EQ(SQLiteUtils::BindTextToStatement(stmt, 2, std::get(vBucket[COL_NAME])), E_OK); // 2 is name ASSERT_EQ(SQLiteUtils::MapSQLiteErrno( sqlite3_bind_double(stmt, 3, std::get(vBucket[COL_HEIGHT]))), E_OK); // 3 is height - RuntimeContext::GetInstance()->AssetsToBlob(std::get(vBucket[COL_ASSETS]), assetBlob); - ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 4, assetBlob, false), E_OK); // 4 is assets - ASSERT_EQ(SQLiteUtils::BindInt64ToStatement(stmt, 5, std::get(vBucket[COL_AGE])), E_OK); // 5 is age + ASSERT_EQ(sqlite3_bind_null(stmt, 4), SQLITE_OK); // 4 is asset + std::vector assetsBlob = g_virtualCloudDataTranslate->AssetsToBlob( + std::get(vBucket[COL_ASSETS])); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 5, assetsBlob, false), E_OK); // 5 is assets + ASSERT_EQ(SQLiteUtils::BindInt64ToStatement(stmt, 6, std::get(vBucket[COL_AGE])), E_OK); // 6 is age EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); SQLiteUtils::ResetStatement(stmt, true, errCode); } - LOGD("insert into student table [primary key]:[%" PRId64 " - %" PRId64 ")", begin, begin + count); } -void DeleteCloudDBData(int64_t begin, int64_t count) +void UpdateLocalData(sqlite3 *&db, const std::string &tableName, const Assets &assets) +{ + int errCode; + std::vector assetBlob; + const string sql = "update " + tableName + " set assets=?;"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + assetBlob = g_virtualCloudDataTranslate->AssetsToBlob(assets); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +void DeleteLocalRecord(sqlite3 *&db, int64_t begin, int64_t count, const std::string &tableName) +{ + ASSERT_NE(db, nullptr); + for (int64_t i = begin; i < begin + count; i++) { + string sql = "DELETE FROM " + tableName + " WHERE id ='" + std::to_string(i) + "';"; + ASSERT_EQ(SQLiteUtils::ExecuteRawSQL(db, sql), E_OK); + } +} + +void DeleteCloudDBData(int64_t begin, int64_t count, const std::string &tableName) { for (int64_t i = begin; i < begin + count; i++) { VBucket idMap; idMap.insert_or_assign("#_gid", std::to_string(i)); - ASSERT_EQ(g_virtualCloudDb->DeleteByGid(ASSETS_TABLE_NAME, idMap), DBStatus::OK); + ASSERT_EQ(g_virtualCloudDb->DeleteByGid(tableName, idMap), DBStatus::OK); } } -void InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart) +void InsertCloudDBData(int64_t begin, int64_t count, int64_t gidStart, const std::string &tableName) { std::vector record; std::vector extend; GenerateDataRecords(begin, count, gidStart, record, extend); - ASSERT_EQ(g_virtualCloudDb->BatchInsertWithGid(ASSETS_TABLE_NAME, std::move(record), extend), DBStatus::OK); + ASSERT_EQ(g_virtualCloudDb->BatchInsertWithGid(tableName, std::move(record), extend), DBStatus::OK); } void WaitForSyncFinish(SyncProcess &syncProcess, const int64_t &waitTime) @@ -162,16 +221,17 @@ void WaitForSyncFinish(SyncProcess &syncProcess, const int64_t &waitTime) LOGD("-------------------sync end--------------"); } -void CallSync(const std::vector &tableNames, SyncMode mode, DBStatus dbStatus) +void CallSync(const std::vector &tableNames, SyncMode mode, DBStatus dbStatus, DBStatus errCode = OK) { g_syncProcess = {}; Query query = Query::Select().FromTable(tableNames); std::vector expectProcess; - CloudSyncStatusCallback callback = [](const std::map &process) { + CloudSyncStatusCallback callback = [&errCode](const std::map &process) { ASSERT_EQ(process.begin()->first, DEVICE_CLOUD); g_syncProcess = std::move(process.begin()->second); if (g_syncProcess.process == FINISHED) { g_processCondition.notify_one(); + ASSERT_EQ(g_syncProcess.errCode, errCode); } }; ASSERT_EQ(g_delegate->Sync({DEVICE_CLOUD}, mode, query, callback, SYNC_WAIT_TIME), dbStatus); @@ -185,8 +245,8 @@ void CheckDownloadForTest001(int index, map &assets) { for (auto &item : assets) { for (auto &asset : item.second) { - EXPECT_EQ(asset.status, static_cast(AssetStatus::DOWNLOADING)); - if (index > 2) { // 1, 2 is deleted; 3, 4 is inserted + EXPECT_EQ(AssetOperationUtils::EraseBitMask(asset.status), static_cast(AssetStatus::DOWNLOADING)); + if (index > 4) { // 1-4 is deleted; 5-8 is inserted EXPECT_EQ(asset.flag, static_cast(AssetOpType::INSERT)); } else { EXPECT_EQ(asset.flag, static_cast(AssetOpType::DELETE)); @@ -197,6 +257,29 @@ void CheckDownloadForTest001(int index, map &assets) } } +void CheckDownloadFailedForTest002(sqlite3 *&db) +{ + std::string sql = "SELECT assets from " + ASSETS_TABLE_NAME; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + while (SQLiteUtils::StepWithRetry(stmt) == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_BLOB); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + std::vector assetsBlob; + Assets assets; + ASSERT_EQ(CloudStorageUtils::GetValueFromOneField(cloudValue, assetsBlob), E_OK); + ASSERT_EQ(RuntimeContext::GetInstance()->BlobToAssets(assetsBlob, assets), E_OK); + ASSERT_EQ(assets.size(), 2u); // 2 is asset num + for (size_t i = 0; i < assets.size(); ++i) { + EXPECT_EQ(assets[i].hash, ""); + EXPECT_EQ(assets[i].status, AssetStatus::ABNORMAL); + } + } + int errCode; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + void CloseDb() { delete g_observer; @@ -215,6 +298,9 @@ class DistributedDBCloudSyncerDownloadAssetsTest : public testing::Test { void TearDown(); protected: + void CheckLocaLAssets(const std::string &tableName, const std::string &expectAssetId, + const std::set &failIndex); + void CheckLocalAssetIsEmpty(const std::string &tableName); sqlite3 *db = nullptr; }; @@ -223,7 +309,8 @@ void DistributedDBCloudSyncerDownloadAssetsTest::SetUpTestCase(void) DistributedDBToolsUnitTest::TestDirInit(g_testDir); g_storePath = g_testDir + "/" + STORE_ID + DB_SUFFIX; LOGI("The test db is:%s", g_storePath.c_str()); - RuntimeConfig::SetCloudTranslate(std::make_shared()); + g_virtualCloudDataTranslate = std::make_shared(); + RuntimeConfig::SetCloudTranslate(g_virtualCloudDataTranslate); } void DistributedDBCloudSyncerDownloadAssetsTest::TearDownTestCase(void) {} @@ -245,6 +332,8 @@ void DistributedDBCloudSyncerDownloadAssetsTest::SetUp(void) DBStatus::OK); ASSERT_NE(g_delegate, nullptr); ASSERT_EQ(g_delegate->CreateDistributedTable(ASSETS_TABLE_NAME, CLOUD_COOPERATION), DBStatus::OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(NO_PRIMARY_TABLE, CLOUD_COOPERATION), DBStatus::OK); + ASSERT_EQ(g_delegate->CreateDistributedTable(COMPOUND_PRIMARY_TABLE, CLOUD_COOPERATION), DBStatus::OK); g_virtualCloudDb = make_shared(); g_virtualAssetLoader = make_shared(); g_syncProcess = {}; @@ -257,12 +346,52 @@ void DistributedDBCloudSyncerDownloadAssetsTest::SetUp(void) void DistributedDBCloudSyncerDownloadAssetsTest::TearDown(void) { + g_virtualCloudDb->ForkUpload(nullptr); + CloseDb(); EXPECT_EQ(sqlite3_close_v2(db), SQLITE_OK); if (DistributedDBToolsUnitTest::RemoveTestDbFiles(g_testDir) != 0) { LOGE("rm test db files error."); } } +void DistributedDBCloudSyncerDownloadAssetsTest::CheckLocaLAssets(const std::string &tableName, + const std::string &expectAssetId, const std::set &failIndex) +{ + std::string sql = "SELECT assets FROM " + tableName + ";"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + int index = 0; + while (SQLiteUtils::StepWithRetry(stmt) != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_BLOB); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + Assets assets = g_virtualCloudDataTranslate->BlobToAssets(std::get(cloudValue)); + for (const auto &asset : assets) { + index++; + if (failIndex.find(index) != failIndex.end()) { + EXPECT_EQ(asset.assetId, "0"); + } else { + EXPECT_EQ(asset.assetId, expectAssetId); + } + } + } + int errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +void DistributedDBCloudSyncerDownloadAssetsTest::CheckLocalAssetIsEmpty(const std::string &tableName) +{ + std::string sql = "SELECT asset FROM " + tableName + ";"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + int index = 0; + while (SQLiteUtils::StepWithRetry(stmt) != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_NULL); + } + int errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + /** * @tc.name: DownloadAssetForDupDataTest001 * @tc.desc: Test the download interface call with duplicate data for the same primary key. @@ -280,7 +409,7 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest ASSERT_EQ(g_delegate->SetIAssetLoader(assetLoader), DBStatus::OK); int index = 1; EXPECT_CALL(*assetLoader, Download(testing::_, testing::_, testing::_, testing::_)) - .Times(4) + .Times(8) .WillRepeatedly( [&index](const std::string &, const std::string &gid, const Type &, std::map &assets) { LOGD("Download GID:%s", gid.c_str()); @@ -293,22 +422,680 @@ HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest * @tc.steps:step2. Insert local data [0, 10), sync data * @tc.expected: step2. sync success. */ - InsertLocalData(db, 0, 10); + InsertLocalData(db, 0, 10, ASSETS_TABLE_NAME); CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); /** * @tc.steps:step3. delete cloud data [1, 2], then insert cloud data [1,2] with new gid. Finally sync data. * @tc.expected: step3. sync success. */ - DeleteCloudDBData(1, 2); - InsertCloudDBData(1, 2, 10); + DeleteCloudDBData(1, 2, ASSETS_TABLE_NAME); + InsertCloudDBData(1, 2, 10, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); +} + +/** + * @tc.name: FillAssetId001 + * @tc.desc: Test if assetId is filled in single primary key table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId001, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); /** - * @tc.steps:step4. close db. - * @tc.expected: step4. close success. + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. */ - CloseDb(); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocalAssetIsEmpty(ASSETS_TABLE_NAME); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId002 + * @tc.desc: Test if assetId is filled in no primary key table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId002, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, NO_PRIMARY_TABLE); + CallSync({NO_PRIMARY_TABLE}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(NO_PRIMARY_TABLE, "10", {}); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + UpdateLocalData(db, NO_PRIMARY_TABLE, ASSETS_COPY1); + CallSync({NO_PRIMARY_TABLE}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(NO_PRIMARY_TABLE, "10", {}); +} + +/** + * @tc.name: FillAssetId003 + * @tc.desc: Test if assetId is filled in compound primary key table + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId003, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, COMPOUND_PRIMARY_TABLE); + CallSync({COMPOUND_PRIMARY_TABLE}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(COMPOUND_PRIMARY_TABLE, "10", {}); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + UpdateLocalData(db, COMPOUND_PRIMARY_TABLE, ASSETS_COPY1); + CallSync({COMPOUND_PRIMARY_TABLE}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(COMPOUND_PRIMARY_TABLE, "10", {}); +} + +/** + * @tc.name: FillAssetId004 + * @tc.desc: Test if assetId is filled in single primary key table when CLOUD_FORCE_PUSH + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId004, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId001 + * @tc.desc: Test if assetId is filled in no primary key table when CLOUD_FORCE_PUSH + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId005, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, NO_PRIMARY_TABLE); + CallSync({NO_PRIMARY_TABLE}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + CheckLocaLAssets(NO_PRIMARY_TABLE, "10", {}); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + UpdateLocalData(db, NO_PRIMARY_TABLE, ASSETS_COPY1); + CallSync({NO_PRIMARY_TABLE}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + CheckLocaLAssets(NO_PRIMARY_TABLE, "10", {}); +} + +/** + * @tc.name: FillAssetId006 + * @tc.desc: Test if assetId is filled in compound primary key table when CLOUD_FORCE_PUSH + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId006, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, COMPOUND_PRIMARY_TABLE); + CallSync({COMPOUND_PRIMARY_TABLE}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + CheckLocaLAssets(COMPOUND_PRIMARY_TABLE, "10", {}); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + UpdateLocalData(db, COMPOUND_PRIMARY_TABLE, ASSETS_COPY1); + CallSync({COMPOUND_PRIMARY_TABLE}, SYNC_MODE_CLOUD_FORCE_PUSH, DBStatus::OK); + CheckLocaLAssets(COMPOUND_PRIMARY_TABLE, "10", {}); +} + +/** + * @tc.name: FillAssetId007 + * @tc.desc: Test if assetId is filled when extend lack of assets + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId007, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + g_virtualCloudDb->ForkUpload([](const std::string &tableName, VBucket &extend) { + extend.erase("assets"); + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "0", {}); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + int addLocalCount = 10; + InsertLocalData(db, localCount, addLocalCount, ASSETS_TABLE_NAME); + g_virtualCloudDb->ForkUpload([](const std::string &tableName, VBucket &extend) { + if (extend.find("assets") != extend.end()) { + for (auto &asset : std::get(extend["assets"])) { + asset.name = "pad"; + } + } + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + int beginFailFillNum = 101; + int endFailFillNum = 120; + std::set index; + for (int i = beginFailFillNum; i <= endFailFillNum; i++) { + index.insert(i); + } + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", index); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + g_virtualCloudDb->ForkUpload(nullptr); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId008 + * @tc.desc: Test if assetId is filled when extend lack of assetId + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId008, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + g_virtualCloudDb->ForkUpload([](const std::string &tableName, VBucket &extend) { + if (extend.find("assets") != extend.end()) { + for (auto &asset : std::get(extend["assets"])) { + asset.assetId = ""; + } + } + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "0", {}); + + /** + * @tc.steps:step2. local update assets and sync ,check the local assetId. + * @tc.expected: step2. sync success. + */ + g_virtualCloudDb->ForkUpload(nullptr); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId009 + * @tc.desc: Test if assetId is filled when extend exists useless assets + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId009, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + g_virtualCloudDb->ForkUpload([](const std::string &tableName, VBucket &extend) { + if (extend.find("assets") != extend.end()) { + Asset asset = ASSET_COPY2; + Assets &assets = std::get(extend["assets"]); + assets.push_back(asset); + } + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId010 + * @tc.desc: Test if assetId is filled when some success and some fail + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId010, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 30; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + g_virtualCloudDb->SetInsertFailed(1); + std::atomic count = 0; + g_virtualCloudDb->ForkUpload([&count](const std::string &tableName, VBucket &extend) { + if (extend.find("assets") != extend.end() && count == 0) { + extend["#_error"] = std::string(""); + count++; + } + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", { 1, 2 }); // 1st, 2nd asset do not fill +} + +/** + * @tc.name: FillAssetId011 + * @tc.desc: Test if assetId is null when removedevicedata in FLAG_ONLY + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId011, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + + g_delegate->RemoveDeviceData("", FLAG_ONLY); + CheckLocaLAssets(ASSETS_TABLE_NAME, "", {}); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); +} + +/** + * @tc.name: FillAssetId012 + * @tc.desc: Test if assetid is filled when extend size is not equal to record size + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId012, TestSize.Level0) +{ + /** + * @tc.steps:step1. set extend size missing then sync, check the asseid. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + std::atomic count = 1; + g_virtualCloudDb->SetClearExtend(count); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "0", {}); + + /** + * @tc.steps:step2. set extend size normal then sync, check the asseid. + * @tc.expected: step2. return OK. + */ + g_virtualCloudDb->SetClearExtend(0); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + + /** + * @tc.steps:step3. set extend size large then sync, check the asseid. + * @tc.expected: step3. return OK. + */ + count = -1; // -1 means extend push a empty vBucket + g_virtualCloudDb->SetClearExtend(count); + UpdateLocalData(db, ASSETS_TABLE_NAME, ASSETS_COPY1); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "0", {}); +} + +/** + * @tc.name: FillAssetId013 + * @tc.desc: Test fill assetId and removedevicedata when data is delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId013, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert data and sync, then delete local data and insert new data + * @tc.expected: step1. return OK. + */ + int localCount = 20; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + int deleteLocalCount = 10; + DeleteLocalRecord(db, 0, deleteLocalCount, ASSETS_TABLE_NAME); + int addLocalCount = 30; + InsertLocalData(db, localCount, addLocalCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + + /** + * @tc.steps:step2. RemoveDeviceData. + * @tc.expected: step2. return OK. + */ + g_delegate->RemoveDeviceData("", FLAG_ONLY); + CheckLocaLAssets(ASSETS_TABLE_NAME, "", {}); +} + +/** + * @tc.name: FillAssetId014 + * @tc.desc: Test if asset status is reset when removedevicedata in FLAG_ONLY + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId014, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert assets and sync, check the local assetId. + * @tc.expected: step1. return OK. + */ + int localCount = 50; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + + /** + * @tc.steps:step2. RemoveDeviceData + * @tc.expected: step2. return OK. + */ + Assets assets; + std::vector statusVec = { + AssetStatus::INSERT, AssetStatus::UPDATE, AssetStatus::DELETE, AssetStatus::NORMAL, + AssetStatus::ABNORMAL, AssetStatus::DOWNLOADING, AssetStatus::DOWNLOAD_WITH_NULL + }; + for (auto &status : statusVec) { + Asset temp = ASSET_COPY; + temp.name += std::to_string(status); + temp.status = status | AssetStatus::UPLOADING; + assets.emplace_back(temp); + } + UpdateLocalData(db, ASSETS_TABLE_NAME, assets); + EXPECT_EQ(g_delegate->RemoveDeviceData("", FLAG_ONLY), OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "", {}); + + /** + * @tc.steps:step3. check status + * @tc.expected: step3. return OK. + */ + std::string sql = "SELECT assets FROM " + ASSETS_TABLE_NAME + ";"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + int index = 0; + while (SQLiteUtils::StepWithRetry(stmt) != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) { + ASSERT_EQ(sqlite3_column_type(stmt, 0), SQLITE_BLOB); + Type cloudValue; + ASSERT_EQ(SQLiteRelationalUtils::GetCloudValueByType(stmt, TYPE_INDEX, 0, cloudValue), E_OK); + Assets newAssets = g_virtualCloudDataTranslate->BlobToAssets(std::get(cloudValue)); + for (const auto &ast : newAssets) { + EXPECT_EQ(ast.status, statusVec[index++ % statusVec.size()]); + } + } + int errCode = E_OK; + SQLiteUtils::ResetStatement(stmt, true, errCode); +} + +/** + * @tc.name: FillAssetId015 + * @tc.desc: Test if fill assetId when upload return cloud network error + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId015, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert data and fork batchinsert return CLOUD_NETWORK_ERROR, then sync + * @tc.expected: step1. return OK, errcode is CLOUD_NETWORK_ERROR. + */ + int localCount = 20; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + g_virtualCloudDb->SetCloudNetworkError(true); + std::atomic count = 0; + g_virtualCloudDb->ForkUpload([&count](const std::string &tableName, VBucket &extend) { + if (extend.find("assets") != extend.end() && count == 0) { + extend["#_error"] = std::string(""); + count++; + } + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_NETWORK_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", { 1, 2 }); // 1st, 2nd asset do not fill + g_virtualCloudDb->SetCloudNetworkError(false); + g_virtualCloudDb->ForkUpload(nullptr); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {}); + + /** + * @tc.steps:step2. local insert data and fork batchinsert return CLOUD_NETWORK_ERROR, then sync. + * @tc.expected: step2. return OK, errcode is CLOUD_ERROR. + */ + int addLocalCount = 10; + InsertLocalData(db, localCount, addLocalCount, ASSETS_TABLE_NAME); + std::atomic num = 0; + g_virtualCloudDb->ForkUpload([&num](const std::string &tableName, VBucket &extend) { + if (extend.find("assets") != extend.end() && num == 0) { + for (auto &asset : std::get(extend["assets"])) { + asset.name = "pad"; + break; + } + num++; + } + }); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + CheckLocaLAssets(ASSETS_TABLE_NAME, "10", {41}); // // 41th asset do not fill +} + +/** + * @tc.name: FillAssetId016 + * @tc.desc: Test fill assetId and removedevicedata when last data is delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, FillAssetId016, TestSize.Level0) +{ + /** + * @tc.steps:step1. local insert data and sync, then delete last local data + * @tc.expected: step1. return OK. + */ + int localCount = 20; + InsertLocalData(db, 0, localCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + int deletLocalCount = 10; + DeleteLocalRecord(db, deletLocalCount, deletLocalCount, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + + /** + * @tc.steps:step2. RemoveDeviceData. + * @tc.expected: step2. return OK. + */ + g_delegate->RemoveDeviceData("", FLAG_ONLY); + CheckLocaLAssets(ASSETS_TABLE_NAME, "", {}); +} + +/** + * @tc.name: DownloadAssetForDupDataTest002 + * @tc.desc: Test download failed + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest002, TestSize.Level0) +{ + /** + * @tc.steps:step1. Mock asset download return CLOUD_ERROR. + * @tc.expected: step1. return OK + */ + std::shared_ptr assetLoader = make_shared(); + ASSERT_EQ(g_delegate->SetIAssetLoader(assetLoader), DBStatus::OK); + int index = 0; + EXPECT_CALL(*assetLoader, Download(testing::_, testing::_, testing::_, testing::_)) + .WillRepeatedly( + [&](const std::string &, const std::string &gid, const Type &, std::map &assets) { + LOGD("Download GID:%s, index:%d", gid.c_str(), ++index); + return DBStatus::CLOUD_ERROR; + }); + + /** + * @tc.steps:step2. Insert cloud data [0, 10), sync data + * @tc.expected: step2. sync success. + */ + InsertCloudDBData(0, 10, 0, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + + /** + * @tc.steps:step3. check if the hash of assets in db is empty + * @tc.expected: step3. OK + */ + CheckDownloadFailedForTest002(db); +} + +/** + * @tc.name: DownloadAssetForDupDataTest003 + * @tc.desc: Test download failed and flag was modified + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest003, TestSize.Level0) +{ + /** + * @tc.steps:step1. Mock asset download return CLOUD_ERROR. + * @tc.expected: step1. return OK + */ + std::shared_ptr assetLoader = make_shared(); + ASSERT_EQ(g_delegate->SetIAssetLoader(assetLoader), DBStatus::OK); + int index = 0; + EXPECT_CALL(*assetLoader, Download(testing::_, testing::_, testing::_, testing::_)) + .WillRepeatedly( + [&](const std::string &, const std::string &gid, const Type &, std::map &assets) { + LOGD("Download GID:%s, index:%d", gid.c_str(), ++index); + for (auto &[key, value] : assets) { + for (auto &asset : value) { + asset.flag = static_cast(AssetOpType::NO_CHANGE); + } + } + return DBStatus::CLOUD_ERROR; + }); + + /** + * @tc.steps:step2. Insert cloud data [0, 10), sync data + * @tc.expected: step2. sync success. + */ + InsertCloudDBData(0, 10, 0, ASSETS_TABLE_NAME); + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, DBStatus::CLOUD_ERROR); + + /** + * @tc.steps:step3. check if the hash of assets in db is empty + * @tc.expected: step3. OK + */ + CheckDownloadFailedForTest002(db); +} + +/** + * @tc.name: DownloadAssetForDupDataTest004 + * @tc.desc: test sync with deleted assets + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudSyncerDownloadAssetsTest, DownloadAssetForDupDataTest004, TestSize.Level0) +{ + /** + * @tc.steps:step1. Mock asset download return CLOUD_ERROR. + * @tc.expected: step1. return OK + */ + std::shared_ptr assetLoader = make_shared(); + ASSERT_EQ(g_delegate->SetIAssetLoader(assetLoader), DBStatus::OK); + int index = 0; + EXPECT_CALL(*assetLoader, Download(testing::_, testing::_, testing::_, testing::_)) + .WillRepeatedly( + [&](const std::string &, const std::string &gid, const Type &, std::map &assets) { + LOGD("Download GID:%s, index:%d", gid.c_str(), ++index); + return DBStatus::OK; + }); + + /** + * @tc.steps:step2. insert local data, update assets status to delete, then insert cloud data + * @tc.expected: step2. return OK + */ + InsertLocalData(db, 0, 10, ASSETS_TABLE_NAME); + Assets assets; + Asset asset = ASSET_COPY; + asset.name = ASSET_COPY.name + std::to_string(1); + asset.status = AssetStatus::DELETE; + assets.emplace_back(asset); + asset.name = ASSET_COPY.name + std::to_string(1) + "_copy"; + assets.emplace_back(asset); + int errCode; + std::vector assetBlob; + const string sql = "update " + ASSETS_TABLE_NAME + " set assets=? where id = 1;"; + sqlite3_stmt *stmt = nullptr; + ASSERT_EQ(SQLiteUtils::GetStatement(db, sql, stmt), E_OK); + assetBlob = g_virtualCloudDataTranslate->AssetsToBlob(assets); + ASSERT_EQ(SQLiteUtils::BindBlobToStatement(stmt, 1, assetBlob, false), E_OK); + EXPECT_EQ(SQLiteUtils::StepWithRetry(stmt), SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)); + SQLiteUtils::ResetStatement(stmt, true, errCode); + InsertCloudDBData(0, 10, 0, ASSETS_TABLE_NAME); + + /** + * @tc.steps:step3. sync, check download num + * @tc.expected: step3. return OK + */ + CallSync({ASSETS_TABLE_NAME}, SYNC_MODE_CLOUD_MERGE, DBStatus::OK); + EXPECT_GE(index, 2); // 2 is download num } } // namespace #endif // RELATIONAL_STORE diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp index 70891e4bebb162833f914b051741e81b81fb6dc7..fc6123aa9d64fe3f4da9031232c22f0aec130257 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_download_test.cpp @@ -28,6 +28,7 @@ using namespace DistributedDBUnitTest; namespace { static int64_t g_photoCount = 10; static double g_dataHeight = 166.0; +static uint64_t g_invalidOptCount = 5u; class DistributedDBCloudSyncerDownloadTest : public testing::Test { public: static void SetUpTestCase(void); @@ -53,6 +54,7 @@ void DistributedDBCloudSyncerDownloadTest::SetUpTestCase(void) void DistributedDBCloudSyncerDownloadTest::TearDownTestCase(void) { + g_cloudSyncer->CallClose(); RefObject::KillAndDecObjRef(g_cloudSyncer); g_cloudSyncer = nullptr; g_storageProxy = nullptr; @@ -103,6 +105,7 @@ void GenerateTableSchema(TableSchema &tableSchema) { tableSchema = { "TestTable1", + "", {{"name", TYPE_INDEX, true}} }; } @@ -368,7 +371,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest003, TestSiz g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidTypeCloudData(5, {.invalidCursor = false}); + InvalidCloudDataOpt opt; + opt.invalidCursor = false; + data = GetInvalidTypeCloudData(g_invalidOptCount, opt); return QUERY_END; }); int errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -378,7 +383,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest003, TestSiz g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidTypeCloudData(5, {.invalidCursor = false}); + InvalidCloudDataOpt opt; + opt.invalidCursor = false; + data = GetInvalidTypeCloudData(g_invalidOptCount, opt); return QUERY_END; }); errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -389,7 +396,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest003, TestSiz g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidTypeCloudData(5, {.invalidDeleteField = false}); + InvalidCloudDataOpt opt; + opt.invalidDeleteField = false; + data = GetInvalidTypeCloudData(g_invalidOptCount, opt); return QUERY_END; }); errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -419,7 +428,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00302, TestS g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidTypeCloudData(5, {.invalidGID = false}); + InvalidCloudDataOpt opt; + opt.invalidGID = false; + data = GetInvalidTypeCloudData(g_invalidOptCount, opt); return QUERY_END; }); int errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -429,7 +440,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00302, TestS g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidTypeCloudData(5, {.invalidModifyField = false}); + InvalidCloudDataOpt opt; + opt.invalidModifyField = false; + data = GetInvalidTypeCloudData(g_invalidOptCount, opt); return QUERY_END; }); errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -460,7 +473,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest004, TestSiz g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidFieldCloudData(5, {.invalidCreateField = false}); + InvalidCloudDataOpt opt; + opt.invalidCreateField = false; + data = GetInvalidFieldCloudData(g_invalidOptCount, opt); return QUERY_END; }); int errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -470,7 +485,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest004, TestSiz g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidFieldCloudData(5, {.invalidCursor = false}); + InvalidCloudDataOpt opt; + opt.invalidCursor = false; + data = GetInvalidFieldCloudData(g_invalidOptCount, opt); return QUERY_END; }); errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -500,7 +517,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00402, TestS g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidFieldCloudData(5, {.invalidDeleteField = false}); // Generate 5 data + InvalidCloudDataOpt opt; + opt.invalidDeleteField = false; + data = GetInvalidFieldCloudData(g_invalidOptCount, opt); return QUERY_END; }); int errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -510,7 +529,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00402, TestS g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidFieldCloudData(5, {.invalidGID = false}); // Generate 5 data + InvalidCloudDataOpt opt; + opt.invalidGID = false; + data = GetInvalidFieldCloudData(g_invalidOptCount, opt); return QUERY_END; }); errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -520,7 +541,9 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockQueryTest00402, TestS g_cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_MERGE); EXPECT_CALL(*g_idb, Query(_, _, _)) .WillOnce([](const std::string &, VBucket &, std::vector &data) { - data = GetInvalidFieldCloudData(5, {.invalidModifyField = false}); // Generate 5 data + InvalidCloudDataOpt opt; + opt.invalidModifyField = false; + data = GetInvalidFieldCloudData(g_invalidOptCount, opt); return QUERY_END; }); errCode = g_cloudSyncer->CallDoDownload(taskId); @@ -708,4 +731,29 @@ HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest007, TestSize.Lev EXPECT_EQ(errCode, E_OK); } +/** + * @tc.name: DownloadMockTest008 + * @tc.desc: Get sync param when task resume + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudSyncerDownloadTest, DownloadMockTest008, TestSize.Level0) +{ + TaskId taskId = 1u; + g_cloudSyncer->SetTaskResume(taskId, true); + + std::string expectCloudWaterMark = "waterMark"; + ICloudSyncer::SyncParam param; + param.cloudWaterMark = expectCloudWaterMark; + param.tableName = "table"; + g_cloudSyncer->SetResumeSyncParam(taskId, param); + g_cloudSyncer->SetCloudWaterMarks(param.tableName, param.cloudWaterMark); + ICloudSyncer::SyncParam actualParam; + EXPECT_EQ(g_cloudSyncer->CallGetSyncParamForDownload(taskId, actualParam), E_OK); + EXPECT_EQ(actualParam.cloudWaterMark, expectCloudWaterMark); + + g_cloudSyncer->SetTaskResume(taskId, false); + g_cloudSyncer->ClearResumeTaskInfo(taskId); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp index 377b906ef92c96843c2ad86d400cac6cb9719111..bae35ceaa0faafd8f38a0a1c33b8c89ff8525b02 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_progress_manager_test.cpp @@ -292,4 +292,74 @@ HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMgrCheck005, TestSiz delete iCloud; idb = nullptr; } + +/** + * @tc.name: SyncerMockCheck001 + * @tc.desc: Test Syncer pause tasks + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMockCheck001, TestSize.Level0) +{ + auto *iCloud = new MockICloudSyncStorageInterface(); + ASSERT_NE(iCloud, nullptr); + std::shared_ptr storageProxy = std::make_shared(iCloud); + auto cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); + ASSERT_NE(cloudSyncer, nullptr); + + cloudSyncer->SetCurrentContext(2u); // 2 is taskId + cloudSyncer->SetLastTaskId(3u); // 3 is taskId + cloudSyncer->SetCurrentTaskPause(); + cloudSyncer->SetAssetFields("test", {{}}); + cloudSyncer->SetAssetDownloadList(1); + EXPECT_EQ(cloudSyncer->CallDownloadAssets(), -E_TASK_PAUSED); + cloudSyncer->SetCurrentContext(0); + cloudSyncer->Close(); + RefObject::KillAndDecObjRef(cloudSyncer); + storageProxy.reset(); + delete iCloud; +} + +/** + * @tc.name: SyncerMockCheck002 + * @tc.desc: Test Syncer get current query + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBCloudSyncerProgressManagerTest, SyncerMockCheck002, TestSize.Level0) +{ + auto *iCloud = new MockICloudSyncStorageInterface(); + std::shared_ptr storageProxy = std::make_shared(iCloud); + ASSERT_NE(iCloud, nullptr); + EXPECT_CALL(*iCloud, GetIdentify).WillRepeatedly(Return("")); + auto cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); + ASSERT_NE(cloudSyncer, nullptr); + + // prepare current query and last query + // make them has diff sort type + const TaskId currentTask = 2u; + QuerySyncObject currentQuery; + currentQuery.SetTableName("current"); + currentQuery.SetSortType(SortType::TIMESTAMP_ASC); + cloudSyncer->SetQuerySyncObject(currentTask, currentQuery); + const TaskId lastTask = 3u; + QuerySyncObject lastQuery; + lastQuery.SetTableName("last"); + lastQuery.SetSortType(SortType::TIMESTAMP_DESC); + cloudSyncer->SetQuerySyncObject(lastTask, lastQuery); + cloudSyncer->SetCurrentContext(currentTask); + cloudSyncer->SetLastTaskId(lastTask); + // check get current query from syncer + QuerySyncObject actualQuery = cloudSyncer->CallGetQuerySyncObject(currentQuery.GetTableName()); + EXPECT_EQ(actualQuery.GetSortType(), currentQuery.GetSortType()); + EXPECT_NE(actualQuery.GetSortType(), lastQuery.GetSortType()); + + cloudSyncer->SetCurrentContext(0); + cloudSyncer->Close(); + RefObject::KillAndDecObjRef(cloudSyncer); + storageProxy = nullptr; + delete iCloud; +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp index 77eb89f0a928e12a1329acb84f989254a9c2a75f..7f6f38378a275ccf208aa4a360997de35b775464 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_syncer_upload_test.cpp @@ -30,7 +30,16 @@ namespace { constexpr auto TABLE_NAME_1 = "tableName1"; constexpr auto CLOUD_WATER_MARK = "tableName1"; - +const Asset ASSET_COPY = { .version = 1, + .name = "Phone", + .assetId = "0", + .subpath = "/local/sync", + .uri = "/local/sync", + .modifyTime = "123456", + .createTime = "", + .size = "256", + .hash = "ASE" }; +const int COUNT = 1000; static void CommonExpectCall(MockICloudSyncStorageInterface *iCloud) { @@ -48,7 +57,6 @@ static void CommonExpectCall(MockICloudSyncStorageInterface *iCloud) static void BatchExpectCall(MockICloudSyncStorageInterface *iCloud) { EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); } class DistributedDBCloudSyncerUploadTest : public testing::Test { public: @@ -56,6 +64,11 @@ public: static void TearDownTestCase(void); void SetUp(); void TearDown(); +protected: + void PrepareRecord(VBucket &tmp, VBucket &assets); + void PrepareUploadDataInsData(const VBucket &tmp, const VBucket &assets, CloudSyncData &uploadData); + void PrepareUploadDataUpdData(const VBucket &tmp, const VBucket &assets, CloudSyncData &uploadData); + void PrepareUploadDataForUploadModeCheck012(CloudSyncData &uploadData); }; void DistributedDBCloudSyncerUploadTest::SetUpTestCase(void) @@ -75,6 +88,42 @@ void DistributedDBCloudSyncerUploadTest::TearDown(void) { } +void DistributedDBCloudSyncerUploadTest::PrepareRecord(VBucket &tmp, VBucket &assets) +{ + tmp = { pair(CloudDbConstant::MODIFY_FIELD, 1), + pair(CloudDbConstant::CREATE_FIELD, 1), + pair(CloudDbConstant::ASSET, ASSET_COPY) }; + assets = { pair(CloudDbConstant::ASSET, ASSET_COPY) }; +} + +void DistributedDBCloudSyncerUploadTest::PrepareUploadDataInsData(const VBucket &tmp, + const VBucket &assets, CloudSyncData &uploadData) +{ + uploadData.insData.record = std::vector(COUNT, tmp); + uploadData.insData.extend = std::vector(COUNT, tmp); + uploadData.insData.assets = std::vector(COUNT, assets); +} + +void DistributedDBCloudSyncerUploadTest::PrepareUploadDataUpdData(const VBucket &tmp, + const VBucket &assets, CloudSyncData &uploadData) +{ + uploadData.updData.record = std::vector(COUNT, tmp); + uploadData.updData.extend = std::vector(COUNT, tmp); + uploadData.updData.assets = std::vector(COUNT, assets); +} + +void DistributedDBCloudSyncerUploadTest::PrepareUploadDataForUploadModeCheck012(CloudSyncData &uploadData) +{ + VBucket tmp; + VBucket assets; + PrepareRecord(tmp, assets); + uploadData.insData.record = std::vector(COUNT, tmp); + uploadData.insData.extend = std::vector(COUNT, tmp); + uploadData.insData.assets = std::vector(COUNT, assets); + uploadData.delData.record = std::vector(COUNT, tmp); + uploadData.delData.extend = std::vector(COUNT, tmp); +} + /** * @tc.name: UploadModeCheck001 * @tc.desc: Test different strategies of sync task call DoUpload() @@ -223,7 +272,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck004, TestSize.Level1 std::shared_ptr idb = std::make_shared(); cloudSyncer->SetMockICloudDB(idb); cloudSyncer->InitCloudSyncer(3u, SYNC_MODE_CLOUD_FORCE_PUSH); - + EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, ChkSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, Commit()).WillRepeatedly(Return(E_OK)); @@ -283,6 +332,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck005, TestSize.Level1 errCode = cloudSyncer->CallDoUpload(11u); EXPECT_EQ(errCode, E_OK); + EXPECT_FALSE(cloudSyncer->IsResumeTaskUpload(11u)); RuntimeContext::GetInstance()->StopTaskPool(); cloudSyncer->CallClose(); @@ -323,7 +373,6 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck006, TestSize.Level1 count = 1000; return E_OK; }); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); VBucket tmp = {pair(CloudDbConstant::MODIFY_FIELD, 1)}; @@ -377,10 +426,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck007, TestSize.Level1 // Batch_n CloudSyncData quantity > total count cloudSyncer->InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName()); - VBucket tmp = { pair(CloudDbConstant::MODIFY_FIELD, 1), - pair(CloudDbConstant::CREATE_FIELD, 1) }; - uploadData2.insData.record = std::vector(1000, tmp); - uploadData2.insData.extend = std::vector(1000, tmp); + VBucket tmp; + VBucket assets; + PrepareRecord(tmp, assets); + PrepareUploadDataInsData(tmp, assets, uploadData2); SyncTimeRange syncTimeRange = { .beginTime = 1u }; QueryObject queryObject(Query::Select()); @@ -445,7 +494,6 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 count = 1000; return E_OK; }); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); // empty CloudSyncData @@ -461,7 +509,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck008, TestSize.Level1 cloudDataResult = uploadData2; return -E_UNFINISHED; }); - + int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, -E_INTERNAL_ERROR); @@ -491,14 +539,14 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 TaskId taskId = 5u; cloudSyncer->InitCloudSyncer(taskId, SYNC_MODE_CLOUD_FORCE_PUSH); - VBucket tmp = { pair(CloudDbConstant::MODIFY_FIELD, 1), - pair(CloudDbConstant::CREATE_FIELD, 1) }; + VBucket tmp; + VBucket assets; + PrepareRecord(tmp, assets); CommonExpectCall(iCloud); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, BatchDelete(_, _)).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, BatchUpdate(_, _, _)).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)) .WillRepeatedly([](const QuerySyncObject &, const Timestamp &, const bool, int64_t & count) { count = 10000; @@ -506,8 +554,7 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck009, TestSize.Level1 }); CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); - uploadData.insData.record = std::vector(1000, tmp); - uploadData.insData.extend = std::vector(1000, tmp); + PrepareUploadDataInsData(tmp, assets, uploadData); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)) .WillOnce([&uploadData](const TableSchema &, const QuerySyncObject &, const Timestamp &, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { @@ -562,7 +609,6 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck017, TestSize.Level1 EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, BatchDelete(_, _)).WillRepeatedly(Return(OK)); EXPECT_CALL(*idb, BatchUpdate(_, _, _)).WillRepeatedly(Return(OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)) .WillRepeatedly([](const QuerySyncObject &, const Timestamp &, const bool, int64_t & count) { count = 10000; @@ -633,7 +679,6 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck010, TestSize.Level1 EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); int errCode = cloudSyncer->CallDoUpload(taskId); EXPECT_EQ(errCode, E_OK); @@ -663,8 +708,9 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); cloudSyncer->SetMockICloudDB(idb); - VBucket tmp = { pair(CloudDbConstant::MODIFY_FIELD, 1), - pair(CloudDbConstant::CREATE_FIELD, 1) }; + VBucket tmp; + VBucket assets; + PrepareRecord(tmp, assets); cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); @@ -684,12 +730,10 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck011, TestSize.Level1 EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); // insert has no data, update and delete have data CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName()); - uploadData2.updData.record = std::vector(1000, tmp); - uploadData2.updData.extend = std::vector(1000, tmp); + PrepareUploadDataUpdData(tmp, assets, uploadData2); uploadData2.delData.record = std::vector(1000, tmp); uploadData2.delData.extend = std::vector(1000, tmp); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)) @@ -726,8 +770,6 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 TestCloudSyncer *cloudSyncer = new(std::nothrow) TestCloudSyncer(storageProxy); std::shared_ptr idb = std::make_shared(); cloudSyncer->SetMockICloudDB(idb); - VBucket tmp = { pair(CloudDbConstant::MODIFY_FIELD, 1), - pair(CloudDbConstant::CREATE_FIELD, 1) }; cloudSyncer->InitCloudSyncer(6u, SYNC_MODE_CLOUD_FORCE_PUSH); EXPECT_CALL(*iCloud, StartTransaction(_)).WillRepeatedly(Return(E_OK)); @@ -747,23 +789,23 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck012, TestSize.Level1 EXPECT_CALL(*iCloud, GetCloudDataNext(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudDbSchema(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudTableSchema(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); // insert has data, update has no data, delete has data CloudSyncData uploadData3(cloudSyncer->GetCurrentContextTableName()); - uploadData3.insData.record = std::vector(1000, tmp); - uploadData3.insData.extend = std::vector(1000, tmp); - uploadData3.delData.record = std::vector(1000, tmp); - uploadData3.delData.extend = std::vector(1000, tmp); + PrepareUploadDataForUploadModeCheck012(uploadData3); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)) .WillOnce([cloudSyncer, &uploadData3](const TableSchema &, const QuerySyncObject &, const Timestamp &, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { cloudDataResult = uploadData3; + cloudSyncer->CallRecordWaterMark(6u, 1u); // task id is 6 return E_OK; }); int errCode = cloudSyncer->CallDoUpload(6u); // task id is 6 std::this_thread::sleep_for(std::chrono::seconds(1)); EXPECT_EQ(errCode, E_OK); + uint64_t waterMark = 0u; + cloudSyncer->CallReloadWaterMarkIfNeed(6u, waterMark); // taskId is 6 + EXPECT_EQ(waterMark, 0u); EXPECT_EQ(cloudSyncer->GetUploadSuccessCount(6u), 2000); // task id is 6, success count is 2000 EXPECT_EQ(cloudSyncer->GetUploadFailCount(6u), 0); // task id is 6 @@ -842,7 +884,6 @@ void MockMethod014(MockICloudSyncStorageInterface *iCloud) { CommonExpectCall(iCloud); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); } /** * @tc.name: UploadModeCheck014 @@ -1016,7 +1057,6 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck016, TestSize.Level1 CloudSyncData uploadData(cloudSyncer->GetCurrentContextTableName()); cloudSyncer->initFullCloudSyncData(uploadData, 1000); - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetCloudData(_, _, _, _, _)) .WillRepeatedly([&uploadData](const TableSchema &, const QuerySyncObject &, const Timestamp &, ContinueToken &continueStmtToken, CloudSyncData &cloudDataResult) { @@ -1040,7 +1080,6 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck016, TestSize.Level1 void MockCall(MockICloudSyncStorageInterface *iCloud, const std::shared_ptr &idb) { - EXPECT_CALL(*iCloud, FillCloudGid(_)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*idb, BatchInsert(_, _, _)).WillRepeatedly(Return(OK)); EXPECT_CALL(*iCloud, PutMetaData(_, _)).WillRepeatedly(Return(E_OK)); EXPECT_CALL(*iCloud, GetUploadCount(_, _, _, _)) @@ -1074,12 +1113,12 @@ HWTEST_F(DistributedDBCloudSyncerUploadTest, UploadModeCheck018, TestSize.Level1 PrepareEnv018(iCloud, idb); // Batch_n CloudSyncData quantity > total count - VBucket tmp = { pair(CloudDbConstant::MODIFY_FIELD, 1), - pair(CloudDbConstant::CREATE_FIELD, 1) }; + VBucket tmp; + VBucket assets; + PrepareRecord(tmp, assets); cloudSyncer->InitCloudSyncer(5u, SYNC_MODE_CLOUD_FORCE_PUSH); CloudSyncData uploadData2(cloudSyncer->GetCurrentContextTableName()); - uploadData2.insData.record = std::vector(1000, tmp); - uploadData2.insData.extend = std::vector(1000, tmp); + PrepareUploadDataInsData(tmp, assets, uploadData2); SyncTimeRange syncTimeRange = { .beginTime = 1u }; QueryObject queryObject(Query::Select()); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp index fac9fef34de1e4ec8bf0258b643f852e82434b78..146fc544f91f86f40e726985e42830908af26605 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_compound_primary_key_sync_test.cpp @@ -16,7 +16,7 @@ #include #include #include "cloud/cloud_storage_utils.h" -#include "cloud_db_constant.h" +#include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "process_system_api_adapter_impl.h" diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp index 86036a3c8cccc6bc4d3866c9d0c050fc807633d2..b2137d8ad7ca57509ad69a48c5f996d6e83095b7 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/distributeddb_cloud_table_without_primary_key_sync_test.cpp @@ -16,7 +16,7 @@ #include #include #include "cloud/cloud_storage_utils.h" -#include "cloud_db_constant.h" +#include "cloud/cloud_db_constant.h" #include "distributeddb_data_generate_unit_test.h" #include "distributeddb_tools_unit_test.h" #include "process_system_api_adapter_impl.h" @@ -49,6 +49,17 @@ namespace { std::shared_ptr g_virtualAssetLoader; RelationalStoreObserverUnitTest *g_observer = nullptr; RelationalStoreDelegate *g_delegate = nullptr; + TrackerSchema g_trackerSchema = { + .tableName = g_tableName, .extendColName = "name", .trackerColNames = {"age"} + }; + TrackerSchema g_trackerSchema2 = { + .tableName = g_tableName, .extendColName = "age", .trackerColNames = {"height"} + }; + TrackerSchema g_trackerSchema3 = { + .tableName = g_tableName, .extendColName = "", .trackerColNames = {} + }; + ChangeProperties g_onChangeProperties = { .isTrackedDataChange = true }; + ChangeProperties g_unChangeProperties = { .isTrackedDataChange = false }; const std::vector g_tables = {g_tableName}; const std::string CREATE_LOCAL_TABLE_WITHOUT_PRIMARY_KEY_SQL = "CREATE TABLE IF NOT EXISTS " + g_tableName + "(" \ @@ -76,6 +87,67 @@ namespace { g_observer->SetExpectedResult(changedDataForTable); } + void InitExpectChangedDataByDetailsType(ChangedDataType dataType, int64_t count, ChangeType changeType, + ChangeProperties properties, uint32_t detailsType) + { + ChangedData changedDataForTable; + changedDataForTable.tableName = g_tableName; + if (detailsType & static_cast(CallbackDetailsType::DEFAULT)) { + changedDataForTable.type = dataType; + changedDataForTable.field.push_back(std::string("rowid")); + for (int64_t i = 1; i <= count; ++i) { + changedDataForTable.primaryData[changeType].push_back({i}); + } + } + if (detailsType & static_cast(CallbackDetailsType::BRIEF)) { + changedDataForTable.properties = properties; + } + g_observer->SetExpectedResult(changedDataForTable); + } + + void TestChangedDataInTrackerTable(const TrackerSchema &trackerSchema, uint32_t detailsType, + std::vector &expectProperties) + { + EXPECT_EQ(expectProperties.size(), 3u); // 3 is the num to check change properties + /** + * @tc.steps:step1. set tracker table + * @tc.expected: step1. check the changeddata and return ok + */ + EXPECT_EQ(g_delegate->SetTrackerTable(trackerSchema), OK); + g_observer->SetCallbackDetailsType(detailsType); + int64_t cloudCount = 10; // 10 is random cloud count + int64_t paddingSize = 10; // 10 is padding size + int index = 0; + InitExpectChangedDataByDetailsType(ChangedDataType::DATA, cloudCount, ChangeType::OP_INSERT, + expectProperties[index++], detailsType); + CloudDBSyncUtilsTest::InsertCloudTableRecord(0, cloudCount, paddingSize, true, g_virtualCloudDb); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + EXPECT_TRUE(g_observer->IsAllChangedDataEq()); + g_observer->ClearChangedData(); + + /** + * @tc.steps:step2. update cloud data + * @tc.expected: step2. check the changeddata and return ok + */ + InitExpectChangedDataByDetailsType(ChangedDataType::DATA, cloudCount, ChangeType::OP_UPDATE, + expectProperties[index++], detailsType); + CloudDBSyncUtilsTest::UpdateCloudTableRecord(0, cloudCount, paddingSize, true, g_virtualCloudDb); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + EXPECT_TRUE(g_observer->IsAllChangedDataEq()); + g_observer->ClearChangedData(); + + /** + * @tc.steps:step3. delete cloud data + * @tc.expected: step3. check the changeddata and return ok + */ + InitExpectChangedDataByDetailsType(ChangedDataType::DATA, cloudCount, ChangeType::OP_DELETE, + expectProperties[index++], detailsType); + CloudDBSyncUtilsTest::DeleteCloudTableRecordByGid(0, cloudCount, g_virtualCloudDb); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + EXPECT_TRUE(g_observer->IsAllChangedDataEq()); + g_observer->ClearChangedData(); + } + class DistributedDBCloudTableWithoutPrimaryKeySyncTest : public testing::Test { public: static void SetUpTestCase(void); @@ -301,5 +373,118 @@ HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest006, Tes CloudDBSyncUtilsTest::CheckLocalRecordNum(db, g_tableName, 0); } +/* + * @tc.name: CloudSyncTest007 + * @tc.desc: test sync when device delete + * @tc.type: FUNC + * @tc.require: + * @tc.author: chenchaohao + */ +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, CloudSyncTest007, TestSize.Level0) +{ + /** + * @tc.steps:step1. insert cloud asset and merge + * @tc.expected: step1. check the changeddata and return ok + */ + int64_t cloudCount = 30; // 30 is random cloud count + int64_t paddingSize = 10; // 10 is padding size + CloudDBSyncUtilsTest::InsertCloudTableRecord(0, cloudCount, paddingSize, false, g_virtualCloudDb); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CloudDBSyncUtilsTest::CheckDownloadResult(db, {cloudCount}, CLOUD); + CloudDBSyncUtilsTest::CheckCloudTotalCount({cloudCount}, g_virtualCloudDb); + + /** + * @tc.steps:step2. delete user data and update cloud data + * @tc.expected: step2. check sync reseult and return ok + */ + int64_t deviceBegin = 20; // 20 is device begin + int64_t deviceCount = 10; // 10 is device delete + CloudDBSyncUtilsTest::DeleteUserTableRecord(db, 0, deviceCount); + CloudDBSyncUtilsTest::DeleteUserTableRecord(db, deviceBegin, deviceCount); + CloudDBSyncUtilsTest::UpdateCloudTableRecord(0, deviceCount, paddingSize, false, g_virtualCloudDb); + CloudDBSyncUtilsTest::callSync(g_tables, SYNC_MODE_CLOUD_MERGE, DBStatus::OK, g_delegate); + CloudDBSyncUtilsTest::CheckLocalRecordNum(db, g_tableName, deviceBegin); + CloudDBSyncUtilsTest::CheckCloudTotalCount({deviceBegin}, g_virtualCloudDb); +} + +/* + * @tc.name: ChangeTrackerDataTest001 + * @tc.desc: test changed data on BRIEF type of sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest001, TestSize.Level0) +{ + std::vector expectProperties = { + g_onChangeProperties, g_unChangeProperties, g_onChangeProperties + }; + TestChangedDataInTrackerTable(g_trackerSchema, static_cast(CallbackDetailsType::BRIEF), + expectProperties); +} + +/* + * @tc.name: ChangeTrackerDataTest002 + * @tc.desc: test changed data on DETAILED type of sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest002, TestSize.Level0) +{ + std::vector expectProperties = { + g_onChangeProperties, g_unChangeProperties, g_onChangeProperties + }; + TestChangedDataInTrackerTable(g_trackerSchema, static_cast(CallbackDetailsType::DETAILED), + expectProperties); +} + +/* + * @tc.name: ChangeTrackerDataTest003 + * @tc.desc: test changed data on DEFAULT type of sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest003, TestSize.Level0) +{ + std::vector expectProperties = { + g_unChangeProperties, g_unChangeProperties, g_unChangeProperties + }; + TestChangedDataInTrackerTable(g_trackerSchema, static_cast(CallbackDetailsType::DEFAULT), + expectProperties); +} + +/* + * @tc.name: ChangeTrackerDataTest004 + * @tc.desc: test changed data on DETAILED type of sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest004, TestSize.Level0) +{ + std::vector expectProperties = { + g_onChangeProperties, g_onChangeProperties, g_onChangeProperties + }; + TestChangedDataInTrackerTable(g_trackerSchema2, static_cast(CallbackDetailsType::DETAILED), + expectProperties); +} + +/* + * @tc.name: ChangeTrackerDataTest005 + * @tc.desc: test changed data on unTracker table + * @tc.type: FUNC + * @tc.require: + * @tc.author: bty + */ +HWTEST_F(DistributedDBCloudTableWithoutPrimaryKeySyncTest, ChangeTrackerDataTest005, TestSize.Level0) +{ + std::vector expectProperties = { + g_unChangeProperties, g_unChangeProperties, g_unChangeProperties + }; + TestChangedDataInTrackerTable(g_trackerSchema3, static_cast(CallbackDetailsType::DETAILED), + expectProperties); +} } #endif // RELATIONAL_STORE \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_asset_loader.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_asset_loader.h index f694ef09ad48f7c1d8821bf81c108d7a1ee60a35..2ccdb760805feeb59cfb34f740d8c655350eaaab 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_asset_loader.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_asset_loader.h @@ -16,7 +16,7 @@ #ifndef MOCK_ASSET_LOADER_H #define MOCK_ASSET_LOADER_H #include -#include "iAssetLoader.h" +#include "cloud/iAssetLoader.h" namespace DistributedDB { class MockAssetLoader : public IAssetLoader { diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h index 18072f3111baf064aaaf580b13ea7b2ddffa769e..22275b2296f5506605fcea7ce3633b430524022e 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/mock_icloud_sync_storage_interface.h @@ -25,13 +25,12 @@ public: MOCK_METHOD2(PutMetaData, int(const Key &, const Value &)); MOCK_METHOD1(ChkSchema, int(const TableName &)); MOCK_METHOD1(SetCloudDbSchema, int(const DataBaseSchema &)); - MOCK_METHOD1(GetCloudDbSchema, int(DataBaseSchema &)); + MOCK_METHOD1(GetCloudDbSchema, int(std::shared_ptr &)); MOCK_METHOD2(GetCloudTableSchema, int(const TableName &, TableSchema &)); MOCK_METHOD1(StartTransaction, int(TransactType)); MOCK_METHOD0(Commit, int(void)); MOCK_METHOD0(Rollback, int(void)); MOCK_METHOD4(GetUploadCount, int(const QuerySyncObject &, const Timestamp &, bool, int64_t &)); - MOCK_METHOD1(FillCloudGid, int(const CloudSyncData &)); MOCK_METHOD5(GetCloudData, int(const TableSchema &, const QuerySyncObject &, const Timestamp &, ContinueToken &, CloudSyncData &)); MOCK_METHOD2(GetCloudDataNext, int(ContinueToken &, CloudSyncData &)); @@ -44,9 +43,11 @@ public: const RelationalSchemaObject &localSchema, std::vector &assets)); MOCK_METHOD3(FillCloudAssetForDownload, int(const std::string &, VBucket &, bool)); MOCK_METHOD1(SetLogTriggerStatus, int(bool)); - MOCK_METHOD2(FillCloudGidAndAsset, int(OpType, const CloudSyncData &)); + MOCK_METHOD4(FillCloudLogAndAsset, int(OpType, const CloudSyncData &, bool, bool)); MOCK_CONST_METHOD0(GetIdentify, std::string()); + MOCK_METHOD3(GetCloudDataGid, int(const QuerySyncObject &, Timestamp, std::vector &)); MOCK_METHOD1(CheckQueryValid, int(const QuerySyncObject &)); + MOCK_METHOD1(IsSharedTable, bool(const std::string &)); }; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp index cd7ce4272dae7994983d21c415218255b6ef75f2..2f29ce4a951fad7eddd750475a4d8256b165c29f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.cpp @@ -26,6 +26,9 @@ DBStatus VirtualAssetLoader::Download(const std::string &tableName, const std::s } } LOGD("Download GID:%s", gid.c_str()); + if (downloadCallBack_) { + downloadCallBack_(assets); + } for (auto &item: assets) { for (auto &asset: item.second) { LOGD("asset [name]:%s, [status]:%u, [flag]:%u", asset.name.c_str(), asset.status, asset.flag); @@ -37,6 +40,9 @@ DBStatus VirtualAssetLoader::Download(const std::string &tableName, const std::s DBStatus VirtualAssetLoader::RemoveLocalAssets(const std::vector &assets) { + if (removeAssetsCallBack_) { + removeAssetsCallBack_(assets); + } return DBStatus::OK; } @@ -46,4 +52,14 @@ void VirtualAssetLoader::SetDownloadStatus(DBStatus status) LOGD("[VirtualAssetLoader] set download status :%d", static_cast(status)); downloadStatus_ = status; } + +void VirtualAssetLoader::ForkDownload(const DownloadCallBack &callback) +{ + downloadCallBack_ = callback; +} + +void VirtualAssetLoader::ForkRemoveLocalAssets(const RemoveAssetsCallBack &callback) +{ + removeAssetsCallBack_ = callback; +} } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h index 172031445afb2f004765986cab2000e398569f84..5e03934d95f15e4b044931530675a88ca9f7950f 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_asset_loader.h @@ -16,9 +16,11 @@ #ifndef VIRTUAL_ASSETLOADER_H #define VIRTUAL_ASSETLOADER_H #include -#include "iAssetLoader.h" +#include "cloud/iAssetLoader.h" namespace DistributedDB { +using DownloadCallBack = std::function &assets)>; +using RemoveAssetsCallBack = std::function &assets)>; class VirtualAssetLoader : public IAssetLoader { public: VirtualAssetLoader() = default; @@ -30,9 +32,15 @@ public: DBStatus RemoveLocalAssets(const std::vector &assets) override; void SetDownloadStatus(DBStatus status); + + void ForkDownload(const DownloadCallBack &callback); + + void ForkRemoveLocalAssets(const RemoveAssetsCallBack &callback); private: std::mutex dataMutex_; DBStatus downloadStatus_ = OK; + DownloadCallBack downloadCallBack_; + RemoveAssetsCallBack removeAssetsCallBack_; }; } #endif // VIRTUAL_ASSETLOADER_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_data_translate.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_data_translate.cpp index 41207e5261de0310950c4a84feca00a6996dd842..f534c7be2a62614f425e46e613e552af23a86afe 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_data_translate.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_data_translate.cpp @@ -22,6 +22,7 @@ uint32_t CalculateLens(const Asset &asset) uint32_t len = 0; len += Parcel::GetUInt32Len(); len += Parcel::GetStringLen(asset.name); + len += Parcel::GetStringLen(asset.assetId); len += Parcel::GetStringLen(asset.uri); len += Parcel::GetStringLen(asset.modifyTime); len += Parcel::GetStringLen(asset.createTime); @@ -45,6 +46,7 @@ void WriteAsset(Parcel &parcel, const Asset &asset) { parcel.WriteUInt32(asset.version); parcel.WriteString(asset.name); + parcel.WriteString(asset.assetId); parcel.WriteString(asset.uri); parcel.WriteString(asset.modifyTime); parcel.WriteString(asset.createTime); @@ -58,6 +60,7 @@ void ReadAsset(Parcel &parcel, Asset &asset) { parcel.ReadUInt32(asset.version); parcel.ReadString(asset.name); + parcel.ReadString(asset.assetId); parcel.ReadString(asset.uri); parcel.ReadString(asset.modifyTime); parcel.ReadString(asset.createTime); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp index 944476ee97eb98f8fc16be32b61202c04d684abf..e2f5a19dde93f0e1438785cf6afd7afaee1f9cda 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.cpp @@ -15,10 +15,11 @@ #include "virtual_cloud_db.h" #include -#include "cloud_db_types.h" +#include "cloud/cloud_db_constant.h" +#include "cloud/cloud_db_types.h" #include "db_constant.h" -#include "cloud_db_constant.h" #include "log_print.h" +#include "relational_store_manager.h" #include "time_helper.h" namespace DistributedDB { @@ -27,6 +28,7 @@ namespace { const char *g_gidField = CloudDbConstant::GID_FIELD; const char *g_cursorField = CloudDbConstant::CURSOR_FIELD; const char *g_modifiedField = CloudDbConstant::MODIFY_FIELD; + const char *g_queryField = CloudDbConstant::QUERY_FIELD; } DBStatus VirtualCloudDb::BatchInsert(const std::string &tableName, std::vector &&record, @@ -43,6 +45,30 @@ DBStatus VirtualCloudDb::BatchInsert(const std::string &tableName, std::vector autoLock(cloudDataMutex_); + DBStatus status = InnerBatchInsert(tableName, std::move(record), extend); + if (status != OK) { + return status; + } + if (missingExtendCount_ > 0) { + extend.erase(extend.end()); + } else if (missingExtendCount_ < 0) { + VBucket vBucket; + extend.push_back(vBucket); + } + if (insertFailedCount_ > 0) { + insertFailedCount_--; + LOGW("[VirtualCloud] Insert failed by testcase config"); + return DB_ERROR; + } + if (cloudNetworkError_) { + return CLOUD_NETWORK_ERROR; + } + return OK; +} + +DBStatus VirtualCloudDb::InnerBatchInsert(const std::string &tableName, std::vector &&record, + std::vector &extend) +{ for (size_t i = 0; i < record.size(); ++i) { if (extend[i].find(g_gidField) != extend[i].end()) { LOGE("[VirtualCloudDb] Insert data should not have gid"); @@ -51,6 +77,11 @@ DBStatus VirtualCloudDb::BatchInsert(const std::string &tableName, std::vector 0) { + extend.erase(extend.end()); + } else if (missingExtendCount_ < 0) { + VBucket vBucket; + extend.push_back(vBucket); + } + if (cloudNetworkError_) { + return CLOUD_NETWORK_ERROR; + } LOGI("[VirtualCloudDb] BatchInsertWithGid records"); return OK; } @@ -140,6 +184,7 @@ DBStatus VirtualCloudDb::HeartBeat() std::pair VirtualCloudDb::Lock() { + lockCount_++; if (actionStatus_ != OK) { return { actionStatus_, DBConstant::MIN_TIMEOUT }; } @@ -200,6 +245,9 @@ DBStatus VirtualCloudDb::Query(const std::string &tableName, VBucket &extend, st if (blockTimeMs_ != 0) { std::this_thread::sleep_for(std::chrono::milliseconds(blockTimeMs_)); } + if (forkFunc_) { + forkFunc_(tableName, extend); + } if (queryTimes_.find(tableName) == queryTimes_.end()) { queryTimes_.try_emplace(tableName, 0); } @@ -213,10 +261,10 @@ DBStatus VirtualCloudDb::Query(const std::string &tableName, VBucket &extend, st LOGD("extend size: %zu type: %zu expect: %zu, cursor: %s", extend.size(), extend[g_cursorField].index(), TYPE_INDEX, cursor.c_str()); if (isIncreCursor) { - GetCloudData(cursor, isIncreCursor, incrementCloudData_[tableName], data); + GetCloudData(cursor, isIncreCursor, incrementCloudData_[tableName], data, extend); } else { cursor = cursor.empty() ? "0" : cursor; - GetCloudData(cursor, isIncreCursor, cloudData_[tableName], data); + GetCloudData(cursor, isIncreCursor, cloudData_[tableName], data, extend); } if (!isIncreCursor && data.empty() && isSetCrementCloudData_) { extend[g_cursorField] = increPrefix_; @@ -226,11 +274,22 @@ DBStatus VirtualCloudDb::Query(const std::string &tableName, VBucket &extend, st } void VirtualCloudDb::GetCloudData(const std::string &cursor, bool isIncreCursor, std::vector allData, - std::vector &data) + std::vector &data, VBucket &extend) { + std::vector queryNodes; + auto it = extend.find(g_queryField); + if (it != extend.end()) { + Bytes bytes = std::get(extend[g_queryField]); + DBStatus status = OK; + queryNodes = RelationalStoreManager::ParserQueryNodes(bytes, status); + } for (auto &tableData : allData) { std::string srcCursor = std::get(tableData.extend[g_cursorField]); if ((!isIncreCursor && std::stol(srcCursor) > std::stol(cursor)) || isIncreCursor) { + if ((!queryNodes.empty()) && (!IsCloudGidMatching(queryNodes, tableData.extend)) && + (!IsPrimaryKeyMatching(queryNodes, tableData.record))) { + continue; + } VBucket bucket = tableData.record; for (const auto &ex: tableData.extend) { bucket.insert(ex); @@ -243,6 +302,53 @@ void VirtualCloudDb::GetCloudData(const std::string &cursor, bool isIncreCursor, } } +bool VirtualCloudDb::IsPrimaryKeyMatching(const std::vector &queryNodes, VBucket &record) +{ + if (record.empty()) { + return false; + } + for (const auto &queryNode : queryNodes) { + if ((queryNode.type == QueryNodeType::IN) && (queryNode.fieldName != g_gidField)) { + if (IsPrimaryKeyMatchingInner(queryNode, record)) { + return true; + } + } + } + return false; +} + +bool VirtualCloudDb::IsPrimaryKeyMatchingInner(const QueryNode &queryNode, VBucket &record) +{ + for (const auto &value : queryNode.fieldValue) { + if (std::get(record[queryNode.fieldName]) == std::get(value)) { + return true; + } + } + return false; +} + +bool VirtualCloudDb::IsCloudGidMatching(const std::vector &queryNodes, VBucket &extend) +{ + for (const auto &queryNode : queryNodes) { + if ((queryNode.type == QueryNodeType::IN) && (queryNode.fieldName == g_gidField)) { + if (IsCloudGidMatchingInner(queryNode, extend)) { + return true; + } + } + } + return false; +} + +bool VirtualCloudDb::IsCloudGidMatchingInner(const QueryNode &queryNode, VBucket &extend) +{ + for (const auto &value : queryNode.fieldValue) { + if (std::get(extend[g_gidField]) == std::get(value)) { + return true; + } + } + return false; +} + DBStatus VirtualCloudDb::InnerUpdate(const std::string &tableName, std::vector &&record, std::vector &extend, bool isDelete) { @@ -250,12 +356,36 @@ DBStatus VirtualCloudDb::InnerUpdate(const std::string &tableName, std::vector autoLock(cloudDataMutex_); + DBStatus res = InnerUpdateWithoutLock(tableName, std::move(record), extend, isDelete); + if (res != OK) { + return res; + } + if (missingExtendCount_ > 0) { + extend.erase(extend.end()); + } else if (missingExtendCount_ < 0) { + VBucket vBucket; + extend.push_back(vBucket); + } + if (cloudNetworkError_) { + return CLOUD_NETWORK_ERROR; + } + return OK; +} + +DBStatus VirtualCloudDb::InnerUpdateWithoutLock(const std::string &tableName, std::vector &&record, + std::vector &extend, bool isDelete) +{ for (size_t i = 0; i < record.size(); ++i) { if (extend[i].find(g_gidField) == extend[i].end()) { LOGE("[VirtualCloudDb] Update data should have gid"); return DB_ERROR; } extend[i][g_cursorField] = std::to_string(currentCursor_++); + extend[i][CloudDbConstant::VERSION_FIELD] = std::to_string(currentVersion_++); + AddAssetIdForExtend(record[i], extend[i]); + if (forkUploadFunc_) { + forkUploadFunc_(tableName, extend[i]); + } if (isDelete) { extend[i][g_deleteField] = true; } else { @@ -377,4 +507,62 @@ void VirtualCloudDb::ClearAllData() incrementCloudData_.clear(); queryTimes_.clear(); } + +void VirtualCloudDb::ForkQuery(const std::function &forkFunc) +{ + forkFunc_ = forkFunc; +} + +void VirtualCloudDb::ForkUpload(const std::function &forkUploadFunc) +{ + forkUploadFunc_ = forkUploadFunc; +} + +int32_t VirtualCloudDb::GetLockCount() +{ + return lockCount_; +} + +void VirtualCloudDb::Reset() +{ + lockCount_ = 0; +} + +void VirtualCloudDb::SetInsertFailed(int32_t count) +{ + insertFailedCount_ = count; +} + +void VirtualCloudDb::SetClearExtend(int32_t count) +{ + missingExtendCount_ = count; +} + +void VirtualCloudDb::SetCloudNetworkError(bool cloudNetworkError) +{ + cloudNetworkError_ = cloudNetworkError; +} + +void VirtualCloudDb::AddAssetIdForExtend(VBucket &record, VBucket &extend) +{ + for (auto &recordData : record) { + if (recordData.second.index() == TYPE_INDEX) { + auto &asset = std::get(recordData.second); + if (asset.flag == static_cast(DistributedDB::AssetOpType::INSERT)) { + asset.assetId = "10"; + } + extend[recordData.first] = asset; + } + if (recordData.second.index() != TYPE_INDEX) { + continue; + } + auto &assets = std::get(recordData.second); + for (auto &asset : assets) { + if (asset.flag == static_cast(DistributedDB::AssetOpType::INSERT)) { + asset.assetId = "10"; + } + } + extend[recordData.first] = assets; + } +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h index d54e6cd8e66339ddfa0d5ed775ceca62cfabe69b..a72d8816bf9c99f8524a75b7f8b38fda054aa849 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/cloud/virtual_cloud_db.h @@ -68,28 +68,63 @@ public: DBStatus GetDataStatus(const std::string &gid, bool &deleteStatus); void ClearAllData(); + + void ForkQuery(const std::function &forkFunc); + + void ForkUpload(const std::function &forkUploadFunc); + + int32_t GetLockCount(); + + void Reset(); + + void SetInsertFailed(int32_t count); + + void SetClearExtend(int32_t count); + + void SetCloudNetworkError(bool cloudNetworkError); private: struct CloudData { VBucket record; VBucket extend; }; + DBStatus InnerBatchInsert(const std::string &tableName, std::vector &&record, + std::vector &extend); + DBStatus InnerUpdate(const std::string &tableName, std::vector &&record, std::vector &extend, bool isDelete); + DBStatus InnerUpdateWithoutLock(const std::string &tableName, std::vector &&record, + std::vector &extend, bool isDelete); + DBStatus UpdateCloudData(const std::string &tableName, CloudData &&cloudData); void GetCloudData(const std::string &cursor, bool isIncreCursor, std::vector allData, - std::vector &data); + std::vector &data, VBucket &extend); + + bool IsCloudGidMatching(const std::vector &queryNodes, VBucket &extend); + + bool IsCloudGidMatchingInner(const QueryNode &queryNode, VBucket &extend); + + bool IsPrimaryKeyMatching(const std::vector &queryNodes, VBucket &record); + + bool IsPrimaryKeyMatchingInner(const QueryNode &queryNode, VBucket &record); + + void AddAssetIdForExtend(VBucket &record, VBucket &extend); std::atomic cloudError_ = false; + std::atomic cloudNetworkError_ = false; std::atomic heartbeatError_ = false; std::atomic lockStatus_ = false; std::atomic blockTimeMs_ = 0; std::atomic currentGid_ = 0; std::atomic currentCursor_ = 1; + std::atomic currentVersion_ = 0; std::atomic queryLimit_ = 100; std::atomic heartbeatCount_ = 0; + std::atomic lockCount_ = 0; + std::atomic insertFailedCount_ = 0; + std::atomic missingExtendCount_ = 0; std::mutex cloudDataMutex_; std::map> cloudData_; std::map> incrementCloudData_; @@ -97,6 +132,8 @@ private: std::string increPrefix_ = "increPrefix_"; std::map queryTimes_; DBStatus actionStatus_ = OK; + std::function forkFunc_; + std::function forkUploadFunc_; }; } #endif // VIRTUAL_CLOUD_DB_H diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp index 27cd9b0caf0f06a2972c29fa5a09c77d009f5a78..e608d89b2b0de53dc9daa5acac660a2c3f2f12dd 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_mock_sync_module_test.cpp @@ -337,9 +337,9 @@ void SyncLifeTest003() virtualCommunicatorAggregator->OfflineDevice(DEVICE_B); EXPECT_EQ(syncDBInterface->Close(), E_OK); RefObject::KillAndDecObjRef(syncDBInterface); - RuntimeContext::GetInstance()->StopTaskPool(); std::this_thread::sleep_for(std::chrono::seconds(1)); RuntimeContext::GetInstance()->SetCommunicatorAggregator(nullptr); + RuntimeContext::GetInstance()->StopTaskPool(); } void MockRemoteQuery002() @@ -1080,7 +1080,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest002, TestSize.Level3) * @tc.require: AR000CCPOM * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBMockSyncModuleTest, SyncLifeTest003, TestSize.Level3) +HWTEST_F(DistributedDBMockSyncModuleTest, DISABLED_SyncLifeTest003, TestSize.Level3) { ASSERT_NO_FATAL_FAILURE(SyncLifeTest003()); } @@ -1935,7 +1935,7 @@ HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck002, TestSize.Level1) * @tc.require: AR000CCPOM * @tc.author: zhangqiquan */ -HWTEST_F(DistributedDBMockSyncModuleTest, SyncerCheck003, TestSize.Level1) +HWTEST_F(DistributedDBMockSyncModuleTest, DISABLE_SyncerCheck003, TestSize.Level1) { MockSingleVerKVSyncer syncer; InternalSyncParma param; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp index 479841dedf178a0aba94c8a39eba2bf2b2af8411..3b9a4067d7a169428ba897335df7c4983d853573 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_multi_ver_p2p_sync_test.cpp @@ -82,7 +82,7 @@ namespace { std::string identifierDir = DBCommon::TransferStringToHex(identifier); prop.SetStringProp(KvDBProperties::IDENTIFIER_DIR, identifierDir); prop.SetStringProp(KvDBProperties::DATA_DIR, dir); - prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); prop.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); errCode = E_OK; auto conn = KvDBManager::GetDatabaseConnection(prop, errCode); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp index dc1518ff4029a09ef0e5a9b7746b98aecb0d09e4..76ae9e9750b0cba18e3e0902af8ff4783a4dc407 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_relational_ver_p2p_sync_test.cpp @@ -687,7 +687,7 @@ namespace { } if (localOption.securityLabel == static_cast(SecurityLabel::NOT_SET) || remoteOption.securityLabel == static_cast(SecurityLabel::NOT_SET)) { - return OK; + return SECURITY_OPTION_CHECK_ERROR; } if (localOption.securityLabel != remoteOption.securityLabel) { return SECURITY_OPTION_CHECK_ERROR; @@ -726,6 +726,9 @@ namespace { condition.sql = "SELECT * FROM " + g_tableName; std::shared_ptr result = nullptr; ASSERT_NE(g_rdbDelegatePtr, nullptr); + LOGW("local:label %d, flag %d, remote:label %d, flag %d, expect %d", localOption.securityLabel, + localOption.securityFlag, remoteOption.securityLabel, remoteOption.securityFlag, + static_cast(resStatus)); EXPECT_EQ(g_rdbDelegatePtr->RemoteQuery(DEVICE_B, condition, DBConstant::MIN_TIMEOUT, result), resStatus); } else { BlockSync(SYNC_MODE_PUSH_ONLY, resStatus, {DEVICE_B}); diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp index 8bfa79a0d5306cf01f9e5e06ceaf2710a7fe1d9c..2f836613d3573821fd04cc727fedf94623ce02e4 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_query_sync_test.cpp @@ -1686,7 +1686,7 @@ HWTEST_F(DistributedDBSingleVerP2PQuerySyncTest, VerifyManagerQuerySyncStorage00 DBCommon::StringToVector(QuerySyncWaterMarkHelper::GetQuerySyncPrefixKey() + DBCommon::TransferHashString(deviceId) + newQueryId, dbKey); Value wrongValue; - EXPECT_EQ(storage.PutMetaData(dbKey, wrongValue), E_OK); + EXPECT_EQ(storage.PutMetaData(dbKey, wrongValue, false), E_OK); /** * @tc.steps: step4. initialize new meta with storage diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp index 32a6042760601875449516f8ec5eb42d7c0b7842..f0a57537106463376bb3823136fca539b039fa00 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/distributeddb_single_ver_p2p_sync_check_test.cpp @@ -63,7 +63,6 @@ namespace { const int VALUE_LEN = 4 * 1024 * 1024; // 4MB const int ENTRY_NUM = 2; // 16 entries #endif -} class DistributedDBSingleVerP2PSyncCheckTest : public testing::Test { public: @@ -127,12 +126,17 @@ void DistributedDBSingleVerP2PSyncCheckTest::SetUp(void) g_syncInterfaceB = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(g_syncInterfaceB != nullptr); ASSERT_EQ(g_deviceB->Initialize(g_communicatorAggregator, g_syncInterfaceB), E_OK); + SecurityOption virtualOption; + virtualOption.securityLabel = option.secOption.securityLabel; + virtualOption.securityFlag = option.secOption.securityFlag; + g_syncInterfaceB->SetSecurityOption(virtualOption); g_deviceC = new (std::nothrow) KvVirtualDevice(DEVICE_C); ASSERT_TRUE(g_deviceC != nullptr); g_syncInterfaceC = new (std::nothrow) VirtualSingleVerSyncDBInterface(); ASSERT_TRUE(g_syncInterfaceC != nullptr); ASSERT_EQ(g_deviceC->Initialize(g_communicatorAggregator, g_syncInterfaceC), E_OK); + g_syncInterfaceC->SetSecurityOption(virtualOption); } void DistributedDBSingleVerP2PSyncCheckTest::TearDown(void) @@ -348,6 +352,41 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck004, TestSize.Lev g_syncInterfaceB->ForkGetSecurityOption(nullptr); } +/** + * @tc.name: sec option check Sync 005 + * @tc.desc: if sec option equal, check not pass, forbid sync + * @tc.type: FUNC + * @tc.require: + * @tc.author: zhangqiquan + */ +HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, SecOptionCheck005, TestSize.Level1) +{ + auto adapter = std::make_shared(); + RuntimeContext::GetInstance()->SetProcessSystemApiAdapter(adapter); + g_syncInterfaceB->ForkGetSecurityOption([](SecurityOption &option) { + option.securityLabel = NOT_SET; + return E_OK; + }); + adapter->ForkGetSecurityOption([](const std::string &, SecurityOption &securityOption) { + securityOption.securityLabel = NOT_SET; + return OK; + }); + + std::vector devices; + devices.push_back(g_deviceB->GetDeviceId()); + std::map result; + DBStatus status = g_tool.SyncTest(g_kvDelegatePtr, devices, SYNC_MODE_PULL_ONLY, result); + EXPECT_EQ(status, OK); + for (const auto &pair : result) { + LOGD("dev %s, status %d", pair.first.c_str(), pair.second); + EXPECT_TRUE(pair.second == SECURITY_OPTION_CHECK_ERROR); + } + + adapter->ForkCheckDeviceSecurityAbility(nullptr); + adapter->ForkGetSecurityOption(nullptr); + g_syncInterfaceB->ForkGetSecurityOption(nullptr); +} + #ifndef LOW_LEVEL_MEM_DEV /** * @tc.name: BigDataSync001 @@ -1512,4 +1551,5 @@ HWTEST_F(DistributedDBSingleVerP2PSyncCheckTest, GetDataNotify002, TestSize.Leve EXPECT_EQ(result[DEVICE_B], OK); asyncThread.join(); std::this_thread::sleep_for(std::chrono::seconds(TEN_SECONDS)); +} } \ No newline at end of file diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.cpp index f725d7b9c4133af0d810aadb012c689825a81be5..092655c06876974bb04810d52c8e879bc89aa9fb 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.cpp @@ -59,9 +59,9 @@ int VirtualMultiVerSyncDBInterface::GetMetaData(const Key &key, Value &value) co return kvStore_->GetMetaData(key, value); } -int VirtualMultiVerSyncDBInterface::PutMetaData(const Key &key, const Value &value) +int VirtualMultiVerSyncDBInterface::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { - return kvStore_->PutMetaData(key, value); + return kvStore_->PutMetaData(key, value, isInTransaction); } int VirtualMultiVerSyncDBInterface::DeleteMetaData(const std::vector &keys) @@ -153,7 +153,7 @@ int VirtualMultiVerSyncDBInterface::Initialize(const std::string &deviceId) std::string identifierDir = DBCommon::TransferStringToHex(identifier); prop.SetStringProp(KvDBProperties::IDENTIFIER_DIR, identifierDir); prop.SetStringProp(KvDBProperties::DATA_DIR, dir + "/commitstore"); - prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE); + prop.SetIntProp(KvDBProperties::DATABASE_TYPE, KvDBProperties::MULTI_VER_TYPE_SQLITE); prop.SetBoolProp(KvDBProperties::CREATE_IF_NECESSARY, true); int errCode = E_OK; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.h index 81cc98e1f3d382e463a7674448c06d1032c62e1b..6823e2c0e159ff53f9356396833dcfb6ce3eda1d 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_multi_ver_sync_db_interface.h @@ -38,7 +38,7 @@ public: int GetMetaData(const Key &key, Value &value) const override; - int PutMetaData(const Key &key, const Value &value) override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; // Delete multiple meta data records in a transaction. int DeleteMetaData(const std::vector &keys) override; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp index e8a4e26597d563dd75cb27ab2d82fbd0561d9d8e..b7dbb11a5abdd3e5f3181f09d9269faa15dabbe6 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.cpp @@ -222,8 +222,9 @@ int VirtualRelationalVerSyncDBInterface::GetMetaData(const Key &key, Value &valu return -E_NOT_FOUND; } -int VirtualRelationalVerSyncDBInterface::PutMetaData(const Key &key, const Value &value) +int VirtualRelationalVerSyncDBInterface::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { + (void)isInTransaction; metadata_[key] = value; return E_OK; } @@ -367,7 +368,9 @@ int ObjectData::GetDataValue(const std::string &fieldName, DataValue &value) con int VirtualRelationalVerSyncDBInterface::GetSecurityOption(SecurityOption &option) const { - return RuntimeContext::GetInstance()->GetSecurityOption("", option); + int errCode = RuntimeContext::GetInstance()->GetSecurityOption("", option); + LOGW("virtual get option errCode is %d", errCode); + return errCode; } void VirtualRelationalVerSyncDBInterface::ReleaseRemoteQueryContinueToken(ContinueToken &token) const diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h index 3abf5aef19f9eaa3e80281cce7484e740366dae4..a542ce0be236d622d4a1ecda9a6dbd1905c77515 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_relational_ver_sync_db_interface.h @@ -73,7 +73,7 @@ public: int GetMetaData(const Key &key, Value &value) const override; - int PutMetaData(const Key &key, const Value &value) override; + int PutMetaData(const Key &key, const Value &value, bool isInTransaction) override; int DeleteMetaData(const std::vector &keys) override; diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp index 10b51199ddbbae5080af3007c919f6159622ef34..312f59400367a0532c29b8a0bd593e78d1f93c87 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.cpp @@ -101,8 +101,9 @@ int VirtualSingleVerSyncDBInterface::GetMetaData(const Key &key, Value &value) c return -E_NOT_FOUND; } -int VirtualSingleVerSyncDBInterface::PutMetaData(const Key &key, const Value &value) +int VirtualSingleVerSyncDBInterface::PutMetaData(const Key &key, const Value &value, bool isInTransaction) { + (void)isInTransaction; if (busy_) { return -E_BUSY; } @@ -365,6 +366,9 @@ int VirtualSingleVerSyncDBInterface::GetSecurityOption(SecurityOption &option) c if (getSecurityOptionCallBack_) { return getSecurityOptionCallBack_(option); } + if (secOption_.securityLabel == NOT_SET) { + return -E_NOT_SUPPORT; + } option = secOption_; return E_OK; } diff --git a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h index efa21e972cf85b694713e92e3fd91aacf2304fcd..e34ceafb393046e03c38c51a2bbe2ad4b44a9963 100644 --- a/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h +++ b/kv_store/frameworks/libs/distributeddb/test/unittest/common/syncer/virtual_single_ver_sync_db_Interface.h @@ -54,7 +54,7 @@ public: int GetMetaData(const Key& key, Value& value) const override; - int PutMetaData(const Key& key, const Value& value) override; + int PutMetaData(const Key& key, const Value& value, bool isInTransaction) override; int DeleteMetaData(const std::vector &keys) override; // Delete multiple meta data records with key prefix in a transaction. diff --git a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn index 836faa33cf5dc135649f2e66c447c64a3573b2ee..9ee384a3898dafc7df80f1a0c8a5632f95891501 100644 --- a/kv_store/interfaces/innerkits/distributeddata/BUILD.gn +++ b/kv_store/interfaces/innerkits/distributeddata/BUILD.gn @@ -17,7 +17,10 @@ import("//foundation/distributeddatamgr/kv_store/kv_store.gni") group("build_module") { deps = [] if (!use_platform_win && !use_platforn_mac) { - deps += [ ":distributeddata_inner" ] + deps += [ + ":distributeddata_client_sync", + ":distributeddata_inner", + ] } } @@ -92,6 +95,7 @@ kvdb_source_config = [ deps_config = [ "../../../frameworks/libs/distributeddb:distributeddb", "../distributeddatamgr:distributeddata_mgr", + "../distributeddata:distributeddata_client_sync", ] external_deps_config = [ @@ -118,3 +122,22 @@ ohos_shared_library("distributeddata_inner") { subsystem_name = "distributeddatamgr" part_name = "kv_store" } + +ohos_shared_library("distributeddata_client_sync") { + sources = [ + "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/process_communication_impl.cpp", + "${kv_store_base_path}/frameworks/innerkitsimpl/kvdb/src/process_system_api_adapter_impl.cpp", + ] + + configs = [ ":distributeddatafwk_config" ] + + deps = [ "${kv_store_base_path}/frameworks/libs/distributeddb:distributeddb" ] + + external_deps = [ + "c_utils:utils", + "hilog:libhilog", + ] + innerapi_tags = [ "platformsdk" ] + subsystem_name = "distributeddatamgr" + part_name = "kv_store" +} diff --git a/kv_store/interfaces/innerkits/distributeddata/include/data_query.h b/kv_store/interfaces/innerkits/distributeddata/include/data_query.h index 5daafcc939c8b3d5c994014b89cb11e97c9bd24a..0eb680df79c11f7dc0bf41e7b637fc2a8a3655a0 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/data_query.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/data_query.h @@ -259,6 +259,14 @@ public: */ DataQuery &IsNull(const std::string &field); + /** + * @brief Greater than or equal to small value and less than or equal to large value. + * @param field The small value. + * @param value The large value. + * @return This query + */ + DataQuery& Between(const std::string& valueLow, const std::string& valueHigh); + /** * @brief Is not null field value. * @param field The field name. diff --git a/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h b/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h index 93280684c41fd268c545af850fb7fb0036576d61..33e84d7b2b893678b5a1e1b64aae215f538fb233 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/distributed_kv_data_manager.h @@ -15,7 +15,7 @@ #ifndef DISTRIBUTED_KV_DATA_MANAGER_H #define DISTRIBUTED_KV_DATA_MANAGER_H - +#include #include #include "executor_pool.h" #include "kvstore.h" @@ -23,6 +23,7 @@ #include "kvstore_observer.h" #include "single_kvstore.h" #include "types.h" +#include "end_point.h" namespace OHOS { namespace DistributedKv { @@ -154,6 +155,16 @@ public: * @param executors The executors. */ API_EXPORT void SetExecutors(std::shared_ptr executors); + + /** + * @brief set endpoint for client sync. + * @param endpoint The pointer of endpoint. + * @return Return SUCCESS for success, others for failure. + */ + API_EXPORT Status SetEndpoint(std::shared_ptr endpoint); +private: + static bool isAlreadySet_; + std::mutex mutex_; }; } // namespace DistributedKv } // namespace OHOS diff --git a/kv_store/interfaces/innerkits/distributeddata/include/end_point.h b/kv_store/interfaces/innerkits/distributeddata/include/end_point.h new file mode 100644 index 0000000000000000000000000000000000000000..e8e070ca13fabcbf11cb344c17d6a1814bcef00d --- /dev/null +++ b/kv_store/interfaces/innerkits/distributeddata/include/end_point.h @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2021 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 END_POINT_H +#define END_POINT_H + +#include +#include +#include +#include +#include "types.h" + +namespace OHOS { +namespace DistributedKv { +struct StoreBriefInfo { + std::string userId; + std::string appId; + std::string storeId; + std::string deviceId; + int32_t instanceId = 0; + std::map extraConditions; +}; + +class API_EXPORT Endpoint { +public: + + using RecvHandler = std::function; + + /** + * @brief Constructor. + */ + API_EXPORT Endpoint() = default; + + /** + * @brief Destructor. + */ + API_EXPORT virtual ~Endpoint() {}; + + /** + * @brief Start the Process Communicator. + * @param processLabel Identifies current process. + * @return Return SUCCESS for success, others for failure. + */ + virtual Status Start() = 0; + + /** + * @brief Start the Process Communicator. + * @return Return SUCCESS for success, others for failure. + */ + virtual Status Stop() = 0; + + /** + * @brief Close all opened kvstores for this appId. + * @param callback Callback to register data change. + * @return Return SUCCESS for success, others for failure. + */ + virtual Status RegOnDataReceive(const RecvHandler &callback) = 0; + + /** + * @brief Used to send data to the softbus. + * @param dstDevInfo Target device ID. + * @param data Pointer to data to be send. + * @param length Data length. + * @return Return SUCCESS for success, others for failure. + */ + virtual Status SendData(const std::string &dtsIdentifier, const uint8_t *data, uint32_t length) = 0; + + /** + * @brief Obtains the size of maximum unit sent by the bottom layer. + * @param devInfo Remote device ID. + * @return Data size. + */ + virtual uint32_t GetMtuSize(const std::string &identifier) = 0; + + /** + * @brief Obtains the ID of the loacl device info. + * @return loacl device info. + */ + virtual std::string GetLocalDeviceInfos() = 0; + + /** + * @brief Determines whether the device has the capability of data of this level. + * @param devId Target device ID. + * @param option Security params. + * @return Return true for success, false for failure. + */ + virtual bool IsSaferThanDevice(int securityLevel, const std::string &devId) = 0; + + /** + * @brief Verify sync permission. + * @param param Params for sync permission. + * @param flag The direction of sync. + * @return Return true for success, false for failure. + */ + virtual bool HasDataSyncPermission(const StoreBriefInfo ¶m, uint8_t flag) = 0; +}; +} // namespace DistributedKv +} // namespace OHOS +#endif // END_POINT_H diff --git a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h index 309e562f426e9b3f06ee4343c474409bddd2a6a0..8357b84c5102e8c334d7b32e9d6028233459c7db 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/executor_pool.h @@ -130,7 +130,7 @@ public: task.interval = interval; } auto time = std::chrono::steady_clock::now() + interval; - return std::pair{ true, time }; + return std::pair{ task.interval != INVALID_INTERVAL, time }; }); return updated ? taskId : INVALID_TASK_ID; } diff --git a/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h b/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h index de6974d29a80e42ac4587e88a1ca444b07417292..395a0ac25ff46d04b4955b9e93dd1e5babf59469 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/priority_queue.h @@ -94,10 +94,7 @@ public: std::unique_lock lock(pqMtx_); auto index = indexes_.find(id); if (index != indexes_.end()) { - auto [updated, time] = updater(index->second->second.task_); - if (!updated) { - return false; - } + auto [repeat, time] = updater(index->second->second.task_); auto matrix = std::move(index->second->second); tasks_.erase(index->second); index->second = tasks_.emplace(time, std::move(matrix)); @@ -107,8 +104,8 @@ public: auto running = running_.find(id); if (running != running_.end()) { - auto [updated, time] = updater((*running).second.task_); - return updated; + auto [repeat, time] = updater((*running).second.task_); + return repeat; } return false; diff --git a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h index 41d2e31771ffc00893a584d88a79e52383e52e80..b732dc0a1d6e8b25fb9a7f8f77ee1620763d66bf 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/single_kvstore.h @@ -232,6 +232,20 @@ public: * @return Return SUCCESS for success, others for failure. */ virtual Status UnsubscribeWithQuery(const std::vector &devices, const DataQuery &query) = 0; + + /** + * @brief Set identifier. + * @param accountId The accountId. + * @param appId The name of the application. + * @param storeId The name of kvstore. + * @param tagretDev target device list. + * @return Return SUCCESS for success, others for failure. + */ + virtual Status SetIdentifier(const std::string &accountId, const std::string &appId, + const std::string &storeId, const std::vector &tagretDev) + { + return Status::SUCCESS; + }; }; } // namespace DistributedKv } // namespace OHOS diff --git a/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h b/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h index 63fe563301b01296ae80a07dd73b48c1d4ec1ab2..5b471c64fd69a51f02bf929e7c598d9b3c246932 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/store_errno.h @@ -184,6 +184,11 @@ enum Status : int32_t { * The wal file size over limit. */ WAL_OVER_LIMITS = DISTRIBUTEDDATAMGR_ERR_OFFSET + 37, + + /** + * Session is opening. + */ + RATE_LIMIT = DISTRIBUTEDDATAMGR_ERR_OFFSET + 38, }; } // namespace OHOS::DistributedKv #endif // OHOS_DISTRIBUTED_DATA_INTERFACES_DISTRIBUTEDDATA_STORE_ERRNO_H diff --git a/kv_store/interfaces/innerkits/distributeddata/include/types.h b/kv_store/interfaces/innerkits/distributeddata/include/types.h index ce70a10edc31144244c362394ce10c788e954b71..05cda15ddcdf59768317368fa5d54c7ff50c769f 100644 --- a/kv_store/interfaces/innerkits/distributeddata/include/types.h +++ b/kv_store/interfaces/innerkits/distributeddata/include/types.h @@ -171,6 +171,7 @@ enum SubscribeType : uint32_t { * Both local changes and synced data changes. */ SUBSCRIBE_TYPE_ALL = 3, + }; /** @@ -244,6 +245,7 @@ enum KvStoreType : int32_t { * Not support type. */ MULTI_VERSION, + LOCAL_ONLY, INVALID_TYPE, }; @@ -251,6 +253,7 @@ enum KvStoreType : int32_t { * @brief Enumeration of database security level. */ enum SecurityLevel : int32_t { + INVALID_LABEL = -1, NO_LABEL, S0, S1, @@ -332,6 +335,25 @@ struct SyncPolicy { std::variant value; }; +/** + * @brief Role Type value. +*/ +enum RoleType : uint32_t { + /** + * The user has administrative rights. + */ + OWNER = 0, + /** + * The user has read-only permission. + */ + VISITOR, +}; + +struct Group { + std::string groupDir = ""; + std::string groupId = ""; +}; + /** * @brief Provide configuration information for database creation. */ @@ -372,7 +394,7 @@ struct Options { /** * Set database security level. */ - int32_t securityLevel = NO_LABEL; + int32_t securityLevel = INVALID_LABEL; /** * Set database directory area. */ @@ -404,8 +426,38 @@ struct Options { */ inline bool IsValidType() const { - return kvStoreType == KvStoreType::DEVICE_COLLABORATION || kvStoreType == KvStoreType::SINGLE_VERSION; + return kvStoreType == KvStoreType::DEVICE_COLLABORATION || kvStoreType == KvStoreType::SINGLE_VERSION || + kvStoreType == KvStoreType::LOCAL_ONLY; + } + /** + * Get the databaseDir. + */ + inline std::string GetDatabaseDir() const + { + if (baseDir.empty()) { + return group.groupDir; + } + return !group.groupDir.empty() ? "" : baseDir; } + /** + * Whether the databaseDir is valid. + */ + inline bool IsPathValid() const + { + if ((baseDir.empty() && group.groupDir.empty()) || (!baseDir.empty() && !group.groupDir.empty())) { + return false; + } + return true; + } + Group group; + /** + * Set database role. + */ + RoleType role; + /** + * Whether the sync happend in client. + */ + bool isClientSync = false; }; /** diff --git a/kv_store/kvstoremock/distributeddb/BUILD.gn b/kv_store/kvstoremock/distributeddb/BUILD.gn index a35db118ce1e85b37af9a37640d32e169a131c01..ee9eeba78353bba3b9ff264a8d9ee8e5723e9060 100644 --- a/kv_store/kvstoremock/distributeddb/BUILD.gn +++ b/kv_store/kvstoremock/distributeddb/BUILD.gn @@ -22,8 +22,14 @@ distrdb_Dir = [ "${kv_store_distributeddb_path}common/include", "${kv_store_distributeddb_path}common/include/relational", "${kv_store_distributeddb_path}communicator/include", + "${kv_store_distributeddb_path}gaussdb_rd", + "${kv_store_distributeddb_path}gaussdb_rd/include", + "${kv_store_distributeddb_path}gaussdb_rd/include/grd_base", + "${kv_store_distributeddb_path}gaussdb_rd/include/grd_document", + "${kv_store_distributeddb_path}gaussdb_rd/include/grd_kv", "${kv_store_distributeddb_path}storage/include", "${kv_store_distributeddb_path}storage/src", + "${kv_store_distributeddb_path}storage/src/gaussdb_rd", "${kv_store_distributeddb_path}storage/src/multiver", "${kv_store_distributeddb_path}storage/src/operation", "${kv_store_distributeddb_path}storage/src/sqlite", @@ -31,6 +37,13 @@ distrdb_Dir = [ "${kv_store_distributeddb_path}storage/src/upgrader", "${kv_store_distributeddb_path}syncer/include", "${kv_store_distributeddb_path}syncer/src", + "${kv_store_distributeddb_path}gaussdb_rd/src/common/include", + "${kv_store_distributeddb_path}gaussdb_rd/src/executor/include", + "${kv_store_distributeddb_path}gaussdb_rd/src/executor/document", + "${kv_store_distributeddb_path}gaussdb_rd/src/oh_adapter/include", + "${kv_store_distributeddb_path}gaussdb_rd/src/oh_adapter/src", + "${kv_store_distributeddb_path}gaussdb_rd/src/interface/include", + "//third_party/openssl/include/", "//third_party/bounds_checking_function/include", ] @@ -54,6 +67,9 @@ config("distrdb_public_config") { "${kv_store_distributeddb_path}interfaces/include", "${kv_store_distributeddb_path}interfaces/include/relational", "${kv_store_distributeddb_path}include", + "${kv_store_distributeddb_path}gaussdb_rd/include/grd_base", + "${kv_store_distributeddb_path}gaussdb_rd/include/grd_document", + "${kv_store_distributeddb_path}gaussdb_rd/include/grd_kv", ] } @@ -80,6 +96,7 @@ config("distrdb_config") { "EVLOOP_TIMER_ONLY", "USING_PRINTF_LOGGER", "OPENSSL_SUPPRESS_DEPRECATED", + "OMIT_cJSON", ] if (use_platform_win) { defines += [ "OS_TYPE_WINDOWS" ] @@ -91,6 +108,7 @@ config("distrdb_config") { ohos_shared_library("distributeddb_mock") { cflags_cc = [ "-std=c++17" ] sources = distrdb_sources + sources += distributeddb_src_rd configs = [ ":distrdb_config" ] public_configs = [ ":distrdb_public_config" ] ldflags = [ "-v" ] diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h index 831e60a5fc443bfe692806a85b46272029090acd..1c2d1efdd026f4eb336036b68fc37e2b86c526df 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/include/single_store_impl.h @@ -76,6 +76,8 @@ public: const std::vector &remote) const override; Status SubscribeWithQuery(const std::vector &devices, const DataQuery &query) override; Status UnsubscribeWithQuery(const std::vector &devices, const DataQuery &query) override; + Status SetIdentifier(const std::string &accountId, const std::string &appId, + const std::string &storeId, const std::vector &tagretDev) override; private: static constexpr size_t MAX_VALUE_LENGTH = 4 * 1024 * 1024; static constexpr size_t MAX_OBSERVER_SIZE = 8; diff --git a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp index cf5439e7cd6540be983c9a192483938d8f05e2db..8bfc7dc8b1be62ac9c9544a09a666f865db40599 100644 --- a/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp +++ b/kv_store/kvstoremock/frameworks/innerkitsimpl/kvdb/src/single_store_impl.cpp @@ -459,4 +459,9 @@ Status SingleStoreImpl::UnsubscribeWithQuery(const std::vector &dev { return SERVER_UNAVAILABLE; } +Status SingleStoreImpl::SetIdentifier(const std::string &accountId, const std::string &appId, + const std::string &storeId, const std::vector &tagretDev) +{ + return SERVER_UNAVAILABLE; +} } // namespace OHOS::DistributedKv \ No newline at end of file diff --git a/kv_store/test/distributedtest/single_kvstore_client/distributed_test.cpp b/kv_store/test/distributedtest/single_kvstore_client/distributed_test.cpp index f26150d5e7dd990248f6e94b37111d6d551455ea..1f69b58cc7f371856c3296a0a52562102534508a 100644 --- a/kv_store/test/distributedtest/single_kvstore_client/distributed_test.cpp +++ b/kv_store/test/distributedtest/single_kvstore_client/distributed_test.cpp @@ -97,6 +97,7 @@ void DistributedTest::SetUpTestCase() Options options = { .createIfMissing = true, .encrypt = false, .autoSync = false, .kvStoreType = KvStoreType::SINGLE_VERSION }; options.area = EL1; + options.securityLevel = S1; options.baseDir = std::string("/data/service/el1/public/database/odmf"); AppId appId = { "odmf" }; StoreId storeId = { "student" }; diff --git a/kv_store/test/distributedtest/single_kvstore_client/distributed_test_agent.cpp b/kv_store/test/distributedtest/single_kvstore_client/distributed_test_agent.cpp index 66c0a2acc49e30fa13f7c9d855a0e88fc16b0b45..ceca347ddd92dce30e1cc2b2995c36239bcbe9ba 100644 --- a/kv_store/test/distributedtest/single_kvstore_client/distributed_test_agent.cpp +++ b/kv_store/test/distributedtest/single_kvstore_client/distributed_test_agent.cpp @@ -111,6 +111,7 @@ bool DistributedTestAgent::SetUp() Options options = { .createIfMissing = true, .encrypt = false, .autoSync = false, .kvStoreType = KvStoreType::SINGLE_VERSION }; options.area = EL1; + options.securityLevel = S1; options.baseDir = std::string("/data/service/el1/public/database/odmf"); AppId appId = { "odmf" }; StoreId storeId = { "student" }; diff --git a/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp b/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp index 5729e237bb18b43902ccf467678e71530339d45a..55c8df5582380c20fe42de510ffa8bfb996286f2 100644 --- a/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp +++ b/kv_store/test/fuzztest/devicekvstore_fuzzer/devicekvstore_fuzzer.cpp @@ -64,6 +64,7 @@ void SetUpTestCase(void) .createIfMissing = true, .encrypt = false, .autoSync = true, + .securityLevel = S1, .kvStoreType = KvStoreType::DEVICE_COLLABORATION }; options.area = EL1; diff --git a/kv_store/test/fuzztest/singlekvstore_fuzzer/singlekvstore_fuzzer.cpp b/kv_store/test/fuzztest/singlekvstore_fuzzer/singlekvstore_fuzzer.cpp index 1e246c08e45dd652695d4ee7b577e506079dd7a1..a2d45d1b1b0ca5a1dc56c1ebf50b5de6ee297b06 100644 --- a/kv_store/test/fuzztest/singlekvstore_fuzzer/singlekvstore_fuzzer.cpp +++ b/kv_store/test/fuzztest/singlekvstore_fuzzer/singlekvstore_fuzzer.cpp @@ -62,10 +62,13 @@ void DeviceSyncCallbackTestImpl::SyncCompleted(const std::map -#include #include "uri.h" #include "uri_permission_manager_interface.h" @@ -27,62 +26,95 @@ namespace AAFwk { using ClearProxyCallback = std::function; class UriPermissionManagerClient { public: - static UriPermissionManagerClient& GetInstance(); - ~UriPermissionManagerClient() = default; + static UriPermissionManagerClient& GetInstance(); + ~UriPermissionManagerClient() = default; - /** - * @brief Authorize the uri permission of to targetBundleName. - * - * @param uri The file uri. - * @param flag Want::FLAG_AUTH_READ_URI_PERMISSION or Want::FLAG_AUTH_WRITE_URI_PERMISSION. - * @param targetBundleName The user of uri. - * @param autoremove the uri is temperarily or not - */ - int GrantUriPermission(const Uri &uri, unsigned int flag, - const std::string targetBundleName, int autoremove); + /** + * @brief Authorize the uri permission of to targetBundleName. + * + * @param uri The file uri. + * @param flag Want::FLAG_AUTH_READ_URI_PERMISSION or Want::FLAG_AUTH_WRITE_URI_PERMISSION. + * @param targetBundleName The user of uri. + */ + int GrantUriPermission(const Uri &uri, unsigned int flag, const std::string targetBundleName, int32_t appIndex = 0); - /** - * @brief Clear user's uri authorization record with auto remove flag. - * - * @param tokenId A tokenId of an application. - */ - void RevokeUriPermission(const Security::AccessToken::AccessTokenID tokenId); + /** + * @brief Authorize the uri permission of to targetBundleName. + * + * @param uriVec The file uri list. + * @param flag Want::FLAG_AUTH_READ_URI_PERMISSION or Want::FLAG_AUTH_WRITE_URI_PERMISSION. + * @param targetBundleName The user of uri. + */ + int GrantUriPermission(const std::vector &uriVec, unsigned int flag, + const std::string targetBundleName, int32_t appIndex = 0); - /** - * @brief Clear user's uri authorization record. - * - * @param uri The file uri. - * @param BundleName A BundleName of an application. - */ - int RevokeUriPermissionManually(const Uri &uri, const std::string bundleName); + /** + * @brief Clear user's uri authorization record with auto remove flag. + * + * @param tokenId A tokenId of an application. + */ + void RevokeUriPermission(const Security::AccessToken::AccessTokenID tokenId); - void OnLoadSystemAbilitySuccess(const sptr &remoteObject); - void OnLoadSystemAbilityFail(); + /** + * @brief Clear user's all uri authorization record with auto remove flag. + * + * @param tokenId A tokenId of an application. + */ + int RevokeAllUriPermissions(const Security::AccessToken::AccessTokenID tokenId); + + /** + * @brief Clear user's uri authorization record. + * + * @param uri The file uri. + * @param BundleName A BundleName of an application. + */ + int RevokeUriPermissionManually(const Uri &uri, const std::string bundleName); + + /** + * @brief check if caller can grant persistable uri permission + * + * @param uri The file uri. + * @param flag Want::FLAG_AUTH_READ_URI_PERMISSION or Want::FLAG_AUTH_WRITE_URI_PERMISSION. + * @param tokenId A tokenId of an application. + */ + bool CheckPersistableUriPermissionProxy(const Uri& uri, uint32_t flag, uint32_t tokenId); + + /** + * @brief verify if tokenId have uri permission of flag, including temporary permission and persistable permission + * + * @param uri The file uri. + * @param flag Want::FLAG_AUTH_READ_URI_PERMISSION or Want::FLAG_AUTH_WRITE_URI_PERMISSION. + * @param tokenId A tokenId of an application. + */ + bool VerifyUriPermission(const Uri& uri, uint32_t flag, uint32_t tokenId); + + void OnLoadSystemAbilitySuccess(const sptr &remoteObject); + void OnLoadSystemAbilityFail(); private: - UriPermissionManagerClient() = default; - sptr ConnectUriPermService(); - void ClearProxy(); - bool LoadUriPermService(); - void SetUriPermMgr(const sptr &remoteObject); - sptr GetUriPermMgr(); - DISALLOW_COPY_AND_MOVE(UriPermissionManagerClient); + UriPermissionManagerClient() = default; + sptr ConnectUriPermService(); + void ClearProxy(); + bool LoadUriPermService(); + void SetUriPermMgr(const sptr &remoteObject); + sptr GetUriPermMgr(); + DISALLOW_COPY_AND_MOVE(UriPermissionManagerClient); - class UpmsDeathRecipient : public IRemoteObject::DeathRecipient { - public: - explicit UpmsDeathRecipient(const ClearProxyCallback &proxy) : proxy_(proxy) {} - ~UpmsDeathRecipient() = default; - virtual void OnRemoteDied([[maybe_unused]] const wptr& remote) override; + class UpmsDeathRecipient : public IRemoteObject::DeathRecipient { + public: + explicit UpmsDeathRecipient(const ClearProxyCallback &proxy) : proxy_(proxy) {} + ~UpmsDeathRecipient() = default; + virtual void OnRemoteDied([[maybe_unused]] const wptr& remote) override; - private: - ClearProxyCallback proxy_; - }; + private: + ClearProxyCallback proxy_; + }; private: - std::mutex mutex_; - std::mutex saLoadMutex_; - std::condition_variable loadSaVariable_; - bool saLoadFinished_ = false; - sptr uriPermMgr_ = nullptr; + std::mutex mutex_; + std::mutex saLoadMutex_; +// std::condition_variable loadSaVariable_; + bool saLoadFinished_ = false; + sptr uriPermMgr_ = nullptr; }; } // namespace AAFwk } // namespace OHOS diff --git a/mock/innerkits/appexecfwk_base/include/module_info.h b/mock/innerkits/appexecfwk_base/include/module_info.h index ad280f9d638aab141863910502c3955ab0558a5b..67a614c7e499b548fdabff6f92cf51f67be7f769 100644 --- a/mock/innerkits/appexecfwk_base/include/module_info.h +++ b/mock/innerkits/appexecfwk_base/include/module_info.h @@ -22,6 +22,13 @@ namespace OHOS { namespace AppExecFwk { +enum ProfileType { + INTENT_PROFILE = 1, + ADDITION_PROFILE = 2, + NETWORK_PROFILE = 3, + UTD_SDT_PROFILE = 4 +}; + // stores module information about an application struct ModuleInfo : public Parcelable { std::string moduleName; // the "name" in module part in config.json diff --git a/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h b/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h index ad77c945963914c91534055552a1d0244e9d4780..b46fa015f014187710892f5bab6dabb3261ead9b 100644 --- a/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h +++ b/mock/innerkits/appexecfwk_core/include/bundlemgr/bundle_mgr_interface.h @@ -32,6 +32,7 @@ #include "form_info.h" #include "hap_module_info.h" #include "module_usage_record.h" +#include "module_info.h" #include "permission_define.h" #ifdef BUNDLE_FRAMEWORK_GRAPHICS #include "pixel_map.h" @@ -902,6 +903,13 @@ public: return false; } + virtual ErrCode GetJsonProfile(ProfileType profileType, const std::string &bundleName, + const std::string &moduleName, std::string &profile, int32_t userId = Constants::UNSPECIFIED_USERID) + { + return 0; + } + + virtual bool CheckAbilityEnableInstall( const Want &want, int32_t missionId, int32_t userId, const sptr &callback) { diff --git a/mock/src/mock_account.cpp b/mock/src/mock_account.cpp index 46055a0f05567117172aa2df0ec764f8f1d091c6..ad0cdd26bd9d76e6caad300aba360150ea4d58bc 100644 --- a/mock/src/mock_account.cpp +++ b/mock/src/mock_account.cpp @@ -47,6 +47,10 @@ ErrCode OsAccountManager::IsOsAccountActived(const int id, bool &isOsAccountActi isOsAccountActived = (id == 0 || id == 100); return ERR_OK; } +ErrCode OsAccountManager::IsOsAccountVerified(const int id, bool& isVerified) +{ + return ERR_OK; +} } std::pair OhosAccountKitsImpl::QueryOhosAccountInfo() { diff --git a/mock/src/mock_notification.cpp b/mock/src/mock_notification.cpp index 5951fef57734a9708754ddd2b8dfccc614a39d10..e2391d310ff3afd6b1170946ec07c89083eb4356 100644 --- a/mock/src/mock_notification.cpp +++ b/mock/src/mock_notification.cpp @@ -190,14 +190,27 @@ CommonEventSubscriber::CommonEventSubscriber() {} CommonEventSubscriber::CommonEventSubscriber(const CommonEventSubscribeInfo &subscribeInfo) {} CommonEventSubscriber::~CommonEventSubscriber() {} const std::string CommonEventSupport::COMMON_EVENT_USER_REMOVED = "COMMON_EVENT_USER_REMOVED"; +const std::string CommonEventSupport::COMMON_EVENT_USER_UNLOCKED = "COMMON_EVENT_USER_UNLOCKED"; +const std::string CommonEventSupport::COMMON_EVENT_USER_STOPPED = "COMMON_EVENT_USER_STOPPED"; const std::string CommonEventSupport::COMMON_EVENT_HWID_TOKEN_INVALID = "COMMON_EVENT_HWID_TOKEN_INVALID"; const std::string CommonEventSupport::COMMON_EVENT_HWID_LOGOUT = "COMMON_EVENT_HWID_LOGOUT"; const std::string CommonEventSupport::COMMON_EVENT_HWID_LOGIN = "COMMON_EVENT_HWID_LOGIN"; +const std::string CommonEventSupport::COMMON_EVENT_PACKAGE_ADDED = "COMMON_EVENT_PACKAGE_ADDED"; const std::string CommonEventSupport::COMMON_EVENT_PACKAGE_REMOVED = "COMMON_EVENT_PACKAGE_REMOVED"; const std::string CommonEventSupport::COMMON_EVENT_PACKAGE_CHANGED = "COMMON_EVENT_PACKAGE_CHANGED"; +const std::string CommonEventSupport::COMMON_EVENT_USER_STARTED = "COMMON_EVENT_USER_STARTED"; const std::string CommonEventSupport::COMMON_EVENT_USER_SWITCHED = "COMMON_EVENT_USER_SWITCHED"; +const std::string CommonEventSupport::COMMON_EVENT_UID_REMOVED = "COMMON_EVENT_UID_REMOVED"; +const std::string CommonEventSupport::COMMON_EVENT_LOCALE_CHANGED = "COMMON_EVENT_LOCALE_CHANGED"; const std::string CommonEventSupport::COMMON_EVENT_SANDBOX_PACKAGE_REMOVED = "COMMON_EVENT_SANDBOX_PACKAGE_REMOVED"; +const std::string CommonEventSupport::COMMON_EVENT_DRIVE_MODE = "COMMON_EVENT_DRIVE_MODE"; +const std::string CommonEventSupport::COMMON_EVENT_HOME_MODE = "COMMON_EVENT_HOME_MODE"; +const std::string CommonEventSupport::COMMON_EVENT_BOOT_COMPLETED = "COMMON_EVENT_BOOT_COMPLETED"; +const std::string CommonEventSupport::COMMON_EVENT_BATTERY_CHANGED = "COMMON_EVENT_BATTERY_CHANGED"; +const std::string CommonEventSupport::COMMON_EVENT_POWER_CONNECTED = "COMMON_EVENT_POWER_CONNECTED"; +const std::string CommonEventSupport::COMMON_EVENT_TIME_TICK = "COMMON_EVENT_TIME_TICK"; const std::string CommonEventSupport::COMMON_EVENT_TIME_CHANGED = "COMMON_EVENT_TIME_CHANGED"; +const std::string CommonEventSupport::COMMON_EVENT_DATE_CHANGED = "COMMON_EVENT_DATE_CHANGED"; const std::string CommonEventSupport::COMMON_EVENT_TIMEZONE_CHANGED = "COMMON_EVENT_TIMEZONE_CHANGED"; bool CommonEventSubscribeInfo::Marshalling(OHOS::Parcel &) const { return true; } CommonEventSubscribeInfo::CommonEventSubscribeInfo(const CommonEventSubscribeInfo &commonEventSubscribeInfo) {} diff --git a/preferences/frameworks/js/napi/common/include/js_utils.h b/preferences/frameworks/js/napi/common/include/js_utils.h index 1b15d858cc3574ba757b940b618cccb76d559702..d2b31172fbf9355d31790022da33d8fc9f98c9e2 100644 --- a/preferences/frameworks/js/napi/common/include/js_utils.h +++ b/preferences/frameworks/js/napi/common/include/js_utils.h @@ -46,6 +46,7 @@ int32_t Convert2NativeValue(napi_env env, napi_value jsValue, float &output); int32_t Convert2NativeValue(napi_env env, napi_value jsValue, double &output); int32_t Convert2NativeValue(napi_env env, napi_value jsValue, int32_t &output); int32_t Convert2NativeValue(napi_env env, napi_value jsValue, int64_t &output); +int32_t Convert2NativeValue(napi_env env, napi_value jsValue, std::vector &output); int32_t Convert2NativeValue(napi_env env, napi_value jsValue, std::string &output); int32_t Convert2NativeValue(napi_env env, napi_value jsValue, std::monostate &value); @@ -60,6 +61,7 @@ napi_value Convert2JSValue(napi_env env, uint32_t value); napi_value Convert2JSValue(napi_env env, bool value); napi_value Convert2JSValue(napi_env env, float value); napi_value Convert2JSValue(napi_env env, double value); +napi_value Convert2JSValue(napi_env env, const std::vector &value); napi_value Convert2JSValue(napi_env env, const std::string &value); napi_value Convert2JSValue(napi_env env, const std::monostate &value); diff --git a/preferences/frameworks/js/napi/common/src/js_utils.cpp b/preferences/frameworks/js/napi/common/src/js_utils.cpp index 54edff72327ccc2fa2491d0742b7c23624488432..7b10e6ef73cdeb8f256b5f9e3c8577877adcfad9 100644 --- a/preferences/frameworks/js/napi/common/src/js_utils.cpp +++ b/preferences/frameworks/js/napi/common/src/js_utils.cpp @@ -32,7 +32,7 @@ int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, std::stri return napi_invalid_arg; } if (bufferSize > MAX_VALUE_LENGTH) { - LOG_ERROR("get std::string maximum length."); + LOG_ERROR("string must be less than the limit length."); return EXCEED_MAX_LENGTH; } char *buffer = (char *)malloc(bufferSize + 1); @@ -93,6 +93,38 @@ int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, int64_t & return napi_invalid_arg; } +int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, std::vector &output) +{ + bool isTypedarray = false; + napi_status result = napi_is_typedarray(env, jsValue, &isTypedarray); + if (result != napi_ok || !isTypedarray) { + LOG_ERROR("napi_is_typedarray fail"); + return napi_invalid_arg; + } + napi_typedarray_type type = napi_uint8_array; + size_t length = 0; + void *data = nullptr; + result = napi_get_typedarray_info(env, jsValue, &type, &length, &data, nullptr, nullptr); + if (result != napi_ok) { + LOG_ERROR("napi_get_typedarray_info fail"); + return napi_invalid_arg; + } + if (type != napi_uint8_array) { + LOG_ERROR("value is not napi_uint8_array"); + return napi_invalid_arg; + } + if (length > MAX_VALUE_LENGTH) { + LOG_ERROR("unit8Array must be less than the limit length."); + return EXCEED_MAX_LENGTH; + } + output.clear(); + if (length > 0) { + output.resize(length); + output.assign(static_cast(data), static_cast(data) + length); + } + return napi_ok; +} + int32_t JSUtils::Convert2NativeValue(napi_env env, napi_value jsValue, std::monostate &value) { napi_value tempValue; @@ -185,9 +217,31 @@ napi_value JSUtils::Convert2JSValue(napi_env env, float value) return jsValue; } +napi_value JSUtils::Convert2JSValue(napi_env env, const std::vector &value) +{ + size_t size = value.size(); + void *data = nullptr; + napi_value buffer = nullptr; + napi_status ret = napi_create_arraybuffer(env, size, &data, &buffer); + if (ret != napi_ok) { + LOG_ERROR("napi_create_arraybuffer failed %{public}d", ret); + return nullptr; + } + if (size != 0) { + std::copy(value.begin(), value.end(), static_cast(data)); + } + napi_value napiValue = nullptr; + ret = napi_create_typedarray(env, napi_uint8_array, size, buffer, 0, &napiValue); + if (ret != napi_ok) { + LOG_ERROR("napi_create_typedarray failed %{public}d", ret); + return nullptr; + } + return napiValue; +} + napi_value JSUtils::Convert2JSValue(napi_env env, const std::string &value) { - napi_value jsValue; + napi_value jsValue = nullptr; if (napi_create_string_utf8(env, value.c_str(), value.size(), &jsValue) != napi_ok) { LOG_DEBUG("Convert std::string failed"); return nullptr; diff --git a/preferences/frameworks/js/napi/preferences/BUILD.gn b/preferences/frameworks/js/napi/preferences/BUILD.gn index db122862394004d80bd660d120fc39f4a5081742..c142313324a7dd87b7e34f1fdddb2d6e7c0c2613 100644 --- a/preferences/frameworks/js/napi/preferences/BUILD.gn +++ b/preferences/frameworks/js/napi/preferences/BUILD.gn @@ -40,6 +40,12 @@ if (is_ohos) { } ohos_shared_library("preferences") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = base_include sources = base_sources sources += [ "${preferences_napi_path}/common/src/js_ability.cpp" ] diff --git a/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp b/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp index 2369c30af6d67bdf7cf57720137624315069462a..b57b1d7394f37136d4e717829f2df3aba2e878b0 100644 --- a/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp +++ b/preferences/frameworks/js/napi/preferences/src/napi_preferences.cpp @@ -148,7 +148,7 @@ int ParseKey(napi_env env, const napi_value arg, std::shared_ptrkey); PRE_CHECK_RETURN_ERR_SET(rc == napi_ok, std::make_shared("value", "string.")); PRE_CHECK_RETURN_ERR_SET(context->key.length() <= MAX_KEY_LENGTH, - std::make_shared("value", "less than 80 bytes.")); + std::make_shared("key", "less than 80 bytes.")); return OK; } diff --git a/preferences/frameworks/js/napi/storage/BUILD.gn b/preferences/frameworks/js/napi/storage/BUILD.gn index 80866979d47b94eefd150eec32c74b7b98807b7c..503618f0904218df3b65f4cfad9c9c32f2239148 100644 --- a/preferences/frameworks/js/napi/storage/BUILD.gn +++ b/preferences/frameworks/js/napi/storage/BUILD.gn @@ -26,6 +26,12 @@ if (!is_mingw && !is_mac) { } ohos_shared_library("storage") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "include", "../common/include", diff --git a/preferences/frameworks/js/napi/storage/src/napi_storage.cpp b/preferences/frameworks/js/napi/storage/src/napi_storage.cpp index aefcebbf812003c8c92c3bccc13e787d0f8e66b7..f7e844e1cb89d2b4e7966dad97cd1f8546392bd7 100644 --- a/preferences/frameworks/js/napi/storage/src/napi_storage.cpp +++ b/preferences/frameworks/js/napi/storage/src/napi_storage.cpp @@ -269,7 +269,7 @@ int ParseKey(const napi_env env, const napi_value arg, std::shared_ptr MAX_KEY_LENGTH) { LOG_ERROR("the length of the key is over maximum length."); - std::shared_ptr paramError = std::make_shared("value", "less than 80 bytes."); + std::shared_ptr paramError = std::make_shared("key", "less than 80 bytes."); asyncContext->SetError(paramError); return ERR; } diff --git a/preferences/frameworks/js/napi/system_storage/BUILD.gn b/preferences/frameworks/js/napi/system_storage/BUILD.gn index eb1f8a6bb10ff66779b22b071c9ba0dae5a25972..2f386e6fd15e7113695c3517be66fbc990a0db8b 100644 --- a/preferences/frameworks/js/napi/system_storage/BUILD.gn +++ b/preferences/frameworks/js/napi/system_storage/BUILD.gn @@ -26,6 +26,12 @@ if (!is_mingw && !is_mac) { } ohos_shared_library("storage_napi") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } include_dirs = [ "include", "../common/include", diff --git a/datamgr_service/test/fuzztest/autolaunch_fuzzer/autolaunch_fuzzer.h b/preferences/frameworks/native/include/base64_helper.h similarity index 52% rename from datamgr_service/test/fuzztest/autolaunch_fuzzer/autolaunch_fuzzer.h rename to preferences/frameworks/native/include/base64_helper.h index c18cb9c4e0f2d1386914669e18c2b3315fa04780..9c8c684b8f4795a2686b6ae4cd842067a81501b6 100644 --- a/datamgr_service/test/fuzztest/autolaunch_fuzzer/autolaunch_fuzzer.h +++ b/preferences/frameworks/native/include/base64_helper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -13,10 +13,20 @@ * limitations under the License. */ -#ifndef AUTOLAUNCH_FUZZER_H -#define AUTOLAUNCH_FUZZER_H +#ifndef PREFERENCES_FRAMEWORKS_BASE64_HELPER_H +#define PREFERENCES_FRAMEWORKS_BASE64_HELPER_H -#define FUZZ_PROJECT_NAME "AutoLaunch_fuzzer" +#include +#include -#endif // AUTOLAUNCH_FUZZER_H +namespace OHOS { +namespace NativePreferences { +class Base64Helper { +public: + static std::string Encode(const std::vector &input); + static bool Decode(const std::string &input, std::vector &output); +}; +} // namespace NativePreferences +} // namespace OHOS +#endif // PREFERENCES_FRAMEWORKS_EXECUTOR_POOL_H \ No newline at end of file diff --git a/preferences/frameworks/native/include/executor_pool.h b/preferences/frameworks/native/include/executor_pool.h index 76862e703b8c01c42d75f2501bd7352b338f683d..7070bcb1ac01e62c71db5a4b951203c4e21279e4 100644 --- a/preferences/frameworks/native/include/executor_pool.h +++ b/preferences/frameworks/native/include/executor_pool.h @@ -77,6 +77,7 @@ public: TaskId Execute(Task task) { if (poolStatus != Status::RUNNING) { + LOG_ERROR("execute task failed."); return INVALID_TASK_ID; } diff --git a/preferences/frameworks/native/include/preferences_impl.h b/preferences/frameworks/native/include/preferences_impl.h index f2275bafc167fded4c30ea3ca8ff73ede0d37caa..b5524f488579206bd025bd786fc47a6903c08546 100644 --- a/preferences/frameworks/native/include/preferences_impl.h +++ b/preferences/frameworks/native/include/preferences_impl.h @@ -175,7 +175,6 @@ private: bool isSyncRequest_; int64_t memoryStateGeneration_; std::map writeToDiskMap_; - std::mutex reqMutex_; std::condition_variable reqCond_; std::list keysModified_; std::vector> localObservers_; diff --git a/preferences/frameworks/native/include/priority_queue.h b/preferences/frameworks/native/include/priority_queue.h index a93232bd31df8148950c82004f391e1d578253a8..115031d32bad9a5c310006aae199facf204f2304 100644 --- a/preferences/frameworks/native/include/priority_queue.h +++ b/preferences/frameworks/native/include/priority_queue.h @@ -15,7 +15,6 @@ #ifndef PREFERENCES_PRIORITY_QUEUE_H #define PREFERENCES_PRIORITY_QUEUE_H -#include #include #include #include diff --git a/preferences/frameworks/native/src/base64_helper.cpp b/preferences/frameworks/native/src/base64_helper.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4a0c936879660926f8971f64a5a42f7217de4500 --- /dev/null +++ b/preferences/frameworks/native/src/base64_helper.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "base64_helper.h" +#include +#include "log_print.h" + +namespace OHOS { +namespace NativePreferences { +static const uint8_t base64Encoder[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const char base64Decoder[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +const uint32_t BASE64_DEST_UNIT_SIZE = 4; +const uint32_t BASE64_SRC_UNIT_SIZE = 3; +const uint32_t BASE64_ONE_PADDING = 1; +const uint32_t BASE64_TWO_PADDING = 2; +const uint8_t BASE64_INVALID = 0xFF; +const uint8_t BASE64_MASK1 = 0x03; +const uint8_t BASE64_MASK2 = 0x0F; +const uint8_t BASE64_MASK3 = 0x3F; +const uint8_t BASE64_SHIFT_HIBYTE = 2; +const uint8_t BASE64_SHIFT = 4; +const uint8_t BASE64_SHIFT_LOBYTE = 6; + +std::string Base64Helper::Encode(const std::vector &input) +{ + std::string result = ""; + uint32_t index = 0; + uint8_t code = 0; + for (uint32_t len = input.size(); len > 0; len -= BASE64_SRC_UNIT_SIZE) { + result += base64Encoder[input.at(index) >> BASE64_SHIFT_HIBYTE]; + code = (input.at(index++) & BASE64_MASK1) << BASE64_SHIFT; + if (len > BASE64_ONE_PADDING) { + result += base64Encoder[code | (input.at(index) >> BASE64_SHIFT)]; + code = (input.at(index++) & BASE64_MASK2) << BASE64_SHIFT_HIBYTE; + if (len > BASE64_TWO_PADDING) { + result += base64Encoder[code | (input.at(index) >> BASE64_SHIFT_LOBYTE)]; + result += base64Encoder[input.at(index++) & BASE64_MASK3]; + } else { + result += base64Encoder[code]; + result += "="; + break; + } + } else { + result += base64Encoder[code]; + result += "=="; + break; + } + } + return result; +} + +bool Base64Helper::Decode(const std::string &input, std::vector &output) +{ + if (input.length() % BASE64_DEST_UNIT_SIZE != 0) { + return false; + } + uint8_t ch1 = 0; + uint8_t ch2 = 0; + uint8_t ch3 = 0; + uint8_t ch4 = 0; + uint32_t index = 0; + std::vector result {}; + while (index < input.length()) { + ch1 = base64Decoder[static_cast(input.at(index++))]; + ch2 = base64Decoder[static_cast(input.at(index++))]; + if (ch1 == BASE64_INVALID || ch2 == BASE64_INVALID) { + return false; + } + result.emplace_back((ch1 << BASE64_SHIFT_HIBYTE) | (ch2 >> BASE64_SHIFT)); + if (input.at(index) == '=') { + break; + } + ch3 = base64Decoder[static_cast(input.at(index++))]; + if (ch3 == BASE64_INVALID) { + return false; + } + result.emplace_back((ch2 << BASE64_SHIFT) | (ch3 >> BASE64_SHIFT_HIBYTE)); + if (input.at(index) == '=') { + break; + } + ch4 = base64Decoder[static_cast(input.at(index++))]; + if (ch4 == BASE64_INVALID) { + return false; + } + result.emplace_back((ch3 << BASE64_SHIFT_LOBYTE) | ch4); + } + output = result; + return true; +} +} // End of namespace NativePreferences +} // End of namespace OHOS diff --git a/preferences/frameworks/native/src/preferences_impl.cpp b/preferences/frameworks/native/src/preferences_impl.cpp index 1739754653510351d409ccb29a67495717318b90..72ddb68e7a6af92df32b4245c8c4d406dfc39d21 100644 --- a/preferences/frameworks/native/src/preferences_impl.cpp +++ b/preferences/frameworks/native/src/preferences_impl.cpp @@ -22,6 +22,7 @@ #include #include +#include "base64_helper.h" #include "executor_pool.h" #include "log_print.h" #include "preferences_errno.h" @@ -81,6 +82,11 @@ template<> std::string GetTypeName>() return "boolArray"; } +template<> std::string GetTypeName>() +{ + return "uint8Array"; +} + ExecutorPool PreferencesImpl::executorPool_ = ExecutorPool(1, 0); PreferencesImpl::PreferencesImpl(const Options &options) : loaded_(false), options_(options) @@ -154,6 +160,7 @@ void PreferencesImpl::AwaitLoadFile() void PreferencesImpl::WriteToDiskFile(std::shared_ptr pref, std::shared_ptr mcr) { + std::unique_lock lock(pref->mutex_); if (!pref->CheckRequestValidForStateGeneration(mcr)) { mcr->SetDiskWriteResult(true, E_OK); return; @@ -229,6 +236,13 @@ template bool GetPrefValue(const Element &element, T &value) return false; } +static void Convert2PrefValue(const Element &element, std::vector &value) +{ + if (!Base64Helper::Decode(element.value_, value)) { + value.clear(); + } +} + template bool GetPrefValue(const Element &element, T &value) { if (element.tag_ == GetTypeName()) { @@ -288,6 +302,12 @@ template void Convert2Element(Element &elem, const std::vector &v } } +void Convert2Element(Element &elem, const std::vector &value) +{ + elem.tag_ = GetTypeName>(); + elem.value_ = Base64Helper::Encode(value); +} + template void GetElement(Element &elem, const T &value) { LOG_WARN("unknown element type. the key is %{public}s", elem.key_.c_str()); @@ -407,7 +427,6 @@ int PreferencesImpl::Put(const std::string &key, const PreferencesValue &value) return errCode; } } - AwaitLoadFile(); std::lock_guard lock(mutex_); @@ -419,7 +438,6 @@ int PreferencesImpl::Put(const std::string &key, const PreferencesValue &value) return E_OK; } } - map_.insert_or_assign(key, value); modifiedKeys_.push_back(key); return E_OK; @@ -494,7 +512,6 @@ int PreferencesImpl::FlushSync() { std::shared_ptr request = commitToMemory(); request->isSyncRequest_ = true; - std::unique_lock lock(request->reqMutex_); PreferencesImpl::WriteToDiskFile(shared_from_this(), request); if (request->wasWritten_) { LOG_DEBUG("Successfully written to disk file, memory state generation is %{public}" PRId64 "", diff --git a/preferences/frameworks/native/src/preferences_value.cpp b/preferences/frameworks/native/src/preferences_value.cpp index 4034923d66b255d8b4828e00cf521e88ea4cc077..3dbe0cfe1ed477772a0204cdf4b7547d08b6597c 100644 --- a/preferences/frameworks/native/src/preferences_value.cpp +++ b/preferences/frameworks/native/src/preferences_value.cpp @@ -83,6 +83,11 @@ PreferencesValue::PreferencesValue(std::vector value) value_ = value; } +PreferencesValue::PreferencesValue(std::vector value) +{ + value_ = value; +} + PreferencesValue &PreferencesValue::operator=(PreferencesValue &&preferencesValue) noexcept { if (this == &preferencesValue) { @@ -136,6 +141,11 @@ bool PreferencesValue::IsDoubleArray() const return std::holds_alternative>(value_); } +bool PreferencesValue::IsUint8Array() const +{ + return std::holds_alternative>(value_); +} + bool PreferencesValue::IsStringArray() const { return std::holds_alternative>(value_); @@ -191,6 +201,11 @@ PreferencesValue::operator std::vector() const return std::get>(value_); } +PreferencesValue::operator std::vector() const +{ + return std::get>(value_); +} + bool PreferencesValue::operator==(const PreferencesValue &value) { return (this->value_ == value.value_); diff --git a/preferences/frameworks/native/src/preferences_xml_utils.cpp b/preferences/frameworks/native/src/preferences_xml_utils.cpp index 7e4168af6fd83cd360e39ef662a6329c06cf4c6b..5c18e60d0d60eaadffb0b56b15561b57a0c3aa42 100644 --- a/preferences/frameworks/native/src/preferences_xml_utils.cpp +++ b/preferences/frameworks/native/src/preferences_xml_utils.cpp @@ -163,7 +163,8 @@ bool ParseNodeElement(const xmlNode *node, Element &element) return ParsePrimitiveNodeElement(node, element); } - if (!xmlStrcmp(node->name, reinterpret_cast("string"))) { + if (!xmlStrcmp(node->name, reinterpret_cast("string")) + || !xmlStrcmp(node->name, reinterpret_cast("uint8Array"))) { return ParseStringNodeElement(node, element); } @@ -354,7 +355,7 @@ xmlNode *CreateElementNode(Element &element) return CreatePrimitiveNode(element); } - if (element.tag_.compare("string") == 0) { + if (element.tag_.compare("string") == 0 || element.tag_.compare("uint8Array") == 0) { return CreateStringNode(element); } diff --git a/preferences/interfaces/inner_api/BUILD.gn b/preferences/interfaces/inner_api/BUILD.gn index c1a7e6b6daeea03ce0c59ae690c175cab95306ec..833059024b59ea7efee4130fb87a6b40a09eaf92 100644 --- a/preferences/interfaces/inner_api/BUILD.gn +++ b/preferences/interfaces/inner_api/BUILD.gn @@ -45,6 +45,7 @@ config("adaptor_config") { base_sources = [ "${preferences_native_path}/platform/src/preferences_file_lock.cpp", "${preferences_native_path}/platform/src/preferences_thread.cpp", + "${preferences_native_path}/src/base64_helper.cpp", "${preferences_native_path}/src/preferences_helper.cpp", "${preferences_native_path}/src/preferences_impl.cpp", "${preferences_native_path}/src/preferences_observer.cpp", @@ -66,10 +67,19 @@ if (!is_ohos) { if (is_ohos) { ohos_shared_library("native_preferences") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } all_dependent_configs = [ ":native_preferences_public_config" ] sources = base_sources - innerapi_tags = [ "platformsdk" ] + innerapi_tags = [ + "platformsdk", + "sasdk", + ] configs = [ ":native_preferences_config" ] @@ -188,6 +198,14 @@ ohos_static_library("native_preferences_static") { "//third_party/libxml2:static_libxml2", ] } else { + if (is_ohos) { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + } deps = [ "//third_party/libxml2:libxml2" ] external_deps = [ "ability_base:zuri", diff --git a/preferences/interfaces/inner_api/include/preferences_value.h b/preferences/interfaces/inner_api/include/preferences_value.h index 0a4e3d1cea41fc2519e5031de752e9546963bcd2..2907e61498bd877f4e4598d5a46fe4f671c98e81 100644 --- a/preferences/interfaces/inner_api/include/preferences_value.h +++ b/preferences/interfaces/inner_api/include/preferences_value.h @@ -134,6 +134,15 @@ public: */ PREF_API_EXPORT PreferencesValue(std::vector value); + /** + * @brief Constructor. + * + * This constructor is used to convert the vector input parameter to a value of type PreferencesValue. + * + * @param value Indicates a vector input parameter. + */ + PREF_API_EXPORT PreferencesValue(std::vector value); + /** * @brief Move assignment operator overloaded function. */ @@ -207,6 +216,13 @@ public: */ PREF_API_EXPORT bool IsDoubleArray() const; + /** + * @brief Determines whether the uint8 array type PreferencesValue is currently used. + * + * @return Returning true means it is, false means it isn't. + */ + PREF_API_EXPORT bool IsUint8Array() const; + /** * @brief Type conversion function. * @@ -270,6 +286,13 @@ public: */ PREF_API_EXPORT operator std::vector() const; + /** + * @brief Type conversion function. + * + * @return Returns vector type PreferencesValue. + */ + PREF_API_EXPORT operator std::vector() const; + /** * @brief Overloaded operator "==". * @@ -282,8 +305,7 @@ public: PREF_API_EXPORT bool operator==(const PreferencesValue &value); std::variant, std::vector, - std::vector> - value_; + std::vector, std::vector> value_; }; } // End of namespace NativePreferences } // End of namespace OHOS diff --git a/preferences/test/js/unittest/preferences/src/PreferencesCallBackJsunit.test.js b/preferences/test/js/unittest/preferences/src/PreferencesCallBackJsunit.test.js index 175e25edb13d21e46b3f3782dd8873ee889a0542..236b9757f18590fa4230019795745e357c53f84b 100644 --- a/preferences/test/js/unittest/preferences/src/PreferencesCallBackJsunit.test.js +++ b/preferences/test/js/unittest/preferences/src/PreferencesCallBackJsunit.test.js @@ -13,7 +13,8 @@ * limitations under the License. */ import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' -import data_preferences from '@ohos.data.preferences' +import data_preferences from '@ohos.data.preferences'; +import util from '@ohos.util'; import featureAbility from '@ohos.ability.featureAbility'; const NAME = 'test_preferences'; @@ -25,6 +26,7 @@ const KEY_TEST_STRING_ELEMENT = 'key_test_string'; const KEY_TEST_NUMBER_ARRAY_ELEMENT = 'key_test_number_array'; const KEY_TEST_STRING_ARRAY_ELEMENT = 'key_test_string_array'; const KEY_TEST_BOOL_ARRAY_ELEMENT = 'key_test_bool_array'; +const KEY_TEST_UINT8ARRAY = 'key_test_uint8array'; var mPreferences; var context; @@ -196,6 +198,20 @@ describe('PreferencesCallBackJsunit', function () { }); }) + /** + * @tc.name get Uint8Array callback interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0140 + * @tc.desc get Uint8Array callback interface test + */ + it('testPreferencesGetUint8Array103', 0, async function (done) { + let uInt8Array = new util.TextEncoder().encodeInto("π\\n\\b@.(){},"); + await mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array); + mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0), function (err, ret) { + expect(uInt8Array.toString() === ret.toString()).assertTrue(); + done(); + }); + }) + /** * @tc.name put boolean callback interface test * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0080 @@ -330,6 +346,64 @@ describe('PreferencesCallBackJsunit', function () { }); }) + /** + * @tc.name put Uint8Array callback interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0080 + * @tc.desc put Uint8Array callback interface test + */ + it('testPreferencesPutUint8Array0182', 0, async function (done) { + let uInt8Array = new util.TextEncoder().encodeInto("qweasdzxc@#$%123"); + mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array, async function (err, ret) { + let pre = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + expect(uInt8Array.toString() === pre.toString()).assertTrue(); + await mPreferences.flush(); + await data_preferences.removePreferencesFromCache(context, NAME); + mPreferences = null; + mPreferences = await data_preferences.getPreferences(context, NAME); + let pre2 = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + done(); + expect(uInt8Array.toString() === pre2.toString()).assertTrue(); + }); + }) + + /** + * @tc.name put Uint8Array callback interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0080 + * @tc.desc put Uint8Array callback interface test + */ + it('testPreferencesPutUint8Array0183', 0, async function (done) { + let uInt8Array = new Uint8Array(8192); + uInt8Array.fill(100); + mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array, async function (err, ret) { + let pre = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + expect(uInt8Array.toString() === pre.toString()).assertTrue(); + await mPreferences.flush(); + await data_preferences.removePreferencesFromCache(context, NAME); + mPreferences = null; + mPreferences = await data_preferences.getPreferences(context, NAME); + let pre2 = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + done(); + expect(uInt8Array.toString() === pre2.toString()).assertTrue(); + }); + }) + + /** + * @tc.name put Uint8Array callback interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0080 + * @tc.desc put Uint8Array callback interface test + */ + it('testPreferencesPutUint8Array0183', 0, async function (done) { + let uInt8Array = new Uint8Array(8193); + uInt8Array.fill(100); + try { + await mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array); + } catch (err) { + console.log("try catch err =" + err + ", code =" + err.code +", message =" + err.message); + expect("401").assertEqual(err.code.toString()); + done(); + } + }) + /** * @tc.name put StringArray callback interface test * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0001 @@ -378,6 +452,20 @@ describe('PreferencesCallBackJsunit', function () { }); }) + /** + * @tc.name put Uint8Array callback interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0005 + * @tc.desc put Uint8Array callback interface test + */ + it('testPreferencesPutUint8Array0001', 0, async function (done) { + let uInt8Array = new util.TextEncoder().encodeInto("π\\n\\b@.(){},"); + await mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array, async function (err, ret) { + let pre = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)) + expect(uInt8Array.toString() === pre.toString()).assertTrue(); + done(); + }); + }) + /** * @tc.name getAll callback interface test * @tc.number SUB_DDM_AppDataFWK_JSPreferences_CallBack_0004 diff --git a/preferences/test/js/unittest/preferences/src/PreferencesPromiseJsunit.test.js b/preferences/test/js/unittest/preferences/src/PreferencesPromiseJsunit.test.js index 7985a3702ddb5e4b2558e8d4a2ad26af0225f770..1e59cb02ec6e7a947e5770d4c1ae7a05c0d3eb80 100644 --- a/preferences/test/js/unittest/preferences/src/PreferencesPromiseJsunit.test.js +++ b/preferences/test/js/unittest/preferences/src/PreferencesPromiseJsunit.test.js @@ -13,7 +13,8 @@ * limitations under the License. */ import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from 'deccjsunit/index' -import data_preferences from '@ohos.data.preferences' +import data_preferences from '@ohos.data.preferences'; +import util from '@ohos.util'; import featureAbility from '@ohos.ability.featureAbility'; const NAME = 'test_preferences'; @@ -22,9 +23,10 @@ const KEY_TEST_LONG_ELEMENT = 'key_test_long'; const KEY_TEST_FLOAT_ELEMENT = 'key_test_float'; const KEY_TEST_BOOLEAN_ELEMENT = 'key_test_boolean'; const KEY_TEST_STRING_ELEMENT = 'key_test_string'; -const KEY_TEST_NUMBER_ARRAY_ELEMENT = 'key_test_number_array' -const KEY_TEST_STRING_ARRAY_ELEMENT = 'key_test_string_array' -const KEY_TEST_BOOL_ARRAY_ELEMENT = 'key_test_bool_array' +const KEY_TEST_NUMBER_ARRAY_ELEMENT = 'key_test_number_array'; +const KEY_TEST_STRING_ARRAY_ELEMENT = 'key_test_string_array'; +const KEY_TEST_BOOL_ARRAY_ELEMENT = 'key_test_bool_array'; +const KEY_TEST_UINT8ARRAY = 'key_test_uint8array'; var mPreferences; var context; @@ -90,6 +92,18 @@ describe('PreferencesPromiseJsunit', function () { } }); + /** + * @tc.name put Uint8Array promise interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_Preferences_0134 + * @tc.desc put Uint8Array promise interface test + */ + it('testPreferencesPutUint8Array0134', 0, async function () { + let uInt8Array = new util.TextEncoder().encodeInto("π\\n\\b@.(){},"); + await mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array); + let promise = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + expect(uInt8Array.toString() === promise.toString()).assertTrue(); + }); + /** * @tc.name getAll promise interface test * @tc.number SUB_DDM_AppDataFWK_JSPreferences_Preferences_0133 @@ -294,6 +308,22 @@ describe('PreferencesPromiseJsunit', function () { }); }) + /** + * @tc.name get Uint8Array promise interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_Preferences_0080 + * @tc.desc get Uint8Array promise interface test + */ + it('tesPreferencesGetUint8Array102', 0, async function () { + let uInt8Array = new util.TextEncoder().encodeInto("π\\n\\b@.(){},"); + await mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array); + const promise = mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + await promise.then((ret) => { + expect(uInt8Array.toString() === ret.toString()).assertTrue(); + }).catch((err) => { + expect(null).assertFail(); + }); + }) + /** * @tc.name put boolean promise interface test * @tc.number SUB_DDM_AppDataFWK_JSPreferences_Preferences_0090 @@ -465,4 +495,67 @@ describe('PreferencesPromiseJsunit', function () { expect(null).assertFail(); }); }) + + /** + * @tc.name put Uint8Array promise interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_Preferences_0201 + * @tc.desc put Uint8Array promise interface test + */ + it('testPreferencesPutUint8Array0201', 0, async function () { + let uInt8Array = new util.TextEncoder().encodeInto("abc@#$%123"); + const promise = mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array); + await promise.then(async (ret) => { + let pre = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + expect(uInt8Array.toString() === pre.toString()).assertTrue(); + await mPreferences.flush(); + await data_preferences.removePreferencesFromCache(context, NAME); + mPreferences = null; + mPreferences = await data_preferences.getPreferences(context, NAME); + let pre2 = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + expect(uInt8Array.toString() === pre2.toString()).assertTrue(); + }).catch((err) => { + expect(null).assertFail(); + }); + }) + + /** + * @tc.name put Uint8Array promise interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_Preferences_0202 + * @tc.desc put Uint8Array promise interface test + */ + it('testPreferencesPutUint8Array0202', 0, async function () { + let uInt8Array = new Uint8Array(8192); + uInt8Array.fill(100); + const promise = mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array); + await promise.then(async (ret) => { + let pre = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + expect(uInt8Array.toString() === pre.toString()).assertTrue(); + await mPreferences.flush(); + await data_preferences.removePreferencesFromCache(context, NAME); + mPreferences = null; + mPreferences = await data_preferences.getPreferences(context, NAME); + let pre2 = await mPreferences.get(KEY_TEST_UINT8ARRAY, new Uint8Array(0)); + expect(uInt8Array.toString() === pre2.toString()).assertTrue(); + }).catch((err) => { + expect(null).assertFail(); + }); + }) + + /** + * @tc.name put Uint8Array promise interface test + * @tc.number SUB_DDM_AppDataFWK_JSPreferences_Preferences_0203 + * @tc.desc put Uint8Array promise interface test + */ + it('testPreferencesPutUint8Array0203', 0, async function (done) { + let uInt8Array = new Uint8Array(8193); + uInt8Array.fill(100); + try { + await mPreferences.put(KEY_TEST_UINT8ARRAY, uInt8Array); + } catch (err) { + console.log("try catch err =" + err + ", code =" + err.code + ", message =" + err.message); + expect("401").assertEqual(err.code.toString()); + done(); + } + }) + }) \ No newline at end of file diff --git a/preferences/test/native/BUILD.gn b/preferences/test/native/BUILD.gn index fcfd89996634417a041b2cefad31d6efcb2113fd..96c274764b4cb0cde7df9bc919cae3e11d71dded 100644 --- a/preferences/test/native/BUILD.gn +++ b/preferences/test/native/BUILD.gn @@ -30,6 +30,7 @@ ohos_unittest("NativePreferencesTest") { module_out_path = module_output_path sources = [ + "unittest/base64_helper_test.cpp", "unittest/preferences_file_test.cpp", "unittest/preferences_helper_test.cpp", "unittest/preferences_test.cpp", diff --git a/preferences/test/native/unittest/base64_helper_test.cpp b/preferences/test/native/unittest/base64_helper_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..884c0e75802fd6dd06c81f29e653330608ac841a --- /dev/null +++ b/preferences/test/native/unittest/base64_helper_test.cpp @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021 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 "base64_helper.h" + +#include + +#include + +#include "log_print.h" + +using namespace testing::ext; +using namespace OHOS::NativePreferences; +namespace { +class Base64HelperTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void Base64HelperTest::SetUpTestCase(void) +{ +} + +void Base64HelperTest::TearDownTestCase(void) +{ +} + +void Base64HelperTest::SetUp(void) +{ +} + +void Base64HelperTest::TearDown(void) +{ +} + +/** + * @tc.name: Base64HelperTest_0001 + * @tc.desc: normal testcase of base64 encode + * @tc.type: FUNC + * @tc.require: SR000CU2BL + * @tc.author: xiuhongju + */ +HWTEST_F(Base64HelperTest, Base64HelperTest_001, TestSize.Level1) +{ + std::vector emptyArray {}; + std::vector oneArray { 'a' }; + std::vector twoArray { 'a', 'b' }; + std::vector threeArray { 'a', 'b', 'c' }; + auto result = Base64Helper::Encode(emptyArray); + EXPECT_EQ(result, ""); + + result = Base64Helper::Encode(oneArray); + EXPECT_EQ(result.length(), 4); + EXPECT_EQ(result, "YQ=="); + + result = Base64Helper::Encode(twoArray); + EXPECT_EQ(result.length(), 4); + EXPECT_EQ(result, "YWI="); + + result = Base64Helper::Encode(threeArray); + EXPECT_EQ(result.length(), 4); + EXPECT_EQ(result, "YWJj"); +} + +/** + * @tc.name: Base64HelperTest_002 + * @tc.desc: normal testcase of base64 decode + * @tc.type: FUNC + */ +HWTEST_F(Base64HelperTest, Base64HelperTest_002, TestSize.Level1) +{ + std::vector oneArray { 1 }; + std::vector twoArray { 1, 2 }; + std::vector threeArray { 1, 2, 3 }; + std::vector result {}; + + EXPECT_TRUE(Base64Helper::Decode(Base64Helper::Encode(oneArray), result)); + EXPECT_EQ(result, oneArray); + + EXPECT_TRUE(Base64Helper::Decode(Base64Helper::Encode(twoArray), result)); + EXPECT_EQ(result, twoArray); + + EXPECT_TRUE(Base64Helper::Decode(Base64Helper::Encode(threeArray), result)); + EXPECT_EQ(result, threeArray); +} + +/** + * @tc.name: Base64HelperTest_003 + * @tc.desc: error testcase of base64 decode + * @tc.type: FUNC + */ +HWTEST_F(Base64HelperTest, Base64HelperTest_003, TestSize.Level1) +{ + std::string wrongText = "abc"; + std::vector result {}; + EXPECT_FALSE(Base64Helper::Decode(wrongText, result)); + + wrongText = "@bcd"; + EXPECT_FALSE(Base64Helper::Decode(wrongText, result)); + + wrongText = "a@cd"; + EXPECT_FALSE(Base64Helper::Decode(wrongText, result)); + + wrongText = "ab@d"; + EXPECT_FALSE(Base64Helper::Decode(wrongText, result)); + + wrongText = "abc@"; + EXPECT_FALSE(Base64Helper::Decode(wrongText, result)); +} + +/** + * @tc.name: Base64HelperTest_004 + * @tc.desc: error testcase of base64 decode + * @tc.type: FUNC + */ +HWTEST_F(Base64HelperTest, Base64HelperTest_004, TestSize.Level1) +{ + std::vector array; + for (size_t i = 0; i < 256; ++i) { + array.push_back(i); + } + std::string encodeStr = Base64Helper::Encode(array); + std::vector decodeArray; + EXPECT_TRUE(Base64Helper::Decode(encodeStr, decodeArray)); + EXPECT_TRUE(array == decodeArray); +} +} diff --git a/preferences/test/native/unittest/preferences_test.cpp b/preferences/test/native/unittest/preferences_test.cpp index a0982a18adf3e9987204a3ed86596b3aaf189f53..716a0c9a16d0fd0fd065c89c213f39fb7a7ca5dc 100644 --- a/preferences/test/native/unittest/preferences_test.cpp +++ b/preferences/test/native/unittest/preferences_test.cpp @@ -44,6 +44,7 @@ const std::string KEY_TEST_STRING_ELEMENT = "key_test_string"; const std::string KEY_TEST_STRING_ARRAY_ELEMENT = "key_test_string_array"; const std::string KEY_TEST_BOOL_ARRAY_ELEMENT = "key_test_bool_array"; const std::string KEY_TEST_DOUBLE_ARRAY_ELEMENT = "key_test_double_array"; +const std::string KEY_TEST_UINT8_ARRAY_ELEMENT = "key_test_uint8_array"; class PreferencesTest : public testing::Test { public: static void SetUpTestCase(void); @@ -141,6 +142,26 @@ void PreferencesObserverCrossProcess::OnChange(const std::string &key) cond.notify_all(); } +/** + * @tc.name: NativePreferencesGroupIdTest_001 + * @tc.desc: normal testcase of GetGroupId + * @tc.type: FUNC + * @tc.require: AR000CU2BN + * @tc.author: lirui + */ +HWTEST_F(PreferencesTest, NativePreferencesGroupIdTest_001, TestSize.Level1) +{ + int errCode = E_OK; + Options option = Options("/data/test/test1", "ohos.test.demo", "2002001"); + std::shared_ptr preferences = PreferencesHelper::GetPreferences(option, errCode); + EXPECT_EQ(errCode, E_OK); + EXPECT_EQ(preferences->GetGroupId(), "2002001"); + + preferences = nullptr; + int ret = PreferencesHelper::DeletePreferences("/data/test/test1"); + EXPECT_EQ(ret, E_OK); +} + /** * @tc.name: NativePreferencesTest_001 * @tc.desc: normal testcase of FlushSync @@ -786,9 +807,11 @@ HWTEST_F(PreferencesTest, NativePreferencesTest_026, TestSize.Level1) std::vector stringArray = { "str1", "str2" }; std::vector boolArray = { false, true }; std::vector doubleArray = { 0.1, 0.2 }; + std::vector uint8Array = { 1, 2, 3, 4, 5, 6, 7 }; pref1->Put(KEY_TEST_STRING_ARRAY_ELEMENT, stringArray); pref1->Put(KEY_TEST_BOOL_ARRAY_ELEMENT, boolArray); pref1->Put(KEY_TEST_DOUBLE_ARRAY_ELEMENT, doubleArray); + pref1->Put(KEY_TEST_UINT8_ARRAY_ELEMENT, uint8Array); pref1->FlushSync(); PreferencesHelper::RemovePreferencesFromCache("/data/test/test1"); @@ -807,6 +830,10 @@ HWTEST_F(PreferencesTest, NativePreferencesTest_026, TestSize.Level1) PreferencesValue doubleArrayRes = pref1->Get(KEY_TEST_DOUBLE_ARRAY_ELEMENT, defValue); EXPECT_EQ(doubleArrayRes.IsDoubleArray(), true); EXPECT_EQ(static_cast>(doubleArrayRes), doubleArray); + + PreferencesValue uint8ArrayRes = pref1->Get(KEY_TEST_UINT8_ARRAY_ELEMENT, defValue); + EXPECT_EQ(uint8ArrayRes.IsUint8Array(), true); + EXPECT_EQ(static_cast>(uint8ArrayRes), uint8Array); PreferencesHelper::DeletePreferences("/data/test/test1"); } @@ -910,5 +937,9 @@ HWTEST_F(PreferencesTest, PreferencesValueTest_001, TestSize.Level1) std::vector valueVectorString(2, "test"); std::vector retVectorString = PreferencesValue(valueVectorString); EXPECT_EQ(valueVectorString, retVectorString); + + std::vector valueVectorUint8(3, 1); + std::vector retVectorUint8 = PreferencesValue(valueVectorUint8); + EXPECT_EQ(valueVectorUint8, retVectorUint8); } } // namespace diff --git a/relational_store/CMakeLists.txt b/relational_store/CMakeLists.txt index b5c5ec0f2a31ed0f9c35bd629ba68b88cb8e05ee..6733a42f1a5c0cb70f194987fa0142ec7adfbb8e 100644 --- a/relational_store/CMakeLists.txt +++ b/relational_store/CMakeLists.txt @@ -83,5 +83,5 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/cloud_data/s aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/native/cloud_data/src cloud_data_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/frameworks/js/napi/common/src cloud_data_src) add_library(cloud_data SHARED ${cloud_data_src}) -target_link_libraries(cloud_data mock) +target_link_libraries(cloud_data mock relational_store) target_include_directories(cloud_data PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/interfaces/inner_api/cloud_data/include) \ No newline at end of file diff --git a/relational_store/bundle.json b/relational_store/bundle.json index 967784a40e8c21f679a9a8cb3fe08efc5242d5b6..9be1bb1d4c26f894ba7a3b0b0cab2ae7b150f8a0 100644 --- a/relational_store/bundle.json +++ b/relational_store/bundle.json @@ -38,7 +38,8 @@ "name": "relational_store", "subsystem": "distributeddatamgr", "syscap": [ - "SystemCapability.DistributedDataManager.RelationalStore.Core" + "SystemCapability.DistributedDataManager.RelationalStore.Core", + "SystemCapability.DistributedDataManager.CommonType" ], "features": ["relational_store_rdb_support_icu"], "adapted_system_type": [ @@ -81,7 +82,8 @@ "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/dataability:dataability", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:rdb", "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/rdb:napi_rdb", - "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/relationalstore:relationalstore" + "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/relationalstore:relationalstore", + "//foundation/distributeddatamgr/relational_store/frameworks/js/napi/cloud_extension:cloudextension" ], "inner_kits": [ { diff --git a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn index 2aaac109e732b9e8f5c66570da7e3d05eddb74d1..a5053131fa80903706fb753923042f2f8488b21f 100644 --- a/relational_store/frameworks/js/napi/cloud_data/BUILD.gn +++ b/relational_store/frameworks/js/napi/cloud_data/BUILD.gn @@ -22,14 +22,24 @@ ohos_copy("relational_store_declaration") { } ohos_shared_library("clouddata") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ "${cloud_data_napi_path}/src/entry_point.cpp", + "${cloud_data_napi_path}/src/js_cloud_share.cpp", + "${cloud_data_napi_path}/src/js_cloud_utils.cpp", "${cloud_data_napi_path}/src/js_config.cpp", "${cloud_data_napi_path}/src/js_const_properties.cpp", "${cloud_data_napi_path}/src/js_error_utils.cpp", "${cloud_data_napi_path}/src/napi_queue.cpp", "${cloud_data_native_path}/src/cloud_manager.cpp", "${cloud_data_native_path}/src/cloud_service_proxy.cpp", + "${cloud_data_native_path}/src/cloud_types_util.cpp", "${relational_store_napi_path}/common/src/js_utils.cpp", ] @@ -37,6 +47,7 @@ ohos_shared_library("clouddata") { "include", "${relational_store_js_common_path}/include", "${cloud_data_native_path}/include", + "${datashare_path}/provider/include", "${kvstore_path}/common", "${relational_store_common_path}/include", "${relational_store_innerapi_path}/rdb/include", @@ -45,6 +56,8 @@ ohos_shared_library("clouddata") { "${relational_store_napi_path}/common/include", ] + deps = [ "${relational_store_innerapi_path}/rdb:native_rdb" ] + external_deps = [ "ability_runtime:abilitykit_native", "ability_runtime:napi_base_context", diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_share.h b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_share.h index 7b36f18519be9df816c0c38bff705999e1cae68c..e48ff0ed9574d1f74acfa06e0dc3749de8e0e07c 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_share.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_share.h @@ -21,6 +21,6 @@ #include "napi/native_node_api.h" namespace OHOS::CloudData { -napi_value InitCloudDataShare(napi_env env, napi_value exports); +napi_value InitCloudSharing(napi_env env, napi_value exports); } // namespace OHOS::CloudData #endif // CLOUD_DATA_JS_CLOUD_SHARE_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h index e0b6bfa5c597772a627d4696a136b4ae4c276c7d..b9c202a59046f6a2bb4c31954c305c258954289e 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_cloud_utils.h @@ -17,11 +17,20 @@ #include "js_utils.h" #include "cloud_types.h" +#include "rdb_predicates.h" +#include "result_set.h" +#include "js_config.h" namespace OHOS::AppDataMgrJsKit { namespace JSUtils { using Participant = OHOS::CloudData::Participant; using Privilege = OHOS::CloudData::Privilege; +using RdbPredicates = OHOS::NativeRdb::RdbPredicates; +using ResultSet = OHOS::NativeRdb::ResultSet; +using ExtraData = OHOS::CloudData::JsConfig::ExtraData; + +template<> +int32_t Convert2Value(napi_env env, napi_value input, ExtraData &output); template<> int32_t Convert2Value(napi_env env, napi_value input, Participant &output); @@ -29,11 +38,21 @@ int32_t Convert2Value(napi_env env, napi_value input, Participant &output); template<> int32_t Convert2Value(napi_env env, napi_value input, Privilege &output); +template<> +int32_t Convert2Value(napi_env env, napi_value input, std::shared_ptr &output); + template<> napi_value Convert2JSValue(napi_env env, const Participant &value); template<> napi_value Convert2JSValue(napi_env env, const Privilege &value); + +template<> +napi_value Convert2JSValue(napi_env env, const std::shared_ptr &value); + +template<> +napi_value Convert2JSValue(napi_env env, const std::pair &value); + }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit #endif // CLOUD_DATA_JS_CLOUD_SHARE_H diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h index b49b9c0169ec6da1aec41350d44746e66f6cc4e2..cf1c8a0ae874b6adc47515975659a11c31f1cde4 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_config.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_config.h @@ -33,6 +33,11 @@ public: CLEAR_CLOUD_DATA_AND_INFO = 1, }; + struct ExtraData { + std::string eventId; + std::string extraData; + }; + static inline bool ValidSubscribeType(int32_t type) { return (CLEAR_CLOUD_INFO <= type) && (type <= CLEAR_CLOUD_DATA_AND_INFO); diff --git a/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h index 6245a158699a31639fa32b27ee61834b5fd2b393..b5e855982330557ba255aae81045d4f36fd94781 100644 --- a/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h +++ b/relational_store/frameworks/js/napi/cloud_data/include/js_const_properties.h @@ -21,5 +21,6 @@ namespace OHOS::CloudData { napi_status InitConstProperties(napi_env env, napi_value exports); +napi_status InitSharingConstProperties(napi_env env, napi_value exports); } // namespace OHOS::CloudData #endif //LDBPROJ_JS_CONST_PROPERTIES_H diff --git a/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp index 417b0bb53cfdbf8aff31d364bec512b7ce5c7002..a1a38cebd8e60e832b4ae5686980dfc9abd75849 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/entry_point.cpp @@ -23,9 +23,11 @@ using namespace OHOS::Rdb; static napi_value Init(napi_env env, napi_value exports) { - InitCloudDataShare(env, exports); + auto sharingExport = InitCloudSharing(env, exports); + napi_status status = InitSharingConstProperties(env, sharingExport); + LOG_INFO("init Enumerate Constants %{public}d", status); exports = JsConfig::InitConfig(env, exports); - napi_status status = InitConstProperties(env, exports); + status = InitConstProperties(env, exports); LOG_INFO("init Enumerate Constants %{public}d", status); return exports; } diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_share.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_share.cpp index e26ab9a300a391061c68b77f6581fbde296241d1..3af9b8fc55d0f4cb6ceb8de7b0cbf433a8c5a22c 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_share.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_share.cpp @@ -15,14 +15,17 @@ #include "js_cloud_share.h" +#include "cache_result_set.h" #include "cloud_manager.h" #include "cloud_service.h" #include "cloud_types.h" +#include "js_cloud_utils.h" #include "js_error_utils.h" #include "js_utils.h" #include "logger.h" #include "napi_queue.h" #include "rdb_predicates.h" +#include "result_set.h" namespace OHOS::CloudData { using namespace OHOS::NativeRdb; @@ -43,12 +46,55 @@ using namespace OHOS::AppDataMgrJsKit; napi_value AllocResourceAndShare(napi_env env, napi_callback_info info) { struct AllocResAndShareContext : public ContextBase { - std::string sharingRes; - std::vector participants; + std::string storeId; + Participants participants; std::vector columns; std::shared_ptr predicates = nullptr; + std::shared_ptr resultSet; + }; + auto ctxt = std::make_shared(); + ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { + ASSERT_BUSINESS_ERR(ctxt, argc >= 3, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + int status = JSUtils::Convert2Value(env, argv[0], ctxt->storeId); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + Status::INVALID_ARGUMENT, "The type of storeId must be string."); + status = JSUtils::Convert2Value(env, argv[1], ctxt->predicates); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of predicates must be relationalStore.RdbPredicates"); + status = JSUtils::Convert2Value(env, argv[2], ctxt->participants); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + Status::INVALID_ARGUMENT, "The type of participants must be Array."); + if (argc > 3) { + status = JSUtils::Convert2Value(env, argv[3], ctxt->columns); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + Status::INVALID_ARGUMENT, "The type of columns must be Array."); + } + }); + ASSERT_NULL(!ctxt->isThrowError, "AllocResourceAndShare exit"); + auto execute = [env, ctxt]() { + auto [status, proxy] = CloudManager::GetInstance().GetCloudService(); + if (proxy == nullptr) { + if (status != CloudService::SERVER_UNAVAILABLE) { + status = CloudService::NOT_SUPPORT; + } + ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok + : napi_generic_failure; + return; + } + + auto [result, valueBuckets] = proxy->AllocResourceAndShare( + ctxt->storeId, ctxt->predicates->GetDistributedPredicates(), ctxt->columns, ctxt->participants); + ctxt->resultSet = std::make_shared(std::move(valueBuckets)); + LOG_DEBUG("AllocResourceAndShare result: %{public}d, size:%{public}zu", result, valueBuckets.size()); + ctxt->status = + (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; - return nullptr; + auto output = [env, ctxt](napi_value& result) { + result = JSUtils::Convert2JSValue(env, ctxt->resultSet); + ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); + }; + return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } /* @@ -64,17 +110,17 @@ napi_value Share(napi_env env, napi_callback_info info) { struct ShareContext : public ContextBase { std::string sharingRes; - std::vector participants; - Result>> value; + Participants participants; + Results results; }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(), Status::INVALID_ARGUMENT, "The type of sharingRes must be string."); status = JSUtils::Convert2Value(env, argv[1], ctxt->participants); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->participants.empty(), Status::INVALID_ARGUMENT, "The type of participants must be Array."); }); ASSERT_NULL(!ctxt->isThrowError, "share exit"); @@ -89,13 +135,13 @@ napi_value Share(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->Share(ctxt->sharingRes, ctxt->participants, ctxt->value); + int32_t result = proxy->Share(ctxt->sharingRes, ctxt->participants, ctxt->results); LOG_DEBUG("share result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->results); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); @@ -114,17 +160,17 @@ napi_value Unshare(napi_env env, napi_callback_info info) { struct UnshareContext : public ContextBase { std::string sharingRes; - std::vector participants; - Result>> value; + Participants participants; + Results results; }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(), Status::INVALID_ARGUMENT, "The type of sharingRes must be string."); status = JSUtils::Convert2Value(env, argv[1], ctxt->participants); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->participants.empty(), Status::INVALID_ARGUMENT, "The type of participants must be Array."); }); auto execute = [env, ctxt]() { @@ -137,13 +183,13 @@ napi_value Unshare(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->Unshare(ctxt->sharingRes, ctxt->participants, ctxt->value); + int32_t result = proxy->Unshare(ctxt->sharingRes, ctxt->participants, ctxt->results); LOG_DEBUG("unshare result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->results); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); @@ -161,13 +207,13 @@ napi_value Exit(napi_env env, napi_callback_info info) { struct ExitContext : public ContextBase { std::string sharingRes; - Result value; + std::pair result; }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(), Status::INVALID_ARGUMENT, "The type of sharingRes must be string."); }); auto execute = [env, ctxt]() { @@ -180,13 +226,13 @@ napi_value Exit(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->ExitSharing(ctxt->sharingRes, ctxt->value); + int32_t result = proxy->Exit(ctxt->sharingRes, ctxt->result); LOG_DEBUG("exit sharing result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->result); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); @@ -205,17 +251,17 @@ napi_value ChangePrivilege(napi_env env, napi_callback_info info) { struct ChangePrivilegeContext : public ContextBase { std::string sharingRes; - std::vector participants; - Result>> value; + Participants participants; + Results results; }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(), Status::INVALID_ARGUMENT, "The type of sharingRes must be string."); status = JSUtils::Convert2Value(env, argv[1], ctxt->participants); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->participants.empty(), Status::INVALID_ARGUMENT, "The type of participants must be Array."); }); auto execute = [env, ctxt]() { @@ -228,13 +274,13 @@ napi_value ChangePrivilege(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->ChangePrivilege(ctxt->sharingRes, ctxt->participants, ctxt->value); + int32_t result = proxy->ChangePrivilege(ctxt->sharingRes, ctxt->participants, ctxt->results); LOG_DEBUG("change privilege result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->results); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); @@ -248,17 +294,17 @@ napi_value ChangePrivilege(napi_env env, napi_callback_info info) * [Promise] * queryParticipants(sharingRes: string): Promise>>; */ -napi_value QueryParticipants(napi_env env, napi_callback_info info) +napi_value Query(napi_env env, napi_callback_info info) { - struct QueryParticipantsContext : public ContextBase { + struct QueryContext : public ContextBase { std::string sharingRes; - Result> value; + QueryResults results; }; - auto ctxt = std::make_shared(); + auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(), Status::INVALID_ARGUMENT, "The type of sharingRes must be string."); }); auto execute = [env, ctxt]() { @@ -271,13 +317,13 @@ napi_value QueryParticipants(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->QueryParticipants(ctxt->sharingRes, ctxt->value); + int32_t result = proxy->Query(ctxt->sharingRes, ctxt->results); LOG_DEBUG("query participants result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->results); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); @@ -292,17 +338,17 @@ napi_value QueryParticipants(napi_env env, napi_callback_info info) * [Promise] * queryParticipantsByInvitation(invitationCode: string): Promise>>; */ -napi_value QueryParticipantsByInvitation(napi_env env, napi_callback_info info) +napi_value QueryByInvitation(napi_env env, napi_callback_info info) { struct QueryByInvitationContext : public ContextBase { std::string invitationCode; - Result> value; + QueryResults results; }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->invitationCode); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->invitationCode.empty(), Status::INVALID_ARGUMENT, "The type of invitationCode must be string."); }); auto execute = [env, ctxt]() { @@ -315,13 +361,13 @@ napi_value QueryParticipantsByInvitation(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->QueryParticipantsByInvitation(ctxt->invitationCode, ctxt->value); + int32_t result = proxy->QueryByInvitation(ctxt->invitationCode, ctxt->results); LOG_DEBUG("query participants by invitation result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->results); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); @@ -339,21 +385,21 @@ napi_value ConfirmInvitation(napi_env env, napi_callback_info info) { struct ConfirmInvitationContext : public ContextBase { std::string invitationCode; - Confirmation confirmation; - Result value; + int32_t confirmation; + std::tuple result; }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->invitationCode); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->invitationCode.empty(), Status::INVALID_ARGUMENT, "The type of invitationCode must be string."); int32_t confirmation; - status = JSUtils::Convert2Value(env, argv[1], confirmation); + status = JSUtils::Convert2ValueExt(env, argv[1], confirmation); ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && confirmation > Confirmation::CFM_NIL && confirmation <= Confirmation::CFM_BUTT, Status::INVALID_ARGUMENT, "The type of status must be Status."); - ctxt->confirmation = static_cast(confirmation); + ctxt->confirmation = confirmation; }); auto execute = [env, ctxt]() { auto [status, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -365,13 +411,13 @@ napi_value ConfirmInvitation(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->ConfirmInvitation(ctxt->invitationCode, ctxt->confirmation, ctxt->value); + int32_t result = proxy->ConfirmInvitation(ctxt->invitationCode, ctxt->confirmation, ctxt->result); LOG_DEBUG("confirm invitation result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->result); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); @@ -389,21 +435,21 @@ napi_value ChangeConfirmation(napi_env env, napi_callback_info info) { struct ChangeConfirmationContext : public ContextBase { std::string sharingRes; - Confirmation confirmation; - Result value; + int32_t confirmation; + std::pair results; }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); int status = JSUtils::Convert2Value(env, argv[0], ctxt->sharingRes); - ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && !ctxt->sharingRes.empty(), Status::INVALID_ARGUMENT, "The type of sharingRes must be string."); int32_t confirmation; - status = JSUtils::Convert2Value(env, argv[1], confirmation); + status = JSUtils::Convert2ValueExt(env, argv[1], confirmation); ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK && confirmation > Confirmation::CFM_NIL && confirmation < Confirmation::CFM_BUTT, Status::INVALID_ARGUMENT, "The type of status must be Status."); - ctxt->confirmation = static_cast(confirmation); + ctxt->confirmation = confirmation; }); auto execute = [env, ctxt]() { auto [status, proxy] = CloudManager::GetInstance().GetCloudService(); @@ -415,32 +461,38 @@ napi_value ChangeConfirmation(napi_env env, napi_callback_info info) napi_ok : napi_generic_failure; return; } - int32_t result = proxy->ChangeConfirmation(ctxt->sharingRes, ctxt->confirmation, ctxt->value); + int32_t result = proxy->ChangeConfirmation(ctxt->sharingRes, ctxt->confirmation, ctxt->results); LOG_DEBUG("change confirmation result %{public}d", result); ctxt->status = (GenerateNapiError(result, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ? napi_ok : napi_generic_failure; }; auto output = [env, ctxt](napi_value& result) { - result = JSUtils::Convert2JSValue(env, ctxt->value); + result = JSUtils::Convert2JSValue(env, ctxt->results); ASSERT_VALUE(ctxt, result != nullptr, napi_generic_failure, "output failed"); }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output); } -napi_value InitCloudDataShare(napi_env env, napi_value exports) +napi_value InitCloudSharing(napi_env env, napi_value exports) { + napi_value sharing = nullptr; + napi_status status = napi_create_object(env, &sharing); + if (status != napi_ok || sharing == nullptr) { + return nullptr; + } napi_property_descriptor properties[] = { DECLARE_NAPI_FUNCTION("allocResourceAndShare", AllocResourceAndShare), DECLARE_NAPI_FUNCTION("share", Share), DECLARE_NAPI_FUNCTION("unshare", Unshare), DECLARE_NAPI_FUNCTION("exit", Exit), DECLARE_NAPI_FUNCTION("changePrivilege", ChangePrivilege), - DECLARE_NAPI_FUNCTION("queryParticipants", QueryParticipants), - DECLARE_NAPI_FUNCTION("queryParticipantsByInvitation", QueryParticipantsByInvitation), + DECLARE_NAPI_FUNCTION("queryParticipants", Query), + DECLARE_NAPI_FUNCTION("queryParticipantsByInvitation", QueryByInvitation), DECLARE_NAPI_FUNCTION("confirmInvitation", ConfirmInvitation), DECLARE_NAPI_FUNCTION("changeConfirmation", ChangeConfirmation), }; - NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties)); - return exports; + NAPI_CALL(env, napi_define_properties(env, sharing, sizeof(properties) / sizeof(*properties), properties)); + NAPI_CALL(env, napi_set_named_property(env, exports, "sharing", sharing)); + return sharing; } } // namespace OHOS::CloudData \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp index 3c192df587c88122dfd773237308a77f0ff3ba85..467ba63d4799ccb751b95a1f1d04d12244cb8e52 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_cloud_utils.cpp @@ -14,18 +14,40 @@ */ #include "js_cloud_utils.h" +#include "js_proxy.h" +#include "result_set.h" +#include "result_set_bridge.h" #include "logger.h" -#define NAPI_CALL_RETURN_ERR(call, ret) \ - do { \ - if ((call) != napi_ok) { \ - return ret; \ - } \ +#define NAPI_CALL_RETURN_ERR(call, ret) \ + ASSERT_RETURN((call) == napi_ok, ret) + +#define ASSERT_RETURN(call, ret) \ + do { \ + if (!(call)) { \ + return ret; \ + } \ } while (0) namespace OHOS::AppDataMgrJsKit { namespace JSUtils { using namespace OHOS::Rdb; + +template<> +int32_t Convert2Value(napi_env env, napi_value input, ExtraData &output) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, input, &type); + if (status != napi_ok || type != napi_object) { + return napi_invalid_arg; + } + int32_t result = GET_PROPERTY(env, input, output, eventId); + if (result != napi_ok) { + return napi_invalid_arg; + } + return GET_PROPERTY(env, input, output, extraData); +} + template<> int32_t Convert2Value(napi_env env, napi_value input, Participant &output) { @@ -37,15 +59,16 @@ int32_t Convert2Value(napi_env env, napi_value input, Participant &output) } NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, identity), napi_invalid_arg); NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "role", output.role), napi_invalid_arg); - if (output.role < CloudData::Role::ROLE_INVITER || output.role > CloudData::Role::ROLE_INVITEES) { + if (output.role < CloudData::Role::ROLE_INVITER || output.role > CloudData::Role::ROLE_INVITEE) { return napi_invalid_arg; } - NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "status", output.status), napi_invalid_arg); - if (output.status < CloudData::Confirmation::CFM_UNKNOWN || - output.status > CloudData::Confirmation::CFM_SUSPENDED) { + NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "state", output.state), napi_invalid_arg); + if (output.state < CloudData::Confirmation::CFM_UNKNOWN || + output.state > CloudData::Confirmation::CFM_SUSPENDED) { return napi_invalid_arg; } NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "privilege", output.privilege), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "attachInfo", output.attachInfo), napi_invalid_arg); return napi_ok; } @@ -58,7 +81,7 @@ int32_t Convert2Value(napi_env env, napi_value input, Privilege &output) LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type); return napi_invalid_arg; } - NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "writeable", output.writeable), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "writable", output.writable), napi_invalid_arg); NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "readable", output.readable), napi_invalid_arg); NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "creatable", output.creatable), napi_invalid_arg); NAPI_CALL_RETURN_ERR(GetOptionalValue(env, input, "deletable", output.deletable), napi_invalid_arg); @@ -66,6 +89,22 @@ int32_t Convert2Value(napi_env env, napi_value input, Privilege &output) return napi_ok; } +template<> +int32_t Convert2Value(napi_env env, napi_value input, std::shared_ptr &output) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, input, &type); + if (status != napi_ok || type != napi_object) { + LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type); + return napi_invalid_arg; + } + JSProxy::JSProxy *jsProxy = nullptr; + status = napi_unwrap(env, input, reinterpret_cast(&jsProxy)); + ASSERT_RETURN(status == napi_ok && jsProxy != nullptr && jsProxy->GetInstance() != nullptr, napi_invalid_arg); + output = jsProxy->GetInstance(); + return napi_ok; +} + template<> napi_value Convert2JSValue(napi_env env, const Participant &value) { @@ -76,15 +115,17 @@ napi_value Convert2JSValue(napi_env env, const Participant &value) } napi_value identity = Convert2JSValue(env, value.identity); napi_value role = Convert2JSValue(env, value.role); - napi_value sharingStatus = Convert2JSValue(env, value.status); + napi_value sharingState = Convert2JSValue(env, value.state); napi_value privilege = Convert2JSValue(env, value.privilege); if (privilege == nullptr) { return nullptr; } + napi_value attachInfo = Convert2JSValue(env, value.attachInfo); napi_set_named_property(env, jsValue, "identity", identity); napi_set_named_property(env, jsValue, "role", role); - napi_set_named_property(env, jsValue, "status", sharingStatus); + napi_set_named_property(env, jsValue, "state", sharingState); napi_set_named_property(env, jsValue, "privilege", privilege); + napi_set_named_property(env, jsValue, "attachInfo", attachInfo); return jsValue; } @@ -96,16 +137,54 @@ napi_value Convert2JSValue(napi_env env, const Privilege &value) if (status != napi_ok) { return nullptr; } - napi_value writeable = Convert2JSValue(env, value.writeable); - napi_value readable = Convert2JSValue(env, value.readable); - napi_value creatable = Convert2JSValue(env, value.creatable); - napi_value deletable = Convert2JSValue(env, value.deletable); - napi_value shareable = Convert2JSValue(env, value.shareable); - napi_set_named_property(env, jsValue, "writeable", writeable); - napi_set_named_property(env, jsValue, "readable", readable); - napi_set_named_property(env, jsValue, "creatable", creatable); - napi_set_named_property(env, jsValue, "deletable", deletable); - napi_set_named_property(env, jsValue, "shareable", shareable); + + napi_set_named_property(env, jsValue, "writable", Convert2JSValue(env, value.writable)); + napi_set_named_property(env, jsValue, "readable", Convert2JSValue(env, value.readable)); + napi_set_named_property(env, jsValue, "creatable", Convert2JSValue(env, value.creatable)); + napi_set_named_property(env, jsValue, "deletable", Convert2JSValue(env, value.deletable)); + napi_set_named_property(env, jsValue, "shareable", Convert2JSValue(env, value.shareable)); + return jsValue; +} + +template<> +napi_value Convert2JSValue(napi_env env, const std::shared_ptr &value) +{ + auto constructor = JSUtils::GetClass(env, "ohos.data.relationalStore", "ResultSet"); + if (constructor == nullptr) { + LOG_ERROR("Constructor of ResultSet is nullptr!"); + return nullptr; + } + napi_value instance = nullptr; + napi_status status = napi_new_instance(env, constructor, 0, nullptr, &instance); + if (status != napi_ok) { + LOG_ERROR("NewInstance ResultSet failed! status:%{public}d!", status); + return nullptr; + } + JSProxy::JSEntity *proxy = nullptr; + status = napi_unwrap(env, instance, reinterpret_cast(&proxy)); + if (status != napi_ok || proxy == nullptr) { + LOG_ERROR("napi_unwrap failed! status:%{public}d!", status); + return nullptr; + } + proxy->SetInstance(value); + return instance; +} + +template<> +napi_value Convert2JSValue(napi_env env, const std::pair &value) +{ + napi_value jsValue; + napi_status status = napi_create_object(env, &jsValue); + if (status != napi_ok) { + return nullptr; + } + napi_value code = Convert2JSValue(env, value.first); + napi_value description = Convert2JSValue(env, value.second); + napi_value val; + napi_get_undefined(env, &val); + napi_set_named_property(env, jsValue, "code", code); + napi_set_named_property(env, jsValue, "description", description); + napi_set_named_property(env, jsValue, "value", val); return jsValue; } }; // namespace JSUtils diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp index 869ab80196d73446483856e41630679074118b26..533d87f62e5e26a00cd903e5d52b7e5b736b70df 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_config.cpp @@ -22,6 +22,7 @@ #include "cloud_service.h" #include "js_error_utils.h" #include "js_utils.h" +#include "js_cloud_utils.h" #include "logger.h" #include "napi_queue.h" @@ -245,26 +246,45 @@ napi_value JsConfig::Clean(napi_env env, napi_callback_info info) * [JS API Prototype] * [AsyncCallback] * notifyDataChange(accountId: string, bundleName: string, callback: AsyncCallback): void; + * notifyDataChange(extInfo: ExtraData, callback: AsyncCallback): void; + * notifyDataChange(extInfo: ExtraData, userId: number,callback: AsyncCallback): void; * [Promise] * notifyDataChange(accountId: string, bundleName: string): Promise; + * notifyDataChange(extInfo: ExtraData, userId?: number): Promise; */ +struct ChangeAppSwitchContext : public ContextBase { + std::string accountId; + std::string bundleName; + int32_t userId = CloudService::INVALID_USER_ID; + bool notifyStatus = false; + OHOS::CloudData::JsConfig::ExtraData extInfo; +}; napi_value JsConfig::NotifyDataChange(napi_env env, napi_callback_info info) { - struct ChangeAppSwitchContext : public ContextBase { - std::string accountId; - std::string bundleName; - }; auto ctxt = std::make_shared(); ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) { // required 2 arguments :: - ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); - // 0 is the index of argument accountId, 1 is the index of argument bundleName - int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); - ASSERT_BUSINESS_ERR( - ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of accountId must be string."); - status = JSUtils::Convert2Value(env, argv[1], ctxt->bundleName); - ASSERT_BUSINESS_ERR( - ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, "The type of bundleName must be string."); + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT, "The number of parameters is incorrect."); + napi_valuetype type = napi_undefined; + if (argc > 1 && napi_typeof(env, argv[0], &type) == napi_ok && type != napi_object) { + // 0 is the index of argument accountId, 1 is the index of argument bundleName + int status = JSUtils::Convert2Value(env, argv[0], ctxt->accountId); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of accountId must be string."); + status = JSUtils::Convert2Value(env, argv[1], ctxt->bundleName); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of bundleName must be string."); + } else { + int status = JSUtils::Convert2Value(env, argv[0], ctxt->extInfo); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of extInfo must be Extradata."); + if (argc > 1) { + status = JSUtils::Convert2ValueExt(env, argv[1], ctxt->userId); + ASSERT_BUSINESS_ERR(ctxt, status == JSUtils::OK, Status::INVALID_ARGUMENT, + "The type of user must be number."); + } + ctxt->notifyStatus = true; + } }); ASSERT_NULL(!ctxt->isThrowError, "NotifyDataChange exit"); @@ -276,15 +296,18 @@ napi_value JsConfig::NotifyDataChange(napi_env env, napi_callback_info info) state = CloudService::NOT_SUPPORT; } ctxt->status = (GenerateNapiError(state, ctxt->jsCode, ctxt->error) == Status::SUCCESS) - ? napi_ok - : napi_generic_failure; + ? napi_ok : napi_generic_failure; return; } - int32_t cStatus = proxy->NotifyDataChange(ctxt->accountId, ctxt->bundleName); - LOG_DEBUG("NotifyDataChange return %{public}d", cStatus); - ctxt->status = (GenerateNapiError(cStatus, ctxt->jsCode, ctxt->error) == Status::SUCCESS) - ? napi_ok - : napi_generic_failure; + int32_t status ; + if (ctxt->notifyStatus == true) { + status = proxy->NotifyDataChange(ctxt->extInfo.eventId, ctxt->extInfo.extraData, ctxt->userId); + } else { + status = proxy->NotifyDataChange(ctxt->accountId, ctxt->bundleName); + } + LOG_DEBUG("NotifyDataChange return %{public}d", status); + ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) + ? napi_ok : napi_generic_failure; }; return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute); } diff --git a/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp index d103e98d61fd6de9f86d55ff27e91021380223c6..e12c5d888b71de321cb5e9bb6b4a71ff6ce51c37 100644 --- a/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp +++ b/relational_store/frameworks/js/napi/cloud_data/src/js_const_properties.cpp @@ -48,21 +48,43 @@ static napi_value ExportRole(napi_env env) napi_value role = nullptr; napi_create_object(env, &role); SetNamedProperty(env, role, "ROLE_INVITER", Role::ROLE_INVITER); - SetNamedProperty(env, role, "ROLE_INVITEE", Role::ROLE_INVITEES); + SetNamedProperty(env, role, "ROLE_INVITEE", Role::ROLE_INVITEE); napi_object_freeze(env, role); return role; } -static napi_value ExportShareStatus(napi_env env) +static napi_value ExportShareState(napi_env env) { - napi_value status = nullptr; - napi_create_object(env, &status); - SetNamedProperty(env, status, "STATUS_UNKNOWN", Confirmation::CFM_UNKNOWN); - SetNamedProperty(env, status, "STATUS_ACCEPTED", Confirmation::CFM_ACCEPTED); - SetNamedProperty(env, status, "STATUS_REJECTED", Confirmation::CFM_REJECTED); - SetNamedProperty(env, status, "STATUS_SUSPENDED", Confirmation::CFM_SUSPENDED); - napi_object_freeze(env, status); - return status; + napi_value state = nullptr; + napi_create_object(env, &state); + SetNamedProperty(env, state, "STATE_UNKNOWN", Confirmation::CFM_UNKNOWN); + SetNamedProperty(env, state, "STATE_ACCEPTED", Confirmation::CFM_ACCEPTED); + SetNamedProperty(env, state, "STATE_REJECTED", Confirmation::CFM_REJECTED); + SetNamedProperty(env, state, "STATE_SUSPENDED", Confirmation::CFM_SUSPENDED); + napi_object_freeze(env, state); + return state; +} + +static napi_value ExportShareCode(napi_env env) +{ + napi_value code = nullptr; + napi_create_object(env, &code); + SetNamedProperty(env, code, "SUCCESS", SharingCode::SUCCESS); + SetNamedProperty(env, code, "REPEATED_REQUEST", SharingCode::REPEATED_REQUEST); + SetNamedProperty(env, code, "NOT_INVITER", SharingCode::NOT_INVITER); + SetNamedProperty(env, code, "NOT_INVITER_OR_INVITEE", SharingCode::NOT_INVITER_OR_INVITEE); + SetNamedProperty(env, code, "OVER_QUOTA", SharingCode::OVER_QUOTA); + SetNamedProperty(env, code, "TOO_MANY_PARTICIPANTS", SharingCode::TOO_MANY_PARTICIPANTS); + SetNamedProperty(env, code, "INVALID_ARGS", SharingCode::INVALID_ARGS); + SetNamedProperty(env, code, "NETWORK_ERROR", SharingCode::NETWORK_ERROR); + SetNamedProperty(env, code, "CLOUD_DISABLED", SharingCode::CLOUD_DISABLED); + SetNamedProperty(env, code, "SERVER_ERROR", SharingCode::SERVER_ERROR); + SetNamedProperty(env, code, "INNER_ERROR", SharingCode::INNER_ERROR); + SetNamedProperty(env, code, "INVALID_INVITATION", SharingCode::INVALID_INVITATION); + SetNamedProperty(env, code, "RATE_LIMIT", SharingCode::RATE_LIMIT); + SetNamedProperty(env, code, "CUSTOM_ERROR", SharingCode::CUSTOM_ERROR); + napi_object_freeze(env, code); + return code; } napi_status InitConstProperties(napi_env env, napi_value exports) @@ -70,8 +92,21 @@ napi_status InitConstProperties(napi_env env, napi_value exports) const napi_property_descriptor properties[] = { DECLARE_NAPI_PROPERTY("Action", ExportAction(env)), DECLARE_NAPI_PROPERTY("ClearAction", ExportAction(env)), + }; + size_t count = sizeof(properties) / sizeof(properties[0]); + + return napi_define_properties(env, exports, count, properties); +} + +napi_status InitSharingConstProperties(napi_env env, napi_value exports) +{ + if (exports == nullptr) { + return napi_generic_failure; + } + const napi_property_descriptor properties[] = { DECLARE_NAPI_PROPERTY("Role", ExportRole(env)), - DECLARE_NAPI_PROPERTY("Status", ExportShareStatus(env)), + DECLARE_NAPI_PROPERTY("State", ExportShareState(env)), + DECLARE_NAPI_PROPERTY("SharingCode", ExportShareCode(env)), }; size_t count = sizeof(properties) / sizeof(properties[0]); diff --git a/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn b/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3a7f6a699033b5284e7d3170d69c9adb7cf97fee --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_extension/BUILD.gn @@ -0,0 +1,43 @@ +# Copyright (c) 2023 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//arkcompiler/ets_frontend/es2panda/es2abc_config.gni") +import("//build/ohos.gni") +import("//foundation/arkui/ace_engine/ace_config.gni") + +es2abc_gen_abc("gen_cloud_extension_abc") { + src_js = rebase_path("cloud_sharing_types_util.js") + dst_file = rebase_path(target_out_dir + "/cloud_extension.abc") + in_puts = [ "cloud_sharing_types_util.js" ] + out_puts = [ target_out_dir + "/cloud_extension.abc" ] + extra_args = [ "--module" ] +} + +gen_js_obj("cloud_extension_abc") { + input = get_label_info(":gen_cloud_extension_abc", "target_out_dir") + + "/cloud_extension.abc" + output = target_out_dir + "/cloud_extension_abc.o" + dep = ":gen_cloud_extension_abc" +} + +ohos_shared_library("cloudextension") { + sources = [ "cloud_extension.cpp" ] + + deps = [ ":cloud_extension_abc" ] + + external_deps = [ "napi:ace_napi" ] + + relative_install_dir = "module/data" + subsystem_name = "distributeddatamgr" + part_name = "relational_store" +} diff --git a/relational_store/frameworks/js/napi/cloud_extension/cloud_extension.cpp b/relational_store/frameworks/js/napi/cloud_extension/cloud_extension.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f4862727dcc5acfce315fd68c5bc504cd116e0dd --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_extension/cloud_extension.cpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "native_engine/native_engine.h" + +#include "napi/native_api.h" +#include "napi/native_node_api.h" + +extern const char _binary_cloud_extension_abc_start[]; +extern const char _binary_cloud_extension_abc_end[]; + +extern "C" __attribute__((visibility("default"))) void NAPI_data_cloudExtension_GetABCCode(const char **buf, int *buflen) +{ + if (buf != nullptr) { + *buf = _binary_cloud_extension_abc_start; + } + + if (buf != nullptr) { + *buflen = _binary_cloud_extension_abc_end - _binary_cloud_extension_abc_start; + } +} + +extern "C" __attribute__((constructor)) void cloudExtensionRegisterModule(void) +{ + static napi_module cloudExtensionModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_modname = "data.cloudExtension", + .nm_priv = ((void*)0), + .reserved = { 0 }, + }; + napi_module_register(&cloudExtensionModule); +} \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/cloud_extension/cloud_sharing_types_util.js b/relational_store/frameworks/js/napi/cloud_extension/cloud_sharing_types_util.js new file mode 100644 index 0000000000000000000000000000000000000000..c70d3372af0c9ed87dd4ae5394580c6a6cff9522 --- /dev/null +++ b/relational_store/frameworks/js/napi/cloud_extension/cloud_sharing_types_util.js @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +let rpc = requireNapi('rpc'); + +const TAG = "sharingCenterExtension"; + +export var cloudExtension; +!function(e) { + let t; + !function(e) { + e[e.ConnectShareCenter = 0] = "ConnectShareCenter" + }(t = e.CloudService_Function || (e.CloudService_Function = {})); + let a; + !function(e) { + e[e.Share = 0] = "Share"; + e[e.Unshare = 1] = "Unshare"; + e[e.Exit = 2] = "Exit"; + e[e.ChangePrivilege = 3] = "ChangePrivilege"; + e[e.QueryParticipants = 4] = "QueryParticipants"; + e[e.QueryParticipantsByInvitation = 5] = "QueryParticipantsByInvitation"; + e[e.ConfirmInvitation = 6] = "ConfirmInvitation"; + e[e.ChangeConfirmation = 7] = "ChangeConfirmation" + }(a = e.ShareCenter_Function || (e.ShareCenter_Function = {})); + + class r extends rpc.RemoteObject { + constructor(e, t) { + super(e); + this.cloudService = t; + console.info(`${TAG} CloudServiceProxy constructor`) + } + + async onRemoteMessageRequest(e, a, r, n) { + console.info(`${TAG}, onRemoteRequest called, code = ${e}`); + n.setWaitTime(1e3); + if (e === t.ConnectShareCenter) { + let e = a.readInt(); + let t = a.readInt(); + let n = this.unMarshallingString(a.readRawData(t)); + let i = await this.cloudService.connectShareCenter(e, n); + null == i && console.error(`${TAG}, sharingCenter is null`); + r.writeRemoteObject(i); + return !0 + } + console.error(`${TAG}, invalid request code ${e}`); + return !1 + } + + unMarshallingString(e) { + let t = ""; + e.forEach((e => { + t += String.fromCharCode(e) + })); + return t.toString() + } + } + + e.CloudServiceProxy = r; + + class n extends rpc.RemoteObject { + constructor(e, t) { + super(e); + this.shareCenter = t; + console.info(`${TAG} shareCenter constructor`) + } + + async onRemoteMessageRequest(e, t, r, n) { + console.info(`${TAG}, onRemoteRequest called, code = = ${e}`); + if (void 0 === this.shareCenter) return !1; + n.setWaitTime(1500); + switch(e) { + case a.Share: + let e = t.readInt(); + let n = t.readInt(); + let i = this.unMarshallingString(t.readRawData(n)); + let l = t.readInt(); + let s = this.unMarshallingString(t.readRawData(l)); + let o = this.unMarshallingParticipants(t); + let h = await this.shareCenter.share(e, i, s, o); + this.marshallingResults(r, h); + return !0; + case a.Unshare: + let c = t.readInt(); + let u = t.readInt(); + let g = this.unMarshallingString(t.readRawData(u)); + let d = t.readInt(); + let I = this.unMarshallingString(t.readRawData(d)); + let w = this.unMarshallingParticipants(t); + let S = await this.shareCenter.unshare(c, g, I, w); + this.marshallingResults(r, S); + return !0; + case a.Exit: + let C = t.readInt(); + let m = t.readInt(); + let f = this.unMarshallingString(t.readRawData(m)); + let p = t.readInt(); + let v = this.unMarshallingString(t.readRawData(p)); + let R = await this.shareCenter.exit(C, f, v); + r.writeInt(R.code); + R.description ? this.marshallingString(r, R.description) : r.writeInt(0); + return !0; + case a.ChangePrivilege: + let M = t.readInt(); + let P = t.readInt(); + let y = this.unMarshallingString(t.readRawData(P)); + let D = t.readInt(); + let x = this.unMarshallingString(t.readRawData(D)); + let b = this.unMarshallingParticipants(t); + let $ = await this.shareCenter.changePrivilege(M, y, x, b); + this.marshallingResults(r, $); + return !0; + case a.QueryParticipants: + let B = t.readInt(); + let A = t.readInt(); + let E = this.unMarshallingString(t.readRawData(A)); + let T = t.readInt(); + let q = this.unMarshallingString(t.readRawData(T)); + let j = await this.shareCenter.queryParticipants(B, E, q); + this.marshallingResultsArray(r, j); + return !0; + case a.QueryParticipantsByInvitation: + let G = t.readInt(); + let Q = t.readInt(); + let F = this.unMarshallingString(t.readRawData(Q)); + let O = t.readInt(); + let _ = this.unMarshallingString(t.readRawData(O)); + let z = await this.shareCenter.queryParticipantsByInvitation(G, F, _); + this.marshallingResultsArray(r, z); + return !0; + case a.ConfirmInvitation: + let U = t.readInt(); + let W = t.readInt(); + let J = this.unMarshallingString(t.readRawData(W)); + let N = t.readInt(); + let k = this.unMarshallingString(t.readRawData(N)); + let H = t.readInt(); + let K = await this.shareCenter.confirmInvitation(U, J, k, H); + r.writeInt(K.code); + K.description ? this.marshallingString(r, K.description) : r.writeInt(0); + K.value ? this.marshallingString(r, K.value) : r.writeInt(0); + return !0; + case a.ChangeConfirmation: + let L = t.readInt(); + let V = t.readInt(); + let X = this.unMarshallingString(t.readRawData(V)); + let Y = t.readInt(); + let Z = this.unMarshallingString(t.readRawData(Y)); + let ee = t.readInt(); + let te = await this.shareCenter.changeConfirmation(L, X, Z, ee); + r.writeInt(te.code); + te.description ? this.marshallingString(r, te.description) : r.writeInt(0); + return !0; + default: + console.info(`${TAG}, invalid request code`) + } + return !1 + } + + unMarshallingParticipants(e) { + let t = []; + let a = e.readInt(); + console.info(`${TAG}, query fields length = ${a}`); + for (let r = 0; r < a; r++) t.push(this.unMarshallingParticipant(e)); + return t + } + + unMarshallingParticipant(e) { + let t = e.readInt(); + let a; + a = { + identity: this.unMarshallingString(e.readRawData(t)), + role: e.readInt(), + state: e.readInt(), + privilege: this.unMarshallingPrivilege(e), + attachInfo: this.unMarshallingString(e.readRawData(e.readInt())) + }; + return a + } + + unMarshallingPrivilege(e) { + let t; + t = { + writable: e.readBoolean(), + readable: e.readBoolean(), + creatable: e.readBoolean(), + deletable: e.readBoolean(), + shareable: e.readBoolean() + }; + return t + } + + marshallingResultsArray(e, t) { + e.writeInt(t.code); + t.description ? this.marshallingString(e, t.description) : e.writeInt(0); + if (t.value) { + e.writeInt(t.value.length); + t.value.forEach((t => { + this.marshallingParticipant(e, t) + })) + } + } + + marshallingResults(e, t) { + e.writeInt(t.code); + t.description ? this.marshallingString(e, t.description) : e.writeInt(0); + if (t.value) { + e.writeInt(t.value.length); + t.value.forEach((t => { + e.writeInt(t.code); + t.description ? this.marshallingString(e, t.description) : e.writeInt(0) + })) + } + } + + marshallingParticipant(e, t) { + this.marshallingString(e, t.identity); + e.writeInt(t.role); + e.writeInt(t.state); + t.privilege && this.marshallingPrivilege(e, t.privilege); + t.attachInfo ? this.marshallingString(e, t.attachInfo) : e.writeInt(0) + } + + marshallingPrivilege(e, t) { + e.writeBoolean(t.writable); + e.writeBoolean(t.readable); + e.writeBoolean(t.creatable); + e.writeBoolean(t.deletable); + e.writeBoolean(t.shareable) + } + + unMarshallingString(e) { + let t = ""; + e.forEach((e => { + t += String.fromCharCode(e) + })); + return t.toString() + } + + marshallingString(e, t) { + let a = []; + let r; + r = t; + let n = t.length; + e.writeInt(n); + for (let e = 0; e < n; e++) a.push(r.charCodeAt(e)); + e.writeRawData(a, n) + } + } + + e.ShareCenterProxy = n; + e.createCloudServiceStub = async function (e) { + return new r("CloudServiceProxy", e) + }; + e.createShareServiceStub = async function (e) { + return new n("ShareCenterProxy", e) + } +}(cloudExtension || (cloudExtension = {})); + +export default { + cloudExtension, + createCloudServiceStub: cloudExtension.createCloudServiceStub, + createShareServiceStub: cloudExtension.createShareServiceStub, +}; \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/common/include/js_proxy.h b/relational_store/frameworks/js/napi/common/include/js_proxy.h new file mode 100644 index 0000000000000000000000000000000000000000..67cf505e9925c1a17753e17127d9253021f513fd --- /dev/null +++ b/relational_store/frameworks/js/napi/common/include/js_proxy.h @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef OHOS_RELATIONAL_STORE_JS_NAPI_COMMON_JS_PROXY_H +#define OHOS_RELATIONAL_STORE_JS_NAPI_COMMON_JS_PROXY_H +#include +namespace OHOS::JSProxy { +template +class JSCreator { +public: + virtual std::shared_ptr Create() = 0; +protected: + JSCreator() = default; + ~JSCreator() = default; +}; + +template +class JSProxy { +public: + void SetInstance(std::shared_ptr instance) + { + instance_ = std::move(instance); + } + std::shared_ptr GetInstance() const + { + return instance_; + } + +protected: + JSProxy() = default; + ~JSProxy() = default; + +private: + std::shared_ptr instance_; +}; + +template +class JSEntity : public JSCreator, public JSProxy { +protected: + JSEntity() = default; + ~JSEntity() = default; +}; +} // namespace OHOS::Proxy +#endif // OHOS_RELATIONAL_STORE_JS_NAPI_COMMON_JS_PROXY_H diff --git a/relational_store/frameworks/js/napi/common/include/js_utils.h b/relational_store/frameworks/js/napi/common/include/js_utils.h index 25dca0c418f0ce3756106d41caedf62c4864c24b..23068026ebf4146b1040685fa849c581742943d1 100644 --- a/relational_store/frameworks/js/napi/common/include/js_utils.h +++ b/relational_store/frameworks/js/napi/common/include/js_utils.h @@ -27,7 +27,6 @@ #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" -#include "itypes_util.h" namespace OHOS { namespace AppDataMgrJsKit { @@ -64,7 +63,6 @@ int32_t Convert2ValueExt(napi_env env, napi_value jsValue, int64_t &output); int32_t Convert2Value(napi_env env, napi_value jsValue, bool &output); int32_t Convert2Value(napi_env env, napi_value jsValue, double &output); int32_t Convert2Value(napi_env env, napi_value jsValue, int64_t &output); -int32_t Convert2Value(napi_env env, napi_value jsValue, int32_t &output); // TODO int32_t Convert2Value(napi_env env, napi_value jsValue, std::string &output); int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector &output); int32_t Convert2Value(napi_env env, napi_value jsValue, std::monostate &value); @@ -78,9 +76,15 @@ bool Equal(napi_env env, napi_ref ref, napi_value value); template int32_t Convert2Value(napi_env env, napi_value jsValue, T &output); +template +int32_t Convert2ValueExt(napi_env env, napi_value jsValue, T &output); + template int32_t Convert2Value(napi_env env, napi_value jsValue, std::vector &value); +template +int32_t Convert2Value(napi_env env, napi_value jsValue, std::map &value); + template int32_t Convert2Value(napi_env env, napi_value jsValue, std::variant &value); @@ -116,12 +120,12 @@ napi_value Convert2JSValue(napi_env env, const std::vector &value); template napi_value Convert2JSValue(napi_env env, const std::map &value); +template +napi_value Convert2JSValue(napi_env env, const std::tuple &value); + template napi_value Convert2JSValue(napi_env env, const std::variant &value); -template -napi_value Convert2JSValue(napi_env env, const Result &value); - template std::string ToString(const T &key); @@ -135,6 +139,9 @@ int32_t GetOptionalValue(napi_env env, napi_value in, const char *name, T& out) if (value == nullptr) { return napi_ok; } + if (std::is_same_v) { + return JSUtils::Convert2ValueExt(env, value, out); + } return JSUtils::Convert2Value(env, value, out); } @@ -213,6 +220,45 @@ int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::vector return napi_ok; } +template +int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::map &value) +{ + napi_value jsMapList = nullptr; + uint32_t jsCount = 0; + napi_status status = napi_get_property_names(env, jsValue, &jsMapList); + if (status != napi_ok) { + return napi_invalid_arg; + } + status = napi_get_array_length(env, jsMapList, &jsCount); + if (status != napi_ok || jsCount <= 0) { + return napi_invalid_arg; + } + napi_value jsKey = nullptr; + napi_value jsVal = nullptr; + for (uint32_t index = 0; index < jsCount; index++) { + status = napi_get_element(env, jsMapList, index, &jsKey); + if (status != napi_ok) { + return napi_invalid_arg; + } + std::string key; + int ret = Convert2Value(env, jsKey, key); + if (status != napi_ok) { + return napi_invalid_arg; + } + status = napi_get_property(env, jsValue, jsKey, &jsVal); + if (status != napi_ok || jsVal == nullptr) { + return napi_invalid_arg; + } + T val; + ret = Convert2Value(env, jsVal, val); + if (status != napi_ok) { + return napi_invalid_arg; + } + value.insert(std::pair(key, val)); + } + return napi_ok; +} + template napi_value JSUtils::Convert2JSValue(napi_env env, const std::map &value) { @@ -233,32 +279,29 @@ napi_value JSUtils::Convert2JSValue(napi_env env, const std::map &value) } template -napi_value JSUtils::Convert2JSValue(napi_env env, const Result &value) +napi_value JSUtils::Convert2JSValue(napi_env env, const std::tuple &value) { napi_value jsValue; napi_status status = napi_create_object(env, &jsValue); if (status != napi_ok) { return nullptr; } - napi_value errCode = Convert2JSValue(env, value.errCode); - napi_value result = nullptr; - if (std::is_null_pointer::value) { - napi_get_undefined(env, &result); - } else { - result = Convert2JSValue(env, value.value); - } - if (result == nullptr) { + napi_value code = Convert2JSValue(env, std::get<0>(value)); + napi_value description = Convert2JSValue(env, std::get<1>(value)); + napi_value val = Convert2JSValue(env, std::get<2>(value)); + if (description == nullptr || val == nullptr) { return nullptr; } - napi_set_named_property(env, jsValue, "errCode", errCode); - napi_set_named_property(env, jsValue, "value", result); + napi_set_named_property(env, jsValue, "code", code); + napi_set_named_property(env, jsValue, "description", description); + napi_set_named_property(env, jsValue, "value", val); return jsValue; } template int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, std::variant &value) { - napi_valuetype type; + napi_valuetype type = napi_undefined; napi_status status = napi_typeof(env, jsValue, &type); if (status != napi_ok) { return napi_invalid_arg; @@ -292,4 +335,4 @@ napi_value JSUtils::Convert2JSValue(napi_env env, const std::variant & } } // namespace AppDataMgrJsKit } // namespace OHOS -#endif // DISTRIBUTEDDATAMGR_APPDATAMGR_JSUTILS_H +#endif // DISTRIBUTEDDATAMGR_APPDATAMGR_JSUTILS_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/common/src/js_utils.cpp b/relational_store/frameworks/js/napi/common/src/js_utils.cpp index 419572e07b063887288a771df9506c83f65ed40d..c7aa56bb77274ccb651a849c6706939345922a21 100644 --- a/relational_store/frameworks/js/napi/common/src/js_utils.cpp +++ b/relational_store/frameworks/js/napi/common/src/js_utils.cpp @@ -60,7 +60,6 @@ napi_value JSUtils::GetNamedProperty(napi_env env, napi_value object, const char return jsItem; } - std::pair JSUtils::GetOptionalNamedProperty(napi_env env, napi_value input, const char *name) { bool hasProp = false; @@ -69,7 +68,7 @@ std::pair JSUtils::GetOptionalNamedProperty(napi_env env, return std::make_pair(napi_generic_failure, nullptr); } if (!hasProp) { - return std::make_pair(napi_ok, nullptr);; + return std::make_pair(napi_ok, nullptr); } napi_value inner = nullptr; status = napi_get_named_property(env, input, name, &inner); @@ -123,23 +122,6 @@ int32_t JSUtils::Convert2ValueExt(napi_env env, napi_value jsValue, int32_t &out return status; } -int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, int32_t &output) -{ - napi_valuetype type = napi_undefined; - napi_status status = napi_typeof(env, jsValue, &type); - if (status != napi_ok || type != napi_number) { - LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type); - return napi_invalid_arg; - } - - status = napi_get_value_int32(env, jsValue, &output); - if (status != napi_ok) { - LOG_DEBUG("napi_get_value_int32 failed, status = %{public}d", status); - return status; - } - return status; -} - int32_t JSUtils::Convert2Value(napi_env env, napi_value jsValue, bool &output) { napi_valuetype type = napi_undefined; @@ -491,8 +473,9 @@ napi_value JSUtils::DefineClass(napi_env env, const std::string &spaceName, cons if (!featureSpace.has_value() || !featureSpace->isComponent) { return nullptr; } - if (GetClass(env, spaceName, className)) { - return GetClass(env, spaceName, className); + auto constructor = GetClass(env, spaceName, className); + if (constructor != nullptr) { + return constructor; } auto rootPropName = std::string(featureSpace->nameBase64); napi_value root = nullptr; @@ -508,13 +491,12 @@ napi_value JSUtils::DefineClass(napi_env env, const std::string &spaceName, cons } std::string propName = "constructor_of_" + className; - napi_value constructor = nullptr; bool hasProp = false; napi_has_named_property(env, root, propName.c_str(), &hasProp); if (hasProp) { napi_get_named_property(env, root, propName.c_str(), &constructor); if (constructor != nullptr) { - LOG_DEBUG("got data.cloudData.%{public}s as constructor", propName.c_str()); + LOG_DEBUG("got %{public}s from %{public}s", propName.c_str(), featureSpace->spaceName); return constructor; } hasProp = false; // no constructor. @@ -526,7 +508,7 @@ napi_value JSUtils::DefineClass(napi_env env, const std::string &spaceName, cons if (!hasProp) { napi_set_named_property(env, root, propName.c_str(), constructor); - LOG_DEBUG("save constructor to data.cloudData.%{public}s", propName.c_str()); + LOG_DEBUG("save %{public}s to %{public}s", propName.c_str(), featureSpace->spaceName); } return constructor; } @@ -556,7 +538,7 @@ napi_value JSUtils::GetClass(napi_env env, const std::string &spaceName, const s } napi_get_named_property(env, root, propName.c_str(), &constructor); if (constructor != nullptr) { - LOG_DEBUG("got data.cloudData.%{public}s as constructor", propName.c_str()); + LOG_DEBUG("got %{public}s from %{public}s", propName.c_str(), featureSpace->spaceName); return constructor; } hasProp = false; // no constructor. @@ -573,4 +555,4 @@ bool JSUtils::Equal(napi_env env, napi_ref ref, napi_value value) return isEquals; } } // namespace AppDataMgrJsKit -} // namespace OHOS +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/dataability/BUILD.gn b/relational_store/frameworks/js/napi/dataability/BUILD.gn index 7d79cc09cc1ce6735852fa37655fe99138cf614b..51d68243ad8d733d1e58fe7c372dc9efacf1b29b 100644 --- a/relational_store/frameworks/js/napi/dataability/BUILD.gn +++ b/relational_store/frameworks/js/napi/dataability/BUILD.gn @@ -22,6 +22,13 @@ ohos_copy("relational_store_declaration") { } ohos_shared_library("dataability") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + include_dirs = [ "include", "${relational_store_common_path}/include", diff --git a/relational_store/frameworks/js/napi/rdb/BUILD.gn b/relational_store/frameworks/js/napi/rdb/BUILD.gn index 6a810946cb027fc194db915441d0087259c54bf6..2e4374e8161558d9e2d54f01dd51cc85869c1528 100644 --- a/relational_store/frameworks/js/napi/rdb/BUILD.gn +++ b/relational_store/frameworks/js/napi/rdb/BUILD.gn @@ -63,6 +63,15 @@ ohos_shared_library("napi_rdb") { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] } else { + if (is_ohos) { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + } + include_dirs = [ "include", "${datashare_path}/common/include/", @@ -130,6 +139,15 @@ ohos_shared_library("rdb") { "//foundation/distributeddatamgr/relational_store/interfaces/inner_api/rdb:native_rdb", ] } else { + if (is_ohos) { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + } + include_dirs = [ "include", "${datashare_path}/common/include/", diff --git a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn index 62be81b2161213dc5f6991d69b9041876aa67726..3c860439b96ce36a151503d969b791d1090a4f11 100644 --- a/relational_store/frameworks/js/napi/relationalstore/BUILD.gn +++ b/relational_store/frameworks/js/napi/relationalstore/BUILD.gn @@ -37,6 +37,13 @@ sources = [ if (is_ohos) { ohos_shared_library("relationalstore") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + include_dirs = [ "include", "${datashare_path}/common/include/", diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h index 268d3086a0239c4e5939a18d56ffa9569f2016c2..3d1a401e90497d4d6fed3f99fb07d31b6d6ba2b2 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_js_utils.h @@ -35,6 +35,12 @@ using PRIKey = OHOS::DistributedRdb::RdbStoreObserver::PrimaryKey; template<> int32_t Convert2Value(napi_env env, napi_value input, Asset &output); +template<> +int32_t Convert2Value(napi_env env, napi_value jsValue, DistributedRdb::Reference &output); + +template<> +int32_t Convert2Value(napi_env env, napi_value jsValue, DistributedRdb::DistributedConfig &output); + template<> int32_t Convert2Value(napi_env env, napi_value jsValue, ValueObject &valueObject); @@ -65,4 +71,4 @@ template<> std::string ToString(const PRIKey &key); }; // namespace JSUtils } // namespace OHOS::AppDataMgrJsKit -#endif // RDB_JSKIT_NAPI_RDB_JS_UTILS_H +#endif // RDB_JSKIT_NAPI_RDB_JS_UTILS_H \ No newline at end of file diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h index 5317cbf1fe749d778f2e3b8f941f11f210bda1ad..75c124a0a33324c8f09b8bebd5a23589f2256a07 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_predicates.h @@ -18,6 +18,7 @@ #include +#include "js_proxy.h" #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" @@ -26,7 +27,7 @@ namespace OHOS { namespace RelationalStoreJsKit { -class RdbPredicatesProxy { +class RdbPredicatesProxy : public JSProxy::JSProxy { public: static void Init(napi_env env, napi_value exports); static napi_value NewInstance(napi_env env, std::shared_ptr value); @@ -102,8 +103,6 @@ private: static napi_value GetBindArgs(napi_env env, napi_callback_info info); static napi_value InDevices(napi_env env, napi_callback_info info); static napi_value InAllDevices(napi_env env, napi_callback_info info); - - std::shared_ptr predicates_; }; } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h index 7ced61d051c0f34e5864cbc2182f00ee98922057..fa693c174315c6d7db855b35a03957989d1b82fb 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_rdb_store.h @@ -72,9 +72,11 @@ private: static napi_value Sync(napi_env env, napi_callback_info info); static napi_value CloudSync(napi_env env, napi_callback_info info); static napi_value GetModifyTime(napi_env env, napi_callback_info info); + static napi_value CleanDirtyData(napi_env env, napi_callback_info info); static napi_value OnEvent(napi_env env, napi_callback_info info); static napi_value OffEvent(napi_env env, napi_callback_info info); static napi_value Notify(napi_env env, napi_callback_info info); + static napi_value QuerySharingResource(napi_env env, napi_callback_info info); static constexpr int EVENT_HANDLE_NUM = 2; diff --git a/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h b/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h index d9d8b6d9165b2bcdabf0c90ae29529f2773fd2e4..0f7131b24c58e360a7efdfc43aec30f53f6305f4 100644 --- a/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h +++ b/relational_store/frameworks/js/napi/relationalstore/include/napi_result_set.h @@ -19,6 +19,7 @@ #include #include "asset_value.h" +#include "js_proxy.h" #include "napi/native_api.h" #include "napi/native_common.h" #include "napi/native_node_api.h" @@ -28,14 +29,14 @@ namespace OHOS { namespace RelationalStoreJsKit { -class ResultSetProxy final : public DataShare::ResultSetBridge::Creator { +class ResultSetProxy final : public JSProxy::JSEntity { public: ResultSetProxy() = default; ~ResultSetProxy(); ResultSetProxy(std::shared_ptr resultSet); ResultSetProxy &operator=(std::shared_ptr resultSet); + static void Init(napi_env env, napi_value exports); static napi_value NewInstance(napi_env env, std::shared_ptr resultSet); - static napi_value GetConstructor(napi_env env); std::shared_ptr Create() override; private: @@ -74,8 +75,6 @@ private: static napi_value IsColumnNull(napi_env env, napi_callback_info info); static napi_value GetRow(napi_env env, napi_callback_info info); static napi_value IsClosed(napi_env env, napi_callback_info info); - - std::shared_ptr resultSet_; }; } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp b/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp index bd71af436d771a0049c0c55c5236904f4b4e1a61..f47662bfa0a06af171de38ac4b11c7c6fcf992c3 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/entry_point.cpp @@ -17,6 +17,7 @@ #include "napi_rdb_store.h" #include "napi_rdb_store_helper.h" #include "napi_rdb_const_properties.h" +#include "napi_result_set.h" #include "napi/native_api.h" using namespace OHOS::RelationalStoreJsKit; @@ -30,6 +31,7 @@ static napi_value Init(napi_env env, napi_value exports) InitRdbHelper(env, exports); RdbStoreProxy::Init(env, exports); RdbPredicatesProxy::Init(env, exports); + ResultSetProxy::Init(env, exports); InitConstProperties(env, exports); return exports; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp index a40206bc58838941b3c1d9bdb3b257a2434a0914..90fb362000a3cd4256fbe389c019947157fd5d64 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_const_properties.cpp @@ -16,47 +16,36 @@ #include "napi_rdb_const_properties.h" #include "rdb_common.h" #include "rdb_store.h" +#include "js_utils.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #include "rdb_store_config.h" #include "rdb_types.h" using OHOS::DistributedRdb::SyncMode; using OHOS::DistributedRdb::SubscribeMode; + #endif using OHOS::NativeRdb::SecurityLevel; using OHOS::NativeRdb::ConflictResolution; +using OHOS::DistributedRdb::ProgressCode; +using OHOS::DistributedRdb::DistributedTableType; -#define SET_NAPI_PROPERTY(object, propName, value) \ -{ \ - (void) SetNamedProperty(env, (object), (propName), (int32_t)(value)); \ -} +#define SET_NAPI_PROPERTY(object, prop, value) \ + napi_set_named_property((env), (object), (prop), AppDataMgrJsKit::JSUtils::Convert2JSValue((env), (value))) namespace OHOS::RelationalStoreJsKit { #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) -static napi_status SetNamedProperty(napi_env env, napi_value& obj, const std::string& name, int32_t value) -{ - napi_value property = nullptr; - napi_status status = napi_create_int32(env, value, &property); - if (status != napi_ok) { - return status; - } - status = napi_set_named_property(env, obj, name.c_str(), property); - if (status != napi_ok) { - return status; - } - return status; -} static napi_value ExportSyncMode(napi_env env) { napi_value syncMode = nullptr; napi_create_object(env, &syncMode); - SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_PUSH", SyncMode::PUSH); - SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_PULL", SyncMode::PULL); - SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_TIME_FIRST", SyncMode::TIME_FIRST); - SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_NATIVE_FIRST", SyncMode::NATIVE_FIRST); - SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_CLOUD_FIRST", SyncMode::CLOUD_FIRST); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_PUSH", int32_t(SyncMode::PUSH)); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_PULL", int32_t(SyncMode::PULL)); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_TIME_FIRST", int32_t(SyncMode::TIME_FIRST)); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_NATIVE_FIRST", int32_t(SyncMode::NATIVE_FIRST)); + SET_NAPI_PROPERTY(syncMode, "SYNC_MODE_CLOUD_FIRST", int32_t(SyncMode::CLOUD_FIRST)); napi_object_freeze(env, syncMode); return syncMode; } @@ -66,9 +55,9 @@ static napi_value ExportSubscribeType(napi_env env) napi_value subscribeType = nullptr; napi_create_object(env, &subscribeType); - SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_REMOTE", SubscribeMode::REMOTE); - SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_CLOUD", SubscribeMode::CLOUD); - SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_CLOUD_DETAILS", SubscribeMode::CLOUD_DETAIL); + SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_REMOTE", int32_t(SubscribeMode::REMOTE)); + SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_CLOUD", int32_t(SubscribeMode::CLOUD)); + SET_NAPI_PROPERTY(subscribeType, "SUBSCRIBE_TYPE_CLOUD_DETAILS", int32_t(SubscribeMode::CLOUD_DETAIL)); napi_object_freeze(env, subscribeType); return subscribeType; } @@ -78,10 +67,10 @@ static napi_value ExportSecurityLevel(napi_env env) napi_value securityLevel = nullptr; napi_create_object(env, &securityLevel); - SET_NAPI_PROPERTY(securityLevel, "S1", SecurityLevel::S1); - SET_NAPI_PROPERTY(securityLevel, "S2", SecurityLevel::S2); - SET_NAPI_PROPERTY(securityLevel, "S3", SecurityLevel::S3); - SET_NAPI_PROPERTY(securityLevel, "S4", SecurityLevel::S4); + SET_NAPI_PROPERTY(securityLevel, "S1", int32_t(SecurityLevel::S1)); + SET_NAPI_PROPERTY(securityLevel, "S2", int32_t(SecurityLevel::S2)); + SET_NAPI_PROPERTY(securityLevel, "S3", int32_t(SecurityLevel::S3)); + SET_NAPI_PROPERTY(securityLevel, "S4", int32_t(SecurityLevel::S4)); napi_object_freeze(env, securityLevel); return securityLevel; } @@ -92,9 +81,9 @@ static napi_value ExportProgress(napi_env env) napi_value progress = nullptr; napi_create_object(env, &progress); - SET_NAPI_PROPERTY(progress, "SYNC_BEGIN", 0); - SET_NAPI_PROPERTY(progress, "SYNC_IN_PROGRESS", 1); - SET_NAPI_PROPERTY(progress, "SYNC_FINISH", 2); + SET_NAPI_PROPERTY(progress, "SYNC_BEGIN", int32_t(DistributedRdb::Progress::SYNC_BEGIN)); + SET_NAPI_PROPERTY(progress, "SYNC_IN_PROGRESS", int32_t(DistributedRdb::Progress::SYNC_IN_PROGRESS)); + SET_NAPI_PROPERTY(progress, "SYNC_FINISH", int32_t(DistributedRdb::Progress::SYNC_FINISH)); napi_object_freeze(env, progress); return progress; } @@ -104,24 +93,51 @@ static napi_value ExportProgressCode(napi_env env) napi_value progressCode = nullptr; napi_create_object(env, &progressCode); - SET_NAPI_PROPERTY(progressCode, "SUCCESS", 0); - SET_NAPI_PROPERTY(progressCode, "UNKNOWN_ERROR", 1); - SET_NAPI_PROPERTY(progressCode, "NETWORK_ERROR", 2); - SET_NAPI_PROPERTY(progressCode, "CLOUD_DISABLED", 3); - SET_NAPI_PROPERTY(progressCode, "LOCKED_BY_OTHERS", 4); - SET_NAPI_PROPERTY(progressCode, "RECORD_LIMIT_EXCEEDED", 5); - SET_NAPI_PROPERTY(progressCode, "NO_SPACE_FOR_ASSET", 6); + SET_NAPI_PROPERTY(progressCode, "SUCCESS", int32_t(ProgressCode::SUCCESS)); + SET_NAPI_PROPERTY(progressCode, "UNKNOWN_ERROR", int32_t(ProgressCode::UNKNOWN_ERROR)); + SET_NAPI_PROPERTY(progressCode, "NETWORK_ERROR", int32_t(ProgressCode::NETWORK_ERROR)); + SET_NAPI_PROPERTY(progressCode, "CLOUD_DISABLED", int32_t(ProgressCode::CLOUD_DISABLED)); + SET_NAPI_PROPERTY(progressCode, "LOCKED_BY_OTHERS", int32_t(ProgressCode::LOCKED_BY_OTHERS)); + SET_NAPI_PROPERTY(progressCode, "RECORD_LIMIT_EXCEEDED", int32_t(ProgressCode::RECORD_LIMIT_EXCEEDED)); + SET_NAPI_PROPERTY(progressCode, "NO_SPACE_FOR_ASSET", int32_t(ProgressCode::NO_SPACE_FOR_ASSET)); napi_object_freeze(env, progressCode); return progressCode; } +static napi_value ExportOrigin(napi_env env) +{ + napi_value origin = nullptr; + napi_create_object(env, &origin); + + SET_NAPI_PROPERTY(origin, "LOCAL", int32_t(NativeRdb::AbsPredicates::Origin::LOCAL)); + SET_NAPI_PROPERTY(origin, "CLOUD", int32_t(NativeRdb::AbsPredicates::Origin::CLOUD)); + SET_NAPI_PROPERTY(origin, "REMOTE", int32_t(NativeRdb::AbsPredicates::Origin::REMOTE)); + napi_object_freeze(env, origin); + return origin; +} + +static napi_value ExportField(napi_env env) +{ + napi_value field = nullptr; + napi_create_object(env, &field); + + SET_NAPI_PROPERTY(field, "CURSOR_FIELD", std::string(DistributedRdb::Field::CURSOR_FIELD)); + SET_NAPI_PROPERTY(field, "ORIGIN_FIELD", std::string(DistributedRdb::Field::ORIGIN_FIELD)); + SET_NAPI_PROPERTY(field, "DELETED_FLAG_FIELD", std::string(DistributedRdb::Field::DELETED_FLAG_FIELD)); + SET_NAPI_PROPERTY(field, "OWNER_FIELD", std::string(DistributedRdb::Field::OWNER_FIELD)); + SET_NAPI_PROPERTY(field, "PRIVILEGE_FIELD", std::string(DistributedRdb::Field::PRIVILEGE_FIELD)); + SET_NAPI_PROPERTY(field, "SHARING_RESOURCE_FIELD", std::string(DistributedRdb::Field::SHARING_RESOURCE_FIELD)); + napi_object_freeze(env, field); + return field; +} + static napi_value ExportDistributedType(napi_env env) { napi_value distributedType = nullptr; napi_create_object(env, &distributedType); - SET_NAPI_PROPERTY(distributedType, "DISTRIBUTED_DEVICE", 0); - SET_NAPI_PROPERTY(distributedType, "DISTRIBUTED_CLOUD", 1); + SET_NAPI_PROPERTY(distributedType, "DISTRIBUTED_DEVICE", int32_t(DistributedTableType::DISTRIBUTED_DEVICE)); + SET_NAPI_PROPERTY(distributedType, "DISTRIBUTED_CLOUD", int32_t(DistributedTableType::DISTRIBUTED_CLOUD)); napi_object_freeze(env, distributedType); return distributedType; } @@ -131,8 +147,8 @@ static napi_value ExportChangeType(napi_env env) napi_value changeType = nullptr; napi_create_object(env, &changeType); - SET_NAPI_PROPERTY(changeType, "DATA_CHANGE", DistributedRdb::Origin::BASIC_DATA); - SET_NAPI_PROPERTY(changeType, "ASSET_CHANGE", DistributedRdb::Origin::ASSET_DATA); + SET_NAPI_PROPERTY(changeType, "DATA_CHANGE", int32_t(DistributedRdb::Origin::BASIC_DATA)); + SET_NAPI_PROPERTY(changeType, "ASSET_CHANGE", int32_t(DistributedRdb::Origin::ASSET_DATA)); napi_object_freeze(env, changeType); return changeType; } @@ -142,12 +158,12 @@ static napi_value ExportAssetStatus(napi_env env) napi_value assetStatus = nullptr; napi_create_object(env, &assetStatus); - SET_NAPI_PROPERTY(assetStatus, "ASSET_NORMAL", NativeRdb::AssetValue::STATUS_NORMAL); - SET_NAPI_PROPERTY(assetStatus, "ASSET_INSERT", NativeRdb::AssetValue::STATUS_INSERT); - SET_NAPI_PROPERTY(assetStatus, "ASSET_UPDATE", NativeRdb::AssetValue::STATUS_UPDATE); - SET_NAPI_PROPERTY(assetStatus, "ASSET_DELETE", NativeRdb::AssetValue::STATUS_DELETE); - SET_NAPI_PROPERTY(assetStatus, "ASSET_ABNORMAL", NativeRdb::AssetValue::STATUS_ABNORMAL); - SET_NAPI_PROPERTY(assetStatus, "ASSET_DOWNLOADING", NativeRdb::AssetValue::STATUS_DOWNLOADING); + SET_NAPI_PROPERTY(assetStatus, "ASSET_NORMAL", int32_t(NativeRdb::AssetValue::STATUS_NORMAL)); + SET_NAPI_PROPERTY(assetStatus, "ASSET_INSERT", int32_t(NativeRdb::AssetValue::STATUS_INSERT)); + SET_NAPI_PROPERTY(assetStatus, "ASSET_UPDATE", int32_t(NativeRdb::AssetValue::STATUS_UPDATE)); + SET_NAPI_PROPERTY(assetStatus, "ASSET_DELETE", int32_t(NativeRdb::AssetValue::STATUS_DELETE)); + SET_NAPI_PROPERTY(assetStatus, "ASSET_ABNORMAL", int32_t(NativeRdb::AssetValue::STATUS_ABNORMAL)); + SET_NAPI_PROPERTY(assetStatus, "ASSET_DOWNLOADING", int32_t(NativeRdb::AssetValue::STATUS_DOWNLOADING)); napi_object_freeze(env, assetStatus); return assetStatus; } @@ -157,12 +173,12 @@ static napi_value ExportConflictResolution(napi_env env) napi_value conflictResolution = nullptr; napi_create_object(env, &conflictResolution); - SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_NONE", ConflictResolution::ON_CONFLICT_NONE); - SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_ROLLBACK", ConflictResolution::ON_CONFLICT_ROLLBACK); - SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_ABORT", ConflictResolution::ON_CONFLICT_ABORT); - SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_FAIL", ConflictResolution::ON_CONFLICT_FAIL); - SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_IGNORE", ConflictResolution::ON_CONFLICT_IGNORE); - SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_REPLACE", ConflictResolution::ON_CONFLICT_REPLACE); + SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_NONE", int32_t(ConflictResolution::ON_CONFLICT_NONE)); + SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_ROLLBACK", int32_t(ConflictResolution::ON_CONFLICT_ROLLBACK)); + SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_ABORT", int32_t(ConflictResolution::ON_CONFLICT_ABORT)); + SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_FAIL", int32_t(ConflictResolution::ON_CONFLICT_FAIL)); + SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_IGNORE", int32_t(ConflictResolution::ON_CONFLICT_IGNORE)); + SET_NAPI_PROPERTY(conflictResolution, "ON_CONFLICT_REPLACE", int32_t(ConflictResolution::ON_CONFLICT_REPLACE)); napi_object_freeze(env, conflictResolution); return conflictResolution; @@ -182,6 +198,8 @@ napi_status InitConstProperties(napi_env env, napi_value exports) DECLARE_NAPI_PROPERTY("DistributedType", ExportDistributedType(env)), DECLARE_NAPI_PROPERTY("AssetStatus", ExportAssetStatus(env)), DECLARE_NAPI_PROPERTY("ChangeType", ExportChangeType(env)), + DECLARE_NAPI_PROPERTY("Origin", ExportOrigin(env)), + DECLARE_NAPI_PROPERTY("Field", ExportField(env)), }; size_t count = sizeof(properties) / sizeof(properties[0]); diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp index 56ed115685a4d8226a2b2c9b2aa52fb41c6d22d9..27fafe9ce4b742f8c87215d093a6eb341f78bb6a 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_js_utils.cpp @@ -60,7 +60,7 @@ int32_t Convert2Value(napi_env env, napi_value jsValue, Asset &output) } template<> -int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::DistributedConfig &output) +int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::Reference &output) { napi_valuetype type = napi_undefined; napi_status status = napi_typeof(env, input, &type); @@ -69,11 +69,29 @@ int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::Distribute return napi_invalid_arg; } - auto ret = Convert2Value(env, GetNamedProperty(env, input, "autoSync"), output.autoSync); - if (ret != napi_ok) { + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, sourceTable), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, targetTable), napi_invalid_arg); + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, refFields), napi_invalid_arg); + return napi_ok; +} + +template<> +int32_t Convert2Value(napi_env env, napi_value input, DistributedRdb::DistributedConfig &output) +{ + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, input, &type); + if (status != napi_ok || type != napi_object) { + LOG_DEBUG("napi_typeof failed status = %{public}d type = %{public}d", status, type); return napi_invalid_arg; } - return ret; + + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, autoSync), napi_invalid_arg); + bool exist = false; + status = napi_has_named_property(env, input, "references", &exist); + if (status == napi_ok && exist) { + NAPI_CALL_RETURN_ERR(GET_PROPERTY(env, input, output, references), napi_invalid_arg); + } + return napi_ok; } template<> @@ -97,7 +115,8 @@ napi_value Convert2JSValue(napi_env env, const Asset &value) NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, modifyTime), object); NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, size), object); NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, path), object); - NAPI_CALL_RETURN_ERR(ADD_JS_PROPERTY(env, object, value, status), object); + auto outputStatus = value.status & ~0xF0000000; + NAPI_CALL_RETURN_ERR(napi_set_named_property(env, object, "status", Convert2JSValue(env, outputStatus)), object); return object; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp index f31cf1f10fe7b31f433e4439a0488a603ce3c3b5..60aa0cdb7dbcb6573c1875eedbe4b1ecc93d84d6 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_predicates.cpp @@ -153,7 +153,7 @@ napi_value RdbPredicatesProxy::NewInstance(napi_env env, std::shared_ptrpredicates_ = std::move(value); + proxy->GetInstance() = std::move(value); LOG_DEBUG("RdbPredicatesProxy::NewInstance end"); return instance; } @@ -170,8 +170,8 @@ RdbPredicatesProxy::~RdbPredicatesProxy() } RdbPredicatesProxy::RdbPredicatesProxy(std::string &tableName) - : predicates_(std::make_shared(tableName)) { + SetInstance(std::make_shared(tableName)); } RdbPredicatesProxy *RdbPredicatesProxy::GetNativePredicates(napi_env env, napi_callback_info info) @@ -182,7 +182,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::GetNativePredicates(napi_env env, napi_c RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -205,7 +205,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::ParseFieldArrayByName(napi_env env, napi RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -222,7 +222,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::ParseFieldByName( RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -239,7 +239,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::ParseInt32FieldByName( RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -259,7 +259,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::ParseFieldAndValueArray(napi_env env, na RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -280,7 +280,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::ParseFieldAndValue(napi_env env, napi_ca RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -301,7 +301,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::ParseFieldAndStringValue(napi_env env, n RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -324,7 +324,7 @@ RdbPredicatesProxy *RdbPredicatesProxy::ParseFieldLowAndHigh( RdbPredicatesProxy *proxy = nullptr; napi_unwrap(env, thiz, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->predicates_, std::make_shared("predicates", "null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("predicates", "null")); return proxy; } @@ -336,8 +336,8 @@ napi_value RdbPredicatesProxy::EqualTo(napi_env env, napi_callback_info info) std::string field = ""; ValueObject value; auto predicatesProxy = ParseFieldAndValue(env, info, thiz, field, value, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->EqualTo(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->EqualTo(field, value); return thiz; } @@ -348,8 +348,8 @@ napi_value RdbPredicatesProxy::NotEqualTo(napi_env env, napi_callback_info info) std::string field = ""; ValueObject value; auto predicatesProxy = ParseFieldAndValue(env, info, thiz, field, value, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->NotEqualTo(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->NotEqualTo(field, value); return thiz; } @@ -359,8 +359,8 @@ napi_value RdbPredicatesProxy::BeginWrap(napi_env env, napi_callback_info info) napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->BeginWrap(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->BeginWrap(); return thiz; } @@ -370,8 +370,8 @@ napi_value RdbPredicatesProxy::EndWrap(napi_env env, napi_callback_info info) napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->EndWrap(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->EndWrap(); return thiz; } @@ -381,8 +381,8 @@ napi_value RdbPredicatesProxy::Or(napi_env env, napi_callback_info info) napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Or(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Or(); return thiz; } @@ -392,8 +392,8 @@ napi_value RdbPredicatesProxy::And(napi_env env, napi_callback_info info) napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->And(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->And(); return thiz; } @@ -404,8 +404,8 @@ napi_value RdbPredicatesProxy::Contains(napi_env env, napi_callback_info info) std::string field = ""; std::string value = ""; auto predicatesProxy = ParseFieldAndStringValue(env, info, thiz, field, value, "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Contains(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Contains(field, value); return thiz; } @@ -416,8 +416,8 @@ napi_value RdbPredicatesProxy::BeginsWith(napi_env env, napi_callback_info info) std::string field = ""; std::string value = ""; auto predicatesProxy = ParseFieldAndStringValue(env, info, thiz, field, value, "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->BeginsWith(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->BeginsWith(field, value); return thiz; } @@ -428,8 +428,8 @@ napi_value RdbPredicatesProxy::EndsWith(napi_env env, napi_callback_info info) std::string field = ""; std::string value = ""; auto predicatesProxy = ParseFieldAndStringValue(env, info, thiz, field, value, "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->EndsWith(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->EndsWith(field, value); return thiz; } @@ -439,8 +439,8 @@ napi_value RdbPredicatesProxy::IsNull(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::string field = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, field, "field"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->IsNull(field); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->IsNull(field); return thiz; } @@ -450,8 +450,8 @@ napi_value RdbPredicatesProxy::IsNotNull(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::string field = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, field, "field"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->IsNotNull(field); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->IsNotNull(field); return thiz; } @@ -462,8 +462,8 @@ napi_value RdbPredicatesProxy::Like(napi_env env, napi_callback_info info) std::string field = ""; std::string value = ""; auto predicatesProxy = ParseFieldAndStringValue(env, info, thiz, field, value, "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Like(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Like(field, value); return thiz; } @@ -474,8 +474,8 @@ napi_value RdbPredicatesProxy::Glob(napi_env env, napi_callback_info info) std::string field = ""; std::string value = ""; auto predicatesProxy = ParseFieldAndStringValue(env, info, thiz, field, value, "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Glob(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Glob(field, value); return thiz; } @@ -487,8 +487,8 @@ napi_value RdbPredicatesProxy::Between(napi_env env, napi_callback_info info) ValueObject low; ValueObject high; auto predicatesProxy = ParseFieldLowAndHigh(env, info, thiz, field, low, high); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Between(field, low, high); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Between(field, low, high); return thiz; } @@ -500,8 +500,8 @@ napi_value RdbPredicatesProxy::NotBetween(napi_env env, napi_callback_info info) ValueObject low; ValueObject high; auto predicatesProxy = ParseFieldLowAndHigh(env, info, thiz, field, low, high); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->NotBetween(field, low, high); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->NotBetween(field, low, high); return thiz; } @@ -512,8 +512,8 @@ napi_value RdbPredicatesProxy::GreaterThan(napi_env env, napi_callback_info info std::string field = ""; ValueObject value; auto predicatesProxy = ParseFieldAndValue(env, info, thiz, field, value, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->GreaterThan(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->GreaterThan(field, value); return thiz; } @@ -524,8 +524,8 @@ napi_value RdbPredicatesProxy::LessThan(napi_env env, napi_callback_info info) std::string field = ""; ValueObject value; auto predicatesProxy = ParseFieldAndValue(env, info, thiz, field, value, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->LessThan(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->LessThan(field, value); return thiz; } @@ -536,8 +536,8 @@ napi_value RdbPredicatesProxy::GreaterThanOrEqualTo(napi_env env, napi_callback_ std::string field = ""; ValueObject value; auto predicatesProxy = ParseFieldAndValue(env, info, thiz, field, value, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->GreaterThanOrEqualTo(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->GreaterThanOrEqualTo(field, value); return thiz; } @@ -548,8 +548,8 @@ napi_value RdbPredicatesProxy::LessThanOrEqualTo(napi_env env, napi_callback_inf std::string field = ""; ValueObject value; auto predicatesProxy = ParseFieldAndValue(env, info, thiz, field, value, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->LessThanOrEqualTo(field, value); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->LessThanOrEqualTo(field, value); return thiz; } @@ -559,8 +559,8 @@ napi_value RdbPredicatesProxy::OrderByAsc(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::string field = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, field, "field"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->OrderByAsc(field); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->OrderByAsc(field); return thiz; } @@ -570,8 +570,8 @@ napi_value RdbPredicatesProxy::OrderByDesc(napi_env env, napi_callback_info info napi_value thiz = nullptr; std::string field = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, field, "field"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->OrderByDesc(field); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->OrderByDesc(field); return thiz; } @@ -581,8 +581,8 @@ napi_value RdbPredicatesProxy::Distinct(napi_env env, napi_callback_info info) napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Distinct(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Distinct(); return thiz; } @@ -594,7 +594,7 @@ napi_value RdbPredicatesProxy::Limit(napi_env env, napi_callback_info info) napi_value args[2] = { 0 }; napi_get_cb_info(env, info, &argc, args, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); //Ensure that the number of parameters is 1 or 2 RDB_NAPI_ASSERT(env, argc == 1 || argc == 2, std::make_shared("1 or 2")); @@ -603,14 +603,14 @@ napi_value RdbPredicatesProxy::Limit(napi_env env, napi_callback_info info) if (argc == 1) { napi_status status = napi_get_value_int32(env, args[0], &limit); RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("limit", "a number.")); - predicatesProxy->predicates_->Limit(limit); + predicatesProxy->GetInstance()->Limit(limit); } else { napi_status status = napi_get_value_int32(env, args[0], &offset); RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("offset", "a number.")); status = napi_get_value_int32(env, args[1], &limit); RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("limit", "a number.")); - predicatesProxy->predicates_->Limit(offset, limit); + predicatesProxy->GetInstance()->Limit(offset, limit); } return thiz; @@ -622,8 +622,8 @@ napi_value RdbPredicatesProxy::Offset(napi_env env, napi_callback_info info) napi_value thiz = nullptr; int32_t offset = AbsPredicates::INIT_OFFSET_VALUE; auto predicatesProxy = ParseInt32FieldByName(env, info, thiz, offset, "rowOffset"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Offset(offset); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Offset(offset); return thiz; } @@ -633,8 +633,8 @@ napi_value RdbPredicatesProxy::GroupBy(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::vector fields; auto predicatesProxy = ParseFieldArrayByName(env, info, thiz, fields, "fields", "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->GroupBy(fields); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->GroupBy(fields); return thiz; } @@ -644,8 +644,8 @@ napi_value RdbPredicatesProxy::IndexedBy(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::string indexName = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, indexName, "fields"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->IndexedBy(indexName); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->IndexedBy(indexName); return thiz; } @@ -656,8 +656,8 @@ napi_value RdbPredicatesProxy::In(napi_env env, napi_callback_info info) std::string field = ""; std::vector values; auto predicatesProxy = ParseFieldAndValueArray(env, info, thiz, field, values, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->In(field, values); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->In(field, values); return thiz; } @@ -668,8 +668,8 @@ napi_value RdbPredicatesProxy::NotIn(napi_env env, napi_callback_info info) std::string field = ""; std::vector values; auto predicatesProxy = ParseFieldAndValueArray(env, info, thiz, field, values, "ValueType"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->NotIn(field, values); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->NotIn(field, values); return thiz; } @@ -679,8 +679,8 @@ napi_value RdbPredicatesProxy::Using(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::vector fields; auto predicatesProxy = ParseFieldArrayByName(env, info, thiz, fields, "fields", "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Using(fields); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Using(fields); return thiz; } @@ -690,8 +690,8 @@ napi_value RdbPredicatesProxy::LeftOuterJoin(napi_env env, napi_callback_info in napi_value thiz = nullptr; std::string tablename = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, tablename, "tablename"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->LeftOuterJoin(tablename); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->LeftOuterJoin(tablename); return thiz; } @@ -701,8 +701,8 @@ napi_value RdbPredicatesProxy::InnerJoin(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::string tablename = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, tablename, "tablename"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->InnerJoin(tablename); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->InnerJoin(tablename); return thiz; } @@ -712,8 +712,8 @@ napi_value RdbPredicatesProxy::On(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::vector clauses; auto predicatesProxy = ParseFieldArrayByName(env, info, thiz, clauses, "clauses", "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->On(clauses); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->On(clauses); return thiz; } @@ -722,9 +722,9 @@ napi_value RdbPredicatesProxy::GetStatement(napi_env env, napi_callback_info inf napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); - std::string statement = predicatesProxy->predicates_->GetStatement(); + std::string statement = predicatesProxy->GetInstance()->GetStatement(); return JSUtils::Convert2JSValue(env, statement); } @@ -733,9 +733,9 @@ napi_value RdbPredicatesProxy::GetBindArgs(napi_env env, napi_callback_info info napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); - std::vector bindArgs = predicatesProxy->predicates_->GetBindArgs(); + std::vector bindArgs = predicatesProxy->GetInstance()->GetBindArgs(); return JSUtils::Convert2JSValue(env, bindArgs); } @@ -745,8 +745,8 @@ napi_value RdbPredicatesProxy::Clear(napi_env env, napi_callback_info info) napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->Clear(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->Clear(); return thiz; } @@ -756,8 +756,8 @@ napi_value RdbPredicatesProxy::CrossJoin(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::string tablename = ""; auto predicatesProxy = ParseFieldByName(env, info, thiz, tablename, "tablename"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->CrossJoin(tablename); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->CrossJoin(tablename); return thiz; } @@ -767,8 +767,8 @@ napi_value RdbPredicatesProxy::GetJoinCount(napi_env env, napi_callback_info inf napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - int errCode = predicatesProxy->predicates_->GetJoinCount(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + int errCode = predicatesProxy->GetInstance()->GetJoinCount(); return JSUtils::Convert2JSValue(env, errCode); } @@ -778,8 +778,8 @@ napi_value RdbPredicatesProxy::SetJoinCount(napi_env env, napi_callback_info inf napi_value thiz; int32_t joinCount = 0; auto predicatesProxy = ParseInt32FieldByName(env, info, thiz, joinCount, "joinCount"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->SetJoinCount(joinCount); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->SetJoinCount(joinCount); return thiz; } @@ -789,8 +789,8 @@ napi_value RdbPredicatesProxy::GetJoinTypes(napi_env env, napi_callback_info inf napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - auto joinTypes = predicatesProxy->predicates_->GetJoinTypes(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + auto joinTypes = predicatesProxy->GetInstance()->GetJoinTypes(); return JSUtils::Convert2JSValue(env, joinTypes); } @@ -800,8 +800,8 @@ napi_value RdbPredicatesProxy::GetJoinTableNames(napi_env env, napi_callback_inf napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - auto joinTableNames = predicatesProxy->predicates_->GetJoinTableNames(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + auto joinTableNames = predicatesProxy->GetInstance()->GetJoinTableNames(); return JSUtils::Convert2JSValue(env, joinTableNames); } @@ -811,8 +811,8 @@ napi_value RdbPredicatesProxy::GetJoinConditions(napi_env env, napi_callback_inf napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); RdbPredicatesProxy *predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - auto joinConditions = predicatesProxy->predicates_->GetJoinConditions(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + auto joinConditions = predicatesProxy->GetInstance()->GetJoinConditions(); return JSUtils::Convert2JSValue(env, joinConditions); } @@ -822,8 +822,8 @@ napi_value RdbPredicatesProxy::SetJoinConditions(napi_env env, napi_callback_inf napi_value thiz = nullptr; std::vector joinConditions; auto predicatesProxy = ParseFieldArrayByName(env, info, thiz, joinConditions, "joinConditions", "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->SetJoinConditions(joinConditions); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->SetJoinConditions(joinConditions); return thiz; } @@ -833,8 +833,8 @@ napi_value RdbPredicatesProxy::SetJoinTableNames(napi_env env, napi_callback_inf napi_value thiz = nullptr; std::vector joinNames; auto predicatesProxy = ParseFieldArrayByName(env, info, thiz, joinNames, "joinNames", "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->SetJoinTableNames(joinNames); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->SetJoinTableNames(joinNames); return thiz; } @@ -844,14 +844,14 @@ napi_value RdbPredicatesProxy::SetJoinTypes(napi_env env, napi_callback_info inf napi_value thiz = nullptr; std::vector joinTypes; auto predicatesProxy = ParseFieldArrayByName(env, info, thiz, joinTypes, "joinTypes", "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->SetJoinTypes(joinTypes); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->SetJoinTypes(joinTypes); return thiz; } std::shared_ptr RdbPredicatesProxy::GetPredicates() const { - return this->predicates_; + return GetInstance(); } napi_value RdbPredicatesProxy::InDevices(napi_env env, napi_callback_info info) @@ -860,8 +860,8 @@ napi_value RdbPredicatesProxy::InDevices(napi_env env, napi_callback_info info) napi_value thiz = nullptr; std::vector devices; auto predicatesProxy = ParseFieldArrayByName(env, info, thiz, devices, "devices", "string"); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->InDevices(devices); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->InDevices(devices); return thiz; } @@ -871,8 +871,8 @@ napi_value RdbPredicatesProxy::InAllDevices(napi_env env, napi_callback_info inf napi_value thiz = nullptr; napi_get_cb_info(env, info, nullptr, nullptr, &thiz, nullptr); auto predicatesProxy = GetNativePredicates(env, info); - CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->predicates_); - predicatesProxy->predicates_->InAllDevices(); + CHECK_RETURN_NULL(predicatesProxy && predicatesProxy->GetInstance()); + predicatesProxy->GetInstance()->InAllDevices(); return thiz; } } // namespace RelationalStoreJsKit diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp index f7d96721b02755b95baaa4fcc6402cef5623e14a..f3b8eaa6804934a227a436998bfb7014e32f6828 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store.cpp @@ -71,8 +71,7 @@ struct RdbStoreContext : public Context { int64_t int64Output; int intOutput; std::vector newKey; - std::shared_ptr newResultSet; - std::shared_ptr resultSet_value; + std::shared_ptr resultSet; std::string aliasName; std::string pathName; std::string srcName; @@ -80,6 +79,7 @@ struct RdbStoreContext : public Context { int32_t enumArg; int32_t distributedType; int32_t syncMode; + uint64_t cursor = UINT64_MAX; DistributedRdb::DistributedConfig distributedConfig; napi_ref asyncHolder = nullptr; NativeRdb::ConflictResolution conflictResolution; @@ -109,7 +109,6 @@ RdbStoreProxy::RdbStoreProxy() RdbStoreProxy::~RdbStoreProxy() { LOG_DEBUG("RdbStoreProxy destructor"); -#if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) if (rdbStore_ == nullptr) { return; } @@ -140,7 +139,6 @@ RdbStoreProxy::~RdbStoreProxy() for (const auto &obs : syncObservers_) { rdbStore_->UnregisterAutoSyncCallback(obs); } -#endif } bool RdbStoreProxy::IsSystemAppCalled() @@ -199,9 +197,11 @@ void RdbStoreProxy::Init(napi_env env, napi_value exports) DECLARE_NAPI_FUNCTION("sync", Sync), DECLARE_NAPI_FUNCTION("cloudSync", CloudSync), DECLARE_NAPI_FUNCTION("getModifyTime", GetModifyTime), + DECLARE_NAPI_FUNCTION("cleanDirtyData", CleanDirtyData), DECLARE_NAPI_FUNCTION("on", OnEvent), DECLARE_NAPI_FUNCTION("off", OffEvent), DECLARE_NAPI_FUNCTION("emit", Notify), + DECLARE_NAPI_FUNCTION("querySharingResource", QuerySharingResource), #endif }; napi_value cons = nullptr; @@ -291,6 +291,15 @@ int ParseTableName(const napi_env env, const napi_value arg, std::shared_ptr context) +{ + double cursor = 0; + auto status = JSUtils::Convert2Value(env, arg, cursor); + CHECK_RETURN_SET(status == napi_ok && cursor > 0, std::make_shared("cursor", "not invalid cursor")); + context->cursor = static_cast(cursor); + return OK; +} + int ParseColumnName(const napi_env env, const napi_value arg, std::shared_ptr context) { context->columnName = JSUtils::Convert2String(env, arg); @@ -380,8 +389,8 @@ int ParseCloudSyncCallback(const napi_env env, const napi_value arg, std::shared { napi_valuetype valueType = napi_undefined; napi_typeof(env, arg, &valueType); - CHECK_RETURN_SET(valueType == napi_function, std::make_shared("a callback type")); - napi_create_reference(env, arg, 1, &context->asyncHolder); + CHECK_RETURN_SET(valueType == napi_function, std::make_shared("progress", "a callback type")); + NAPI_CALL_BASE(env, napi_create_reference(env, arg, 1, &context->asyncHolder), ERR); return OK; } @@ -685,11 +694,11 @@ napi_value RdbStoreProxy::Query(napi_env env, napi_callback_info info) RdbStoreProxy *obj = reinterpret_cast(context->boundObj); CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); CHECK_RETURN_ERR(context->rdbPredicates != nullptr); - context->resultSet_value = obj->rdbStore_->Query(*(context->rdbPredicates), context->columns); - return (context->resultSet_value != nullptr) ? E_OK : E_ERROR; + context->resultSet = obj->rdbStore_->Query(*(context->rdbPredicates), context->columns); + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->resultSet_value); + result = ResultSetProxy::NewInstance(env, context->resultSet); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); @@ -717,12 +726,12 @@ napi_value RdbStoreProxy::RemoteQuery(napi_env env, napi_callback_info info) int errCode = E_ERROR; CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); CHECK_RETURN_ERR(context->rdbPredicates != nullptr); - context->newResultSet = + context->resultSet = obj->rdbStore_->RemoteQuery(context->device, *(context->rdbPredicates), context->columns, errCode); return errCode; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->newResultSet); + result = ResultSetProxy::NewInstance(env, context->resultSet); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); @@ -747,14 +756,14 @@ napi_value RdbStoreProxy::QuerySql(napi_env env, napi_callback_info info) auto exec = [context]() -> int { RdbStoreProxy *obj = reinterpret_cast(context->boundObj); #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM) - context->resultSet_value = obj->rdbStore_->QueryByStep(context->sql, context->bindArgs); + context->resultSet = obj->rdbStore_->QueryByStep(context->sql, context->bindArgs); #else - context->resultSet_value = obj->rdbStore_->QuerySql(context->sql, context->bindArgs); + context->resultSet = obj->rdbStore_->QuerySql(context->sql, context->bindArgs); #endif - return (context->resultSet_value != nullptr) ? E_OK : E_ERROR; + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->resultSet_value); + result = ResultSetProxy::NewInstance(env, context->resultSet); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); }; context->SetAction(env, info, input, exec, output); @@ -970,12 +979,12 @@ napi_value RdbStoreProxy::QueryByStep(napi_env env, napi_callback_info info) LOG_DEBUG("RdbStoreProxy::QueryByStep Async"); RdbStoreProxy *obj = reinterpret_cast(context->boundObj); CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); - context->resultSet_value = obj->rdbStore_->QueryByStep(context->sql, context->columns); - LOG_ERROR("RdbStoreProxy::QueryByStep is nullptr ? %{public}d ", context->resultSet_value == nullptr); - return (context->resultSet_value != nullptr) ? E_OK : E_ERROR; + context->resultSet = obj->rdbStore_->QueryByStep(context->sql, context->columns); + LOG_ERROR("RdbStoreProxy::QueryByStep is nullptr ? %{public}d ", context->resultSet == nullptr); + return (context->resultSet != nullptr) ? E_OK : E_ERROR; }; auto output = [context](napi_env env, napi_value &result) { - result = ResultSetProxy::NewInstance(env, context->resultSet_value); + result = ResultSetProxy::NewInstance(env, context->resultSet); CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); LOG_DEBUG("RdbStoreProxy::QueryByStep end"); }; @@ -1156,7 +1165,7 @@ napi_value RdbStoreProxy::Sync(napi_env env, napi_callback_info info) InputAction GetCloudSyncInput(std::shared_ptr context) { return [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { - // The number of parameters should be between 2 and 4 + // The number of parameters should be in range (1, 5) CHECK_RETURN_SET_E(argc > 1 && argc < 5, std::make_shared("2 - 4")); CHECK_RETURN(OK == ParserThis(env, self, context)); CHECK_RETURN(OK == ParseCloudSyncModeArg(env, argv[0], context)); @@ -1253,6 +1262,35 @@ napi_value RdbStoreProxy::GetModifyTime(napi_env env, napi_callback_info info) return AsyncCall::Call(env, context); } +napi_value RdbStoreProxy::CleanDirtyData(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("RdbStoreProxy::Clean start"); + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(argc >= 1, std::make_shared("1 - 3")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParseTableName(env, argv[0], context)); + if (argc == 2) { + CHECK_RETURN(OK == ParseCursor(env, argv[1], context)); + } + }; + auto exec = [context]() -> int { + LOG_DEBUG("RdbStoreProxy::CleanDirtyData Async"); + auto *obj = reinterpret_cast(context->boundObj); + CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); + return obj->rdbStore_->CleanDirtyData(context->tableName, context->cursor); + }; + + auto output = [context](napi_env env, napi_value &result) { + napi_status status = napi_get_undefined(env, &result); + CHECK_RETURN_SET_E(status == napi_ok, std::make_shared(E_ERROR)); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return AsyncCall::Call(env, context); +} + napi_value RdbStoreProxy::OnRemote(napi_env env, size_t argc, napi_value *argv) { napi_valuetype type = napi_undefined; @@ -1342,10 +1380,8 @@ napi_value RdbStoreProxy::OffRemote(napi_env env, size_t argc, napi_value *argv) int errCode = rdbStore_->UnSubscribe(option, it->get()); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); it = observers_[mode].erase(it); - LOG_INFO("observer unsubscribe success"); - return nullptr; + LOG_DEBUG("observer unsubscribe success"); } - LOG_INFO("observer not found"); return nullptr; } @@ -1415,6 +1451,7 @@ napi_value RdbStoreProxy::OnEvent(napi_env env, napi_callback_info info) status = JSUtils::Convert2Value(env, argv[1], valueBool); RDB_NAPI_ASSERT(env, status == napi_ok, std::make_shared("interProcess", "a boolean.")); napi_valuetype type = napi_undefined; + // 'argv[2]' is observer function napi_typeof(env, argv[2], &type); RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); SubscribeOption option; @@ -1453,8 +1490,8 @@ napi_value RdbStoreProxy::OffEvent(napi_env env, napi_callback_info info) // 'argc == 3' represents determine whether the value of variable 'argc' is equal to '3' if (argc == 3) { - // 'argv[2]' represents a callback function napi_valuetype type = napi_undefined; + // 'argv[2]' represents a callback function napi_typeof(env, argv[2], &type); RDB_NAPI_ASSERT(env, type == napi_function, std::make_shared("observer", "function")); } @@ -1480,6 +1517,44 @@ napi_value RdbStoreProxy::Notify(napi_env env, napi_callback_info info) return nullptr; } +napi_value RdbStoreProxy::QuerySharingResource(napi_env env, napi_callback_info info) +{ + LOG_DEBUG("RdbStoreProxy::QuerySharingResource start"); + auto context = std::make_shared(); + auto input = [context](napi_env env, size_t argc, napi_value *argv, napi_value self) { + CHECK_RETURN_SET_E(argc > 0 && argc < 4, std::make_shared("1 to 3")); + CHECK_RETURN(OK == ParserThis(env, self, context)); + CHECK_RETURN(OK == ParsePredicates(env, argv[0], context)); + if (argc >= 2) { + bool isArray = false; + napi_is_array(env, argv[1], &isArray); + if (isArray) { + CHECK_RETURN(OK == ParseColumns(env, argv[1], context)); + } + } + }; + auto exec = [context]() -> int { + LOG_DEBUG("RdbStoreProxy::QuerySharingResource Async"); + RdbStoreProxy *obj = reinterpret_cast(context->boundObj); + CHECK_RETURN_ERR(obj != nullptr && obj->rdbStore_ != nullptr); + auto status = E_ERROR; + std::tie(status, context->resultSet) = + obj->rdbStore_->QuerySharingResource(*(context->rdbPredicates), context->columns); + LOG_DEBUG("RdbStoreProxy::QuerySharingResource resultSet is nullptr:%{public}d, status:%{public}d", + context->resultSet == nullptr, status); + return (context->resultSet != nullptr) ? E_OK : E_ERROR; + }; + auto output = [context](napi_env env, napi_value &result) { + result = ResultSetProxy::NewInstance(env, context->resultSet); + CHECK_RETURN_SET_E(result != nullptr, std::make_shared(E_ERROR)); + LOG_DEBUG("RdbStoreProxy::QuerySharingResource end"); + }; + context->SetAction(env, info, input, exec, output); + + CHECK_RETURN_NULL(context->error == nullptr || context->error->GetCode() == OK); + return AsyncCall::Call(env, context); +} + napi_value RdbStoreProxy::RegisterSyncCallback(napi_env env, size_t argc, napi_value *argv) { napi_valuetype type = napi_undefined; @@ -1489,7 +1564,7 @@ napi_value RdbStoreProxy::RegisterSyncCallback(napi_env env, size_t argc, napi_v return *observer == argv[1]; }); if (result) { - LOG_INFO("duplicate subscribe"); + LOG_DEBUG("duplicate subscribe"); return nullptr; } auto observer = std::make_shared(env, argv[0], queue_); @@ -1522,10 +1597,8 @@ napi_value RdbStoreProxy::UnregisterSyncCallback(napi_env env, size_t argc, napi int errCode = rdbStore_->UnregisterAutoSyncCallback(*it); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); it = syncObservers_.erase(it); - LOG_INFO("progress unsubscribe success"); - return nullptr; + LOG_DEBUG("observer unsubscribe success"); } - LOG_INFO("observer not found"); return nullptr; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp index bec31b1846d2c34038701f5a047e84b4ceed0ff5..7d00f58947df949b3aef85c54dba7f19832efb70 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_rdb_store_helper.cpp @@ -72,6 +72,21 @@ int ParseIsEncrypt(const napi_env &env, const napi_value &object, std::shared_pt return OK; } +int ParseIsSearchable(const napi_env &env, const napi_value &object, std::shared_ptr context) +{ + napi_value value = nullptr; + napi_status status = napi_get_named_property(env, object, "isSearchable", &value); + if (status == napi_ok && value != nullptr) { + bool isSearchable = false; + auto status = JSUtils::Convert2Value(env, value, isSearchable); + if (status != napi_ok) { + return napi_invalid_arg; + } + context->config.SetSearchable(isSearchable); + } + return OK; +} + int ParseContextProperty(const napi_env &env, std::shared_ptr context) { context->config.SetModuleName(context->abilitycontext->GetModuleName()); @@ -126,8 +141,8 @@ int ParseDatabasePath(const napi_env &env, const napi_value &object, std::shared } auto [realPath, errCode] = RdbSqlUtils::GetDefaultDatabasePath(defaultDir, context->config.GetName(), customDir); - // customDir length is limited to 1024 bytes - CHECK_RETURN_SET(errCode == E_OK && realPath.length() <= 1024, + // customDir length is limited to 128 bytes + CHECK_RETURN_SET(errCode == E_OK && realPath.length() <= 128, std::make_shared("config", "a StoreConfig.")); context->config.SetPath(std::move(realPath)); @@ -175,14 +190,31 @@ int ParseDataGroupId(const napi_env &env, const napi_value &object, std::shared_ return OK; } +int ParseAutoCleanDirtyData(const napi_env &env, const napi_value &object, std::shared_ptr context) +{ + bool hasProp = false; + napi_status status = napi_has_named_property(env, object, "autoCleanDirtyData", &hasProp); + if (status == napi_ok && hasProp) { + napi_value value = nullptr; + status = napi_get_named_property(env, object, "autoCleanDirtyData", &value); + CHECK_RETURN_SET(status == napi_ok, std::make_shared("config", "with autoCleanDirtyData.")); + bool isAutoClean = true; + JSUtils::Convert2Value(env, value, isAutoClean); + context->config.SetAutoClean(isAutoClean); + } + return OK; +} + int ParseStoreConfig(const napi_env &env, const napi_value &object, std::shared_ptr context) { CHECK_RETURN_CORE(OK == ParseIsEncrypt(env, object, context), RDB_REVT_NOTHING, ERR); CHECK_RETURN_CORE(OK == ParseSecurityLevel(env, object, context), RDB_REVT_NOTHING, ERR); CHECK_RETURN_CORE(OK == ParseDataGroupId(env, object, context), RDB_REVT_NOTHING, ERR); + CHECK_RETURN_CORE(OK == ParseAutoCleanDirtyData(env, object, context), RDB_REVT_NOTHING, ERR); CHECK_RETURN_CORE(OK == ParseContextProperty(env, context), RDB_REVT_NOTHING, ERR); CHECK_RETURN_CORE(OK == ParseDatabaseName(env, object, context), RDB_REVT_NOTHING, ERR); CHECK_RETURN_CORE(OK == ParseDatabasePath(env, object, context), RDB_REVT_NOTHING, ERR); + CHECK_RETURN_CORE(OK == ParseIsSearchable(env, object, context), RDB_REVT_NOTHING, ERR); return OK; } diff --git a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp index 03f44b4e5b90c286922fe3b0c5b70a047357167f..5a51e3c47ae1df2bac607edf40338a80274892d0 100644 --- a/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp +++ b/relational_store/frameworks/js/napi/relationalstore/src/napi_result_set.cpp @@ -35,18 +35,17 @@ namespace OHOS { namespace RelationalStoreJsKit { using Asset = AssetValue; using Assets = std::vector; -static napi_ref __thread ctorRef_ = nullptr; static const int E_OK = 0; napi_value ResultSetProxy::NewInstance(napi_env env, std::shared_ptr resultSet) { - napi_value cons = GetConstructor(env); + napi_value cons = JSUtils::GetClass(env, "ohos.data.relationalStore", "ResultSet"); if (cons == nullptr) { - LOG_ERROR("NewInstance GetConstructor is nullptr!"); + LOG_ERROR("Constructor of ResultSet is nullptr!"); return nullptr; } napi_value instance = nullptr; - napi_status status = napi_new_instance(env, cons, 0, nullptr, &instance); + auto status = napi_new_instance(env, cons, 0, nullptr, &instance); if (status != napi_ok) { LOG_ERROR("NewInstance napi_new_instance failed! code:%{public}d!", status); return nullptr; @@ -58,68 +57,20 @@ napi_value ResultSetProxy::NewInstance(napi_env env, std::shared_ptrSetInstance(std::move(resultSet)); return instance; } #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) std::shared_ptr ResultSetProxy::Create() { - if (resultSet_ == nullptr) { + if (GetInstance() == nullptr) { LOG_ERROR("resultSet is null"); return nullptr; } - return std::make_shared(std::move(resultSet_)); + return std::make_shared(GetInstance()); } #endif - -napi_value ResultSetProxy::GetConstructor(napi_env env) -{ - napi_value cons = nullptr; - if (ctorRef_ != nullptr) { - NAPI_CALL(env, napi_get_reference_value(env, ctorRef_, &cons)); - return cons; - } - - LOG_INFO("GetConstructor result set constructor"); - napi_property_descriptor clzDes[] = { - DECLARE_NAPI_FUNCTION("goToRow", GoToRow), - DECLARE_NAPI_FUNCTION("getLong", GetLong), - DECLARE_NAPI_FUNCTION("getColumnType", GetColumnType), - DECLARE_NAPI_FUNCTION("goTo", GoTo), - DECLARE_NAPI_FUNCTION("getColumnIndex", GetColumnIndex), - DECLARE_NAPI_FUNCTION("getColumnName", GetColumnName), - DECLARE_NAPI_FUNCTION("close", Close), - DECLARE_NAPI_FUNCTION("goToFirstRow", GoToFirstRow), - DECLARE_NAPI_FUNCTION("goToLastRow", GoToLastRow), - DECLARE_NAPI_FUNCTION("goToNextRow", GoToNextRow), - DECLARE_NAPI_FUNCTION("goToPreviousRow", GoToPreviousRow), - DECLARE_NAPI_FUNCTION("getInt", GetInt), - DECLARE_NAPI_FUNCTION("getBlob", GetBlob), - DECLARE_NAPI_FUNCTION("getAsset", GetAsset), - DECLARE_NAPI_FUNCTION("getAssets", GetAssets), - DECLARE_NAPI_FUNCTION("getString", GetString), - DECLARE_NAPI_FUNCTION("getDouble", GetDouble), - DECLARE_NAPI_FUNCTION("isColumnNull", IsColumnNull), - DECLARE_NAPI_FUNCTION("getRow", GetRow), - - DECLARE_NAPI_GETTER("columnNames", GetAllColumnNames), - DECLARE_NAPI_GETTER("columnCount", GetColumnCount), - DECLARE_NAPI_GETTER("isEnded", IsEnded), - DECLARE_NAPI_GETTER("isStarted", IsBegin), - DECLARE_NAPI_GETTER("isClosed", IsClosed), - DECLARE_NAPI_GETTER("rowCount", GetRowCount), - DECLARE_NAPI_GETTER("rowIndex", GetRowIndex), - DECLARE_NAPI_GETTER("isAtFirstRow", IsAtFirstRow), - DECLARE_NAPI_GETTER("isAtLastRow", IsAtLastRow), - }; - - NAPI_CALL(env, napi_define_class(env, "ResultSet", NAPI_AUTO_LENGTH, Initialize, nullptr, - sizeof(clzDes) / sizeof(napi_property_descriptor), clzDes, &cons)); - NAPI_CALL(env, napi_create_reference(env, cons, 1, &ctorRef_)); - return cons; -} - napi_value ResultSetProxy::Initialize(napi_env env, napi_callback_info info) { napi_value self = nullptr; @@ -149,18 +100,18 @@ ResultSetProxy::~ResultSetProxy() ResultSetProxy::ResultSetProxy(std::shared_ptr resultSet) { - if (resultSet_ == resultSet) { + if (GetInstance() == resultSet) { return; } - resultSet_ = std::move(resultSet); + SetInstance(std::move(resultSet)); } ResultSetProxy &ResultSetProxy::operator=(std::shared_ptr resultSet) { - if (resultSet_ == resultSet) { + if (GetInstance() == resultSet) { return *this; } - resultSet_ = std::move(resultSet); + SetInstance(std::move(resultSet)); return *this; } @@ -171,7 +122,7 @@ ResultSetProxy *ResultSetProxy::GetInnerResultSet(napi_env env, napi_callback_in ResultSetProxy *proxy = nullptr; napi_unwrap(env, self, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->resultSet_, std::make_shared(E_RESULT_GOTO_ERROR)); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared(E_RESULT_GOTO_ERROR)); return proxy; } @@ -190,7 +141,7 @@ ResultSetProxy *ResultSetProxy::ParseInt32FieldByName( ResultSetProxy *proxy = nullptr; napi_unwrap(env, self, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->resultSet_, std::make_shared("resultSet", "not null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("resultSet", "not null")); return proxy; } @@ -208,17 +159,17 @@ ResultSetProxy *ResultSetProxy::ParseFieldByName( ResultSetProxy *proxy = nullptr; napi_unwrap(env, self, reinterpret_cast(&proxy)); - RDB_NAPI_ASSERT(env, proxy && proxy->resultSet_, std::make_shared("resultSet", "not null")); + RDB_NAPI_ASSERT(env, proxy && proxy->GetInstance(), std::make_shared("resultSet", "not null")); return proxy; } napi_value ResultSetProxy::GetAllColumnNames(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); std::vector colNames; - int errCode = resultSetProxy->resultSet_->GetAllColumnNames(colNames); + int errCode = resultSetProxy->GetInstance()->GetAllColumnNames(colNames); if (errCode != E_OK) { LOG_ERROR("GetAllColumnNames failed code:%{public}d", errCode); } @@ -229,10 +180,10 @@ napi_value ResultSetProxy::GetAllColumnNames(napi_env env, napi_callback_info in napi_value ResultSetProxy::GetColumnCount(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); int32_t count = 0; - int errCode = resultSetProxy->resultSet_->GetColumnCount(count); + int errCode = resultSetProxy->GetInstance()->GetColumnCount(count); if (errCode != E_OK) { LOG_ERROR("GetColumnCount failed code:%{public}d", errCode); } @@ -244,10 +195,10 @@ napi_value ResultSetProxy::GetColumnType(napi_env env, napi_callback_info info) { int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); ColumnType columnType; - int errCode = resultSetProxy->resultSet_->GetColumnType(columnIndex, columnType); + int errCode = resultSetProxy->GetInstance()->GetColumnType(columnIndex, columnType); if (errCode != E_OK) { LOG_ERROR("GetColumnType failed code:%{public}d", errCode); } @@ -258,10 +209,10 @@ napi_value ResultSetProxy::GetColumnType(napi_env env, napi_callback_info info) napi_value ResultSetProxy::GetRowCount(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); int32_t result; - int errCode = resultSetProxy->resultSet_->GetRowCount(result); + int errCode = resultSetProxy->GetInstance()->GetRowCount(result); if (errCode != E_OK) { LOG_ERROR("GetRowCount failed code:%{public}d", errCode); } @@ -272,10 +223,10 @@ napi_value ResultSetProxy::GetRowCount(napi_env env, napi_callback_info info) napi_value ResultSetProxy::GetRowIndex(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); int32_t result; - int errCode = resultSetProxy->resultSet_->GetRowIndex(result); + int errCode = resultSetProxy->GetInstance()->GetRowIndex(result); if (errCode != E_OK) { LOG_ERROR("GetRowIndex failed code:%{public}d", errCode); } @@ -286,10 +237,10 @@ napi_value ResultSetProxy::GetRowIndex(napi_env env, napi_callback_info info) napi_value ResultSetProxy::IsEnded(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); bool result = false; - int errCode = resultSetProxy->resultSet_->IsEnded(result); + int errCode = resultSetProxy->GetInstance()->IsEnded(result); if (errCode != E_OK) { LOG_ERROR("IsEnded failed code:%{public}d", errCode); } @@ -300,10 +251,10 @@ napi_value ResultSetProxy::IsEnded(napi_env env, napi_callback_info info) napi_value ResultSetProxy::IsBegin(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); bool result = false; - int errCode = resultSetProxy->resultSet_->IsStarted(result); + int errCode = resultSetProxy->GetInstance()->IsStarted(result); if (errCode != E_OK) { LOG_ERROR("IsBegin failed code:%{public}d", errCode); } @@ -314,10 +265,10 @@ napi_value ResultSetProxy::IsBegin(napi_env env, napi_callback_info info) napi_value ResultSetProxy::IsAtFirstRow(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); bool result = false; - int errCode = resultSetProxy->resultSet_->IsAtFirstRow(result); + int errCode = resultSetProxy->GetInstance()->IsAtFirstRow(result); if (errCode != E_OK) { LOG_ERROR("IsAtFirstRow failed code:%{public}d", errCode); } @@ -328,10 +279,10 @@ napi_value ResultSetProxy::IsAtFirstRow(napi_env env, napi_callback_info info) napi_value ResultSetProxy::IsAtLastRow(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); bool result = false; - int errCode = resultSetProxy->resultSet_->IsAtLastRow(result); + int errCode = resultSetProxy->GetInstance()->IsAtLastRow(result); if (errCode != E_OK) { LOG_ERROR("IsAtLastRow failed code:%{public}d", errCode); } @@ -342,9 +293,9 @@ napi_value ResultSetProxy::IsAtLastRow(napi_env env, napi_callback_info info) napi_value ResultSetProxy::Close(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); - int errCode = resultSetProxy->resultSet_->Close(); + int errCode = resultSetProxy->GetInstance()->Close(); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); napi_value result = nullptr; @@ -356,9 +307,9 @@ napi_value ResultSetProxy::GoToRow(napi_env env, napi_callback_info info) { int32_t position; auto resultSetProxy = ParseInt32FieldByName(env, info, position, "position"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); - int errCode = resultSetProxy->resultSet_->GoToRow(position); + int errCode = resultSetProxy->GetInstance()->GoToRow(position); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -366,45 +317,45 @@ napi_value ResultSetProxy::GoTo(napi_env env, napi_callback_info info) { int32_t offset; auto resultSetProxy = ParseInt32FieldByName(env, info, offset, "offset"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); - int errCode = resultSetProxy->resultSet_->GoTo(offset); + int errCode = resultSetProxy->GetInstance()->GoTo(offset); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } napi_value ResultSetProxy::GoToFirstRow(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); - int errCode = resultSetProxy->resultSet_->GoToFirstRow(); + int errCode = resultSetProxy->GetInstance()->GoToFirstRow(); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } napi_value ResultSetProxy::GoToLastRow(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); - int errCode = resultSetProxy->resultSet_->GoToLastRow(); + int errCode = resultSetProxy->GetInstance()->GoToLastRow(); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } napi_value ResultSetProxy::GoToNextRow(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); - int errCode = resultSetProxy->resultSet_->GoToNextRow(); + int errCode = resultSetProxy->GetInstance()->GoToNextRow(); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } napi_value ResultSetProxy::GoToPreviousRow(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); - int errCode = resultSetProxy->resultSet_->GoToPreviousRow(); + int errCode = resultSetProxy->GetInstance()->GoToPreviousRow(); return JSUtils::Convert2JSValue(env, (errCode == E_OK)); } @@ -412,10 +363,10 @@ napi_value ResultSetProxy::GetInt(napi_env env, napi_callback_info info) { int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); int32_t result; - int errCode = resultSetProxy->resultSet_->GetInt(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetInt(columnIndex, result); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); @@ -425,10 +376,10 @@ napi_value ResultSetProxy::GetLong(napi_env env, napi_callback_info info) { int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); int64_t result; - int errCode = resultSetProxy->resultSet_->GetLong(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetLong(columnIndex, result); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); @@ -439,10 +390,10 @@ napi_value ResultSetProxy::GetBlob(napi_env env, napi_callback_info info) DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); std::vector result; - int errCode = resultSetProxy->resultSet_->GetBlob(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetBlob(columnIndex, result); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); @@ -453,10 +404,10 @@ napi_value ResultSetProxy::GetAsset(napi_env env, napi_callback_info info) DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); Asset result; - int errCode = resultSetProxy->resultSet_->GetAsset(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetAsset(columnIndex, result); if (errCode == E_NULL_OBJECT) { LOG_DEBUG("getAsset col %{public}d is null ", columnIndex); return JSUtils::Convert2JSValue(env, std::monostate()); @@ -471,10 +422,10 @@ napi_value ResultSetProxy::GetAssets(napi_env env, napi_callback_info info) DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); Assets result; - int errCode = resultSetProxy->resultSet_->GetAssets(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetAssets(columnIndex, result); if (errCode == E_NULL_OBJECT) { LOG_DEBUG("getAssets col %{public}d is null ", columnIndex); return JSUtils::Convert2JSValue(env, std::monostate()); @@ -489,10 +440,10 @@ napi_value ResultSetProxy::GetString(napi_env env, napi_callback_info info) DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); std::string result; - int errCode = resultSetProxy->resultSet_->GetString(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetString(columnIndex, result); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); @@ -502,10 +453,10 @@ napi_value ResultSetProxy::GetDouble(napi_env env, napi_callback_info info) { int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); double result = 0.0; - int errCode = resultSetProxy->resultSet_->GetDouble(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetDouble(columnIndex, result); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); @@ -515,10 +466,10 @@ napi_value ResultSetProxy::GetColumnIndex(napi_env env, napi_callback_info info) { std::string input; auto resultSetProxy = ParseFieldByName(env, info, input, "columnName"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); int32_t result = -1; - int errCode = resultSetProxy->resultSet_->GetColumnIndex(input, result); + int errCode = resultSetProxy->GetInstance()->GetColumnIndex(input, result); if (errCode != E_OK) { LOG_ERROR("IsAtLastRow failed code:%{public}d", errCode); } @@ -530,10 +481,10 @@ napi_value ResultSetProxy::GetColumnName(napi_env env, napi_callback_info info) { int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); std::string result; - int errCode = resultSetProxy->resultSet_->GetColumnName(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->GetColumnName(columnIndex, result); if (errCode != E_OK) { LOG_ERROR("IsAtLastRow failed code:%{public}d", errCode); } @@ -545,10 +496,10 @@ napi_value ResultSetProxy::IsColumnNull(napi_env env, napi_callback_info info) { int32_t columnIndex; auto resultSetProxy = ParseInt32FieldByName(env, info, columnIndex, "columnIndex"); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); bool result = false; - int errCode = resultSetProxy->resultSet_->IsColumnNull(columnIndex, result); + int errCode = resultSetProxy->GetInstance()->IsColumnNull(columnIndex, result); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, result); @@ -557,10 +508,10 @@ napi_value ResultSetProxy::IsColumnNull(napi_env env, napi_callback_info info) napi_value ResultSetProxy::GetRow(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); RowEntity rowEntity; - int errCode = resultSetProxy->resultSet_->GetRow(rowEntity); + int errCode = resultSetProxy->GetInstance()->GetRow(rowEntity); RDB_NAPI_ASSERT(env, errCode == E_OK, std::make_shared(errCode)); return JSUtils::Convert2JSValue(env, rowEntity); } @@ -568,10 +519,54 @@ napi_value ResultSetProxy::GetRow(napi_env env, napi_callback_info info) napi_value ResultSetProxy::IsClosed(napi_env env, napi_callback_info info) { ResultSetProxy *resultSetProxy = GetInnerResultSet(env, info); - CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->resultSet_); - bool result = resultSetProxy->resultSet_->IsClosed(); + CHECK_RETURN_NULL(resultSetProxy && resultSetProxy->GetInstance()); + bool result = resultSetProxy->GetInstance()->IsClosed(); return JSUtils::Convert2JSValue(env, result); } + +void ResultSetProxy::Init(napi_env env, napi_value exports) +{ + LOG_INFO("ResultSetProxy::Init"); + auto lambda = []() -> std::vector { + std::vector properties = { + DECLARE_NAPI_FUNCTION("goToRow", GoToRow), + DECLARE_NAPI_FUNCTION("getLong", GetLong), + DECLARE_NAPI_FUNCTION("getColumnType", GetColumnType), + DECLARE_NAPI_FUNCTION("goTo", GoTo), + DECLARE_NAPI_FUNCTION("getColumnIndex", GetColumnIndex), + DECLARE_NAPI_FUNCTION("getColumnName", GetColumnName), + DECLARE_NAPI_FUNCTION("close", Close), + DECLARE_NAPI_FUNCTION("goToFirstRow", GoToFirstRow), + DECLARE_NAPI_FUNCTION("goToLastRow", GoToLastRow), + DECLARE_NAPI_FUNCTION("goToNextRow", GoToNextRow), + DECLARE_NAPI_FUNCTION("goToPreviousRow", GoToPreviousRow), + DECLARE_NAPI_FUNCTION("getInt", GetInt), + DECLARE_NAPI_FUNCTION("getBlob", GetBlob), + DECLARE_NAPI_FUNCTION("getAsset", GetAsset), + DECLARE_NAPI_FUNCTION("getAssets", GetAssets), + DECLARE_NAPI_FUNCTION("getString", GetString), + DECLARE_NAPI_FUNCTION("getDouble", GetDouble), + DECLARE_NAPI_FUNCTION("isColumnNull", IsColumnNull), + DECLARE_NAPI_FUNCTION("getRow", GetRow), + + DECLARE_NAPI_GETTER("columnNames", GetAllColumnNames), + DECLARE_NAPI_GETTER("columnCount", GetColumnCount), + DECLARE_NAPI_GETTER("isEnded", IsEnded), + DECLARE_NAPI_GETTER("isStarted", IsBegin), + DECLARE_NAPI_GETTER("isClosed", IsClosed), + DECLARE_NAPI_GETTER("rowCount", GetRowCount), + DECLARE_NAPI_GETTER("rowIndex", GetRowIndex), + DECLARE_NAPI_GETTER("isAtFirstRow", IsAtFirstRow), + DECLARE_NAPI_GETTER("isAtLastRow", IsAtLastRow), + }; + return properties; + }; + + auto jsCtor = JSUtils::DefineClass(env, "ohos.data.relationalStore", "ResultSet", lambda, Initialize); + NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "ResultSet", jsCtor)); + + LOG_DEBUG("ResultSetProxy::Init end"); +} } // namespace RelationalStoreJsKit } // namespace OHOS diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h index c6f8133f155527d6e8c710e5b4252f848669021b..e03c74caa299fce5660b7bfe8c9fe73a3e5e81ef 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_service_proxy.h @@ -30,21 +30,22 @@ public: int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) override; int32_t Clean(const std::string &id, const std::map &actions) override; int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) override; + int32_t NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId) override; - int32_t Share(const std::string &sharingRes, const std::vector &participants, - Result>> &result) override; - int32_t Unshare(const std::string &sharingRes, const std::vector &participants, - Result>> &result) override; - int32_t ExitSharing(const std::string &sharingRes, Result &result) override; - int32_t ChangePrivilege(const std::string &sharingRes, const std::vector &participants, - Result>> &result) override; - int32_t QueryParticipants(const std::string &sharingRes, Result> &result) override; - int32_t QueryParticipantsByInvitation(const std::string &invitationCode, - Result> &result) override; - int32_t ConfirmInvitation(const std::string &invitationCode, Confirmation confirmation, - Result &result) override; + std::pair> AllocResourceAndShare(const std::string& storeId, + const DistributedRdb::PredicatesMemo& predicates, const std::vector& columns, + const Participants& participants) override; + int32_t Share(const std::string &sharingRes, const Participants &participants, Results &results) override; + int32_t Unshare(const std::string &sharingRes, const Participants &participants, Results &results) override; + int32_t Exit(const std::string &sharingRes, std::pair &result) override; + int32_t ChangePrivilege( + const std::string &sharingRes, const Participants &participants, Results &results) override; + int32_t Query(const std::string &sharingRes, QueryResults &results) override; + int32_t QueryByInvitation(const std::string &invitation, QueryResults &results) override; + int32_t ConfirmInvitation(const std::string &invitation, + int32_t confirmation, std::tuple &result) override; int32_t ChangeConfirmation(const std::string &sharingRes, - Confirmation confirmation, Result &result) override; + int32_t confirmation, std::pair &result) override; private: sptr remote_; diff --git a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h index 053cb14cee07118cb65443c5e7f8d374395d01d1..68c48bdd3c5c299d42a94d7c9f804da043f6b27d 100644 --- a/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h +++ b/relational_store/frameworks/native/cloud_data/include/cloud_types_util.h @@ -17,13 +17,18 @@ #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H #include "itypes_util.h" #include "cloud_types.h" +#include "values_bucket.h" namespace OHOS::ITypesUtil { -using OHOS::CloudData::Participant; -using OHOS::CloudData::Privilege; -using OHOS::CloudData::Role; -using OHOS::CloudData::Confirmation; -using OHOS::CloudData::SharingCode; +using Participant = OHOS::CloudData::Participant; +using Privilege = OHOS::CloudData::Privilege; +using Role = OHOS::CloudData::Role; +using Confirmation = OHOS::CloudData::Confirmation; +using SharingCode = OHOS::CloudData::SharingCode; +using Asset = OHOS::NativeRdb::AssetValue; +using ValueObject = OHOS::NativeRdb::ValueObject; +using ValuesBucket = OHOS::NativeRdb::ValuesBucket; + template<> bool Marshalling(const Participant &input, MessageParcel &data); template<> @@ -48,5 +53,18 @@ template<> bool Marshalling(const SharingCode &input, MessageParcel &data); template<> bool Unmarshalling(SharingCode &output, MessageParcel &data); + +template<> +bool Marshalling(const Asset &input, MessageParcel &data); +template<> +bool Unmarshalling(Asset &output, MessageParcel &data); +template<> +bool Marshalling(const ValueObject &input, MessageParcel &data); +template<> +bool Unmarshalling(ValueObject &output, MessageParcel &data); +template<> +bool Marshalling(const ValuesBucket &input, MessageParcel &data); +template<> +bool Unmarshalling(ValuesBucket &output, MessageParcel &data); } // namespace OHOS::ITypesUtil #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp index 06e123c136fa8dcd502f9c9ae362efd4e5b4cd68..869fa1642c00cc2a855090f88ad8db3f7cba6030 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_service_proxy.cpp @@ -102,8 +102,33 @@ int32_t CloudServiceProxy::NotifyDataChange(const std::string &id, const std::st return static_cast(status); } -int32_t CloudServiceProxy::Share(const std::string &sharingRes, const std::vector &participants, - Result>> &result) +std::pair> CloudServiceProxy::AllocResourceAndShare( + const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates, + const std::vector &columns, const std::vector &participants) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_ALLOC_RESOURCE_AND_SHARE, reply, storeId, predicates, columns, participants); + if (status != SUCCESS) { + LOG_ERROR("status:0x%{public}x storeName:%{public}.6s", status, storeId.c_str()); + } + std::vector valueBuckets; + ITypesUtil::Unmarshal(reply, valueBuckets); + return { static_cast(status), valueBuckets }; +} + +int32_t CloudServiceProxy::NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId) +{ + MessageParcel reply; + int32_t status = IPC_SEND(TRANS_NOTIFY_DATA_CHANGE_EXT, reply, eventId, extraData, userId); + if (status != SUCCESS) { + LOG_ERROR("status:0x%{public}x eventId:%{public}.6s extraData:%{public}.6s", status, eventId.c_str(), + extraData.c_str()); + } + return static_cast(status); +} + +int32_t CloudServiceProxy::Share( + const std::string &sharingRes, const Participants &participants, Results &results) { MessageParcel reply; int32_t status = IPC_SEND(TRANS_SHARE, reply, sharingRes, participants); @@ -111,12 +136,12 @@ int32_t CloudServiceProxy::Share(const std::string &sharingRes, const std::vecto LOG_ERROR("status:0x%{public}x sharingRes:%{public}.6s participants:%{public}zu", status, sharingRes.c_str(), participants.size()); } - ITypesUtil::Unmarshal(reply, result); + ITypesUtil::Unmarshal(reply, results); return static_cast(status); } -int32_t CloudServiceProxy::Unshare(const std::string &sharingRes, const std::vector &participants, - Result>> &result) +int32_t CloudServiceProxy::Unshare( + const std::string &sharingRes, const Participants &participants, Results &results) { MessageParcel reply; int32_t status = IPC_SEND(TRANS_UNSHARE, reply, sharingRes, participants); @@ -124,14 +149,14 @@ int32_t CloudServiceProxy::Unshare(const std::string &sharingRes, const std::vec LOG_ERROR("status:0x%{public}x sharingRes:%{public}.6s participants:%{public}zu", status, sharingRes.c_str(), participants.size()); } - ITypesUtil::Unmarshal(reply, result); + ITypesUtil::Unmarshal(reply, results); return static_cast(status); } -int32_t CloudServiceProxy::ExitSharing(const std::string &sharingRes, Result &result) +int32_t CloudServiceProxy::Exit(const std::string &sharingRes, std::pair &result) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_EXIT_SHARING, reply, sharingRes); + int32_t status = IPC_SEND(TRANS_EXIT, reply, sharingRes); if (status != SUCCESS) { LOG_ERROR("status:0x%{public}x sharingRes:%{public}.6s", status, sharingRes.c_str()); } @@ -139,8 +164,8 @@ int32_t CloudServiceProxy::ExitSharing(const std::string &sharingRes, Result(status); } -int32_t CloudServiceProxy::ChangePrivilege(const std::string &sharingRes, const std::vector &participants, - Result>> &result) +int32_t CloudServiceProxy::ChangePrivilege( + const std::string &sharingRes, const Participants &participants, Results &results) { MessageParcel reply; int32_t status = IPC_SEND(TRANS_CHANGE_PRIVILEGE, reply, sharingRes, participants); @@ -148,52 +173,52 @@ int32_t CloudServiceProxy::ChangePrivilege(const std::string &sharingRes, const LOG_ERROR("status:0x%{public}x sharingRes:%{public}.6s participants:%{public}zu", status, sharingRes.c_str(), participants.size()); } - ITypesUtil::Unmarshal(reply, result); + ITypesUtil::Unmarshal(reply, results); return static_cast(status); } -int32_t CloudServiceProxy::QueryParticipants(const std::string &sharingRes, Result> &result) +int32_t CloudServiceProxy::Query(const std::string &sharingRes, QueryResults &results) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_QUERY_PARTICIPANTS, reply, 02); + int32_t status = IPC_SEND(TRANS_QUERY, reply, sharingRes); if (status != SUCCESS) { LOG_ERROR("status:0x%{public}x sharingRes:%{public}.6s", status, sharingRes.c_str()); } - ITypesUtil::Unmarshal(reply, result); + ITypesUtil::Unmarshal(reply, results); return static_cast(status); } -int32_t CloudServiceProxy::QueryParticipantsByInvitation( - const std::string &invitationCode, Result> &result) +int32_t CloudServiceProxy::QueryByInvitation( + const std::string &invitation, QueryResults &results) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_QUERY_PARTICIPANTS_BY_INVITATION, reply, invitationCode); + int32_t status = IPC_SEND(TRANS_QUERY_BY_INVITATION, reply, invitation); if (status != SUCCESS) { - LOG_ERROR("status:0x%{public}x invitationCode:%{public}.6s", status, invitationCode.c_str()); + LOG_ERROR("status:0x%{public}x invitation:%{public}.6s", status, invitation.c_str()); } - ITypesUtil::Unmarshal(reply, result); + ITypesUtil::Unmarshal(reply, results); return static_cast(status); } -int32_t CloudServiceProxy::ConfirmInvitation(const std::string &invitationCode, - Confirmation confirmation, Result &result) +int32_t CloudServiceProxy::ConfirmInvitation(const std::string &invitation, + int32_t confirmation, std::tuple &result) { MessageParcel reply; - int32_t status = IPC_SEND(TRANS_CONFIRM_INVITATION, reply, invitationCode, confirmation); + int32_t status = IPC_SEND(TRANS_CONFIRM_INVITATION, reply, invitation, confirmation); if (status != SUCCESS) { - LOG_ERROR("status:0x%{public}x invitationCode:%{public}.6s", status, invitationCode.c_str()); + LOG_ERROR("status:0x%{public}x invitation:%{public}.6s", status, invitation.c_str()); } ITypesUtil::Unmarshal(reply, result); return static_cast(status); } int32_t CloudServiceProxy::ChangeConfirmation(const std::string &sharingRes, - Confirmation confirmation, Result &result) + int32_t confirmation, std::pair &result) { MessageParcel reply; int32_t status = IPC_SEND(TRANS_CHANGE_CONFIRMATION, reply, sharingRes, confirmation); if (status != SUCCESS) { - LOG_ERROR("status:0x%{public}x invitationCode:%{public}.6s", status, sharingRes.c_str()); + LOG_ERROR("status:0x%{public}x sharingRes:%{public}.6s", status, sharingRes.c_str()); } ITypesUtil::Unmarshal(reply, result); return static_cast(status); diff --git a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp index d989703217905f7571084200c7024db67b4a4c5a..b811d9d47ea1d676696d857ee2233adec2de50cf 100644 --- a/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp +++ b/relational_store/frameworks/native/cloud_data/src/cloud_types_util.cpp @@ -19,26 +19,28 @@ namespace OHOS::ITypesUtil { template<> bool Marshalling(const Participant &input, MessageParcel &data) { - return ITypesUtil::Marshal(data, input.identity, input.role, input.status, input.privilege); + return ITypesUtil::Marshal( + data, input.identity, input.role, input.state, input.privilege, input.attachInfo); } template<> bool Unmarshalling(Participant &output, MessageParcel &data) { - return ITypesUtil::Unmarshal(data, output.identity, output.role, output.status, output.privilege); + return ITypesUtil::Unmarshal( + data, output.identity, output.role, output.state, output.privilege, output.attachInfo); } template<> bool Marshalling(const Privilege &input, MessageParcel &data) { - return ITypesUtil::Marshal(data, input.writeable, input.readable, + return ITypesUtil::Marshal(data, input.writable, input.readable, input.creatable, input.deletable, input.shareable); } template<> bool Unmarshalling(Privilege &output, MessageParcel &data) { - return ITypesUtil::Unmarshal(data, output.writeable, output.readable, + return ITypesUtil::Unmarshal(data, output.writable, output.readable, output.creatable, output.deletable, output.shareable); } @@ -52,7 +54,7 @@ template<> bool Unmarshalling(Role &output, MessageParcel &data) { int32_t result; - if (!data.ReadInt32(result) || result < Role::ROLE_NIL || result > Role::ROLE_INVITEES) { + if (!data.ReadInt32(result) || result <= Role::ROLE_NIL || result >= Role::ROLE_BUTT) { return false; } output = static_cast(result); @@ -69,8 +71,8 @@ template<> bool Unmarshalling(Confirmation &output, MessageParcel &data) { int32_t result; - if (!data.ReadInt32(result) || result < Confirmation::CFM_NIL || - result > Confirmation::CFM_SUSPENDED) { + if (!data.ReadInt32(result) || result <= Confirmation::CFM_NIL || + result >= Confirmation::CFM_BUTT) { return false; } output = static_cast(result); @@ -87,10 +89,41 @@ template<> bool Unmarshalling(SharingCode &output, MessageParcel &data) { int32_t result; - if (!data.ReadInt32(result) || result < SharingCode::SHARING_OK || result >= SharingCode::SHARING_BUTT) { + if (!data.ReadInt32(result) || result < SharingCode::SUCCESS) { return false; } output = static_cast(result); return true; } + +template<> +bool Marshalling(const Asset &input, MessageParcel &data) +{ + return Marshal(data, input.version, input.name, input.size, input.modifyTime, input.uri); +} +template<> +bool Unmarshalling(Asset &output, MessageParcel &data) +{ + return Unmarshal(data, output.version, output.name, output.size, output.modifyTime, output.uri); +} +template<> +bool Marshalling(const ValueObject &input, MessageParcel &data) +{ + return Marshal(data, input.value); +} +template<> +bool Unmarshalling(ValueObject &output, MessageParcel &data) +{ + return Unmarshal(data, output.value); +} +template<> +bool Marshalling(const ValuesBucket &input, MessageParcel &data) +{ + return Marshal(data, input.values_); +} +template<> +bool Unmarshalling(ValuesBucket &output, MessageParcel &data) +{ + return Unmarshal(data, output.values_); +} } // namespace OHOS::ITypesUtil \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h index 9ff2aa4aede5b07853740c334c799f0d394f2a5a..d930085823a26aad5ff110296c190fe1aa9db27d 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h +++ b/relational_store/frameworks/native/rdb/include/rdb_service_proxy.h @@ -41,7 +41,7 @@ public: int32_t InitNotifier(const RdbSyncerParam ¶m, sptr notifier) override; int32_t SetDistributedTables(const RdbSyncerParam ¶m, const std::vector &tables, - int32_t type = DISTRIBUTED_DEVICE) override; + const std::vector &references, int32_t type = DISTRIBUTED_DEVICE) override; int32_t Sync(const RdbSyncerParam& param, const Option& option, const PredicatesMemo& predicates, const AsyncDetail &async) override; @@ -68,6 +68,11 @@ public: int32_t GetSchema(const RdbSyncerParam ¶m) override; int32_t Delete(const RdbSyncerParam ¶m) override; + + int32_t NotifyDataChange(const RdbSyncerParam& param, const RdbChangedData &clientChangedData) override; + + std::pair> QuerySharingResource(const RdbSyncerParam ¶m, + const PredicatesMemo &predicates, const std::vector &columns) override; private: using ChangeInfo = RdbStoreObserver::ChangeInfo; using PrimaryFields = RdbStoreObserver::PrimaryFields; diff --git a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h index e0dcb72bfd34c5b9e08bf3ffd7339b16e3900421..e6d44f88042efaa5272f53bcd6a498bf6559d165 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/include/rdb_store_impl.h @@ -141,6 +141,8 @@ public: const AbsRdbPredicates &predicates, const std::vector &columns) override; std::shared_ptr Query( const AbsRdbPredicates &predicates, const std::vector &columns) override; + std::pair> QuerySharingResource( + const AbsRdbPredicates &predicates, const std::vector &columns) override; int Count(int64_t &outValue, const AbsRdbPredicates &predicates) override; int Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates) override; int Delete(int &deletedRows, const AbsRdbPredicates &predicates) override; @@ -172,6 +174,8 @@ public: ModifyTime GetModifyTime(const std::string& table, const std::string& columnName, std::vector& keys) override; + int CleanDirtyData(const std::string &table, uint64_t cursor = UINT64_MAX) override; + private: int InnerOpen(); int CheckAttach(const std::string &sql); @@ -182,7 +186,7 @@ private: int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); int ExecuteSqlInner(const std::string &sql, const std::vector &bindArgs); int ExecuteGetLongInner(const std::string &sql, const std::vector &bindArgs); - void SetAssetStatusWhileInsert(const ValueObject &val); + void SetAssetStatus(const ValueObject &val, int32_t status); void DoCloudSync(const std::string &table); int InnerSync(const DistributedRdb::RdbService::Option &option, const DistributedRdb::PredicatesMemo &predicates, const AsyncDetail &async); @@ -200,6 +204,8 @@ private: int UnSubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer); int UnSubscribeLocalSharedAll(const SubscribeOption& option); int UnSubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer); + int RegisterDataChangeCallback(); + int NotifyDataChange(DistributedRdb::RdbChangedData &rdbChangedData); const RdbStoreConfig rdbStoreConfig; SqliteConnectionPool *connectionPool; diff --git a/relational_store/frameworks/native/rdb/include/rdb_types_util.h b/relational_store/frameworks/native/rdb/include/rdb_types_util.h index 57f45c00350c035860e13269bb82dfb6024f9c9f..e1c20d83ade0b87658bdc2d17cb58eb3488d9956 100644 --- a/relational_store/frameworks/native/rdb/include/rdb_types_util.h +++ b/relational_store/frameworks/native/rdb/include/rdb_types_util.h @@ -40,6 +40,9 @@ using Origin = DistributedRdb::Origin; using ChangeInfo = Observer::ChangeInfo; using PrimaryKey = Observer::PrimaryKey; using PrimaryKeys = std::vector[Observer::CHG_TYPE_BUTT]; +using RdbChangedData = DistributedRdb::RdbChangedData; +using RdbProperties = DistributedRdb::RdbChangeProperties; +using Reference = DistributedRdb::Reference; template<> API_EXPORT bool Marshalling(const SyncerParam &input, MessageParcel &data); template<> @@ -96,5 +99,17 @@ template<> API_EXPORT bool Marshalling(const Origin &input, MessageParcel &data); template<> API_EXPORT bool Unmarshalling(Origin &output, MessageParcel &data); +template<> +API_EXPORT bool Marshalling(const RdbChangedData &input, MessageParcel &data); +template<> +API_EXPORT bool Unmarshalling(RdbChangedData &output, MessageParcel &data); +template<> +API_EXPORT bool Marshalling(const RdbProperties &input, MessageParcel &data); +template<> +API_EXPORT bool Unmarshalling(RdbProperties &output, MessageParcel &data); +template<> +API_EXPORT bool Marshalling(const Reference &input, MessageParcel &data); +template<> +API_EXPORT bool Unmarshalling(Reference &output, MessageParcel &data); } #endif // DISTRIBUTED_RDB_RDB_TYPES_UTIL_H diff --git a/relational_store/frameworks/native/rdb/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/include/sqlite_connection.h index 67c0fdc182de9ef15276e2a01f84608948d0d952..3de49c75811aa8bea7c890b18b262a36da95c244 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_connection.h @@ -26,9 +26,15 @@ #include "value_object.h" #include "shared_block.h" +typedef struct ClientChangedData ClientChangedData; namespace OHOS { namespace NativeRdb { +/** + * @brief Use DataChangeCallback replace std::function. + */ +using DataChangeCallback = std::function; + class SqliteConnection { public: static SqliteConnection *Open(const RdbStoreConfig &config, bool isWriteConnection, int &errCode); @@ -55,6 +61,8 @@ public: #endif int ExecuteForSharedBlock(int &rowNum, std::string sql, const std::vector &bindArgs, AppDataFwk::SharedBlock *sharedBlock, int startPos, int requiredPos, bool isCountAllRows); + int CleanDirtyData(const std::string &table, uint64_t cursor); + int RegisterCallBackObserver(const DataChangeCallback &clientChangedData); private: static constexpr const char *MERGE_ASSETS_FUNC = "merge_assets"; diff --git a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h index 0b070fa43efc83e5838a807c57a0bb9d22ba0a86..f068ae3ee268a3a25ebe7863c300c93851127f90 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_sql_builder.h @@ -34,22 +34,27 @@ public: const std::vector &whereArgs, const std::string &index, const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset, std::vector &bindArgs, ConflictResolution conflictResolution); - static int BuildQueryString(bool distinct, const std::string &table, const std::vector &columns, - const std::string &whereClause, const std::string &groupBy, const std::string &indexName, - const std::string &orderBy, const int &limit, const int &offset, std::string &outSql); + static int BuildQueryString(bool distinct, const std::string &table, const std::string &joinClause, + const std::vector &columns, const std::string &whereClause, const std::string &groupBy, + const std::string &indexName, const std::string &orderBy, const int &limit, + const int &offset, std::string &outSql); static std::string BuildCountString(const std::string &tableName, const std::string &index, const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset); - static std::string BuildSqlStringFromPredicates(const std::string &index, const std::string &whereClause, - const std::string &group, const std::string &order, int limit, int offset); + static std::string BuildSqlStringFromPredicates(const std::string &index, const std::string &joinClause, + const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset); static std::string BuildSqlStringFromPredicatesNoWhere(const std::string &index, const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset); static std::string BuildQueryString(const AbsRdbPredicates &predicates, const std::vector &columns); static std::string BuildCountString(const AbsRdbPredicates &predicates); static std::string BuildSqlStringFromPredicates(const AbsPredicates &predicates); + static std::string BuildCursorQueryString( + const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable); private: - static void AppendClause(std::string &builder, const std::string &name, const std::string &clause); - static void AppendColumns(std::string &builder, const std::vector &columns); + static void AppendClause(std::string &builder, const std::string &name, + const std::string &clause, const std::string &table = ""); + static void AppendColumns( + std::string &builder, const std::vector &columns, const std::string &table = ""); }; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/include/sqlite_utils.h b/relational_store/frameworks/native/rdb/include/sqlite_utils.h index f5264d716eb64c34ced8fedef90cb90cffc4c738..84f4029f22d78624db3b36fba88982f1997b25d1 100644 --- a/relational_store/frameworks/native/rdb/include/sqlite_utils.h +++ b/relational_store/frameworks/native/rdb/include/sqlite_utils.h @@ -35,12 +35,14 @@ public: static const int STATEMENT_DDL; static const int STATEMENT_OTHER; static const int CONFLICT_CLAUSE_COUNT = 6; + static constexpr const char* REP = "#_"; static int GetSqlStatementType(const std::string &sql); static bool IsSqlReadOnly(int sqlType); static bool IsSpecial(int sqlType); static int GetConflictClause(int conflictResolution, std::string &conflictClause); static std::string StrToUpper(std::string s); + static void Replace(std::string &src, const std::string &rep, const std::string &dst); static bool DeleteFile(const std::string path); static int RenameFile(const std::string srcFile, const std::string destFile); static std::string Anonymous(const std::string &srcFile); diff --git a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h index 78c66e3dad983ea8f9f87f706d72301c9213a214..b12ec0dc13216df7421902ae04487d4d047ca605 100644 --- a/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h +++ b/relational_store/frameworks/native/rdb/mock/include/rdb_store_impl.h @@ -108,11 +108,13 @@ private: int GetDataBasePath(const std::string &databasePath, std::string &backupFilePath); int ExecuteSqlInner(const std::string &sql, const std::vector &bindArgs); int ExecuteGetLongInner(const std::string &sql, const std::vector &bindArgs); - void SetAssetStatusWhileInsert(const ValueObject &val); + void SetAssetStatus(const ValueObject &val, int32_t status); void DoCloudSync(const std::string &table); int InnerBackup(const std::string databasePath, const std::vector destEncryptKey = std::vector()); inline std::string GetSqlArgs(size_t size); + int RegisterDataChangeCallback(); + int NotifyDataChange(DistributedRdb::RdbChangedData &rdbChangedData); const RdbStoreConfig rdbStoreConfig; SqliteConnectionPool *connectionPool; diff --git a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h index cdea3b6e5f48236eea211a2c634c2942ce13b491..200cbb5b435b8cf08d528a5691308d3ac187d35c 100644 --- a/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h +++ b/relational_store/frameworks/native/rdb/mock/include/sqlite_connection.h @@ -25,8 +25,14 @@ #include "sqlite_statement.h" #include "value_object.h" +typedef struct ClientChangedData ClientChangedData; namespace OHOS { namespace NativeRdb { +/** + * @brief Use DataChangeCallback replace std::function. + */ +using DataChangeCallback = std::function; + class SqliteConnection { public: static SqliteConnection *Open(const RdbStoreConfig &config, bool isWriteConnection, int &errCode); @@ -52,6 +58,8 @@ public: int ConfigLocale(const std::string localeStr); #endif + int RegisterCallBackObserver(const DataChangeCallback &clientChangedData); + private: static constexpr const char *MERGE_ASSETS_FUNC = "merge_assets"; explicit SqliteConnection(bool isWriteConnection); diff --git a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp index 88b9b9d0cd3a8990f9e4d39aa73b743842066d46..0c55fbed0859185f6cc07023700a917b690817b1 100644 --- a/relational_store/frameworks/native/rdb/src/abs_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_predicates.cpp @@ -21,13 +21,14 @@ #include "logger.h" #include "rdb_trace.h" +#include "rdb_types.h" #include "sqlite_sql_builder.h" #include "string_utils.h" namespace OHOS { namespace NativeRdb { using namespace OHOS::Rdb; - +static constexpr const char* FLAG[AbsPredicates::Origin::BUTT] = { "0x02", "0x0", "0x0" }; AbsPredicates::AbsPredicates() { Initial(); @@ -55,13 +56,31 @@ AbsPredicates *AbsPredicates::EqualTo(const std::string &field, const ValueObjec if (!CheckParameter("equalTo", field, { value })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); + ValueObject valObj = value; + std::string newField = field; + std::string flagVal; + if (newField == DistributedRdb::Field::ORIGIN_FIELD) { + newField = LOG_ORIGIN_FIELD; + double location = 0; + valObj.GetDouble(location); + if (location < 0 || location > Origin::REMOTE) { + return this; + } + flagVal = FLAG[static_cast(location)]; + valObj = ValueObject(flagVal); + } if (isNeedAnd) { whereClause += "AND "; } else { isNeedAnd = true; } - whereClause += field + " = ? "; - bindArgs.push_back(value); + if (flagVal.empty()) { + whereClause += newField + " = ? "; + bindArgs.push_back(std::move(valObj)); + } else { + whereClause += "(" + newField + " & 0x02 = " + flagVal + ")"; + } return this; } @@ -73,6 +92,7 @@ AbsPredicates *AbsPredicates::NotEqualTo(const std::string &field, const ValueOb if (!CheckParameter("notEqualTo", field, { value })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); CheckIsNeedAnd(); whereClause += field + " <> ? "; bindArgs.push_back(value); @@ -223,6 +243,7 @@ AbsPredicates *AbsPredicates::Between(const std::string &field, const ValueObjec if (!CheckParameter("between", field, { low, high })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); CheckIsNeedAnd(); whereClause += field + " BETWEEN ? AND ? "; bindArgs.push_back(low); @@ -238,6 +259,7 @@ AbsPredicates *AbsPredicates::NotBetween(const std::string &field, const ValueOb if (!CheckParameter("notBetween", field, { low, high })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); CheckIsNeedAnd(); whereClause += field + " NOT BETWEEN ? AND ? "; bindArgs.push_back(low); @@ -253,6 +275,7 @@ AbsPredicates *AbsPredicates::GreaterThan(const std::string &field, const ValueO if (!CheckParameter("greaterThan", field, { value })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); CheckIsNeedAnd(); whereClause += field + " > ? "; bindArgs.push_back(value); @@ -267,6 +290,7 @@ AbsPredicates *AbsPredicates::LessThan(const std::string &field, const ValueObje if (!CheckParameter("lessThan", field, { value })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); CheckIsNeedAnd(); whereClause += field + " < ? "; bindArgs.push_back(value); @@ -281,6 +305,7 @@ AbsPredicates *AbsPredicates::GreaterThanOrEqualTo(const std::string &field, con if (!CheckParameter("greaterThanOrEqualTo", field, { value })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); CheckIsNeedAnd(); whereClause += field + " >= ? "; bindArgs.push_back(value); @@ -295,6 +320,7 @@ AbsPredicates *AbsPredicates::LessThanOrEqualTo(const std::string &field, const if (!CheckParameter("greaterThanOrEqualTo", field, { value })) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); CheckIsNeedAnd(); whereClause += field + " <= ? "; bindArgs.push_back(value); @@ -310,6 +336,7 @@ AbsPredicates *AbsPredicates::OrderByAsc(const std::string &field) if (!CheckParameter("orderByAsc", field, {})) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); if (isSorted) { order += ','; } @@ -327,6 +354,7 @@ AbsPredicates *AbsPredicates::OrderByDesc(const std::string &field) if (!CheckParameter("orderByDesc", field, {})) { return this; } + hasSpecificField = hasSpecificField || IsSpecificField(field); if (isSorted) { order += ','; } @@ -599,6 +627,11 @@ bool AbsPredicates::IsSorted() const return isSorted; } +bool AbsPredicates::HasSpecificField() const +{ + return hasSpecificField; +} + std::string AbsPredicates::GetGroup() const { return group; diff --git a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp index 1b757bcf4771d7468bf1d114990e6f5a12735b77..276417c6ff088bd71f947426b0311d04f911f5bf 100644 --- a/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_rdb_predicates.cpp @@ -110,7 +110,7 @@ void AbsRdbPredicates::SetJoinConditions(const std::vector &joinCon */ std::string AbsRdbPredicates::GetJoinClause() const { - return tableName_; + return ""; } /** @@ -251,4 +251,70 @@ AbsPredicates *AbsRdbPredicates::In(const std::string &field, const std::vector< predicates_.AddOperation(DistributedRdb::IN, field, values); return (AbsRdbPredicates *)AbsPredicates::In(field, values); } + +AbsRdbPredicates *AbsRdbPredicates::Contains(const std::string &field, const std::string &value) +{ + predicates_.AddOperation(DistributedRdb::CONTAIN, field, value); + return (AbsRdbPredicates *)AbsPredicates::Contains(field, value); +} + +AbsRdbPredicates *AbsRdbPredicates::BeginsWith(const std::string &field, const std::string &value) +{ + predicates_.AddOperation(DistributedRdb::BEGIN_WITH, field, value); + return (AbsRdbPredicates *)AbsPredicates::BeginsWith(field, value); +} +AbsRdbPredicates *AbsRdbPredicates::EndsWith(const std::string &field, const std::string &value) +{ + predicates_.AddOperation(DistributedRdb::END_WITH, field, value); + return (AbsRdbPredicates *)AbsPredicates::EndsWith(field, value); +} +AbsRdbPredicates *AbsRdbPredicates::IsNull(const std::string &field) +{ + predicates_.AddOperation(DistributedRdb::IS_NULL, field, ""); + return (AbsRdbPredicates *)AbsPredicates::IsNull(field); +} +AbsRdbPredicates *AbsRdbPredicates::IsNotNull(const std::string &field) +{ + predicates_.AddOperation(DistributedRdb::IS_NOT_NULL, field, ""); + return (AbsRdbPredicates *)AbsPredicates::IsNotNull(field); +} +AbsRdbPredicates *AbsRdbPredicates::Like(const std::string &field, const std::string &value) +{ + predicates_.AddOperation(DistributedRdb::LIKE, field, value); + return (AbsRdbPredicates *)AbsPredicates::Like(field, value); +} +AbsRdbPredicates *AbsRdbPredicates::Glob(const std::string &field, const std::string &value) +{ + predicates_.AddOperation(DistributedRdb::GLOB, field, value); + return (AbsRdbPredicates *)AbsPredicates::Glob(field, value); +} +AbsRdbPredicates *AbsRdbPredicates::Distinct() +{ + predicates_.AddOperation(DistributedRdb::DISTINCT, "", ""); + return (AbsRdbPredicates *)AbsPredicates::Distinct(); +} +AbsRdbPredicates *AbsRdbPredicates::IndexedBy(const std::string &indexName) +{ + predicates_.AddOperation(DistributedRdb::INDEXED_BY, indexName, ""); + return (AbsRdbPredicates *)AbsPredicates::IndexedBy(indexName); +} +AbsRdbPredicates *AbsRdbPredicates::NotIn(const std::string &field, const std::vector &values) +{ + predicates_.AddOperation(DistributedRdb::NOT_IN, field, values); + return (AbsRdbPredicates *)AbsPredicates::NotIn(field, values); +} +AbsRdbPredicates *AbsRdbPredicates::NotIn(const std::string &field, const std::vector &values) +{ + std::vector vals; + vals.reserve(values.size()); + for (const auto &value : values) { + auto val = std::get_if(&value.value); + if (val == nullptr) { + return (AbsRdbPredicates *)AbsPredicates::NotIn(field, values); + } + vals.emplace_back(std::move(*val)); + } + predicates_.AddOperation(DistributedRdb::NOT_IN, field, vals); + return (AbsRdbPredicates *)AbsPredicates::NotIn(field, values); +} } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp index 244ef420d09ce3f439b9f2a4bce6cceb4d9aadfc..1eea08f79e12a499ba3c6d7c038617d65d506c07 100644 --- a/relational_store/frameworks/native/rdb/src/abs_result_set.cpp +++ b/relational_store/frameworks/native/rdb/src/abs_result_set.cpp @@ -22,6 +22,7 @@ #include "rdb_errno.h" #include "rdb_trace.h" #include "result_set.h" +#include "sqlite_utils.h" namespace OHOS { namespace NativeRdb { @@ -336,7 +337,7 @@ int AbsResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex LOG_ERROR("Failed to GetAllColumnNames, ret is %{public}d", ret); return ret; } - + SqliteUtils::Replace(columnNameLower, SqliteUtils::REP, ""); columnIndex = 0; for (const auto& name : columnNames) { std::string lowerName = name; diff --git a/relational_store/frameworks/native/rdb/src/cache_result_set.cpp b/relational_store/frameworks/native/rdb/src/cache_result_set.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7673ff76f61e211eb501bed7cddb27b7fe71713b --- /dev/null +++ b/relational_store/frameworks/native/rdb/src/cache_result_set.cpp @@ -0,0 +1,331 @@ +/* +* Copyright (c) 2021 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. +*/ + +#define LOG_TAG "CacheResultSet" +#include "cache_result_set.h" + +#include +#include + +#include "abs_result_set.h" +#include "logger.h" +#include "rdb_errno.h" +#include "rdb_trace.h" +namespace OHOS { +namespace NativeRdb { +CacheResultSet::CacheResultSet(std::vector &&valueBuckets) + : row_(0), maxCol_(0), valueBuckets_(std::move(valueBuckets)) +{ + maxRow_ = valueBuckets_.size(); + if (maxRow_ > 0) { + for (auto it = valueBuckets_[0].values_.begin(); it != valueBuckets_[0].values_.end(); it++) { + colNames_.push_back(it->first); + colTypes_.push_back(it->second.GetType()); + } + maxCol_ = colNames_.size(); + } +} + +CacheResultSet::~CacheResultSet() +{ +} + +int CacheResultSet::GetRowCount(int &count) +{ + count = static_cast(colNames_.size()); + return E_OK; +} + +int CacheResultSet::GetAllColumnNames(std::vector &columnNames) +{ + columnNames = colNames_; + return E_OK; +} + +int CacheResultSet::GetBlob(int columnIndex, std::vector &blob) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[columnIndex]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + return valueBuckets_[row_].values_[name].GetBlob(blob); +} + +int CacheResultSet::GetString(int columnIndex, std::string &value) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[columnIndex]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + return valueBuckets_[row_].values_[name].GetString(value); +} + +int CacheResultSet::GetInt(int columnIndex, int &value) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[columnIndex]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + return valueBuckets_[row_].values_[name].GetInt(value); +} + +int CacheResultSet::GetLong(int columnIndex, int64_t &value) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[columnIndex]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + return valueBuckets_[row_].values_[name].GetLong(value); +} + +int CacheResultSet::GetDouble(int columnIndex, double &value) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[columnIndex]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + return valueBuckets_[row_].values_[name].GetDouble(value); +} + +int CacheResultSet::IsColumnNull(int columnIndex, bool &isNull) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[columnIndex]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + isNull = valueBuckets_[row_].values_[name].GetType() == ValueObject::TYPE_NULL; + return E_OK; +} + +int CacheResultSet::GetRow(RowEntity &rowEntity) +{ + rowEntity.Clear(); + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + ValueObject object; + for (auto &columnName : colNames_) { + if (!valueBuckets_[row_].GetObject(columnName, object)) { + return E_ERROR; + } + rowEntity.Put(columnName, object); + } + return E_OK; +} + +int CacheResultSet::GoToRow(int position) +{ + std::unique_lock lock(rwMutex_); + if (position > maxRow_) { + row_ = maxRow_; + return E_OK; + } + if (position < 0) { + row_ = 0; + return E_OK; + } + row_ = position; + return E_OK; +} + +int CacheResultSet::GetColumnType(int columnIndex, ColumnType &columnType) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + auto index = colTypes_[columnIndex]; + if (index < ValueObject::TYPE_NULL || index >= ValueObject::TYPE_MAX) { + return E_INVALID_ARGS; + } + columnType = COLUMNTYPES[index]; + return E_OK; +} + +int CacheResultSet::GetRowIndex(int &position) const +{ + std::shared_lock lock(rwMutex_); + position = row_; + return E_OK; +} + +int CacheResultSet::GoTo(int offset) +{ + int target = offset; + { + std::shared_lock lock(rwMutex_); + target += row_; + } + return GoToRow(target); +} + +int CacheResultSet::GoToFirstRow() +{ + return GoToRow(0); +} + +int CacheResultSet::GoToLastRow() +{ + return GoToRow(maxRow_ - 1); +} + +int CacheResultSet::GoToNextRow() +{ + return GoTo(1); +} + +int CacheResultSet::GoToPreviousRow() +{ + return GoTo(-1); +} + +int CacheResultSet::IsAtFirstRow(bool &result) const +{ + std::shared_lock lock(rwMutex_); + result = row_ == 0; + return E_OK; +} + +int CacheResultSet::IsAtLastRow(bool &result) +{ + std::shared_lock lock(rwMutex_); + result = row_ == maxRow_ - 1; + return E_OK; +} + +int CacheResultSet::IsStarted(bool &result) const +{ + std::shared_lock lock(rwMutex_); + result = row_ == -1; + return E_OK; +} + +int CacheResultSet::IsEnded(bool &result) +{ + std::shared_lock lock(rwMutex_); + result = maxRow_ == 0 || row_ == maxRow_; + return E_OK; +} + +int CacheResultSet::GetColumnCount(int &count) +{ + return static_cast(colNames_.size()); +} + +int CacheResultSet::GetColumnIndex(const std::string &columnName, int &columnIndex) +{ + for (int i = 0; i < maxCol_; ++i) { + if (colNames_[i] == columnName) { + columnIndex = i; + return E_OK; + } + } + return E_ERROR; +} + +int CacheResultSet::GetColumnName(int columnIndex, std::string &columnName) +{ + if (columnIndex < 0 || columnIndex >= maxCol_) { + return E_INVALID_ARGS; + } + columnName = columnName[columnIndex]; + return E_OK; +} + +bool CacheResultSet::IsClosed() const +{ + return false; +} + +int CacheResultSet::Close() +{ + return E_NOT_SUPPORT; +} + +int CacheResultSet::GetModifyTime(std::string &modifyTime) +{ + return E_NOT_SUPPORT; +} + +int CacheResultSet::GetAsset(int32_t col, ValueObject::Asset &value) +{ + if (col < 0 || col >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[col]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + return valueBuckets_[row_].values_[name].GetAsset(value); +} + +int CacheResultSet::GetAssets(int32_t col, ValueObject::Assets &value) +{ + if (col < 0 || col >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[col]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + return valueBuckets_[row_].values_[name].GetAssets(value); +} + +int CacheResultSet::Get(int32_t col, ValueObject &value) +{ + if (col < 0 || col >= maxCol_) { + return E_INVALID_ARGS; + } + auto name = colNames_[col]; + std::shared_lock lock(rwMutex_); + if (row_ < 0 || row_ >= maxRow_) { + return E_ERROR; + } + value = valueBuckets_[row_].values_[name]; + return E_OK; +} + +int CacheResultSet::GetSize(int columnIndex, size_t &size) +{ + return E_NOT_SUPPORT; +} +} +} // namespace OHOS \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp index fad63f5508e86f265bba003e206b03c7079accaf..4bd1b22bedc04f91d89430375edf21ec2febbeb9 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_helper.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_helper.cpp @@ -57,10 +57,10 @@ int RdbHelper::DeleteRdbStore(const std::string &dbFileName) if (dbFileName.empty()) { return E_EMPTY_FILE_NAME; } - RdbStoreManager::GetInstance().Delete(dbFileName); // maybe need to return here if (access(dbFileName.c_str(), F_OK) != 0) { return E_OK; // not not exist } + RdbStoreManager::GetInstance().Delete(dbFileName); int result = remove(dbFileName.c_str()); if (result != 0) { LOG_ERROR("RdbHelper DeleteRdbStore failed to delete the db file err = %{public}d", errno); diff --git a/relational_store/frameworks/native/rdb/src/rdb_predicates.cpp b/relational_store/frameworks/native/rdb/src/rdb_predicates.cpp index 466714d696c8234d48e19a1b9ef34f5533930063..0cf5828da607a7a1b1b547ec65226e0ad61cf028 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_predicates.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_predicates.cpp @@ -29,10 +29,7 @@ RdbPredicates::RdbPredicates(const std::string &tableName) : AbsRdbPredicates(ta std::string RdbPredicates::GetJoinClause() const { - if (!joinTableNames.empty()) { - return ProcessJoins(); - } - return GetTableName(); + return joinTableNames.empty() ? "" : ProcessJoins(); } /** @@ -120,10 +117,13 @@ RdbPredicates *RdbPredicates::On(const std::vector &clauses) std::string RdbPredicates::ProcessJoins() const { - std::string builder = GetTableName(); + std::string builder; size_t size = joinTableNames.size(); for (size_t i = 0; i < size; i++) { - builder = builder + " " + joinTypes[i] + " " + joinTableNames[i]; + if (i != 0) { + builder = builder + " "; + } + builder = builder + joinTypes[i] + " " + joinTableNames[i]; if (joinConditions[i] != "") { builder = builder + " " + joinConditions[i]; } diff --git a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp index 4a701100736bd6a7b4590354a1d33cff89959650..97b7f04a66ae4f80bfdd48d298b220b563dfea2c 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_service_proxy.cpp @@ -177,11 +177,11 @@ int32_t RdbServiceProxy::DoAsync(const RdbSyncerParam& param, const Option &opti } int32_t RdbServiceProxy::SetDistributedTables(const RdbSyncerParam& param, const std::vector &tables, - int32_t type) + const std::vector &references, int32_t type) { MessageParcel reply; int32_t status = IPC_SEND( - static_cast(RdbServiceCode::RDB_SERVICE_CMD_SET_DIST_TABLE), reply, param, tables, type); + static_cast(RdbServiceCode::RDB_SERVICE_CMD_SET_DIST_TABLE), reply, param, tables, references, type); if (status != RDB_OK) { LOG_ERROR("status:%{public}d, bundleName:%{public}s, storeName:%{public}s, type:%{public}d", status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str(), type); @@ -342,6 +342,21 @@ int32_t RdbServiceProxy::Delete(const RdbSyncerParam ¶m) return status; } +std::pair> RdbServiceProxy::QuerySharingResource( + const RdbSyncerParam ¶m, const PredicatesMemo &predicates, const std::vector &columns) +{ + MessageParcel reply; + int32_t status = IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_QUERY_SHARING_RESOURCE), reply, + param, predicates, columns); + std::vector valueBuckets; + bool success = ITypesUtil::Unmarshal(reply, valueBuckets); + if (status != RDB_OK || !success) { + LOG_ERROR("status:%{public}d, valueBuckets size:%{public}zu", status, valueBuckets.size()); + return { RDB_ERROR, {} }; + } + return { RDB_OK, valueBuckets }; +} + int32_t RdbServiceProxy::RegisterAutoSyncCallback( const RdbSyncerParam ¶m, std::shared_ptr observer) { @@ -461,4 +476,17 @@ void RdbServiceProxy::OnSyncComplete(const std::string &storeName, Details &&res return true; }); } + +int32_t RdbServiceProxy::NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData) +{ + MessageParcel reply; + int32_t status = IPC_SEND(static_cast(RdbServiceCode::RDB_SERVICE_CMD_NOTIFY_DATA_CHANGE), + reply, param, rdbChangedData); + if (status != RDB_OK) { + LOG_ERROR("RdbServiceProxy NotifyDataChange fail, status:%{public}d, " + "bundleName:%{public}s, storeName:%{public}s", + status, param.bundleName_.c_str(), SqliteUtils::Anonymous(param.storeName_).c_str()); + } + return status; +} } // namespace OHOS::DistributedRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp index ce58377c0cf0ddb006fa68613fd4bc0541fb6f2c..34ca126af3f55b59881023719069eb9dda1bdf11 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_config.cpp @@ -399,6 +399,16 @@ std::string RdbStoreConfig::GetDataGroupId() const return dataGroupId_; } +void RdbStoreConfig::SetAutoClean(bool isAutoClean) +{ + isAutoClean_ = isAutoClean; +} + +bool RdbStoreConfig::GetAutoClean() const +{ + return isAutoClean_; +} + void RdbStoreConfig::SetCustomDir(const std::string &customDir) { customDir_ = customDir; @@ -408,4 +418,14 @@ std::string RdbStoreConfig::GetCustomDir() const { return customDir_; } + +bool RdbStoreConfig::IsSearchable() const +{ + return isSearchable_; +} + +void RdbStoreConfig::SetSearchable(bool isSearchable) +{ + isSearchable_ = isSearchable; +} } // namespace OHOS::NativeRdb diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp index edab08d06ddcca7b8534fce5188e80ded1812351..cc09a8f4736267fa9242f64235c687d345ede1b5 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_impl.cpp @@ -21,6 +21,7 @@ #include #include "logger.h" +#include "cache_result_set.h" #include "rdb_errno.h" #include "rdb_sql_utils.h" #include "rdb_store.h" @@ -46,6 +47,8 @@ #include "result_set_proxy.h" #include "runtime_config.h" #include "sqlite_shared_result_set.h" +#include "sqlite_connection.h" +#include "relational_store_client.h" #endif #ifdef WINDOWS_PLATFORM @@ -74,8 +77,15 @@ int RdbStoreImpl::InnerOpen() syncerParam_.level_ = static_cast(rdbStoreConfig.GetSecurityLevel()); syncerParam_.type_ = rdbStoreConfig.GetDistributedType(); syncerParam_.isEncrypt_ = rdbStoreConfig.IsEncrypt(); + syncerParam_.isAutoClean_ = rdbStoreConfig.GetAutoClean(); + syncerParam_.isSearchable_ = rdbStoreConfig.IsSearchable(); syncerParam_.password_ = {}; GetSchema(rdbStoreConfig); + + errCode = RegisterDataChangeCallback(); + if (errCode != E_OK) { + LOG_ERROR("RegisterCallBackObserver is failed, err is %{public}d.", errCode); + } #endif return E_OK; } @@ -226,6 +236,21 @@ RdbStore::ModifyTime RdbStoreImpl::GetModifyTimeByRowId(const std::string &logTa } return { resultSet, {}, true }; } + +int RdbStoreImpl::CleanDirtyData(const std::string &table, uint64_t cursor) +{ + if (table.empty()) { + return E_INVALID_ARGS; + } + SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int errCode = connection->CleanDirtyData(table, cursor); + connectionPool->ReleaseConnection(connection); + return errCode; +} + #endif std::string RdbStoreImpl::GetSqlArgs(size_t size) @@ -352,11 +377,19 @@ std::pair> RdbStoreImpl::GetInsertParams( bindArgs.reserve(bindArgsSize); auto valueIter = valuesMap.begin(); sql.append(valueIter->first); + if (valueIter->second.GetType() == ValueObject::TYPE_ASSET || + valueIter->second.GetType() == ValueObject::TYPE_ASSETS) { + SetAssetStatus(valueIter->second, AssetValue::STATUS_INSERT); + } bindArgs.push_back(valueIter->second); ++valueIter; // prepare batch values & sql.columnName for (; valueIter != valuesMap.end(); ++valueIter) { sql.append(",").append(valueIter->first); + if (valueIter->second.GetType() == ValueObject::TYPE_ASSET || + valueIter->second.GetType() == ValueObject::TYPE_ASSETS) { + SetAssetStatus(valueIter->second, AssetValue::STATUS_INSERT); + } bindArgs.push_back(valueIter->second); } sql.append(") VALUES (").append(GetSqlArgs(bindArgsSize)).append(")"); @@ -400,7 +433,7 @@ int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::str return E_INVALID_ARGS; } if (val.GetType() == ValueObject::TYPE_ASSET || val.GetType() == ValueObject::TYPE_ASSETS) { - SetAssetStatusWhileInsert(val); + SetAssetStatus(val, AssetValue::STATUS_INSERT); } bindArgs.push_back(val); // columnValue split = ","; @@ -425,19 +458,19 @@ int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::str return errCode; } -void RdbStoreImpl::SetAssetStatusWhileInsert(const ValueObject &val) +void RdbStoreImpl::SetAssetStatus(const ValueObject &val, int32_t status) { if (val.GetType() == ValueObject::TYPE_ASSET) { auto *asset = Traits::get_if(&val.value); if (asset != nullptr) { - asset->status = AssetValue::STATUS_INSERT; + asset->status = static_cast(status); } } if (val.GetType() == ValueObject::TYPE_ASSETS) { auto *assets = Traits::get_if(&val.value); if (assets != nullptr) { for (auto &asset : *assets) { - asset.status = AssetValue::STATUS_INSERT; + asset.status = static_cast(status); } } } @@ -576,10 +609,29 @@ std::shared_ptr RdbStoreImpl::Query( const AbsRdbPredicates &predicates, const std::vector &columns) { DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); - std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + std::string sql; + if (predicates.HasSpecificField()) { + std::string table = predicates.GetTableName(); + std::string logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(table); + sql = SqliteSqlBuilder::BuildCursorQueryString(predicates, columns, logTable); + } else { + sql = SqliteSqlBuilder::BuildQueryString(predicates, columns); + } return QuerySql(sql, predicates.GetBindArgs()); } +std::pair> RdbStoreImpl::QuerySharingResource( + const AbsRdbPredicates &predicates, const std::vector &columns) +{ + auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK) { + return { errCode, nullptr }; + } + auto [status, valueBuckets] = + service->QuerySharingResource(syncerParam_, predicates.GetDistributedPredicates(), columns); + return { status, std::make_shared(std::move(valueBuckets)) }; +} + std::shared_ptr RdbStoreImpl::QueryByStep( const AbsRdbPredicates &predicates, const std::vector &columns) { @@ -616,7 +668,7 @@ std::shared_ptr RdbStoreImpl::Query(int &errCode, bool disti DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__)); std::string sql; errCode = SqliteSqlBuilder::BuildQueryString( - distinct, table, columns, whereClause, groupBy, indexName, orderBy, limit, offset, sql); + distinct, table, "", columns, whereClause, groupBy, indexName, orderBy, limit, offset, sql); if (errCode != E_OK) { return nullptr; } @@ -1334,7 +1386,7 @@ int RdbStoreImpl::SetDistributedTables(const std::vector &tables, i if (errCode != E_OK) { return errCode; } - int32_t errorCode = service->SetDistributedTables(syncerParam_, tables, type); + int32_t errorCode = service->SetDistributedTables(syncerParam_, tables, distributedConfig.references, type); if (errorCode != E_OK) { LOG_ERROR("Fail to set distributed tables, error=%{public}d", errorCode); return errorCode; @@ -1648,5 +1700,41 @@ int RdbStoreImpl::UnregisterAutoSyncCallback(std::shared_ptrUnregisterAutoSyncCallback(syncerParam_, observer); } + +int RdbStoreImpl::RegisterDataChangeCallback() +{ + if (!rdbStoreConfig.IsSearchable()) { + return E_OK; + } + auto callBack = [this](ClientChangedData &clientChangedData) { + DistributedRdb::RdbChangedData rdbChangedData; + for (const auto& entry : clientChangedData.tableData) { + DistributedRdb::RdbChangeProperties rdbProperties; + rdbProperties.isTrackedDataChange = entry.second.isTrackedDataChange; + rdbChangedData.tableData[entry.first] = rdbProperties; + } + int errCode = NotifyDataChange(rdbChangedData); + if (errCode != E_OK) { + LOG_ERROR("NotifyDataChange is failed, err is %{public}d.", errCode); + } + }; + SqliteConnection *connection = connectionPool->AcquireConnection(false); + if (connection == nullptr) { + return E_CON_OVER_LIMIT; + } + int code = connection->RegisterCallBackObserver(callBack); + connectionPool->ReleaseConnection(connection); + return code; +} + +int RdbStoreImpl::NotifyDataChange(DistributedRdb::RdbChangedData &rdbChangedData) +{ + auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_); + if (errCode != E_OK || service == nullptr) { + LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode); + return errCode; + } + return service->NotifyDataChange(syncerParam_, rdbChangedData); +} #endif } // namespace OHOS::NativeRdb \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp index 4afd9f3d804849175f4553abe637115d59791c88..f5343731d821971252d26d09e50cd0c3acfcfd0a 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_store_manager.cpp @@ -23,6 +23,7 @@ #include "rdb_store_impl.h" #include "rdb_trace.h" #include "sqlite_global_config.h" +#include "task_executor.h" #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM) @@ -169,12 +170,18 @@ bool RdbStoreManager::Delete(const std::string &path) param.storeName_ = *tokens.rbegin(); std::lock_guard lock(mutex_); param.bundleName_ = bundleName_; - auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); - if (err == E_OK && service != nullptr) { + TaskExecutor::GetInstance().GetExecutor()->Execute([param]() { + auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param); + if (err != E_OK || service == nullptr) { + LOG_DEBUG("GetRdbService failed, err is %{public}d.", err); + return; + } err = service->Delete(param); - } - LOG_DEBUG("service delete store, storeName:%{public}s, err = %{public}d", - SqliteUtils::Anonymous(param.storeName_).c_str(), err); + if (err != E_OK) { + LOG_ERROR("service delete store, storeName:%{public}s, err = %{public}d", + SqliteUtils::Anonymous(param.storeName_).c_str(), err); + } + }); } #endif return Remove(path); diff --git a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp index eb9640738f13289c56ad56e3a5b3fa16116bae82..36ed453db858e05ef8c9c39006ff67ac675bba91 100644 --- a/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp +++ b/relational_store/frameworks/native/rdb/src/rdb_types_util.cpp @@ -19,13 +19,15 @@ template<> bool Marshalling(const SyncerParam &input, MessageParcel &data) { return ITypesUtil::Marshal(data, input.bundleName_, input.hapName_, input.storeName_, input.area_, - input.level_, input.type_, input.isEncrypt_, input.password_, input.customDir_); + input.level_, input.type_, input.isEncrypt_, input.password_, input.customDir_, input.isAutoClean_, + input.isSearchable_); } template<> bool Unmarshalling(SyncerParam &output, MessageParcel &data) { return ITypesUtil::Unmarshal(data, output.bundleName_, output.hapName_, output.storeName_, output.area_, - output.level_, output.type_, output.isEncrypt_, output.password_, output.customDir_); + output.level_, output.type_, output.isEncrypt_, output.password_, output.customDir_, output.isAutoClean_, + output.isSearchable_); } template<> @@ -166,4 +168,37 @@ bool Unmarshalling(Origin &output, MessageParcel &data) { return Unmarshal(data, output.origin, output.dataType, output.id, output.store); } + +template<> +bool Marshalling(const RdbChangedData &input, MessageParcel &data) +{ + return Marshal(data, input.tableData); +} +template<> +bool Unmarshalling(RdbChangedData &output, MessageParcel &data) +{ + return Unmarshal(data, output.tableData); +} + +template<> +bool Marshalling(const RdbProperties &input, MessageParcel &data) +{ + return Marshal(data, input.isTrackedDataChange); +} +template<> +bool Unmarshalling(RdbProperties &output, MessageParcel &data) +{ + return Unmarshal(data, output.isTrackedDataChange); +} + +template<> +bool Marshalling(const Reference &input, MessageParcel &data) +{ + return Marshal(data, input.sourceTable, input.targetTable, input.refFields); +} +template<> +bool Unmarshalling(Reference &output, MessageParcel &data) +{ + return Unmarshal(data, output.sourceTable, output.targetTable, output.refFields); } +} \ No newline at end of file diff --git a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp index 726cc37dc05f2064911d8854bfa921b3e0b33d90..f0dd3e322896183f40e53a08e8d578507d6f91a3 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_connection.cpp @@ -37,8 +37,10 @@ #include "directory_ex.h" #include "rdb_security_manager.h" #include "relational/relational_store_sqlite_ext.h" +#include "relational_store_client.h" #include "share_block.h" #include "shared_block_serializer_info.h" +#include "relational_store_client.h" #endif namespace OHOS { @@ -113,8 +115,10 @@ int SqliteConnection::InnerOpen(const RdbStoreConfig &config) } #endif isReadOnly = !isWriteConnection || config.IsReadOnly(); - int openFileFlags = config.IsReadOnly() ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE); - int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle, openFileFlags | SQLITE_OPEN_FULLMUTEX, nullptr); + int openFileFlags = config.IsReadOnly() ? + (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) : + (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX); + int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle, openFileFlags, nullptr); if (errCode != SQLITE_OK) { LOG_ERROR("SqliteConnection InnerOpen fail to open database err = %{public}d", errCode); #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) @@ -829,6 +833,28 @@ int SqliteConnection::ExecuteForSharedBlock(int &rowNum, std::string sql, const errCode = statement.ResetStatementAndClearBindings(); return errCode; } + +int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor) +{ + if (table.empty()) { + return E_ERROR; + } + uint64_t tmpCursor = cursor == UINT64_MAX ? 0 : cursor; + auto status = DropLogicDeletedData(dbHandle, table, tmpCursor); + return status == DistributedDB::DBStatus::OK ? E_OK : E_ERROR; +} + +int SqliteConnection::RegisterCallBackObserver(const DataChangeCallback &clientChangedData) +{ + if (isWriteConnection && clientChangedData != nullptr) { + int32_t status = RegisterClientObserver(dbHandle, clientChangedData); + if (status != E_OK) { + LOG_ERROR("RegisterClientObserver error, status:%{public}d", status); + } + return status; + } + return E_OK; +} #endif void SqliteConnection::SetInTransaction(bool transaction) @@ -869,7 +895,6 @@ int SqliteConnection::LimitWalSize() void SqliteConnection::MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value **argv) { - LOG_DEBUG("merge assets begin"); // 2 is the number of parameters if (ctx == nullptr || argc != 2 || argv == nullptr) { LOG_ERROR("Parameter does not meet restrictions."); @@ -881,16 +906,13 @@ void SqliteConnection::MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value int len = sqlite3_value_bytes(argv[0]); RawDataParser::ParserRawData(data, len, assets); } - LOG_DEBUG("merge assets get old assets"); std::map newAssets; data = static_cast(sqlite3_value_blob(argv[1])); if (data != nullptr) { int len = sqlite3_value_bytes(argv[1]); RawDataParser::ParserRawData(data, len, newAssets); } - LOG_DEBUG("merge assets get new assets"); CompAssets(assets, newAssets); - LOG_DEBUG("merge assets comp assets"); auto blob = RawDataParser::PackageRawData(assets); sqlite3_result_blob(ctx, blob.data(), blob.size(), SQLITE_TRANSIENT); } @@ -932,11 +954,11 @@ void SqliteConnection::MergeAsset(ValueObject::Asset &oldAsset, ValueObject::Ass using Status = ValueObject::Asset::Status; auto status = static_cast(oldAsset.status); switch (status) { - case Status::STATUS_UNKNOWN: - case Status::STATUS_NORMAL: - case Status::STATUS_ABNORMAL: - case Status::STATUS_INSERT: - case Status::STATUS_UPDATE: + case Status::STATUS_UNKNOWN: // fallthrough + case Status::STATUS_NORMAL: // fallthrough + case Status::STATUS_ABNORMAL: // fallthrough + case Status::STATUS_INSERT: // fallthrough + case Status::STATUS_UPDATE: // fallthrough if (oldAsset.modifyTime != newAsset.modifyTime || oldAsset.size != newAsset.size || oldAsset.uri != newAsset.uri || oldAsset.path != newAsset.path) { oldAsset.version = newAsset.version; diff --git a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp index 43cca8e32d0ae6512c8fc3f3327c2b88d65ea70f..03f03b54cd614b61495cdebec32397de50958d07 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_sql_builder.cpp @@ -22,6 +22,7 @@ #include "rdb_errno.h" #include "rdb_trace.h" #include "string_utils.h" +#include "sqlite_utils.h" namespace OHOS { namespace NativeRdb { @@ -40,7 +41,7 @@ std::string SqliteSqlBuilder::BuildDeleteString(const std::string &tableName, co { std::string sql; sql.append("Delete ").append("FROM ").append(tableName).append( - BuildSqlStringFromPredicates(index, whereClause, group, order, limit, offset)); + BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset)); return sql; } @@ -72,14 +73,14 @@ std::string SqliteSqlBuilder::BuildUpdateString(const ValuesBucket &values, cons bindArgs.push_back(ValueObject(whereArgs[i])); } } - sql.append(BuildSqlStringFromPredicates(index, whereClause, group, order, limit, offset)); + sql.append(BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset)); return sql; } /** * Build a query SQL string using the given condition for SQLite. */ -int SqliteSqlBuilder::BuildQueryString(bool distinct, const std::string &table, +int SqliteSqlBuilder::BuildQueryString(bool distinct, const std::string &table, const std::string &joinClause, const std::vector &columns, const std::string &whereClause, const std::string &groupBy, const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset, std::string &outSql) { @@ -98,7 +99,7 @@ int SqliteSqlBuilder::BuildQueryString(bool distinct, const std::string &table, sql.append("* "); } sql.append("FROM ").append(table).append( - BuildSqlStringFromPredicates(indexName, whereClause, groupBy, orderBy, limit, offset)); + BuildSqlStringFromPredicates(indexName, joinClause, whereClause, groupBy, orderBy, limit, offset)); outSql = sql; return E_OK; @@ -113,12 +114,12 @@ std::string SqliteSqlBuilder::BuildCountString(const std::string &tableName, con std::string sql; sql.append("SELECT COUNT(*) FROM ") .append(tableName) - .append(BuildSqlStringFromPredicates(index, whereClause, group, order, limit, offset)); + .append(BuildSqlStringFromPredicates(index, "", whereClause, group, order, limit, offset)); return sql; } -std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const std::string &index, const std::string &whereClause, - const std::string &group, const std::string &order, int limit, int offset) +std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const std::string &index, const std::string &joinClause, + const std::string &whereClause, const std::string &group, const std::string &order, int limit, int offset) { std::string sqlString; @@ -126,6 +127,7 @@ std::string SqliteSqlBuilder::BuildSqlStringFromPredicates(const std::string &in std::string offsetStr = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); AppendClause(sqlString, " INDEXED BY ", index); + AppendClause(sqlString, " ", joinClause); AppendClause(sqlString, " WHERE ", whereClause); AppendClause(sqlString, " GROUP BY ", group); AppendClause(sqlString, " ORDER BY ", order); @@ -170,40 +172,49 @@ std::string SqliteSqlBuilder::BuildSqlStringFromPredicatesNoWhere(const std::str return sqlString; } -void SqliteSqlBuilder::AppendClause(std::string &builder, const std::string &name, const std::string &clause) +void SqliteSqlBuilder::AppendClause(std::string &builder, const std::string &name, + const std::string &clause, const std::string &table) { if (clause.empty()) { return; } builder.append(name); + if (!table.empty()) { + builder.append(table).append("."); + } builder.append(clause); } /** * Add the names that are non-null in columns to s, separating them with commas. */ -void SqliteSqlBuilder::AppendColumns(std::string &builder, const std::vector &columns) +void SqliteSqlBuilder::AppendColumns( + std::string &builder, const std::vector &columns, const std::string &table) { - size_t length = columns.size(); - for (size_t i = 0; i < length; i++) { - std::string column = columns[i]; - - if (column.size() != 0) { - if (i > 0) { - builder.append(", "); - } - builder.append(column); + for (size_t i = 0; i < columns.size(); i++) { + const auto &col = columns[i]; + if (col.empty()) { + continue; + } + if (i > 0 && !(columns[i - 1].empty())) { + builder.append(", "); } + if (!table.empty()) { + builder.append(table).append("."); + } + builder.append(col); + } + if (table.empty()) { + builder += ' '; } - - builder += ' '; } std::string SqliteSqlBuilder::BuildQueryString( const AbsRdbPredicates &predicates, const std::vector &columns) { bool distinct = predicates.IsDistinct(); - std::string tableNameStr = predicates.GetJoinClause(); + std::string tableName = predicates.GetTableName(); + std::string joinClauseStr = predicates.GetJoinClause(); std::string whereClauseStr = predicates.GetWhereClause(); std::string groupStr = predicates.GetGroup(); std::string indexStr = predicates.GetIndex(); @@ -211,8 +222,8 @@ std::string SqliteSqlBuilder::BuildQueryString( int limit = predicates.GetLimit(); int offset = predicates.GetOffset(); std::string sqlStr; - BuildQueryString( - distinct, tableNameStr, columns, whereClauseStr, groupStr, indexStr, orderStr, limit, offset, sqlStr); + BuildQueryString(distinct, tableName, joinClauseStr, columns, whereClauseStr, + groupStr, indexStr, orderStr, limit, offset, sqlStr); return sqlStr; } @@ -221,5 +232,45 @@ std::string SqliteSqlBuilder::BuildCountString(const AbsRdbPredicates &predicate std::string tableName = predicates.GetTableName(); return "SELECT COUNT(*) FROM " + tableName + BuildSqlStringFromPredicates(predicates); } + +std::string SqliteSqlBuilder::BuildCursorQueryString( + const AbsRdbPredicates &predicates, const std::vector &columns, const std::string &logTable) +{ + std::string sql; + std::string table = predicates.GetTableName(); + if (table.empty() || logTable.empty()) { + return sql; + } + sql.append("SELECT "); + if (predicates.IsDistinct()) { + sql.append("DISTINCT "); + } + if (!columns.empty()) { + AppendColumns(sql, columns, table); + } else { + sql.append(table + ".*"); + } + sql.append(", " + logTable + ".cursor"); + sql.append(", CASE WHEN ").append(logTable).append(".") + .append("flag & 0x8 = 0x8 THEN true ELSE false END AS deleted_flag "); + sql.append("FROM ").append(table); + AppendClause(sql, " INDEXED BY ", predicates.GetIndex()); + sql.append(" INNER JOIN ").append(logTable).append(" ON ").append(table) + .append(".ROWID = ").append(logTable).append(".data_key"); + auto whereClause = predicates.GetWhereClause(); + SqliteUtils::Replace(whereClause, SqliteUtils::REP, logTable + "."); + AppendClause(sql, " WHERE ", whereClause); + AppendClause(sql, " GROUP BY ", predicates.GetGroup(), table); + auto order = predicates.GetOrder(); + SqliteUtils::Replace(order, SqliteUtils::REP, logTable + "."); + AppendClause(sql, " ORDER BY ", order); + int limit = predicates.GetLimit(); + auto limitClause = (limit == AbsPredicates::INIT_LIMIT_VALUE) ? "" : std::to_string(limit); + int offset = predicates.GetOffset(); + auto offsetClause = (offset == AbsPredicates::INIT_OFFSET_VALUE) ? "" : std::to_string(offset); + AppendClause(sql, " LIMIT ", limitClause); + AppendClause(sql, " OFFSET ", offsetClause); + return sql; +} } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp index c08c4b9008417caa35b382044a7060db6efddae2..2e634d852a86d95c9859367a27abd27293cabd40 100644 --- a/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp +++ b/relational_store/frameworks/native/rdb/src/sqlite_utils.cpp @@ -93,6 +93,18 @@ std::string SqliteUtils::StrToUpper(std::string s) return s; } +void SqliteUtils::Replace(std::string &src, const std::string &rep, const std::string &dst) +{ + if (src.empty() || rep.empty()) { + return; + } + size_t pos = 0; + while ((pos = src.find(rep, pos)) != std::string::npos) { + src.replace(pos, rep.length(), dst); + pos += dst.length(); + } +} + bool SqliteUtils::IsSqlReadOnly(int sqlType) { return (sqlType == STATEMENT_SELECT) ? true : false; diff --git a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn index 97b2755ac5217d1b5d8a822cd2e267d7eca1b64d..a461b7718b6fb97d72a9917276caecf922b4b5b0 100644 --- a/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn +++ b/relational_store/interfaces/inner_api/appdatafwk/BUILD.gn @@ -70,6 +70,15 @@ if (is_android || is_ios) { } } else { ohos_shared_library("relational_common_base") { + if (is_ohos) { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + } + sources = [ "${relational_store_native_path}/appdatafwk/src/serializable.cpp" ] @@ -96,6 +105,13 @@ if (is_android || is_ios) { } ohos_shared_library("native_appdatafwk") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ "${relational_store_native_path}/appdatafwk/src/shared_block.cpp" ] diff --git a/relational_store/interfaces/inner_api/cloud_data/BUILD.gn b/relational_store/interfaces/inner_api/cloud_data/BUILD.gn index cb25d869f8603fec80d4020985e5d276ebe39dad..f233ac4ac54abcde1f80057116fd3626967c073c 100644 --- a/relational_store/interfaces/inner_api/cloud_data/BUILD.gn +++ b/relational_store/interfaces/inner_api/cloud_data/BUILD.gn @@ -22,6 +22,13 @@ config("cloud_public_config") { } ohos_static_library("cloud_data_inner") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + part_name = "relational_store" public_configs = [ ":cloud_public_config" ] subsystem_name = "distributeddatamgr" diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h index a933d0a1f4c237cf21f20f885c66e3812e5c216d..ed5687e0f86492220525c2a2297e1dec52ac946d 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_service.h @@ -18,10 +18,12 @@ #include #include #include -#include "rdb_types.h" +#include #include "cloud_types.h" -#include "itypes_util.h" -namespace OHOS::CloudData { +#include "rdb_types.h" +#include "values_bucket.h" +namespace OHOS { +namespace CloudData { class CloudService { public: enum TransId : int32_t { @@ -31,12 +33,14 @@ public: TRANS_CHANGE_APP_SWITCH, TRANS_CLEAN, TRANS_NOTIFY_DATA_CHANGE, + TRANS_NOTIFY_DATA_CHANGE_EXT, + TRANS_ALLOC_RESOURCE_AND_SHARE, TRANS_SHARE, TRANS_UNSHARE, - TRANS_EXIT_SHARING, + TRANS_EXIT, TRANS_CHANGE_PRIVILEGE, - TRANS_QUERY_PARTICIPANTS, - TRANS_QUERY_PARTICIPANTS_BY_INVITATION, + TRANS_QUERY, + TRANS_QUERY_BY_INVITATION, TRANS_CONFIRM_INVITATION, TRANS_CHANGE_CONFIRMATION, TRANS_BUTT, @@ -67,31 +71,33 @@ public: CLOUD_CONFIG_PERMISSION_DENIED }; + static const int INVALID_USER_ID = -1; + virtual ~CloudService() = default; virtual int32_t EnableCloud(const std::string &id, const std::map &switches) = 0; virtual int32_t DisableCloud(const std::string &id) = 0; virtual int32_t ChangeAppSwitch(const std::string &id, const std::string &bundleName, int32_t appSwitch) = 0; virtual int32_t Clean(const std::string &id, const std::map &actions) = 0; virtual int32_t NotifyDataChange(const std::string &id, const std::string &bundleName) = 0; + virtual int32_t NotifyDataChange(const std::string &eventId, const std::string &extraData, int32_t userId) = 0; -// virtual int32_t AllocResourceAndShare(const std::string &storeId, const DistributedRdb::PredicatesMemo &predicates, -// const Participant &participant, const std::vector &columns) = 0; // TODO - virtual int32_t Share(const std::string &sharingRes, const std::vector &participants, - Result>> &result) = 0; - virtual int32_t Unshare(const std::string &sharingRes, const std::vector &participants, - Result>> &result) = 0; - virtual int32_t ExitSharing(const std::string &sharingRes, Result &result) = 0; - virtual int32_t ChangePrivilege(const std::string &sharingRes, const std::vector &participants, - Result>> &result) = 0; - virtual int32_t QueryParticipants(const std::string &sharingRes, Result> &result) = 0; - virtual int32_t QueryParticipantsByInvitation(const std::string &invitationCode, - Result> &result) = 0; - virtual int32_t ConfirmInvitation(const std::string &invitationCode, Confirmation confirmation, - Result &result) = 0; + virtual std::pair> AllocResourceAndShare(const std::string &storeId, + const DistributedRdb::PredicatesMemo &predicates, const std::vector &columns, + const Participants &participants) = 0; + virtual int32_t Share(const std::string &sharingRes, const Participants &participants, Results &results) = 0; + virtual int32_t Unshare(const std::string &sharingRes, const Participants &participants, Results &results) = 0; + virtual int32_t Exit(const std::string &sharingRes, std::pair &result) = 0; + virtual int32_t ChangePrivilege( + const std::string &sharingRes, const Participants &participants, Results &results) = 0; + virtual int32_t Query(const std::string &sharingRes, QueryResults &results) = 0; + virtual int32_t QueryByInvitation(const std::string &invitation, QueryResults &results) = 0; + virtual int32_t ConfirmInvitation(const std::string &invitation, int32_t confirmation, + std::tuple &result) = 0; virtual int32_t ChangeConfirmation(const std::string &sharingRes, - Confirmation confirmation, Result &result) = 0; + int32_t confirmation, std::pair &result) = 0; inline static constexpr const char *SERVICE_NAME = "cloud"; }; -} // namespace OHOS::CloudData +} // namespace CloudData +} // namespace OHOS #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_SERVICE_H diff --git a/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h b/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h index 1950c649fa6605a16422e27f0f4cfe57cd731ae1..ded2571adf4aece67dd8e93b57ae0e702bb8e81d 100644 --- a/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h +++ b/relational_store/interfaces/inner_api/cloud_data/include/cloud_types.h @@ -17,12 +17,13 @@ #define OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_H #include +#include namespace OHOS::CloudData { enum Role : int32_t { ROLE_NIL = -1, ROLE_INVITER, - ROLE_INVITEES, + ROLE_INVITEE, ROLE_BUTT }; @@ -36,8 +37,8 @@ enum Confirmation : int32_t { }; struct Privilege { - bool writeable = false; - bool readable = true; + bool writable = false; + bool readable = false; bool creatable = false; bool deletable = false; bool shareable = false; @@ -46,16 +47,88 @@ struct Privilege { struct Participant { std::string identity; int32_t role = Role::ROLE_NIL; - int32_t status = Confirmation::CFM_NIL; + int32_t state = Confirmation::CFM_NIL; Privilege privilege; + std::string attachInfo; }; +using Participants = std::vector; +using Results = std::tuple>>; +using QueryResults = std::tuple; + +/** + * Enumerates the error code of sharing invitation. + */ enum SharingCode : int32_t { - SHARING_OK = 0, - SHARING_ERROR, - SHARING_NETWORK_ERROR, - SHARING_UNKNOWN_ERROR, - SHARING_BUTT, + /** + * @brief means sharing success. + */ + SUCCESS = 0, + + /** + * @brief means the user has been invited. + */ + REPEATED_REQUEST, + + /** + * @brief means the participant is not inviter. + */ + NOT_INVITER, + + /** + * @brief means the participant is not inviter or invitee. + */ + NOT_INVITER_OR_INVITEE, + + /** + * @brief means the number of sharing times today of current user has reached maximum. + */ + OVER_QUOTA, + + /** + * @brief means the number of participants reaches the maximum. + */ + TOO_MANY_PARTICIPANTS, + + /** + * @brief means invalid arguments. + */ + INVALID_ARGS, + + /** + * @brief means the network is unavailable. + */ + NETWORK_ERROR, + + /** + * @brief means cloud is disabled. + */ + CLOUD_DISABLED, + + /** + * @brief means invoke cloud space failed. + */ + SERVER_ERROR, + + /** + * @brief means an unknown error has occurred. + */ + INNER_ERROR, + + /** + * @brief means the invitation has expired or does not exist. + */ + INVALID_INVITATION, + + /** + * @brief means the data transfer is rate-limited. + */ + RATE_LIMIT, + + /** + * @brief means error codes that exceed this enumerated value are custom error codes. + */ + CUSTOM_ERROR = 1000, }; } // namespace OHOS::CloudData #endif // OHOS_DISTRIBUTED_DATA_CLOUD_CLOUD_TYPES_H diff --git a/relational_store/interfaces/inner_api/dataability/BUILD.gn b/relational_store/interfaces/inner_api/dataability/BUILD.gn index 510d7bc71f9b87c2db7f3f46bd8775f3fa877815..8634eb04509483ea7c4c06d8e74a6249c1188667 100644 --- a/relational_store/interfaces/inner_api/dataability/BUILD.gn +++ b/relational_store/interfaces/inner_api/dataability/BUILD.gn @@ -36,6 +36,13 @@ config("native_dataability_public_config") { } ohos_shared_library("native_dataability") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + part_name = "relational_store" sources = [ "${relational_store_native_path}/dataability/src/data_ability_predicates.cpp", diff --git a/relational_store/interfaces/inner_api/rdb/BUILD.gn b/relational_store/interfaces/inner_api/rdb/BUILD.gn index 33674a1d2f19abbd671fc3fefc9b0e6ea3013013..83e0ebf3e2ee38194cb494ca81553654b9bf2220 100644 --- a/relational_store/interfaces/inner_api/rdb/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb/BUILD.gn @@ -18,7 +18,7 @@ base_sources = [ "${relational_store_native_path}/rdb/src/abs_rdb_predicates.cpp", "${relational_store_native_path}/rdb/src/abs_result_set.cpp", "${relational_store_native_path}/rdb/src/base_transaction.cpp", - "${relational_store_native_path}/rdb/src/base_transaction.h", + "${relational_store_native_path}/rdb/src/cache_result_set.cpp", "${relational_store_native_path}/rdb/src/raw_data_parser.cpp", "${relational_store_native_path}/rdb/src/rdb_helper.cpp", "${relational_store_native_path}/rdb/src/rdb_predicates.cpp", @@ -86,6 +86,13 @@ if (is_ohos && !build_ohos_sdk) { ] ohos_shared_library("native_rdb") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + part_name = "relational_store" sources = base_sources @@ -132,11 +139,21 @@ if (is_ohos && !build_ohos_sdk) { ] public_configs = [ ":native_rdb_public_config" ] - innerapi_tags = [ "platformsdk" ] + innerapi_tags = [ + "platformsdk", + "sasdk", + ] subsystem_name = "distributeddatamgr" } ohos_static_library("native_rdb_static") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = base_sources configs = [ ":native_rdb_config" ] diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h b/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h index fa2accf3580c573af147980207c12d672b8670a0..33571ce79580a46d3d1e49633153955e160ae1a4 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_predicates.h @@ -38,6 +38,13 @@ public: CROSS }; + enum Origin { + LOCAL = 0, + CLOUD, + REMOTE, + BUTT + }; + API_EXPORT std::string GetStatement() const; API_EXPORT std::string GetWhereClause() const; API_EXPORT void SetWhereClause(const std::string &whereClause); @@ -56,6 +63,7 @@ public: API_EXPORT std::string GetIndex() const; API_EXPORT bool IsNeedAnd() const; API_EXPORT bool IsSorted() const; + API_EXPORT bool HasSpecificField() const; public: API_EXPORT virtual void Clear(); @@ -95,6 +103,8 @@ public: API_EXPORT virtual AbsPredicates *NotIn(const std::string &field, const std::vector &values); API_EXPORT virtual AbsPredicates *NotIn(const std::string &field, const std::vector &values); private: + static constexpr const char *LOG_ORIGIN_FIELD = "#_flag"; + std::string whereClause; std::vector bindArgs; std::string order; @@ -105,10 +115,15 @@ private: bool distinct; bool isNeedAnd; bool isSorted; + bool hasSpecificField = false; void Initial(); bool CheckParameter( const std::string &methodName, const std::string &field, const std::initializer_list &args) const; + inline bool IsSpecificField(const std::string &field) + { + return field.find("#_") != std::string::npos; + } std::string RemoveQuotes(const std::string &source) const; void CheckIsNeedAnd(); void AppendWhereClauseWithInOrNotIn(const std::string &methodName, const std::string &field, diff --git a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h index f3820e1242e07712e97ef5134765c786718f7e12..2d2dbeb4117bbc56ba1c8c4113f6280418c49d7e 100644 --- a/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h +++ b/relational_store/interfaces/inner_api/rdb/include/abs_rdb_predicates.h @@ -151,6 +151,83 @@ public: */ API_EXPORT virtual AbsPredicates *In(const std::string &field, const std::vector &values) override; + /** + * @brief Adds an Contains condition to the remote AbsRdbPredicates. + * + * This method indicates that the expected field contains value. + */ + API_EXPORT AbsRdbPredicates *Contains(const std::string &field, const std::string &value) override; + + /** + * @brief Adds an BeginsWith condition to the remote AbsRdbPredicates. + * + * This method indicates that the expected field begin with value. + */ + API_EXPORT AbsRdbPredicates *BeginsWith(const std::string &field, const std::string &value) override; + + /** + * @brief Adds an EndsWith condition to the remote AbsRdbPredicates. + * + * This method indicates that the expected field end with value. + */ + API_EXPORT AbsRdbPredicates *EndsWith(const std::string &field, const std::string &value) override; + + /** + * @brief Adds an IsNull condition to the remote AbsRdbPredicates. + * + * This method indicates that the expected field is null. + */ + API_EXPORT AbsRdbPredicates *IsNull(const std::string &field) override; + + /** + * @brief Adds an IsNotNull condition to the remote AbsRdbPredicates. + * + * This method indicates that the expected field is not null. + */ + API_EXPORT AbsRdbPredicates *IsNotNull(const std::string &field) override; + + /** + * @brief Adds an Like condition to the remote AbsRdbPredicates. + * + * This method is similar to Like of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *Like(const std::string &field, const std::string &value) override; + + /** + * @brief Adds an Glob condition to the remote AbsRdbPredicates. + * + * This method is similar to glob of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *Glob(const std::string &field, const std::string &value) override; + + /** + * @brief Adds an Distinct condition to the remote AbsRdbPredicates. + * + * This method is similar to distinct of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *Distinct() override; + + /** + * @brief Adds an IndexedBy condition to the remote AbsRdbPredicates. + * + * This method is similar to indexed by of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *IndexedBy(const std::string &indexName) override; + + /** + * @brief Adds an NotIn condition to the remote AbsRdbPredicates. + * + * This method is similar to not in of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *NotIn(const std::string &field, const std::vector &values) override; + + /** + * @brief Adds an NotIn condition to the remote AbsRdbPredicates. + * + * This method is similar to not in of the SQL statement. + */ + API_EXPORT AbsRdbPredicates *NotIn(const std::string &field, const std::vector &values) override; + /** * @brief Restricts the ascending order of the return list. When there are several orders, * the one close to the head has the highest priority. diff --git a/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h b/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h new file mode 100644 index 0000000000000000000000000000000000000000..5346a787677fff9f9f99446e79255f510475dc83 --- /dev/null +++ b/relational_store/interfaces/inner_api/rdb/include/cache_result_set.h @@ -0,0 +1,332 @@ +/* +* Copyright (c) 2021 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 NATIVE_RDB_CACHE_RESULT_SET_H +#define NATIVE_RDB_CACHE_RESULT_SET_H + +#include +#include +#include +#include +#include + +#include "result_set.h" +#include "value_object.h" +#include "values_bucket.h" + +namespace OHOS { +namespace NativeRdb { +/** +* The CacheResultSet class of RDB. +* Provides methods for accessing a database result set generated by querying the database. +*/ +class API_EXPORT CacheResultSet : public ResultSet { +public: + /** + * @brief Constructor. + */ + API_EXPORT CacheResultSet(std::vector &&valueBuckets); + /** + * @brief Destructor. + */ + API_EXPORT virtual ~CacheResultSet(); + + /** + * @brief Obtains the number of rows in the result set. + */ + API_EXPORT int GetRowCount(int &count) override; + + /** + * @brief Obtains the names of all columns in a result set. + */ + API_EXPORT int GetAllColumnNames(std::vector &columnNames) override; + + /** + * @brief Obtains the value of the specified column in the current row as a byte array. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the Blob type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a byte array. + */ + API_EXPORT int GetBlob(int columnIndex, std::vector &blob) override; + + /** + * @brief Obtains the value of the specified column in the current row as string. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the string type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a string. + */ + API_EXPORT int GetString(int columnIndex, std::string &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as int. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the integer type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a int. + */ + API_EXPORT int GetInt(int columnIndex, int &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as long. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the long type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a long. + */ + API_EXPORT int GetLong(int columnIndex, int64_t &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as double. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the double type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + API_EXPORT int GetDouble(int columnIndex, double &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as asset. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the Asset type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + API_EXPORT int GetAsset(int32_t col, ValueObject::Asset &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as assets. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the Assets type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + API_EXPORT int GetAssets(int32_t col, ValueObject::Assets &value) override; + + /** + * @brief Obtains the value of the specified column in the current row as ValueObject. + * + * The implementation class determines whether to throw an exception if the value of the specified column + * in the current row is null or the specified column is not of the double type. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the value of the specified column as a double. + */ + API_EXPORT int Get(int32_t col, ValueObject &value) override; + + /** + * @brief Get the modify time of the cloud data. + * + * @param modifyTime Indicates the data modify utc time. + * + * @return Returns true if the value of the specified column in the current row is null; + * returns false otherwise. + */ + API_EXPORT int GetModifyTime(std::string &modifyTime) override; + + /** + * @brief Checks whether the value of the specified column in the current row is null. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns true if the value of the specified column in the current row is null; + * returns false otherwise. + */ + API_EXPORT int IsColumnNull(int columnIndex, bool &isNull) override; + + /** + * @brief Gets the entire row of data for the current row from the result set. + */ + API_EXPORT int GetRow(RowEntity &rowEntity) override; + + /** + * @brief Move the cursor to an absolute position. + * + * @param position Indicates the specified column index, which starts from 0. + * + * @return Returns whether the requested move succeeded. + */ + API_EXPORT int GoToRow(int position) override; + + /** + * @brief Obtains data type of the given column's value. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns column value type. + */ + API_EXPORT int GetColumnType(int columnIndex, ColumnType &columnType) override; + + /** + * @brief Returns the current position of the cursor in the result set. + * + * The value is zero-based. When the result set is first returned the cursor + * will be at position -1, which is before the first row. + * After the last row is returned another call to next() will leave the cursor past + * the last entry, at a position of count(). + * + * @return Returns the current cursor position. + */ + API_EXPORT int GetRowIndex(int &position) const override; + + /** + * @brief Go to the specified row of the result set forwards or backwards by an offset + * relative to its current position. + * + * A positive offset indicates moving backwards, and a negative offset indicates moving forwards. + * + * @param offset Indicates the offset relative to the current position. + * + * @return Returns whether true if the result set is moved successfully and does not go beyond the range; + * returns false otherwise. + */ + API_EXPORT int GoTo(int offset) override; + + /** + * @brief Go to the first row of the result set. + * + * @return Returns if the result set is moved successfully; + * returns false otherwise, for example, if the result set is empty. + */ + API_EXPORT int GoToFirstRow() override; + + /** + * @brief Go to the last row of the result set. + * + * @return Returns if the result set is moved successfully; + * returns false otherwise, for example, if the result set is empty. + */ + API_EXPORT int GoToLastRow() override; + + /** + * @brief Go to the next row of the result set. + * + * @return Returns if the result set is moved successfully; + * returns false otherwise, for example, if the result set is already in the last row. + */ + API_EXPORT int GoToNextRow() override; + + /** + * @brief Go to the previous row of the result set. + * + * @return Returns if the result set is moved successfully; + * returns false otherwise, for example, if the result set is already in the first row. + */ + API_EXPORT int GoToPreviousRow() override; + + /** + * @brief Checks whether the result set is positioned at the first row. + */ + API_EXPORT int IsAtFirstRow(bool &result) const override; + + /** + * @brief Checks whether the result set is positioned at the last row. + */ + API_EXPORT int IsAtLastRow(bool &result) override; + + /** + * @brief Returns whether the cursor is pointing to the position before the first row. + */ + API_EXPORT int IsStarted(bool &result) const override; + + /** + * @brief Checks whether the result set is positioned after the last row. + */ + API_EXPORT int IsEnded(bool &result) override; + + /** + * @brief Obtains the number of columns in the result set. + */ + API_EXPORT int GetColumnCount(int &count) override; + + /** + * @brief Returns the zero-based index for the given column name. + * + * @param columnName Indicates the specified name of the column. + * + * @return Returns the column index for the given column, or -1 if the column does not exist. + */ + API_EXPORT int GetColumnIndex(const std::string &columnName, int &columnIndex) override; + + /** + * @brief Returns the column name at the given column index. + * + * @param columnIndex Indicates the specified column index, which starts from 0. + * + * @return Returns the column name for the given index. + */ + API_EXPORT int GetColumnName(int columnIndex, std::string &columnName) override; + + /** + * @brief Checks whether the current result set is closed. + * + * @return Returns the true if the result set is closed by calling the close method. + */ + API_EXPORT bool IsClosed() const override; + + /** + * @brief Closes the result set. + * + * Calling this method on the result set will release all of its resources and makes it ineffective. + */ + API_EXPORT int Close() override; + int GetSize(int columnIndex, size_t &size) override; + +private: + static constexpr ColumnType COLUMNTYPES[ValueObject::TYPE_MAX] = { + [ValueObject::TYPE_NULL] = ColumnType::TYPE_NULL, + [ValueObject::TYPE_INT] = ColumnType::TYPE_INTEGER, + [ValueObject::TYPE_DOUBLE] = ColumnType::TYPE_FLOAT, + [ValueObject::TYPE_STRING] = ColumnType::TYPE_STRING, + [ValueObject::TYPE_BOOL] = ColumnType::TYPE_INTEGER, + [ValueObject::TYPE_BLOB] = ColumnType::TYPE_BLOB, + [ValueObject::TYPE_ASSET] = ColumnType::TYPE_BLOB, + [ValueObject::TYPE_ASSETS] = ColumnType::TYPE_BLOB, + }; + int32_t row_; + mutable std::shared_mutex rwMutex_; + int32_t maxRow_; + int32_t maxCol_; + std::vector colNames_; + std::vector colTypes_; + std::vector valueBuckets_; +}; +} // namespace NativeRdb +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h index 784458a1bc169d4b2d0c9235b1b07bfd9603e130..3588f25bd44d6b9131dd7242f707701c558a350c 100644 --- a/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h +++ b/relational_store/interfaces/inner_api/rdb/include/distributeddata_relational_store_ipc_interface_code.h @@ -79,6 +79,8 @@ enum class RdbServiceInterfaceCode { RDB_SERVICE_CMD_DELETE, RDB_SERVICE_CMD_REGISTER_AUTOSYNC_PROGRESS_OBSERVER, RDB_SERVICE_CMD_UNREGISTER_AUTOSYNC_PROGRESS_OBSERVER, + RDB_SERVICE_CMD_NOTIFY_DATA_CHANGE, + RDB_SERVICE_CMD_QUERY_SHARING_RESOURCE, RDB_SERVICE_CMD_MAX }; } // namespace RelationalStore diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h index 92fe6ea8c7028faac19f9eeb44cc55d3c2f2995d..92a78dddb27d044a076089bb1d9f8fdc0d69376d 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_service.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_service.h @@ -22,6 +22,7 @@ #include "rdb_types.h" #include "rdb_notifier.h" #include "distributeddata_relational_store_ipc_interface_code.h" +#include "values_bucket.h" namespace OHOS { template @@ -40,7 +41,8 @@ public: virtual std::string ObtainDistributedTableName(const std::string &device, const std::string &table) = 0; virtual int32_t SetDistributedTables( - const RdbSyncerParam ¶m, const std::vector &tables, int32_t type = DISTRIBUTED_DEVICE) = 0; + const RdbSyncerParam ¶m, const std::vector &tables, + const std::vector &references, int32_t type = DISTRIBUTED_DEVICE) = 0; virtual int32_t Sync(const RdbSyncerParam ¶m, const Option &option, const PredicatesMemo &predicates, const AsyncDetail &async) = 0; @@ -64,9 +66,14 @@ public: virtual int32_t GetSchema(const RdbSyncerParam ¶m) = 0; - //only use param.storeName_ + // only use param.storeName_ virtual int32_t Delete(const RdbSyncerParam ¶m) = 0; + virtual std::pair> QuerySharingResource( + const RdbSyncerParam ¶m, const PredicatesMemo &predicates, const std::vector &columns) = 0; + + virtual int32_t NotifyDataChange(const RdbSyncerParam ¶m, const RdbChangedData &rdbChangedData) = 0; + inline static constexpr const char *SERVICE_NAME = "relational_store"; }; } diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h index aef5e799daad0758312ed1fcb2cb939181ad6692..34c0d973da1064383393649873b01e29b731157f 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store.h @@ -333,6 +333,18 @@ public: virtual std::shared_ptr Query( const AbsRdbPredicates &predicates, const std::vector &columns) = 0; + /** + * @brief Queries data in the database based on specified conditions. + * + * @param predicates Indicates the specified query condition by the instance object of {@link AbsRdbPredicates}. + * @param columns Indicates the columns to query. If the value is empty array, the query applies to all columns. + */ + virtual std::pair> QuerySharingResource( + const AbsRdbPredicates &predicates, const std::vector &columns) + { + return { E_NOT_SUPPORT, nullptr }; + } + /** * @brief Queries data in the database based on specified conditions. * @@ -527,6 +539,16 @@ public: */ virtual ModifyTime GetModifyTime(const std::string& table, const std::string& columnName, std::vector& keys) = 0; + + /** + * @brief Cleans dirty data deleted in the cloud. + * + * If a cursor is specified, data with a cursor smaller than the specified cursor will be cleaned up. + * otherwise clean all. + * + * @param table Indicates the specified table. + */ + virtual int CleanDirtyData(const std::string &table, uint64_t cursor = UINT64_MAX) = 0; }; } // namespace OHOS::NativeRdb #endif diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h index c4a478531d519cf6d62cb02841a93616446dbcd5..fa6fb7ab6a6693d96837c17b36d948b46c4e2717 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_store_config.h @@ -452,6 +452,16 @@ public: */ std::string GetDataGroupId() const; + /** + * @brief Sets the autoCleanDirtyData for the object. + */ + void SetAutoClean(bool isAutoClean); + + /** + * @brief Obtains the autoCleanDirtyData in this {@code StoreConfig} object. + */ + bool GetAutoClean() const; + /** * @brief Sets the customDir directory for the object. */ @@ -497,6 +507,15 @@ public: && this->readConSize_ == config.readConSize_ && this->customDir_ == config.customDir_; } + /** + * @brief Checks whether the database isSearchable necessary. + */ + bool IsSearchable() const; + /** + * @brief Sets whether the database Searchable necessary. + */ + void SetSearchable(bool searchable); + private: void ClearEncryptKey(); @@ -524,6 +543,7 @@ private: bool isCreateNecessary_; bool autoCheck; + bool isAutoClean_ = true; int journalSize; int pageSize; int readConSize_ = 4; @@ -532,6 +552,7 @@ private: std::string customDir_; std::map customScalarFunctions; + bool isSearchable_ = false; }; } // namespace OHOS::NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h index c035b409ce3a2bab9a619c04aa8546f0c93f5eec..0bec84c0c0950926f9686d3f8891c9c56731f017 100644 --- a/relational_store/interfaces/inner_api/rdb/include/rdb_types.h +++ b/relational_store/interfaces/inner_api/rdb/include/rdb_types.h @@ -16,8 +16,6 @@ #ifndef DISTRIBUTED_RDB_RDB_TYPES_H #define DISTRIBUTED_RDB_RDB_TYPES_H -#include - #include #include #include @@ -45,6 +43,8 @@ struct RdbSyncerParam { int32_t level_ = 0; int32_t type_ = RDB_DEVICE_COLLABORATION; bool isEncrypt_ = false; + bool isAutoClean_ = true; + bool isSearchable_ = false; std::vector password_; ~RdbSyncerParam() { @@ -71,12 +71,19 @@ enum DistributedTableType { DISTRIBUTED_CLOUD }; +struct Reference { + std::string sourceTable; + std::string targetTable; + std::map refFields; +}; + struct DistributedConfig { bool autoSync = true; + std::vector references = {}; }; enum Progress { - SYNC_BEGIN, + SYNC_BEGIN = 0, SYNC_IN_PROGRESS, SYNC_FINISH, }; @@ -129,6 +136,22 @@ enum RdbPredicateOperator { BEGIN_GROUP, END_GROUP, IN, + NOT_IN, + CONTAIN, + BEGIN_WITH, + END_WITH, + IS_NULL, + IS_NOT_NULL, + LIKE, + GLOB, + BETWEEN, + NOT_BETWEEN, + GREATER_THAN, + GREATER_THAN_OR_EQUAL, + LESS_THAN, + LESS_THAN_OR_EQUAL, + DISTINCT, + INDEXED_BY, OPERATOR_MAX }; @@ -230,5 +253,22 @@ public: struct DropOption { }; + +struct Field { + static constexpr const char *CURSOR_FIELD = "#_cursor"; + static constexpr const char *ORIGIN_FIELD = "#_origin"; + static constexpr const char *DELETED_FLAG_FIELD = "#_deleted_flag"; + static constexpr const char *OWNER_FIELD = "#_cloud_owner"; + static constexpr const char *PRIVILEGE_FIELD = "#_cloud_privilege"; + static constexpr const char *SHARING_RESOURCE_FIELD = "#_sharing_resource_field"; +}; + +struct RdbChangeProperties { + bool isTrackedDataChange = false; +}; + +struct RdbChangedData { + std::map tableData; +}; } // namespace OHOS::DistributedRdb #endif diff --git a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h index ec392e9b500d5fd8ef25d0463a1d49af13e492a3..2850c75aa47ae4a684013441fdb77b86012d64e0 100644 --- a/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h +++ b/relational_store/interfaces/inner_api/rdb/mock/include/rdb_store_config.h @@ -121,6 +121,8 @@ public: std::string GetWritePermission() const; void SetWritePermission(const std::string& permission); void SetCreateNecessary(bool isCreateNecessary); + void SetAutoClean(bool isAutoClean); + bool GetAutoClean() const; static std::string GetJournalModeValue(JournalMode journalMode); static std::string GetSyncModeValue(SyncMode syncMode); @@ -141,6 +143,8 @@ public: void SetCustomDir(const std::string &customDir); std::string GetCustomDir() const; std::map GetScalarFunctions() const; + bool IsSearchable() const; + void SetSearchable(bool searchable); bool operator==(const RdbStoreConfig &config) const { @@ -187,6 +191,7 @@ private: std::string bundleName_; std::string moduleName_; + bool isAutoClean_ = false; bool isEncrypt_ = false; std::vector encryptKey_; SecurityLevel securityLevel = SecurityLevel::LAST; @@ -204,6 +209,7 @@ private: std::string customDir_; std::map customScalarFunctions; + bool isSearchable_ = false; }; } // namespace OHOS::NativeRdb diff --git a/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn index 93e2b904ee29bee6faec71861bdc58ffc24c4f6c..2d044adca7502bbb24684bb581d698444a756a5f 100644 --- a/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_bms_adapter/BUILD.gn @@ -38,6 +38,13 @@ config("rdb_bms_adapter_public_config") { } ohos_shared_library("rdb_bms_adapter") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ "${relational_store_native_path}/rdb_bms_adaptor/src/data_properties.cpp", "${relational_store_native_path}/rdb_bms_adaptor/src/data_share_profile_info.cpp", diff --git a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn index 06d9b35975e40771042be1c61927cb8a47dc9deb..f08981eee9e8b87ba77045da5e6a8714e47c2aa3 100644 --- a/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_data_ability_adapter/BUILD.gn @@ -33,6 +33,13 @@ config("rdb_data_ability_adapter_public_config") { } ohos_shared_library("rdb_data_ability_adapter") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ "${relational_store_native_path}/rdb_data_ability_adapter/src/rdb_data_ability_utils.cpp", "${relational_store_native_path}/rdb_data_ability_adapter/src/result_set_utils.cpp", diff --git a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn index 75849e9a882c01fc4a3207ae1163514c60dbfc6e..34574878a609da9927469e6df4b7a3336a6257a0 100644 --- a/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn +++ b/relational_store/interfaces/inner_api/rdb_data_share_adapter/BUILD.gn @@ -38,6 +38,13 @@ config("rdb_data_share_adapter_public_config") { } ohos_shared_library("rdb_data_share_adapter") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + sources = [ "${relational_store_native_path}/rdb_data_share_adapter/src/rdb_result_set_bridge.cpp", "${relational_store_native_path}/rdb_data_share_adapter/src/rdb_utils.cpp", diff --git a/relational_store/interfaces/ndk/include/data_asset.h b/relational_store/interfaces/ndk/include/data_asset.h index ede58debc288edabedcfd409172dbeac6cd41a37..4b1fe937bb8804cce62b9f8757c00a2b259f2cae 100644 --- a/relational_store/interfaces/ndk/include/data_asset.h +++ b/relational_store/interfaces/ndk/include/data_asset.h @@ -275,7 +275,7 @@ int OH_Data_Asset_GetStatus(Data_Asset *asset, Data_AssetStatus *status); * @see Data_Asset. * @since 11 */ -Data_Asset *OH_Data_Asset_CreateOne(); +Data_Asset *OH_Data_Asset_CreateOne(void); /** * @brief Destroy the {@link Data_Asset} object and reclaim the memory occupied by the object. diff --git a/relational_store/interfaces/ndk/include/relational_store.h b/relational_store/interfaces/ndk/include/relational_store.h index 0377023a73a7f20e74a0b3fd2ac28f64b0ef6f6a..6f77dcf83ce993a7e9caa0210367fa0c0286e072 100644 --- a/relational_store/interfaces/ndk/include/relational_store.h +++ b/relational_store/interfaces/ndk/include/relational_store.h @@ -729,8 +729,8 @@ typedef struct Rdb_ProgressDetails { * * @param progress Represents a pointer to an {@link Rdb_ProgressDetails} instance. * @param version Indicates the version of current {@link Rdb_ProgressDetails}. - * @return If the operation is successful, a pointer to the instance of the @link Rdb_TableDetails} structure is returned. - * Otherwise NULL is returned. + * @return If the operation is successful, a pointer to the instance of the @link Rdb_TableDetails} structure is + * returned. Otherwise NULL is returned. * @see Rdb_ProgressDetails * @see Rdb_TableDetails * @since 11 @@ -761,28 +761,6 @@ typedef void (*Rdb_SyncCallback)(Rdb_ProgressDetails *progressDetails); */ int OH_Rdb_CloudSync(OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[], uint32_t count, Rdb_SyncCallback *callback); - -/** -* @brief Subscribes to the automatic synchronization progress of an RDB store. -* A callback will be invoked when there is a notification of the automatic synchronization progress. -* -* @param store Indicates the pointer to the target {@Link OH_Rdb_Store} instance. -* @param Indicates the callback invoked to return the automatic synchronization progress. -* @see OH_Rdb_Store. -* @since 11 -*/ -int OH_Rdb_SubscribeAutoSyncProgress(OH_Rdb_Store *store, Rdb_SyncCallback *progress); - -/** -* @brief Unsubscribes from the automatic synchronziation progress of an RDB store. -* -* @param store Indicates the pointer to the target {@Link OH_Rdb_Store} instance. -* @param progress Indicates the callback for the automatic synchornizaiton progress. -* If it is a null pointer, all callbacks for the automatic synchornizaiton progress will be unregistered. -* @see OH_Rdb_Store. -* @since 11 -*/ -int OH_Rdb_UnsubscribeAutoSyncProgress(OH_Rdb_Store *store, Rdb_SyncCallback *progress); #ifdef __cplusplus }; #endif diff --git a/relational_store/interfaces/ndk/src/BUILD.gn b/relational_store/interfaces/ndk/src/BUILD.gn index 6ecfc9763b53d95b9d0aa152a7a0ddb207ac5692..0d2fe838c7bd4c624f1e885503c5ab91fe06b3b7 100644 --- a/relational_store/interfaces/ndk/src/BUILD.gn +++ b/relational_store/interfaces/ndk/src/BUILD.gn @@ -15,6 +15,13 @@ import("//build/ohos.gni") import("//foundation/distributeddatamgr/relational_store/relational_store.gni") ohos_shared_library("native_rdb_ndk") { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + debug = false + } + include_dirs = [ "../include", "${kvstore_path}/common", diff --git a/relational_store/interfaces/ndk/src/relational_asset.cpp b/relational_store/interfaces/ndk/src/relational_asset.cpp index c88741d44b32670504d99f9c5b44bfa8a71dc96a..f7ed4557bf1753cd2e35867e995d8c7403258505 100644 --- a/relational_store/interfaces/ndk/src/relational_asset.cpp +++ b/relational_store/interfaces/ndk/src/relational_asset.cpp @@ -17,7 +17,7 @@ #include "logger.h" #include "relational_store_error_code.h" #include "securec.h" -#include +#include using namespace OHOS::RdbNdk; constexpr int ASSET_TRANSFORM_BASE = 10; @@ -92,10 +92,13 @@ int OH_Data_Asset_SetStatus(Data_Asset *asset, Data_AssetStatus status) int OH_Data_Asset_GetName(Data_Asset *asset, char *name, size_t *length) { - size_t nameLength = 0; - if (asset == nullptr || (nameLength = asset->asset_.name.size()) >= *length) { - LOG_ERROR("Asset get name error: asset is NULL ? %{public}d and length is too small ? %{public}d.", - (asset == nullptr), (nameLength >= *length)); + if (asset == nullptr) { + LOG_ERROR("Asset get name error: asset is NULL ? %{public}d.", (asset == nullptr)); + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + size_t nameLength = asset->asset_.name.size(); + if (nameLength >= *length) { + LOG_ERROR("Asset get name error: length is too small ? %{public}d.", (nameLength >= *length)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } errno_t result = strcpy_s(name, *length, asset->asset_.name.c_str()); @@ -109,12 +112,16 @@ int OH_Data_Asset_GetName(Data_Asset *asset, char *name, size_t *length) int OH_Data_Asset_GetUri(Data_Asset *asset, char *uri, size_t *length) { - size_t uriLength = 0; - if (asset == nullptr || (uriLength = asset->asset_.uri.size()) >= *length) { - LOG_ERROR("Asset get uri error: asset is NULL ? %{public}d and length is too small ? %{public}d.", - (asset == nullptr), (uriLength >= *length)); + if (asset == nullptr) { + LOG_ERROR("Asset get uri error: asset is NULL ? %{public}d.", (asset == nullptr)); + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + size_t uriLength = asset->asset_.uri.size(); + if (uriLength >= *length) { + LOG_ERROR("Asset get uri error: length is too small ? %{public}d.", (uriLength >= *length)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } + errno_t result = strcpy_s(uri, *length, asset->asset_.uri.c_str()); if (result != EOK) { LOG_ERROR("strcpy_s failed, result is %{public}d", result); @@ -126,10 +133,13 @@ int OH_Data_Asset_GetUri(Data_Asset *asset, char *uri, size_t *length) int OH_Data_Asset_GetPath(Data_Asset *asset, char *path, size_t *length) { - size_t pathLength = 0; - if (asset == nullptr || (pathLength = asset->asset_.path.size()) >= *length) { - LOG_ERROR("Asset get path error: asset is NULL ? %{public}d and length is too small ? %{public}d.", - (asset == nullptr), (pathLength >= *length)); + if (asset == nullptr) { + LOG_ERROR("Asset get path error: asset is NULL ? %{public}d.", (asset == nullptr)); + return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; + } + size_t pathLength = asset->asset_.path.size(); + if (pathLength >= *length) { + LOG_ERROR("Asset get path error: length is too small ? %{public}d.", (pathLength >= *length)); return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } errno_t result = strcpy_s(path, *length, asset->asset_.path.c_str()); @@ -207,7 +217,7 @@ int OH_Data_Asset_DestroyOne(Data_Asset *asset) Data_Asset **OH_Data_Asset_CreateMultiple(uint32_t count) { auto assets = new Data_Asset *[count]; - for (int i = 0; i < count; ++i) { + for (uint32_t i = 0; i < count; ++i) { assets[i] = new Data_Asset(); } return assets; @@ -215,7 +225,7 @@ Data_Asset **OH_Data_Asset_CreateMultiple(uint32_t count) int OH_Data_Asset_DestroyMultiple(Data_Asset **assets, uint32_t count) { - for (int i = 0; i < count; ++i) { + for (uint32_t i = 0; i < count; ++i) { delete assets[i]; } delete[] assets; diff --git a/relational_store/interfaces/ndk/src/relational_cursor.cpp b/relational_store/interfaces/ndk/src/relational_cursor.cpp index 80a8418a77cdae8b2ae8c007df431c9e29ea7d26..96b8973bbee454605e90e7591ff05c19c62adf9c 100644 --- a/relational_store/interfaces/ndk/src/relational_cursor.cpp +++ b/relational_store/interfaces/ndk/src/relational_cursor.cpp @@ -197,7 +197,7 @@ int RelationalCursor::GetAssets(OH_Cursor *cursor, int32_t columnIndex, Data_Ass if (*length != inputLength) { return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } - for (int i = 0; i < *length; ++i) { + for (uint32_t i = 0; i < *length; ++i) { if (value[i] == nullptr) { return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } diff --git a/relational_store/interfaces/ndk/src/relational_store.cpp b/relational_store/interfaces/ndk/src/relational_store.cpp index b4d7d9ac158253f8672a53faf5593a209535ec26..6176faa70f7ba1d20d0173ad402715d30b1f99b6 100644 --- a/relational_store/interfaces/ndk/src/relational_store.cpp +++ b/relational_store/interfaces/ndk/src/relational_store.cpp @@ -452,9 +452,13 @@ int OH_Rdb_CloudSync(OH_Rdb_Store *store, Rdb_SyncMode mode, const char *tables[ for (uint32_t i = 0; i < count; ++i) { tableNames.emplace_back(tables[i]); } - auto progressCallback = [&callback](Details &&details) { + auto progressCallback = [cb = *callback](Details &&details) { + if (details.empty()) { + LOG_ERROR("CloudSync has no details"); + return; + } RelationalProgressDetails progressDetails = RelationalProgressDetails(details.begin()->second); - (*callback)(&progressDetails); + cb(&progressDetails); progressDetails.DestroyTableDetails(); }; return rdbStore->GetStore()->Sync(syncOption, tableNames, progressCallback); diff --git a/relational_store/interfaces/ndk/src/relational_values_bucket.cpp b/relational_store/interfaces/ndk/src/relational_values_bucket.cpp index 4210a3f347fcea67aa82802b232c59180d94edc4..fabb0201c2a5d18fd332767d69df94deaa2bb172 100644 --- a/relational_store/interfaces/ndk/src/relational_values_bucket.cpp +++ b/relational_store/interfaces/ndk/src/relational_values_bucket.cpp @@ -142,7 +142,7 @@ int OH_VBucket_PutAssets(OH_VBucket *bucket, const char *field, Data_Asset **val return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } std::vector assets; - for (int i = 0; i < count; i++) { + for (uint32_t i = 0; i < count; i++) { if (value[i] == nullptr) { return OH_Rdb_ErrCode::RDB_E_INVALID_ARGS; } diff --git a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js index 64d7458b18da37d09d2514bd77ba110533ef2157..5a8f754b7bf80f2016359a48fd6d4d11a8948d17 100644 --- a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js +++ b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigCallback.js @@ -243,6 +243,60 @@ describe('CloudConfigCallbackTest', function () { } }) + /** + * @tc.name NotifyDataChangeInvalidArgsCallbackTest + * @tc.desc Test Js Api NotifyDataChange with invalid args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('NotifyDataChangeInvalidArgsCallbackTest', 0, function (done) { + console.info('NotifyDataChangeInvalidArgsCallbackTest'); + try { + cloudData.Config.notifyDataChange(null, function(err) { + if (err == undefined) { + expect(null).assertFail(); + console.info('NotifyDataChangeInvalidArgsCallbackTest notifyDataChange success'); + done(); + return; + } + console.error('NotifyDataChangeInvalidArgsCallbackTest notifyDataChange fail' + `, error code is ${err.code}, message is ${err.message}`); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error('NotifyDataChangeInvalidArgsCallbackTest fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + + /** + * @tc.name NotifyDataChangeInvalidArgsNumsCallbackTest + * @tc.desc Test Js Api NotifyDataChange which parameters number are less + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('NotifyDataChangeInvalidArgsNumsCallbackTest', 0, function (done) { + console.info('NotifyDataChangeInvalidArgsNumsCallbackTest'); + try { + cloudData.Config.notifyDataChange(function (err) { + if (err == undefined) { + expect(null).assertFail(); + console.info('NotifyChangeInvalidArgsNumsCallbackTest notifyDataChange success'); + done(); + return; + } + console.error('NotifyChangeInvalidArgsNumsCallbackTest notifyDataChange fail' + `, error code is ${err.code}, message is ${err.message}`); + expect(null).assertFail(); + done(); + }); + } catch (e) { + console.error('NotifyChangeInvalidArgsNumsCallbackTest fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + done(); + } + }) + /** * @tc.name ClearInvalidArgsNumsCallbackTest * @tc.desc Test Js Api Clear which parameters number are less diff --git a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js index 59fa9226f424cf3e5420937e1bd8afc710347abf..4eb98d4242d04052587bbdaa82ccd0f73ab995ca 100644 --- a/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js +++ b/relational_store/test/js/clouddata/unittest/src/CloudSyncConfigPromise.js @@ -212,6 +212,52 @@ describe('CloudConfigPromiseTest', function () { done(); }) + /** + * @tc.name NotifyDataChangeInvalidArgsTest + * @tc.desc Test Js Api NotifyDataChange with invalid args + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('NotifyDataChangeInvalidArgsTest', 0, async function (done) { + console.info('NotifyDataChangeInvalidArgsTest'); + try { + await cloudData.Config.notifyDataChange(null).then(() => { + console.info('NotifyDataChangeInvalidArgsTest success'); + expect(null).assertFail(); + }).catch((error) => { + console.error('NotifyDataChangeInvalidArgsTest NotifyChange fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('NotifyDataChangeInvalidArgsTest fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + } + done(); + }) + + /** + * @tc.name NotifyDataChangeInvalidArgsNumsTest + * @tc.desc Test Js Api NotifyChange which parameters number are less + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('NotifyDataChangeInvalidArgsNumsTest', 0, async function (done) { + console.info('NotifyDataChangeInvalidArgsNumsTest'); + try { + await cloudData.Config.notifyDataChange().then(() => { + console.info('NotifyDataChangeInvalidArgsNumsTest success'); + expect(null).assertFail(); + }).catch((error) => { + console.error('NotifyDataChangeInvalidArgsNumsTest NotifyChange fail' + `, error code is ${error.code}, message is ${error.message}`); + expect(null).assertFail(); + }); + } catch (e) { + console.error('NotifyDataChangeInvalidArgsNumsTest fail' + `, error code is ${e.code}, message is ${e.message}`); + expect(e.code == 401).assertTrue(); + } + done(); + }) + /** * @tc.name ClearInvalidArgsNumsTest * @tc.desc Test Js Api Clean which parameters number are less diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js index 050cf43396b5b85afa112a6c82b6b2a6a322c376..cc664e93aa04cdb7286b827cb6ea34d8f738ffb9 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreAssetResultSetJsunit.test.js @@ -112,6 +112,20 @@ describe('rdbAssetResultSetTest', function () { console.log(TAG + "createTest data end"); } + async function batchInsertTable() { + console.log(TAG + "batchInsertTable start"); + const assets = [asset1, asset2, asset3]; + let valuesBucket = { + "data1": asset1, + "data2": asset2, + "data3": assets, + } + let array = new Array(); + array.push(valuesBucket); + await rdbStore.batchInsert("test", array) + console.log(TAG + "batchInsertTable end"); + } + async function createStatusTest() { console.log(TAG + "createStatusTest data start"); let valuesBucket = { @@ -121,6 +135,60 @@ describe('rdbAssetResultSetTest', function () { console.log(TAG + "createStatusTest data end"); } + /** + * @tc.name resultSet getAsset normal test with batchInsert + * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0010 + * @tc.desc resultSet getAsset normal test + */ + it('testGetAssetBatchInsert0001', 0, async function (done) { + await batchInsertTable(); + console.log(TAG + "************* testGetAssetBatchInsert0001 start *************"); + let predicates = await new data_relationalStore.RdbPredicates("test") + let resultSet = await rdbStore.query(predicates) + try { + expect(true).assertEqual(resultSet.goToFirstRow()) + const id = resultSet.getLong(resultSet.getColumnIndex("id")) + const data1 = resultSet.getAsset(resultSet.getColumnIndex("data1")) + console.log(TAG + "id=" + id + ", data1=" + data1); + expect("name1").assertEqual(data1.name); + expect("uri1").assertEqual(data1.uri); + expect("createTime1").assertEqual(data1.createTime); + expect("modifyTime1").assertEqual(data1.modifyTime); + expect("size1").assertEqual(data1.size); + expect("path1").assertEqual(data1.path); + expect(data_relationalStore.AssetStatus.ASSET_INSERT).assertEqual(data1.status); + + const data2 = resultSet.getAsset(resultSet.getColumnIndex("data2")) + console.log(TAG + "id=" + id + ", data2=" + data2); + expect("name2").assertEqual(data2.name); + expect("uri2").assertEqual(data2.uri); + expect("createTime2").assertEqual(data2.createTime); + expect("modifyTime2").assertEqual(data2.modifyTime); + expect("size2").assertEqual(data2.size); + expect("path2").assertEqual(data2.path); + expect(data_relationalStore.AssetStatus.ASSET_INSERT).assertEqual(data2.status); + + const data3 = resultSet.getAssets(resultSet.getColumnIndex("data3")) + console.log(TAG + "id=" + id + ", data3=" + data3); + const second = data3[1]; + expect("name2").assertEqual(second.name); + expect("uri2").assertEqual(second.uri); + expect("createTime2").assertEqual(second.createTime); + expect("modifyTime2").assertEqual(second.modifyTime); + expect("size2").assertEqual(second.size); + expect("path2").assertEqual(second.path); + expect(data_relationalStore.AssetStatus.ASSET_INSERT).assertEqual(second.status); + + resultSet.close(); + expect(true).assertEqual(resultSet.isClosed) + } catch (e) { + expect(null).assertFail(); + } + resultSet = null + done(); + console.log(TAG + "************* testGetAssetBatchInsert0001 end *************"); + }) + /** * @tc.name resultSet getAsset normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_ResultSet_0010 diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreCloudSync.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreCloudSync.test.js index 1dead3602add1177f939e242628d51fd444da114..77b12ef4e8221d0edca5fff7a03b92e9a47a6ac5 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreCloudSync.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreCloudSync.test.js @@ -426,22 +426,22 @@ describe('rdbStoreCloudSyncTest', function () { console.log(TAG + `Progress:` + JSON.stringify(detail)); done(); } - let predicates = await new relationalStore.RdbPredicates("test") + let predicates = new relationalStore.RdbPredicates("test") predicates.in("id", ["id1","id2"]); try { await rdbStore.cloudSync(relationalStore.SyncMode.SYNC_MODE_CLOUD_FIRST, predicates, Progress) } catch (err) { console.log(TAG + `cloud sync fail, errcode:${JSON.stringify(err)}.`); + done(); expect("202").assertEqual(err.code) } - done(); console.log(TAG + "************* testRdbStoreCloudSync0015 end *************"); }) /** - * @tc.name cloud sync with RdbPredicates, SyncMode is SYNC_MODE_CLOUD_FIRST and promise method - * @tc.number SUB_DDM_AppDataFWK_JSRDB_CLOUD_SYNC_0015 - * @tc.desc cloud sync with RdbPredicates, SyncMode is SYNC_MODE_CLOUD_FIRST and promise method + * @tc.name cloud sync with RdbPredicates, SyncMode is SYNC_MODE_CLOUD_FIRST and callback method + * @tc.number SUB_DDM_AppDataFWK_JSRDB_CLOUD_SYNC_0016 + * @tc.desc cloud sync with RdbPredicates, SyncMode is SYNC_MODE_CLOUD_FIRST and callback method */ it('testRdbStoreCloudSync0016', 0, async function (done) { console.log(TAG + "************* testRdbStoreCloudSync0016 start *************"); @@ -450,17 +450,43 @@ describe('rdbStoreCloudSyncTest', function () { function Progress(detail) { console.log(TAG + `Progress:` + JSON.stringify(detail)); } - let predicates = await new relationalStore.RdbPredicates("test") + let predicates = new relationalStore.RdbPredicates("test") predicates.in("id", ["id1","id2"]); rdbStore.cloudSync(relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, predicates, Progress, () => { + done(); expect(false).assertTrue() }); } catch (err) { console.log(TAG + `cloud sync fail, errcode:${JSON.stringify(err)}.`); + done(); expect("202").assertEqual(err.code) } - done(); console.log(TAG + "************* testRdbStoreCloudSync0016 end *************"); }) + + /** + * @tc.name cloud sync with exception parameter, SyncMode is SYNC_MODE_CLOUD_FIRST and callback method + * @tc.number SUB_DDM_AppDataFWK_JSRDB_CLOUD_SYNC_0017 + * @tc.desc cloud sync with exception parameter, SyncMode is SYNC_MODE_CLOUD_FIRST and callback method + */ + it('testRdbStoreCloudSync0017', 0, async function (done) { + console.log(TAG + "************* testRdbStoreCloudSync0017 start *************"); + try { + + function Progress(detail) { + console.log(TAG + `Progress:` + JSON.stringify(detail)); + } + rdbStore.cloudSync(relationalStore.SyncMode.SYNC_MODE_TIME_FIRST, 1410, Progress, () => { + done(); + expect(false).assertTrue() + }); + } catch (err) { + console.log(TAG + `cloud sync fail, errcode:${JSON.stringify(err)}.`); + done(); + expect(err.code).assertEqual('401'); + } + console.log(TAG + "************* testRdbStoreCloudSync0017 end *************"); + }) + console.log(TAG + "*************Unit Test End*************"); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js index 1dd2d2b86fd14897066f73f99c600ac13a246f91..f5c7003b94792ed10bc3a80824d68240be55d11c 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreDistributedJsunit.test.js @@ -450,15 +450,18 @@ describe('rdbStoreDistributedTest', function () { * @tc.number SUB_DDM_AppDataFWK_JSRDB_Distributed_021 * @tc.desc normal testcase for autoSyncProgress of interface 'on' */ - it('testRdbStoreDistributed0021', 0, async function () { + it('testRdbStoreDistributed0021', 0, async function (done) { console.log(TAG + "************* testRdbStoreDistributed0021 start *************"); try { rdbStore.on("autoSyncProgress", function (detail) { console.log(TAG + `Progress:` + JSON.stringify(detail)); }); + done(); + expect(rdbStore).assertEqual(rdbStore); console.log(TAG + "on autoSyncProgress success"); } catch (err) { console.log(TAG + "on autoSyncProgress" + err); + done(); expect().assertFail(); } console.log(TAG + "************* testRdbStoreDistributed0021 end *************"); @@ -469,15 +472,18 @@ describe('rdbStoreDistributedTest', function () { * @tc.number SUB_DDM_AppDataFWK_JSRDB_Distributed_022 * @tc.desc normal testcase for autoSyncProgress of interface 'off' */ - it('testRdbStoreDistributed0022', 0, async function () { + it('testRdbStoreDistributed0022', 0, async function (done) { console.log(TAG + "************* testRdbStoreDistributed0022 start *************"); try { rdbStore.off("autoSyncProgress", function (detail) { console.log(TAG + `Progress:` + JSON.stringify(detail)); }); + done(); + expect(rdbStore).assertEqual(rdbStore); console.log(TAG + "off autoSyncProgress success"); } catch (err) { console.log(TAG + "off autoSyncProgress" + err); + done(); expect().assertFail(); } console.log(TAG + "************* testRdbStoreDistributed0022 end *************"); @@ -488,13 +494,16 @@ describe('rdbStoreDistributedTest', function () { * @tc.number SUB_DDM_AppDataFWK_JSRDB_Distributed_023 * @tc.desc normal testcase for autoSyncProgress of interface 'off' */ - it('testRdbStoreDistributed0023', 0, async function () { + it('testRdbStoreDistributed0023', 0, async function (done) { console.log(TAG + "************* testRdbStoreDistributed0023 start *************"); try { rdbStore.off("autoSyncProgress", null); + done(); + expect(rdbStore).assertEqual(rdbStore); console.log(TAG + "off autoSyncProgress success"); } catch (err) { console.log(TAG + "off autoSyncProgress" + err); + done(); expect().assertFail(); } console.log(TAG + "************* testRdbStoreDistributed0023 end *************"); @@ -505,13 +514,16 @@ describe('rdbStoreDistributedTest', function () { * @tc.number SUB_DDM_AppDataFWK_JSRDB_Distributed_024 * @tc.desc normal testcase for autoSyncProgress of interface 'off' */ - it('testRdbStoreDistributed0024', 0, async function () { + it('testRdbStoreDistributed0024', 0, async function (done) { console.log(TAG + "************* testRdbStoreDistributed0024 start *************"); try { rdbStore.off("autoSyncProgress", undefined); + done(); + expect(rdbStore).assertEqual(rdbStore); console.log(TAG + "off autoSyncProgress success"); } catch (err) { console.log(TAG + "off autoSyncProgress" + err); + done(); expect().assertFail(); } console.log(TAG + "************* testRdbStoreDistributed0024 end *************"); @@ -522,13 +534,16 @@ describe('rdbStoreDistributedTest', function () { * @tc.number SUB_DDM_AppDataFWK_JSRDB_Distributed_025 * @tc.desc normal testcase for autoSyncProgress of interface 'off' */ - it('testRdbStoreDistributed0025', 0, async function () { + it('testRdbStoreDistributed0025', 0, async function (done) { console.log(TAG + "************* testRdbStoreDistributed0025 start *************"); try { rdbStore.off("autoSyncProgress"); + done(); + expect(rdbStore).assertEqual(rdbStore); console.log(TAG + "off autoSyncProgress success"); } catch (err) { console.log(TAG + "off autoSyncProgress" + err); + done(); expect().assertFail(); } console.log(TAG + "************* testRdbStoreDistributed0025 end *************"); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbStoreQueryByCursor.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbStoreQueryByCursor.test.js new file mode 100644 index 0000000000000000000000000000000000000000..789e7cc37fb4322302a5c093fb9ac4e45b6d08d5 --- /dev/null +++ b/relational_store/test/js/relationalstore/unittest/src/RdbStoreQueryByCursor.test.js @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {describe, beforeAll, beforeEach, afterEach, afterAll, it, expect} from 'deccjsunit/index' +import relationalStore from '@ohos.data.relationalStore'; +import ability_featureAbility from '@ohos.ability.featureAbility' + +const TAG = "[RELATIONAL_STORE_JSKITS_TEST]" +const STORE_NAME = "query_cursor_rdb.db" +var rdbStore = undefined; +var context = ability_featureAbility.getContext() + +describe('rdbStoreQueryByCursorTest', function () { + beforeAll(async function () { + console.info(TAG + 'beforeAll') + const config = { + "name": STORE_NAME, + securityLevel: relationalStore.SecurityLevel.S1, + } + try { + rdbStore = await relationalStore.getRdbStore(context, config); + console.log(TAG + "create rdb store success") + let sql = "CREATE TABLE IF NOT EXISTS query_tb (" + + "data TEXT, " + + "recycled BOOLEAN, " + + "recycledTime INTEGER, " + + "uuid TEXT PRIMARY KEY)"; + await rdbStore.executeSql(sql, null); + console.log(TAG + "create table query_tb success"); + const setConfig = { + autoSync: false, + } + await rdbStore.setDistributedTables( + ["query_tb"], relationalStore.DistributedType.DISTRIBUTED_CLOUD, setConfig); + console.log(TAG + "set distributed tables success"); + } catch (err) { + console.log(TAG + `failed, err: ${JSON.stringify(err)}`) + expect().assertFail() + } + }) + + beforeEach(async function () { + console.info(TAG + 'beforeEach'); + try { + let vBucketArray1 = new Array(); + for (let i = 0; i < 5; i++) { + let valueBucket = { + "data": "cloud_sync_insert", + "recycled": true, + "recycledTime": 12345, + "uuid": "test_key" + i.toString(), + } + vBucketArray1.push(valueBucket); + } + await rdbStore.batchInsert("query_tb", vBucketArray1); + } catch (err) { + console.log(TAG + `insert failed, err: ${JSON.stringify(err)}`) + expect().assertFail() + } + }) + + afterEach(async function () { + console.info(TAG + 'afterEach'); + try { + let predicates = new relationalStore.RdbPredicates("query_tb"); + predicates.equalTo("data", "cloud_sync_insert"); + await rdbStore.delete(predicates); + } catch (err) { + console.log(TAG + `delete failed, err: ${JSON.stringify(err)}`) + expect().assertFail() + } + }) + + afterAll(async function () { + console.info(TAG + 'afterAll'); + rdbStore = null; + await rdbStore.deleteRdbStore(context, STORE_NAME); + }) + + console.log(TAG + "*************Unit Test Begin*************"); + /** + * @tc.name query with cursor + * @tc.number SUB_DDM_AppDataFWK_JSRDB_QUERY_WITH_CURSOR_0001 + * @tc.desc query with cursor, and get all columns. + */ + it('testRdbStoreQueryAllColumnsWithCursor', 0, async function (done) { + console.log(TAG + "************* testRdbStoreQueryAllColumnsWithCursor start *************"); + + let predicates = new relationalStore.RdbPredicates("query_tb"); + predicates.greaterThan(relationalStore.Field.CURSOR_FIELD, 0); + if (rdbStore == undefined) { + return; + } + let promise = rdbStore.query(predicates); + await promise.then((resultSet) => { + expect(6).assertEqual(resultSet.columnCount); + let deletedIndex = resultSet.getColumnIndex(relationalStore.Field.DELETED_FLAG_FIELD); + expect(5).assertEqual(deletedIndex); + let cursorIndex = resultSet.getColumnIndex(relationalStore.Field.CURSOR_FIELD); + expect(4).assertEqual(cursorIndex); + resultSet.close(); + expect(true).assertEqual(resultSet.isClosed); + }).catch((err) => { + console.log(TAG + `query cursor fail, errcode:${JSON.stringify(err)}.`); + done(); + expect().assertFail(); + }); + done(); + }) +0. + /** + * @tc.name query with cursor + * @tc.number SUB_DDM_AppDataFWK_JSRDB_QUERY_WITH_CURSOR_0002 + * @tc.desc query with cursor, and specific columns. + */ + it('testRdbStoreQuerySpecificColumnsWithCursor', 0, async function (done) { + console.log(TAG + "************* testRdbStoreQuerySpecificColumnsWithCursor start *************"); + + let predicates = new relationalStore.RdbPredicates("query_tb"); + predicates.greaterThan(relationalStore.Field.CURSOR_FIELD, 0); + predicates.orderByAsc(relationalStore.Field.CURSOR_FIELD); + predicates.orderByAsc("data"); + if (rdbStore == undefined) { + return; + } + let promise = rdbStore.query(predicates, ["data", "uuid"]); + await promise.then((resultSet) => { + expect(4).assertEqual(resultSet.columnCount); + expect(true).assertEqual(resultSet.goToFirstRow()); + expect(true).assertEqual(resultSet.goToNextRow()); + let cursor = resultSet.getLong(resultSet.getColumnIndex(relationalStore.Field.CURSOR_FIELD)); + expect(12).assertEqual(cursor); + resultSet.close(); + expect(true).assertEqual(resultSet.isClosed); + }).catch((err) => { + console.log(TAG + `query cursor fail, errcode:${JSON.stringify(err)}.`); + done(); + expect().assertFail(); + }); + done(); + }) + + /** + * @tc.name query with cursor + * @tc.number SUB_DDM_AppDataFWK_JSRDB_QUERY_WITH_CURSOR_0003 + * @tc.desc update data, and query with cursor. + */ + it('testRdbStoreQueryCursorAfterUpdate', 0, async function (done) { + console.log(TAG + "************* testRdbStoreQueryCursorAfterUpdate start *************"); + if (rdbStore == undefined) { + return; + } + const valueBucket = { + "recycledTime": "1234567890", + } + let updatePredicates = new relationalStore.RdbPredicates("query_tb"); + updatePredicates.equalTo("uuid", "test_key1"); + updatePredicates.or(); + updatePredicates.equalTo("uuid", "test_key2"); + await rdbStore.update(valueBucket, updatePredicates); + console.log(TAG + `update end.`); + let predicates = new relationalStore.RdbPredicates("query_tb"); + predicates.greaterThanOrEqualTo(relationalStore.Field.CURSOR_FIELD, 26); + predicates.equalTo(relationalStore.Field.ORIGIN_FIELD, relationalStore.Origin.LOCAL); + predicates.orderByDesc(relationalStore.Field.CURSOR_FIELD); + let promise = rdbStore.query(predicates); + await promise.then((resultSet) => { + expect(true).assertEqual(resultSet.goToFirstRow()); + let value1 = resultSet.getString(resultSet.getColumnIndex("recycledTime")); + expect("1234567890").assertEqual(value1); + expect(true).assertEqual(resultSet.goToNextRow()); + let value2 = resultSet.getString(resultSet.getColumnIndex("recycledTime")); + expect("1234567890").assertEqual(value2); + resultSet.close(); + expect(true).assertEqual(resultSet.isClosed); + }).catch((err) => { + console.log(TAG + `query cursor fail, errcode:${JSON.stringify(err)}.`); + done(); + expect().assertFail(); + }); + done(); + }) + + /** + * @tc.name query with cursor + * @tc.number SUB_DDM_AppDataFWK_JSRDB_QUERY_WITH_CURSOR_0004 + * @tc.desc delete data, and query with cursor. + */ + it('testRdbStoreQueryCursorAfterDelete', 0, async function (done) { + console.log(TAG + "************* testRdbStoreQueryCursorAfterDelete start *************"); + if (rdbStore == undefined) { + return; + } + let deletedPred = new relationalStore.RdbPredicates("query_tb"); + deletedPred.equalTo("uuid", "test_key3"); + await rdbStore.delete(deletedPred); + console.log(TAG + `delete end.`); + let predicates = new relationalStore.RdbPredicates("query_tb"); + predicates.greaterThan(relationalStore.Field.CURSOR_FIELD, 37); + predicates.orderByAsc(relationalStore.Field.CURSOR_FIELD); + try { + rdbStore.query(predicates, (err, resultSet) => { + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + expect(true).assertEqual(resultSet.isClosed); + }) + } catch(err) { + console.log(TAG + `query cursor fail, errcode:${JSON.stringify(err)}.`); + done(); + expect().assertFail(); + } + done(); + }) + + /** + * @tc.name query with cursor + * @tc.number SUB_DDM_AppDataFWK_JSRDB_QUERY_WITH_CURSOR_0005 + * @tc.desc query with cursor and origin. + */ + it('testRdbStoreQueryCursorAndOrigin', 0, async function (done) { + console.log(TAG + "************* testRdbStoreQueryCursorAndOrigin start *************"); + if (rdbStore == undefined) { + return; + } + let predicates = new relationalStore.RdbPredicates("query_tb"); + predicates.greaterThan(relationalStore.Field.CURSOR_FIELD, 0); + predicates.and(); + predicates.beginWrap(); + predicates.equalTo(relationalStore.Field.ORIGIN_FIELD, relationalStore.Origin.CLOUD); + predicates.or(); + predicates.equalTo(relationalStore.Field.ORIGIN_FIELD, relationalStore.Origin.REMOTE); + predicates.endWrap(); + predicates.orderByAsc(relationalStore.Field.CURSOR_FIELD); + try { + rdbStore.query(predicates, (err, resultSet) => { + expect(0).assertEqual(resultSet.rowCount); + resultSet.close(); + expect(true).assertEqual(resultSet.isClosed); + }) + } catch(err) { + console.log(TAG + `query cursor fail, errcode:${JSON.stringify(err)}.`); + done(); + expect().assertFail(); + } + done(); + }) + + /** + * @tc.name clean dirty data + * @tc.number SUB_DDM_AppDataFWK_JSRDB_CLEAN_DIRTY_DATA_0001 + * @tc.desc clean dirty data. + */ + it('testRdbStoreCleanDirtyData', 0, async function (done) { + console.log(TAG + "************* testRdbStoreCleanDirtyData start *************"); + if (rdbStore == undefined) { + return; + } + let promise = rdbStore.cleanDirtyData("query_tb"); + await promise.then((err) => { + expect(true).assertTrue(); + }).catch((err) => { + console.log(TAG + `clean dirty data fail, errcode:${JSON.stringify(err)}.`); + done(); + expect().assertFail(); + }); + done(); + }) + + /** + * @tc.name clean dirty data with specified cursor. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_CLEAN_DIRTY_DATA_0002 + * @tc.desc clean dirty data with specified cursor. + */ + it('testRdbStoreCleanDirtyDataWithSpecifiedCursor', 0, async function (done) { + console.log(TAG + "************* testRdbStoreCleanDirtyDataWithSpecifiedCursor start *************"); + if (rdbStore == undefined) { + return; + } + let cursor = 3; + let promise = rdbStore.cleanDirtyData("query_tb", cursor); + await promise.then((err) => { + expect(true).assertTrue(); + }).catch((err) => { + console.log(TAG + `clean dirty data fail, errcode:${JSON.stringify(err)}.`); + done(); + expect().assertFail(); + }); + done(); + }) + + /** + * @tc.name clean dirty data with error param. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_CLEAN_DIRTY_DATA_0003 + * @tc.desc clean dirty data with specified cursor. + */ + it('testRdbStoreCleanDirtyDataWithErrorParam', 0, async function (done) { + console.log(TAG + "************* testRdbStoreCleanDirtyDataWithErrorParam start *************"); + if (rdbStore == undefined) { + return; + } + try { + let cursor = 3; + let promise = rdbStore.cleanDirtyData(); + await promise.then((err) => { + expect().assertFail(); + }).catch((err) => { + console.log(TAG + `clean dirty data fail, errcode:${JSON.stringify(err)}.`); + expect(true).assertTrue(); + done(); + }); + } catch (err) { + console.error("clean dirty data, err: code=" + err.code + " message=" + err.message) + expect(true).assertTrue() + } + done(); + }) + + /** + * @tc.name clean dirty data with specified cursor by callback method. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_CLEAN_DIRTY_DATA_0004 + * @tc.desc clean dirty data with specified cursor. + */ + it('testRdbStoreCleanDirtyDataWithSpecifiedCursorCallback', 0, async function (done) { + console.log(TAG + "************* testRdbStoreCleanDirtyDataWithSpecifiedCursorCallback start *************"); + if (rdbStore == undefined) { + return; + } + try { + let cursor = 100; + rdbStore.cleanDirtyData("query_tb", cursor, (err) => { + if (err) { + console.error(TAG, "clean dirty data failed, err: code=" + err.code + " message=" + err.message); + expect(false).assertTrue() ; + } + done(); + }) + } catch (err) { + console.error("clean dirty data, err: code=" + err.code + " message=" + err.message) + expect(false).assertTrue() + } + done(); + }) + console.log(TAG + "*************Unit Test End*************"); +}) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreCustomDir.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreCustomDir.test.js index 6a55f00dd75535a2b6506b123a7ae91b55c6d313..d9ca41e1c7f45032ea3f5f1c7e48b2a7cf03cd74 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreCustomDir.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreCustomDir.test.js @@ -44,7 +44,7 @@ const STORE_CONFIG3 = { const STORE_CONFIG4 = { name: "RdbCustomDir4.db", securityLevel: data_relationalStore.SecurityLevel.S1, - customDir: "custom".repeat(1000), + customDir: "custom".repeat(30), // customDir length exceeds 128 bytes }; const asset1 = { @@ -415,7 +415,7 @@ describe('rdbStoreCustomTest', function () { /** * @tc.number testRdbStoreCustomDirTest00010 - * @tc.name AbNormal test case of getRdbStore, if customDir length exceeds 1024 bytes + * @tc.name AbNormal test case of getRdbStore, if customDir length exceeds 128 bytes * @tc.desc 1.Configure customDir * 2.Execute getRdbStore */ @@ -431,6 +431,5 @@ describe('rdbStoreCustomTest', function () { } console.info(TAG, "************* testRdbStoreCustomDirTest00010 end *************") }) - console.info(TAG, "*************Unit Test End*************"); }) diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js index b2a494292b6668ba24f133ec8e51cfb293318a9c..b35743ba6bbc08b677f7590ed95a771ad7bab3e5 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstorePredicatesJsunit.test.js @@ -121,14 +121,15 @@ describe('rdbPredicatesTest', function () { console.log(TAG + "*************Unit Test Begin*************"); /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0010 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "equalTo" for boolean value + * @tc.desc 1.Execute equalTo("boolType", true) + * 2.Query data */ it('testEqualTo0001', 0, async function (done) { console.log(TAG + "************* testEqualTo0001 start *************"); - let predicates = new data_relationalStore.RdbPredicates("AllDataType"); + let predicates = new data_relationalStore.RdbPredicates("AllDataType"); predicates.equalTo("booleanValue", true); let result = await rdbStore.query(predicates); expect(1).assertEqual(result.rowCount); @@ -140,9 +141,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0011 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "or" + * @tc.desc 1.Execute equalTo().or().equalTo() + * 2.Query data */ it('testEqualTo0002', 0, async function (done) { console.log(TAG + "************* testEqualTo0002 start *************"); @@ -159,9 +161,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0012 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "equalTo" for string value + * @tc.desc 1.Execute equalTo("stringValue", "ABCDEFGHIJKLMN") + * 2.Query data */ it('testEqualTo0003', 0, async function (done) { console.log(TAG + "************* testEqualTo0003 start *************"); @@ -178,9 +181,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0013 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "equalTo" for boundary value of doubleValue + * @tc.desc 1.Execute equalTo("doubleValue", DOUBLE_MAX) + * 2.Query data */ it('testEqualTo0004', 0, async function (done) { console.log(TAG + "************* testEqualTo0004 start *************"); @@ -197,9 +201,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0014 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "equalTo" for boundary value of shortValue + * @tc.desc 1.Execute equalTo("shortValue", -32768.0) + * 2.Query data */ it('testEqualTo0005', 0, async function (done) { console.log(TAG + "************* testEqualTo0005 start *************"); @@ -216,9 +221,11 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0015 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "equalTo" for integer value + * @tc.desc 1.Execute equalTo("integerValue", 1) + * 2.Query data + * 3.Execute getLong */ it('testEqualTo0006', 0, async function (done) { console.log(TAG + "************* testEqualTo0006 start *************"); @@ -235,9 +242,11 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0016 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "equalTo" for long value + * @tc.desc 1.Execute equalTo("longValue", 1) + * 2.Query data + * 3.Execute getLong */ it('testEqualTo0007', 0, async function (done) { console.log(TAG + "************* testEqualTo0007 start *************"); @@ -254,9 +263,11 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates equalTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0017 - * @tc.desc predicates equalTo normal test + * @tc.name Normal test case of predicates, test "equalTo" for float type + * @tc.desc 1.Execute equalTo("floatValue", -0.123) + * 2.Query data + * 3.Execute getLong */ it('testEqualTo0008', 0, async function (done) { console.log(TAG + "************* testEqualTo0008 start *************"); @@ -274,10 +285,12 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0018 - * @tc.name predicates equalTo test - * @tc.desc 1.equalTo normal test - * 2.equalTo abnormal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0018 + * @tc.name Normal test case of predicates, test "equalTo" for true param + * @tc.desc 1.Execute equalTo('1', 1) + * 2.Query data + * 3.Execute equalTo('1', Number.NaN) + * 4.Query data */ it('testEqualTo0009', 0, async function (done) { console.log(TAG + "************* testEqualTo0009 start *************"); @@ -302,9 +315,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0020 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for boolean value + * @tc.desc 1.Execute notEqualTo("boolType", true) + * 2.Query data */ it('testNotEqualTo0001', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0001 start *************"); @@ -321,9 +335,11 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0021 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for byte value + * @tc.desc 1.Execute notEqualTo("byteValue", -128) + * 2.Execute notEqualTo("byteValue", 1) + * 3.Query data */ it('testNotEqualTo0002', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0002 start *************"); @@ -341,9 +357,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0022 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for string value + * @tc.desc 1.Execute notEqualTo("stringValue", "ABCDEFGHIJKLMN") + * 2.Query data */ it('testNotEqualTo0003', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0003 start *************"); @@ -360,9 +377,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0023 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for double value + * @tc.desc 1.Execute notEqualTo ("doubleValue", DOUBLE_MAX) + * 2.Query data */ it('testNotEqualTo0004', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0004 start *************"); @@ -379,9 +397,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0024 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for boundary value of shortValue + * @tc.desc 1.Execute notEqualTo ("shortValue", -32768) + * 2.Query data */ it('testNotEqualTo0005', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0005 start *************"); @@ -398,9 +417,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0025 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for integer value + * @tc.desc 1.Execute notEqualTo ("integerValue", 1) + * 2.Query data */ it('testNotEqualTo0006', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0006 start *************"); @@ -417,9 +437,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0026 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for long value + * @tc.desc 1.Execute notEqualTo ("longValue", 1) + * 2.Query data */ it('testNotEqualTo0007', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0007 start *************"); @@ -436,9 +457,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates notEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0027 - * @tc.desc predicates notEqualTo normal test + * @tc.name Normal test case of predicates, test "notEqualTo" for float value + * @tc.desc 1.Execute notEqualTo ("floatValue", -0.123) + * 2.Query data */ it('testNotEqualTo0008', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0008 start *************"); @@ -454,11 +476,13 @@ describe('rdbPredicatesTest', function () { console.log(TAG + "************* testNotEqualTo0008 end *************"); }) - /** - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0028 - * @tc.name predicates not equalTo test - * @tc.desc 1.predicates not equalTo normal test - * 2.predicates not equalTo abnormal test + /** + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0028 + * @tc.name Normal test case of predicates, test "notEqualTo" for true field + * @tc.desc 1.Execute notEqualTo ('1', 1) + * 2.Query data + * 3.Execute notEqualTo ('1', Number.NaN) + * 4.Query data */ it('testNotEqualTo0009', 0, async function (done) { console.log(TAG + "************* testNotEqualTo0009 start *************"); @@ -483,9 +507,10 @@ describe('rdbPredicatesTest', function () { /** - * @tc.name predicates isNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0030 - * @tc.desc predicates isNull normal test + * @tc.name Normal test case of predicates, test "isNull" for primLong value + * @tc.desc 1.Execute isNull ("primLongValue") + * 2.Query data */ it('testIsNull0001', 0, async function (done) { console.log(TAG + "************* testIsNull001 start *************"); @@ -500,9 +525,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates isNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0031 - * @tc.desc predicates isNull normal test + * @tc.name Normal test case of predicates, test "isNull" for long value + * @tc.desc 1.Execute isNull ("longValue") + * 2.Query data */ it('testIsNull0002', 0, async function (done) { console.log(TAG + "************* testIsNull0002 start *************"); @@ -517,9 +543,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates isNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0032 - * @tc.desc predicates isNull normal test + * @tc.name Normal test case of predicates, test "isNull" for string value + * @tc.desc 1.Execute isNull ("stringValue") + * 2.Query data */ it('testIsNull0003', 0, async function (done) { console.log(TAG + "************* testIsNull0003 start *************"); @@ -534,9 +561,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates isNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0033 - * @tc.desc predicates isNull normal test + * @tc.name Abnormal test case of predicates, test "isNull" for invalid param + * @tc.desc 1.Execute isNull ("stringValueX") + * 2.Query data */ it('testIsNull0004', 0, async function (done) { console.log(TAG + "************* testIsNull0004 start *************"); @@ -551,9 +579,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates isNotNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0040 - * @tc.desc predicates isNotNull normal test + * @tc.name Normal test case of predicates, test "isNotNull" for primlong value + * @tc.desc 1.Execute isNotNull ("primLongValue") + * 2.Query data */ it('testIsNotNull0001', 0, async function (done) { console.log(TAG + "************* testIsNotNull0001 start *************"); @@ -568,9 +597,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates isNotNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0041 - * @tc.desc predicates isNotNull normal test + * @tc.name Normal test case of predicates, test "isNotNull" for long value + * @tc.desc 1.Execute isNotNull ("longValue") + * 2.Query data */ it('testIsNotNull0002', 0, async function (done) { console.log(TAG + "************* testIsNotNull0002 start *************"); @@ -585,9 +615,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates isNotNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0042 - * @tc.desc predicates isNotNull normal test + * @tc.name Normal test case of predicates, test "isNotNull" for string value + * @tc.desc 1.Execute isNotNull ("stringValue") + * 2.Query data */ it('testIsNotNull0003', 0, async function (done) { console.log(TAG + "************* testIsNotNull0003 start *************"); @@ -602,9 +633,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates isNotNull normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0043 - * @tc.desc predicates isNotNull normal test + * @tc.name Abnormal test case of predicates, test "isNotNull" for invalid param + * @tc.desc 1.Execute isNotNull ("stringValueX") + * 2.Query data */ it('testIsNotNull0004', 0, async function (done) { console.log(TAG + "************* testIsNotNull0004 start *************"); @@ -619,9 +651,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0050 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for string value + * @tc.desc 1.Execute greaterThan ("stringValue", "ABC") + * 2.Query data */ it('testGreaterThan0001', 0, async function (done) { console.log(TAG + "************* testGreaterThan0001 start *************"); @@ -638,9 +671,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0051 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for double value + * @tc.desc 1.Execute greaterThan ("doubleValue", 0.0) + * 2.Query data */ it('testGreaterThan0002', 0, async function (done) { console.log(TAG + "************* testGreaterThan0002 start *************"); @@ -657,9 +691,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0052 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for integer value + * @tc.desc 1.Execute greaterThan ("integerValue", 1) + * 2.Query data */ it('testGreaterThan0003', 0, async function (done) { console.log(TAG + "************* testGreaterThan0003 start *************"); @@ -676,9 +711,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0053 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for long value + * @tc.desc 1.Execute greaterThan ("longValue", 1) + * 2.Query data */ it('testGreaterThan0004', 0, async function (done) { console.log(TAG + "************* testGreaterThan0004 start *************"); @@ -695,9 +731,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0054 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for string value + * @tc.desc 1.Execute greaterThan ("stringValue", "ZZZ") + * 2.Query data */ it('testGreaterThan0005', 0, async function (done) { console.log(TAG + "************* testGreaterThan0005 start *************"); @@ -714,9 +751,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0055 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for double value + * @tc.desc 1.Execute greaterThan ("doubleValue", 999.0) + * 2.Query data */ it('testGreaterThan0006', 0, async function (done) { console.log(TAG + "************* testGreaterThan0006 start *************"); @@ -733,9 +771,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0056 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for integer value + * @tc.desc 1.Execute greaterThan ("integerValue", -999) + * 2.Query data */ it('testGreaterThan0007', 0, async function (done) { console.log(TAG + "************* testGreaterThan0007 start *************"); @@ -752,9 +791,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0057 - * @tc.desc predicates greaterThan normal test + * @tc.name Normal test case of predicates, test "greaterThan" for long value + * @tc.desc 1.Execute greaterThan ("longValue", -999) + * 2.Query data */ it('testGreaterThan0008', 0, async function (done) { console.log(TAG + "************* testGreaterThan0008 start *************"); @@ -771,13 +811,13 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0058 - * @tc.name predicates greaterThan abnormal test - * @tc.desc 1.predicates greaterThan abnormal "Number.NaN" test - * 2.predicates greaterThan abnormal "Number.NEGATIVE_INFINITY" test - * 3.predicates greaterThan abnormal "Number.POSITIVE_INFINITY" test - * 4.predicates greaterThan abnormal "Number.MIN_SAFE_INTEGER" test - * 5.predicates greaterThan abnormal "Number.MAX_SAFE_INTEGER" test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0058 + * @tc.name Normal test case of predicates, test "greaterThan" for boundary value of longValue + * @tc.desc 1.Execute greaterThan ("longValue", Number.NaN) + * 2.Execute greaterThan ("longValue", Number.NEGATIVE_INFINITY) + * 3.Execute greaterThan ("longValue", Number.POSITIVE_INFINITY) + * 4.Execute greaterThan ("longValue", Number.MIN_SAFE_INTEGER) + * 5.Execute greaterThan ("longValue", Number.MAX_SAFE_INTEGER) */ it('testGreaterThan0009', 0, async function (done) { console.log(TAG + "************* testGreaterThan0009 start *************"); @@ -823,9 +863,10 @@ describe('rdbPredicatesTest', function () { /** - * @tc.name predicates greaterThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0060 - * @tc.desc predicates greaterThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "greaterThanOrEqualTo" for string value + * @tc.desc 1.Execute greaterThanOrEqualTo ("stringValue", "ABC") + * 2.Query data */ it('testGreaterThanOrEqualTo0001', 0, async function (done) { console.log(TAG + "************* testGreaterThanOrEqualTo0001 start *************"); @@ -842,9 +883,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0061 - * @tc.desc predicates greaterThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "greaterThanOrEqualTo" for double value + * @tc.desc 1.Execute greaterThanOrEqualTo ("doubleValue", 0.0) + * 2.Query data */ it('testGreaterThanOrEqualTo0002', 0, async function (done) { console.log(TAG + "************* testGreaterThanOrEqualTo0002 start *************"); @@ -861,9 +903,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0062 - * @tc.desc predicates greaterThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "greaterThanOrEqualTo" for integer value + * @tc.desc 1.Execute greaterThanOrEqualTo ("integerValue", 1) + * 2.Query data */ it('testGreaterThanOrEqualTo0003', 0, async function (done) { console.log(TAG + "************* testGreaterThanOrEqualTo0003 start *************"); @@ -880,9 +923,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates greaterThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0063 - * @tc.desc predicates greaterThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "greaterThanOrEqualTo" for long value + * @tc.desc 1.Execute greaterThanOrEqualTo ("longValue", 1) + * 2.Query data */ it('testGreaterThanOrEqualTo0004', 0, async function (done) { console.log(TAG + "************* testGreaterThanOrEqualTo0004 start *************"); @@ -899,9 +943,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0070 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for string value + * @tc.desc 1.Execute lessThan ("stringValue", "ABD") + * 2.Query data */ it('testLessThan0001', 0, async function (done) { console.log(TAG + "************* testLessThan0001 start *************"); @@ -918,9 +963,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0071 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for double value + * @tc.desc 1.Execute lessThan ("doubleValue", 0.0) + * 2.Query data */ it('testLessThan0002', 0, async function (done) { console.log(TAG + "************* testLessThan0002 start *************"); @@ -937,9 +983,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0072 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for integer value + * @tc.desc 1.Execute lessThan ("integerValue", 1) + * 2.Query data */ it('testLessThan0003', 0, async function (done) { console.log(TAG + "************* testLessThan0003 start *************"); @@ -956,9 +1003,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0073 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for long value + * @tc.desc 1.Execute lessThan ("longValue", 1) + * 2.Query data */ it('testLessThan0004', 0, async function (done) { console.log(TAG + "************* testLessThan0004 start *************"); @@ -975,9 +1023,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0074 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for string value + * @tc.desc 1.Execute lessThan ("stringValue", "ABD") + * 2.Query data */ it('testLessThan0005', 0, async function (done) { console.log(TAG + "************* testLessThan0005 start *************"); @@ -994,9 +1043,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0075 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for double value + * @tc.desc 1.Execute lessThan ("doubleValue", 1.0) + * 2.Query data */ it('testLessThan0006', 0, async function (done) { console.log(TAG + "************* testLessThan0006 start *************"); @@ -1013,9 +1063,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0076 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for boundary value of integerValue + * @tc.desc 1.Execute lessThan ("integerValue", -2147483648) + * 2.Query data */ it('testLessThan0007', 0, async function (done) { console.log(TAG + "************* testLessThan0007 start *************"); @@ -1032,9 +1083,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThan normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0077 - * @tc.desc predicates lessThan normal test + * @tc.name Normal test case of predicates, test "lessThan" for boundary value of longValue + * @tc.desc 1.Execute lessThan ("longValue", -9223372036854775808) + * 2.Query data */ it('testLessThan0008', 0, async function (done) { console.log(TAG + "************* testLessThan0008 start *************"); @@ -1051,9 +1103,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0080 - * @tc.desc predicates lessThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "lessThanOrEqualTo" for string value + * @tc.desc 1.Execute lessThanOrEqualTo ("stringValue", "ABD") + * 2.Query data */ it('testLessThanOrEqualTo0001', 0, async function (done) { console.log(TAG + "************* testLessThanOrEqualTo0001 start *************"); @@ -1070,9 +1123,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0081 - * @tc.desc predicates lessThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "lessThanOrEqualTo" for double value + * @tc.desc 1.Execute lessThanOrEqualTo ("doubleValue", 0.0) + * 2.Query data */ it('testLessThanOrEqualTo0002', 0, async function (done) { console.log(TAG + "************* testLessThanOrEqualTo0002 start *************"); @@ -1089,9 +1143,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0082 - * @tc.desc predicates lessThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "lessThanOrEqualTo" for integer value + * @tc.desc 1.Execute lessThanOrEqualTo ("integerValue", 1) + * 2.Query data */ it('testLessThanOrEqualTo0003', 0, async function (done) { console.log(TAG + "************* testLessThanOrEqualTo0003 start *************"); @@ -1108,9 +1163,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates lessThanOrEqualTo normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0083 - * @tc.desc predicates lessThanOrEqualTo normal test + * @tc.name Normal test case of predicates, test "lessThanOrEqualTo" for long value + * @tc.desc 1.Execute lessThanOrEqualTo ("longValue", 1) + * 2.Query data */ it('testLessThanOrEqualTo0004', 0, async function (done) { console.log(TAG + "************* testLessThanOrEqualTo0004 start *************"); @@ -1127,13 +1183,13 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0084 - * @tc.name predicates lessThanOrEqualTo abnormal test - * @tc.desc 1.predicates lessThanOrEqualTo abnormal "Number.NaN" test - * 2.predicates lessThanOrEqualTo abnormal "Number.NEGATIVE_INFINITY" test - * 3.predicates lessThanOrEqualTo abnormal "Number.POSITIVE_INFINITY" test - * 4.predicates lessThanOrEqualTo abnormal "Number.MAX_VALUE" test - * 5.predicates lessThanOrEqualTo abnormal "Number.MIN_VALUE" test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0084 + * @tc.name Normal test case of predicates, test "lessThanOrEqualTo" for boundary value of longValue + * @tc.desc 1.Execute lessThanOrEqualTo ("longValue", Number.NaN) + * 2.Execute lessThanOrEqualTo ("longValue", Number.NEGATIVE_INFINITY) + * 3.Execute lessThanOrEqualTo ("longValue", Number.POSITIVE_INFINITY) + * 4.Execute lessThanOrEqualTo ("longValue", Number.MAX_VALUE) + * 5.Execute lessThanOrEqualTo ("longValue", Number.MIN_VALUE) */ it('testLessThanOrEqualTo0005', 0, async function (done) { console.log(TAG + "************* testLessThanOrEqualTo0005 start *************"); @@ -1178,9 +1234,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0090 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for string value + * @tc.desc 1.Execute between ("stringValue", "ABB", "ABD") + * 2.Query data */ it('testBetween0001', 0, async function (done) { console.log(TAG + "************* testBetween0001 start *************"); @@ -1197,9 +1254,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0091 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for double value + * @tc.desc 1.Execute between ("doubleValue", 0.0, DOUBLE_MAX) + * 2.Query data */ it('testBetween0002', 0, async function (done) { console.log(TAG + "************* testBetween0002 start *************"); @@ -1216,9 +1274,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0092 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for integer value + * @tc.desc 1.Execute between ("integerValue", 0, 1) + * 2.Query data */ it('testBetween0003', 0, async function (done) { console.log(TAG + "************* testBetween0003 start *************"); @@ -1235,9 +1294,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0093 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for long value + * @tc.desc 1.Execute between ("longValue", 0, 2) + * 2.Query data */ it('testBetween0004', 0, async function (done) { console.log(TAG + "************* testBetween0004 start *************"); @@ -1254,9 +1314,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0094 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for string value + * @tc.desc 1.Execute between ("stringValue", "ABB", "ABB") + * 2.Query data */ it('testBetween0005', 0, async function (done) { console.log(TAG + "************* testBetween0005 start *************"); @@ -1273,9 +1334,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0095 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for boundary value of doubleValue + * @tc.desc 1.Execute between ("doubleValue", DOUBLE_MAX, DOUBLE_MAX) + * 2.Query data */ it('testBetween0006', 0, async function (done) { console.log(TAG + "************* testBetween0006 start *************"); @@ -1292,9 +1354,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0096 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for integer value + * @tc.desc 1.Execute between ("integerValue", 1, 0) + * 2.Query data */ it('testBetween0007', 0, async function (done) { console.log(TAG + "************* testBetween0007 start *************"); @@ -1311,9 +1374,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates between normal test * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0097 - * @tc.desc predicates between normal test + * @tc.name Normal test case of predicates, test "between" for long value + * @tc.desc 1.Execute between ("longValue", 2, -1) + * 2.Query data */ it('testBetween0008', 0, async function (done) { console.log(TAG + "************* testBetween0008 start *************"); @@ -1330,14 +1394,13 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0098 - * @tc.name predicates between abnormal test - * @tc.desc 1.predicates between abnormal "Number.POSITIVE_INFINITY" test - * 2.predicates between abnormal "Number.NEGATIVE_INFINITY" test - * 3.predicates between abnormal "Number.NaN" test - * 4.predicates between abnormal "Number.NaN" test - * 5.predicates between abnormal "Number.MIN_VALUE" test - * 6.predicates between abnormal "Number.MAX_VALUE" test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0098 + * @tc.name Normal test case of predicates, test "between" for boundary value of longValue + * @tc.desc 1.Execute between ("longValue", 0, Number.POSITIVE_INFINITY) + * 2.Execute between ("longValue", Number.NEGATIVE_INFINITY, 0) + * 3.Execute between ("longValue", Number.NaN, 0) + * 4.Execute between ("longValue", 0, Number.NaN) + * 5.Execute between ("longValue", Number.MIN_VALUE, 0) */ it('testBetween0009', 0, async function (done) { console.log(TAG + "************* testBetween0009 start *************"); @@ -1389,9 +1452,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testNotBetween0001 - * @tc.number I4JWCV - * @tc.desc test string value with notBetween. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0100 + * @tc.name Normal test case of predicates, test "notBetween" for string value + * @tc.desc 1.Execute notBetween ("stringValue", "ABB", "ABD") + * 2.Query data */ it('testNotBetween0001', 0, async function (done) { console.log(TAG + "************* testNotBetween0001 start *************"); @@ -1408,9 +1472,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testNotBetween0002 - * @tc.number I4JWCV - * @tc.desc test double value with notBetween. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0101 + * @tc.name Normal test case of predicates, test "notBetween" for double value + * @tc.desc 1.Execute notBetween ("doubleValue", 0.0, DOUBLE_MAX) + * 2.Query data */ it('testNotBetween0002', 0, async function (done) { console.log(TAG + "************* testNotBetween0002 start *************"); @@ -1427,9 +1492,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testNotBetween0003 - * @tc.number I4JWCV - * @tc.desc test integer value with notBetween. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0102 + * @tc.name Normal test case of predicates, test "notBetween" for integer value + * @tc.desc 1.Execute notBetween ("integerValue", 0, 1) + * 2.Query data */ it('testNotBetween0003', 0, async function (done) { console.log(TAG + "************* testNotBetween0003 start *************"); @@ -1446,9 +1512,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testNotBetween0004 - * @tc.number I4JWCV - * @tc.desc test long value with notBetween. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0103 + * @tc.name Normal test case of predicates, test "notBetween" for long value + * @tc.desc 1.Execute notBetween ("longValue", 0, 2) + * 2.Query data */ it('testNotBetween0004', 0, async function (done) { console.log(TAG + "************* testNotBetween0004 start *************"); @@ -1465,14 +1532,14 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.number testNotBetween0005 - * @tc.name test long value with notBetween. - * @tc.desc 1.predicates between abnormal "Number.NaN" test - * 2.predicates between abnormal "Number.NaN" test - * 3.predicates between abnormal "Number.MIN_VALUE" test - * 4.predicates between abnormal "Number.MAX_VALUE" test - * 5.predicates between abnormal "Number.NEGATIVE_INFINITY" test - * 6.predicates between abnormal "Number.POSITIVE_INFINITY" test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0104 + * @tc.name Normal test case of predicates, test "notBetween" for boundary value of longValue + * @tc.desc 1.Execute notBetween ("longValue", 0, Number.NaN) + * 2.Execute notBetween ("longValue", Number.NaN, 0) + * 3.Execute notBetween ("longValue", Number.MIN_VALUE, 0) + * 4.Execute notBetween ("longValue", 0, Number.MAX_VALUE) + * 5.Execute notBetween ("longValue", Number.NEGATIVE_INFINITY, 0) + * 6.Execute notBetween ("longValue", 0, Number.POSITIVE_INFINITY) */ it('testNotBetween0005', 0, async function (done) { console.log(TAG + "************* testNotBetween0005 start *************"); @@ -1519,9 +1586,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testGlob0001 - * @tc.number I4JWCV - * @tc.desc end with ? by glob. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0110 + * @tc.name Normal test case of predicates, test "glob" for string value + * @tc.desc 1.Execute glob ("stringValue", "ABC*") + * 2.Query data */ it('testGlob0001', 0, async function (done) { console.log(TAG + "************* testGlob0001 start *************"); @@ -1538,9 +1606,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testGlob0002 - * @tc.number I4JWCV - * @tc.desc begin with * by glob. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0111 + * @tc.name Normal test case of predicates, test "glob" for string value + * @tc.desc 1.Execute glob ("stringValue", "*LMN") + * 2.Query data */ it('testGlob0002', 0, async function (done) { console.log(TAG + "************* testGlob0002 start *************"); @@ -1557,9 +1626,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testGlob0003 - * @tc.number I4JWCV - * @tc.desc end with ? by glob. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0112 + * @tc.name Normal test case of predicates, test "glob" for string value + * @tc.desc 1.Execute glob ("stringValue", "ABCDEFGHIJKLM?") + * 2.Query data */ it('testGlob0003', 0, async function (done) { console.log(TAG + "************* testGlob0003 start *************"); @@ -1576,9 +1646,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testGlob0004 - * @tc.number I4JWCV - * @tc.desc begin with ? by glob. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0113 + * @tc.name Normal test case of predicates, test "glob" for string value + * @tc.desc 1.Execute glob ("stringValue", "?BCDEFGHIJKLMN") + * 2.Query data */ it('testGlob0004', 0, async function (done) { console.log(TAG + "************* testGlob0004 start *************"); @@ -1595,9 +1666,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testGlob0005 - * @tc.number I4JWCV - * @tc.desc begin and end with * by glob. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0114 + * @tc.name Normal test case of predicates, test "glob" for string value + * @tc.desc 1.Execute glob ("stringValue", "*FGHI*") + * 2.Query data */ it('testGlob0005', 0, async function (done) { console.log(TAG + "************* testGlob0005 start *************"); @@ -1614,9 +1686,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testGlob0006 - * @tc.number I4JWCV - * @tc.desc begin and end with ? by glob. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0115 + * @tc.name Normal test case of predicates, test "glob" for string value + * @tc.desc 1.Execute glob ("stringValue", "?BCDEFGHIJKLM?") + * 2.Query data */ it('testGlob0006', 0, async function (done) { console.log(TAG + "************* testGlob0006 start *************"); @@ -1633,9 +1706,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates contains normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0100 - * @tc.desc predicates contains normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0120 + * @tc.name Normal test case of predicates, test "contains" for string value + * @tc.desc 1.Execute contains ("stringValue", "DEF") + * 2.Query data */ it('testContains0001', 0, async function (done) { console.log(TAG + "************* testContains0001 start *************"); @@ -1650,9 +1724,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates contains normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0101 - * @tc.desc predicates contains normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0121 + * @tc.name Normal test case of predicates, test "contains" for string value + * @tc.desc 1.Execute contains ("stringValue", "DEFX") + * 2.Query data */ it('testContains0002', 0, async function (done) { console.log(TAG + "************* testContains0002 start *************"); @@ -1667,9 +1742,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates contains normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0102 - * @tc.desc predicates contains normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0122 + * @tc.name Normal test case of predicates, test "contains" for Chinese character value + * @tc.desc 1.Execute contains ("characterValue", "中") + * 2.Query data */ it('testContains0003', 0, async function (done) { console.log(TAG + "************* testContains0003 start *************"); @@ -1684,9 +1760,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates contains normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0103 - * @tc.desc predicates contains normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0123 + * @tc.name Normal test case of predicates, test "contains" for character value + * @tc.desc 1.Execute contains ("characterValue", "#") + * 2.Query data */ it('testContains0004', 0, async function (done) { console.log(TAG + "************* testContains0004 start *************"); @@ -1701,10 +1778,12 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0104 - * @tc.name predicates contains abnormal test - * @tc.desc 1.predicates contains abnormal "null" test - * 2.predicates contains abnormal "undefined" test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0124 + * @tc.name Abnormal test case of predicates, test "contains" for character value + * @tc.desc 1.Execute contains ("characterValue", null) + * 2.Query data + * 3.Execute contains ("characterValue", undefined) + * 4.Query data */ it('testContains0005', 0, async function (done) { console.info(TAG, `************* testContains0005 start *************`); @@ -1732,9 +1811,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0110 - * @tc.desc predicates beginsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0130 + * @tc.name Normal test case of predicates, test "beginsWith" for character value + * @tc.desc 1.Execute beginsWith ("stringValue", "ABC") + * 2.Query data */ it('testBeginsWith0001', 0, async function (done) { console.log(TAG + "************* testBeginsWith0001 start *************"); @@ -1749,9 +1829,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0111 - * @tc.desc predicates beginsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0131 + * @tc.name Normal test case of predicates, test "beginsWith" for character value + * @tc.desc 1.Execute beginsWith ("stringValue", "ABCX") + * 2.Query data */ it('testBeginsWith0002', 0, async function (done) { console.log(TAG + "************* testBeginsWith0002 start *************"); @@ -1766,9 +1847,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0112 - * @tc.desc predicates beginsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0132 + * @tc.name Normal test case of predicates, test "beginsWith" for Chinese character value + * @tc.desc 1.Execute beginsWith ("characterValue", "中") + * 2.Query data */ it('testBeginsWith0003', 0, async function (done) { console.log(TAG + "************* testBeginsWith0003 start *************"); @@ -1783,9 +1865,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0113 - * @tc.desc predicates beginsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0133 + * @tc.name Normal test case of predicates, test "beginsWith" for character value + * @tc.desc 1.Execute beginsWith ("characterValue", "#") + * 2.Query data */ it('testBeginsWith0004', 0, async function (done) { console.log(TAG + "************* testBeginsWith0004 start *************"); @@ -1800,9 +1883,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates endsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0120 - * @tc.desc predicates endsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0140 + * @tc.name Normal test case of predicates, test "endsWith" for string value + * @tc.desc 1.Execute endsWith ("stringValue", "LMN") + * 2.Query data */ it('testEndsWith0001', 0, async function (done) { console.log(TAG + "************* testEndsWith0001 start *************"); @@ -1817,9 +1901,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates endsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0121 - * @tc.desc predicates endsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0141 + * @tc.name Normal test case of predicates, test "endsWith" for string value + * @tc.desc 1.Execute endsWith ("stringValue", "LMNX") + * 2.Query data */ it('testEndsWith0002', 0, async function (done) { console.log(TAG + "************* testEndsWith0002 start *************"); @@ -1834,9 +1919,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates endsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0122 - * @tc.desc predicates endsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0142 + * @tc.name Normal test case of predicates, test "endsWith" for Chinese character value + * @tc.desc 1.Execute endsWith ("characterValue", "中") + * 2.Query data */ it('testEndsWith0003', 0, async function (done) { console.log(TAG + "************* testEndsWith0003 start *************"); @@ -1851,9 +1937,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates endsWith normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0123 - * @tc.desc predicates endsWith normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0143 + * @tc.name Normal test case of predicates, test "endsWith" for character value + * @tc.desc 1.Execute endsWith ("characterValue", "#") + * 2.Query data */ it('testEndsWith0004', 0, async function (done) { console.log(TAG + "************* testEndsWith0004 start *************"); @@ -1868,9 +1955,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates like normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0130 - * @tc.desc predicates like normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0150 + * @tc.name Normal test case of predicates, test "like" for string value + * @tc.desc 1.Execute like ("stringValue", "%LMN%") + * 2.Query data */ it('testLike0001', 0, async function (done) { console.log(TAG + "************* testLike0001 start *************"); @@ -1885,9 +1973,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates like normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0130 - * @tc.desc predicates like normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0151 + * @tc.name Normal test case of predicates, test "like" for string value + * @tc.desc 1.Execute like ("stringValue", "%LMNX%") + * 2.Query data */ it('testLike0002', 0, async function (done) { console.log(TAG + "************* testLike0002 start *************"); @@ -1902,9 +1991,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates like normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0132 - * @tc.desc predicates like normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0152 + * @tc.name Normal test case of predicates, test "like" for Chinese character value + * @tc.desc 1.Execute like ("characterValue", "%中%") + * 2.Query data */ it('testLike0003', 0, async function (done) { console.log(TAG + "************* testLike0003 start *************"); @@ -1919,9 +2009,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates like normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0133 - * @tc.desc predicates like normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0153 + * @tc.name Normal test case of predicates, test "like" for character value + * @tc.desc 1.Execute like ("characterValue", "%#%") + * 2.Query data */ it('testLike0004', 0, async function (done) { console.log(TAG + "************* testLike0004 start *************"); @@ -1936,10 +2027,12 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0134 - * @tc.name predicates like abnormal test - * @tc.desc 1.predicates like abnormal "null" test - * 2.predicates like abnormal "undefined" test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0154 + * @tc.name Abnormal test case of predicates, test "like" for character value + * @tc.desc 1.Execute like ("characterValue", null) + * 2.Query data + * 3.Execute like ("characterValue", undefined) + * 4.Query data */ it('testLike0005', 0, async function (done) { console.info(TAG, `************* testLike0005 start *************`); @@ -1967,9 +2060,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginWrap normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0140 - * @tc.desc predicates beginWrap normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0160 + * @tc.name Normal test case of predicates, test "beginWrap" + * @tc.desc 1.Execute equalTo().beginWrap().equalTo().or().equalTo().endWrap() + * 2.Query data */ it('testBeginWrap0001', 0, async function (done) { console.log(TAG + "************* testBeginWrap0001 start *************"); @@ -1991,9 +2085,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginWrap normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0141 - * @tc.desc predicates beginWrap normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0161 + * @tc.name Normal test case of predicates, test "beginWrap" + * @tc.desc 1.Execute equalTo().beginWrap().equalTo().endWrap() + * 2.Query data */ it('testBeginWrap0002', 0, async function (done) { console.log(TAG + "************* testBeginWrap0002 start *************"); @@ -2013,9 +2108,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginWrap normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0142 - * @tc.desc predicates beginWrap normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0162 + * @tc.name Normal test case of predicates, test "beginWrap" + * @tc.desc 1.Execute equalTo().beginWrap().equalTo().endWrap() + * 2.Query data */ it('testBeginWrap0003', 0, async function (done) { console.log(TAG + "************* testBeginWrap0003 start *************"); @@ -2034,9 +2130,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginWrap normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0143 - * @tc.desc predicates beginWrap normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0163 + * @tc.name Abnormal test case of predicates, test "beginWrap" without "beginWrap" + * @tc.desc 1.Execute equalTo().equalTo().endWrap() + * 2.Query data */ it('testBeginWrap0004', 0, async function (done) { console.log(TAG + "************* testBeginWrap0004 start *************"); @@ -2055,9 +2152,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates beginWrap normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0144 - * @tc.desc predicates beginWrap normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0164 + * @tc.name Abnormal test case of predicates, test "beginWrap" without "endWrap" + * @tc.desc 1.Execute equalTo().beginWrap().equalTo() + * 2.Query data */ it('testBeginWrap0005', 0, async function (done) { console.log(TAG + "************* testBeginWrap0005 start *************"); @@ -2076,9 +2174,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates and normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0150 - * @tc.desc predicates and normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0170 + * @tc.name Normal test case of predicates, test "and" + * @tc.desc 1.Execute equalTo().and().equalTo() + * 2.Query data */ it('testAnd0001', 0, async function (done) { console.log(TAG + "************* testAnd0001 start *************"); @@ -2097,9 +2196,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates or normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0151 - * @tc.desc predicates or normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0171 + * @tc.name Normal test case of predicates, test "and" + * @tc.desc 1.Execute equalTo().beginWrap().equalTo().or().equalTo().endWrap() + * 2.Query data */ it('testAnd0002', 0, async function (done) { console.log(TAG + "************* testAnd0002 start *************"); @@ -2121,9 +2221,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates and normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0152 - * @tc.desc predicates and normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0172 + * @tc.name Abnormal test case of predicates, test "and" + * @tc.desc 1.Execute equalTo().or().and().equalTo() + * 2.Query data */ it('testAnd0003', 0, async function (done) { console.log(TAG + "************* testAnd0003 start *************"); @@ -2137,9 +2238,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates order normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0160 - * @tc.desc predicates order normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0180 + * @tc.name Normal test case of predicates, test "orderByAsc" for integer value + * @tc.desc 1.Execute orderByAsc ("integerValue") + * 2.Query data */ it('testOrder0001', 0, async function (done) { console.log(TAG + "************* testOrder0001 start *************"); @@ -2154,7 +2256,7 @@ describe('rdbPredicatesTest', function () { expect(2).assertEqual(result.getLong(0)); expect(true).assertEqual(result.goToNextRow()) expect(1).assertEqual(result.getLong(0)); - result.close() + result.close() result = null done(); @@ -2162,9 +2264,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates order normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0161 - * @tc.desc predicates order normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0181 + * @tc.name Normal test case of predicates, test "orderByDesc" for integer value + * @tc.desc 1.Execute orderByDesc ("integerValue") + * 2.Query data */ it('testOrder0002', 0, async function (done) { console.log(TAG + "************* testOrder0002 start *************"); @@ -2187,9 +2290,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates order normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0162 - * @tc.desc predicates order normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0182 + * @tc.name Abnormal test case of predicates, test "orderByDesc" for invalid param + * @tc.desc 1.Execute orderByDesc ("integerValueX") + * 2.Query data */ it('testOrder0003', 0, async function (done) { console.log(TAG + "************* testOrder0003 start *************"); @@ -2206,9 +2310,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates order normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0163 - * @tc.desc predicates order normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0183 + * @tc.name Abnormal test case of predicates, test "orderByAsc" for invalid param + * @tc.desc 1.Execute orderByAsc ("integerValueX") + * 2.Query data */ it('testOrder0004', 0, async function (done) { console.log(TAG + "************* testOrder0004 start *************"); @@ -2225,9 +2330,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates limit normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0170 - * @tc.desc predicates limit normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0190 + * @tc.name Normal test case of predicates, test "limitAs" '1' + * @tc.desc 1.Execute limitAs + * 2.Query data */ it('testLimit0001', 0, async function (done) { console.log(TAG + "************* testLimit0001 start *************"); @@ -2242,9 +2348,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates limit normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0171 - * @tc.desc predicates limit normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0191 + * @tc.name Normal test case of predicates, test "limitAs" '3' + * @tc.desc 1.Execute limitAs + * 2.Query data */ it('testLimit0002', 0, async function (done) { console.log(TAG + "************* testLimit0002 start *************"); @@ -2259,9 +2366,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates limit normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0172 - * @tc.desc predicates limit normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0192 + * @tc.name Normal test case of predicates, test "limitAs" "100" + * @tc.desc 1.Execute limitAs + * 2.Query data */ it('testLimit0003', 0, async function (done) { console.log(TAG + "************* testLimit0003 start *************"); @@ -2276,9 +2384,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates limit normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0173 - * @tc.desc predicates limit normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0193 + * @tc.name Normal test case of predicates, test "limitAs" for Chinese value + * @tc.desc 1.Execute limitAs + * 2.Query data */ it('testLimit0004', 0, async function (done) { console.log(TAG + "************* testLimit0004 start *************"); @@ -2293,9 +2402,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates limit normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0174 - * @tc.desc predicates limit normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0194 + * @tc.name Normal test case of predicates, test "limitAs" '0' + * @tc.desc 1.Execute limitAs + * 2.Query data */ it('testLimit0005', 0, async function (done) { console.log(TAG + "************* testLimit0005 start *************"); @@ -2310,9 +2420,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates limit normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0175 - * @tc.desc predicates limit normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0195 + * @tc.name Normal test case of predicates, test "limitAs" "-1" + * @tc.desc 1.Execute limitAs + * 2.Query data */ it('testLimit0006', 0, async function (done) { console.log(TAG + "************* testLimit0006 start *************"); @@ -2327,9 +2438,14 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates limit normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0176 - * @tc.desc predicates limit normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0196 + * @tc.name Normal test case of predicates, test "limitAs" + * @tc.desc 1.Execute limitAs (-1) + * 2.Execute limitAs (1, 1)) + * 3.Execute limitAs (0, -1) + * 4.Execute like ("stringValue", "ABCDEFGHIJKLMN") + * 5.Execute orderByAsc ("id") + * 6.Execute limitAs (-1, -1) */ it('testLimit0007', 0, async function (done) { console.log(TAG + "************* testLimit0007 start *************"); @@ -2367,9 +2483,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates offset normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0180 - * @tc.desc predicates offset normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0200 + * @tc.name Normal test case of predicates, test "offsetAs" '1' + * @tc.desc 1.Execute offsetAs + * 2.Query data */ it('testOffset0001', 0, async function (done) { console.log(TAG + "************* testOffset0001 start *************"); @@ -2384,9 +2501,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates offset normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0181 - * @tc.desc predicates offset normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0201 + * @tc.name Normal test case of predicates, test "offsetAs" '0' + * @tc.desc 1.Execute offsetAs + * 2.Query data */ it('testOffset0002', 0, async function (done) { console.log(TAG + "************* testOffset0002 start *************"); @@ -2401,9 +2519,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates offset normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0182 - * @tc.desc predicates offset normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0202 + * @tc.name Normal test case of predicates, test "offsetAs" '5' + * @tc.desc 1.Execute offsetAs + * 2.Query data */ it('testOffset0003', 0, async function (done) { console.log(TAG + "************* testOffset0003 start *************"); @@ -2418,9 +2537,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates offset normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0183 - * @tc.desc predicates offset normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0203 + * @tc.name Normal test case of predicates, test "offsetAs" "-1" + * @tc.desc 1.Execute offsetAs + * 2.Query data */ it('testOffset0004', 0, async function (done) { console.log(TAG + "************* testOffset0004 start *************"); @@ -2435,9 +2555,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates in normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0190 - * @tc.desc predicates in normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0210 + * @tc.name Normal test case of predicates, test "in" for boundary value of doubleValue + * @tc.desc 1.Execute in ("doubleValue", Number.MIN_VALUE.toString()) + * 2.Query data */ it('testIn0001', 0, async function (done) { console.log(TAG + "************* testIn0001 start *************"); @@ -2452,9 +2573,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates in normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0191 - * @tc.desc predicates in normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0211 + * @tc.name Normal test case of predicates, test "in" for doubleValue + * @tc.desc 1.Execute in ("doubleValue", "1.0") + * 2.Query data */ it('testIn0002', 0, async function (done) { console.log(TAG + "************* testIn0002 start *************"); @@ -2469,9 +2591,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates in normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0192 - * @tc.desc predicates in normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0212 + * @tc.name Normal test case of predicates, test "in" for boundary value of doubleValue + * @tc.desc 1.Execute in ("doubleValue", DOUBLE_MAX.toString()) + * 2.Query data */ it('testIn0003', 0, async function (done) { console.log(TAG + "************* testIn0003 start *************"); @@ -2486,9 +2609,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates in normal test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0193 - * @tc.desc predicates in normal test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0213 + * @tc.desc Normal test case of predicates, test "in" for boundary value of doubleValue + * @tc.desc 1.Execute in ("doubleValue", Number.MIN_VALUE.toString(), "1.0", DOUBLE_MAX.toString()) + * 2.Query data */ it('testIn0004', 0, async function (done) { console.log(TAG + "************* testIn0004 start *************"); @@ -2503,9 +2627,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testNotIn0001 - * @tc.number I4JWCV - * @tc.desc the common and min value test with notin. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0220 + * @tc.name Normal test case of predicates, test "notIn" for boundary value of integerValue + * @tc.desc 1.Execute notIn ("integerValue", [1, -2147483648]) + * 2.Query data */ it('testNotIn0001', 0, async function (done) { console.log(TAG + "************* testNotIn0001 start *************"); @@ -2520,9 +2645,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testNotIn0002 - * @tc.number I4JWCV - * @tc.desc the common and max value test with notin. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0221 + * @tc.name Normal test case of predicates, test "notIn" for boundary value of integerValue + * @tc.desc 1.Execute notIn ("integerValue", [1, 2147483647]) + * 2.Query data */ it('testNotIn0002', 0, async function (done) { console.log(TAG + "************* testNotIn0002 start *************"); @@ -2537,9 +2663,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name testNotIn0003 - * @tc.number I4JWCV - * @tc.desc the min and max value test with notin. + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0222 + * @tc.name Normal test case of predicates, test "notIn" for boundary value of integerValue + * @tc.desc 1.Execute notIn ("integerValue", [-2147483648, 2147483647]) + * 2.Query data */ it('testNotIn0003', 0, async function (done) { console.log(TAG + "************* testNotIn0003 start *************"); @@ -2554,9 +2681,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates constructor test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0200 - * @tc.desc predicates constructor test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0230 + * @tc.name Normal test case of predicates, test "RdbPredicates" + * @tc.desc 1.Execute RdbPredicates ("AllDataType") + * 2.Query data */ it('testCreate0001', 0, async function (done) { console.log(TAG + "************* testCreate0001 start *************"); @@ -2569,9 +2697,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates constructor test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0201 - * @tc.desc predicates constructor test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0231 + * @tc.name Abnormal test case of predicates, test "RdbPredicates" for creat new table + * @tc.desc 1.Execute RdbPredicates ("test") + * 2.Query data */ it('testCreate0002', 0, async function (done) { console.log(TAG + "************* testCreate0002 start *************"); @@ -2584,9 +2713,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates groupBy test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0210 - * @tc.desc predicates groupBy test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0240 + * @tc.name Normal test case of predicates, test "groupBy" for character value + * @tc.desc 1.Execute groupBy (["characterValue"]) + * 2.Query data */ it('testGroupBy0001', 0, async function (done) { console.log(TAG + "************* testGroupBy0001 start *************"); @@ -2601,9 +2731,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates groupBy test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0211 - * @tc.desc predicates groupBy test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0241 + * @tc.name Abnormal test case of predicates, test "groupBy" for invalid param + * @tc.desc 1.Execute groupBy (["characterValueX"]) + * 2.Query data */ it('testGroupBy0002', 0, async function (done) { console.log(TAG + "************* testGroupBy0002 start *************"); @@ -2618,9 +2749,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates indexedBy test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0220 - * @tc.desc predicates indexedBy test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0250 + * @tc.name Abnormal test case of predicates, test "indexedBy" for character value + * @tc.desc 1.Execute indexedBy ("characterValue") + * 2.Query data */ it('testIndexedBy0001', 0, async function (done) { console.log(TAG + "************* testIndexedBy0001 start *************"); @@ -2636,9 +2768,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name predicates indexedBy test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0221 - * @tc.desc predicates indexedBy test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0251 + * @tc.name Abnormal test case of predicates, test "indexedBy" for invalid param + * @tc.desc 1.Execute indexedBy (["characterValueX"]) + * 2.Query data */ it('testIndexedBy0002', 0, async function (done) { console.log(TAG + "************* testIndexedBy0002 start *************"); @@ -2658,9 +2791,10 @@ describe('rdbPredicatesTest', function () { }) /** - * @tc.name Query Permission Denied test - * @tc.number SUB_DDM_AppDataFWK_JSRDB_Permission_Denied_0221 - * @tc.desc Query Permission Denied test + * @tc.number SUB_DDM_AppDataFWK_JSRDB_Predicates_0260 + * @tc.name Abnormal test case of predicates, call system api + * @tc.desc 1.Configure predicates + * 2.Query data */ it('testQueryPermissionDenied0001', 0, async function (done) { console.log(TAG + "************* testQueryPermissionDenied0001 start *************"); diff --git a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js index 10daeb0002e74e8547d05eb2393838e36d5c6598..801cf6fe24d82d06bf5e75afe1ee7df71f015ea5 100644 --- a/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js +++ b/relational_store/test/js/relationalstore/unittest/src/RdbstoreRdbstoreJsunit.test.js @@ -276,5 +276,28 @@ describe('rdbStoreTest', function () { }) }) + /** + * @tc.name rdb store getRdbStore with invalid securityLevel + * @tc.number SUB_DDM_AppDataFWK_JSRDB_RdbStore_0011 + * @tc.desc rdb store getRdbStore with invalid securityLevel + */ + it('testRdbStore0011', 0, async function () { + console.log(TAG + "************* testRdbStore0011 start *************"); + let config = { + name: "search.db", + securityLevel: data_relationalStore.SecurityLevel.S1, + isSearchable: true + } + let store = await data_relationalStore.getRdbStore(context, config); + try { + store.isSearchable = true + expect(true).assertEqual(store.isSearchable) + } catch (err) { + expect("401").assertEqual(err.code) + } + store = null + console.log(TAG + "************* testRdbStore0011 end *************"); + }) + console.log(TAG + "*************Unit Test End*************"); }) \ No newline at end of file diff --git a/relational_store/test/native/rdb/BUILD.gn b/relational_store/test/native/rdb/BUILD.gn index 5ba5ccb6a5acd68705d1b57a5aa780f3a7864e23..619f6ff3121d6e6d8265a416daa62c3152bc16f9 100644 --- a/relational_store/test/native/rdb/BUILD.gn +++ b/relational_store/test/native/rdb/BUILD.gn @@ -29,6 +29,8 @@ config("module_private_config") { "${common_tool_path}/", ] + defines = [ "RELATIONAL_STORE" ] + if (relational_store_rdb_support_icu) { include_dirs += [ "//third_party/icu/icu4c/source/i18n", @@ -41,6 +43,7 @@ ohos_unittest("NativeRdbTest") { module_out_path = module_output_path sources = [ + "unittest/common.cpp", "unittest/rdb_attach_test.cpp", "unittest/rdb_delete_test.cpp", "unittest/rdb_distributed_test.cpp", diff --git a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn index c443cc79a002eaacff387435d08b969f4a2262fa..6a4498412996fa15612fc05cc73da7fbcab05663 100644 --- a/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn +++ b/relational_store/test/native/rdb/distributedtest/rdb_store_impl_test/BUILD.gn @@ -50,6 +50,7 @@ ohos_distributedtest("DistributedTest") { "device_manager:devicemanagersdk", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddb", ] deps = [ @@ -73,6 +74,7 @@ ohos_distributedtest("DistributedTestAgent") { "device_manager:devicemanagersdk", "hilog:libhilog", "ipc:ipc_core", + "kv_store:distributeddb", ] deps = [ diff --git a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/kvstoredisksize_fuzzer.h b/relational_store/test/native/rdb/unittest/common.cpp similarity index 45% rename from datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/kvstoredisksize_fuzzer.h rename to relational_store/test/native/rdb/unittest/common.cpp index dbb209854c7b75d8683a5bc3c7c56904150c0b5d..f98207135dff0ad3d56fd39bfadb17ee9af94460 100644 --- a/datamgr_service/test/fuzztest/kvstoredisksize_fuzzer/kvstoredisksize_fuzzer.h +++ b/relational_store/test/native/rdb/unittest/common.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2021 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 @@ -13,10 +13,28 @@ * limitations under the License. */ -#ifndef KVSTOREDISKSIZE_FUZZER_H -#define KVSTOREDISKSIZE_FUZZER_H -#define FUZZ_PROJECT_NAME "KvStoreDiskSize_fuzzer" +#include "common.h" +#include -#endif // KVSTOREDISKSIZE_FUZZER_H +namespace OHOS { +namespace NativeRdb { +ValuesBucket UTUtils::SetRowData(const RowData &rowData) +{ + ValuesBucket value; + value.PutInt("id", rowData.id); + value.PutString("name", rowData.name); + value.PutInt("age", rowData.age); + value.PutDouble("salary", rowData.salary); + value.PutBlob("blobType", rowData.blobType); + return value; +} + +const RowData UTUtils::g_rowData[3] = { + {1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 }}, + {2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 }}, + {3, "wangyjing", 20, 300.5, std::vector{ 7, 8, 9 }} +}; +} +} diff --git a/relational_store/test/native/rdb/unittest/common.h b/relational_store/test/native/rdb/unittest/common.h index bab8e71a9d507326c04775940dcdd845254c9a66..97c9ab50c49bdf12139d42852265a6363f6557d6 100644 --- a/relational_store/test/native/rdb/unittest/common.h +++ b/relational_store/test/native/rdb/unittest/common.h @@ -17,11 +17,26 @@ #define NATIVE_RDB_TEST_COMMON_H #include +#include "values_bucket.h" namespace OHOS { namespace NativeRdb { static const std::string RDB_TEST_PATH = "/data/test/"; +struct RowData { + int id; + std::string name; + int age; + double salary; + std::vector blobType; +}; + +class UTUtils { +public: + static ValuesBucket SetRowData(const RowData &rowData); + + static const RowData g_rowData[3]; +}; } // namespace NativeRdb } // namespace OHOS diff --git a/relational_store/test/native/rdb/unittest/rdb_get_store_test.cpp b/relational_store/test/native/rdb/unittest/rdb_get_store_test.cpp index 3bfbf3eba663555abc9305be6a2347dbd694efca..aa405ba6a54d477ebdb5b489bfe20680d40c6ecf 100644 --- a/relational_store/test/native/rdb/unittest/rdb_get_store_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_get_store_test.cpp @@ -421,6 +421,23 @@ HWTEST_F(RdbGetStoreTest, RdbStore_GetStore_00104, TestSize.Level1) sleep(1); } +/** + * @tc.name: RdbStore_GetStore_001 + * @tc.desc: createRDB + * @tc.type: FUNC + * @tc.require: issue + * @tc.author: lcl + */ +HWTEST_F(RdbGetStoreTest, RdbStore_GetStore_00106, TestSize.Level1) +{ + RdbStoreConfig config(RdbGetStoreTest::MAIN_DATABASE_NAME_MINUS); + config.SetCustomDir("SetCustomDirTest/"); + GetOpenCallback helper; + int errCode = E_OK; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(store, nullptr); +} + /** * @tc.name: RdbStore_GetStore_005 * @tc.desc: createRDB diff --git a/relational_store/test/native/rdb/unittest/rdb_predicates_join_b_test.cpp b/relational_store/test/native/rdb/unittest/rdb_predicates_join_b_test.cpp index b8da2499d78a40d95eed57fdcc5cffa4d1d5057e..2368cb46af56385407b0bcadab1fac2a86416e03 100644 --- a/relational_store/test/native/rdb/unittest/rdb_predicates_join_b_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_predicates_join_b_test.cpp @@ -397,7 +397,7 @@ HWTEST_F(RdbStorePredicateJoinBTest, RdbStore_CrossJoinB_001, TestSize.Level1) EXPECT_EQ(joinTypes, predicates.GetJoinTypes()); EXPECT_EQ("dept", predicates.GetJoinTableNames()[0]); EXPECT_EQ("ON(emp.deptId = dept.id)", predicates.GetJoinConditions()[0]); - EXPECT_EQ("emp CROSS JOIN dept ON(emp.deptId = dept.id)", predicates.GetJoinClause()); + EXPECT_EQ("CROSS JOIN dept ON(emp.deptId = dept.id)", predicates.GetJoinClause()); std::vector columns; std::shared_ptr allDataTypes = RdbStorePredicateJoinBTest::store->Query(predicates, columns); diff --git a/relational_store/test/native/rdb/unittest/rdb_predicates_join_test.cpp b/relational_store/test/native/rdb/unittest/rdb_predicates_join_test.cpp index ab0e5bb0f413e8dd0a1a3a3834c3d8961e4b8f54..0be12d0d627631fbd8d8ddd901af47a8de6c4513 100644 --- a/relational_store/test/native/rdb/unittest/rdb_predicates_join_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_predicates_join_test.cpp @@ -201,7 +201,7 @@ HWTEST_F(RdbStorePredicateJoinTest, RdbStore_CrossJoin_001, TestSize.Level1) EXPECT_EQ(joinTypes, predicates.GetJoinTypes()); EXPECT_EQ("book", predicates.GetJoinTableNames()[0]); EXPECT_EQ("ON(user.userId = book.userId)", predicates.GetJoinConditions()[0]); - EXPECT_EQ("user CROSS JOIN book ON(user.userId = book.userId)", predicates.GetJoinClause()); + EXPECT_EQ("CROSS JOIN book ON(user.userId = book.userId)", predicates.GetJoinClause()); std::vector columns; std::shared_ptr allDataTypes = RdbStorePredicateJoinTest::store->Query(predicates, columns); diff --git a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp index 8a2e406e91400de32e8d8398e08253e833dac1e9..c3e64d120619298e243b58870f8893066202796c 100644 --- a/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_predicates_test.cpp @@ -1461,7 +1461,7 @@ HWTEST_F(RdbStorePredicateTest, RdbStore_ClearMethod_022, TestSize.Level1) EXPECT_EQ(0, predicates1.GetJoinCount()); EXPECT_EQ(true, predicates1.GetJoinConditions().empty()); EXPECT_EQ(true, predicates1.GetJoinTypes().empty()); - EXPECT_EQ("AllDataType", predicates1.GetJoinClause()); + EXPECT_EQ("", predicates1.GetJoinClause()); EXPECT_EQ(true, predicates1.GetOrder().empty()); EXPECT_EQ(false, predicates1.IsDistinct()); } @@ -1624,7 +1624,7 @@ HWTEST_F(RdbStorePredicateTest, RdbStore_KeywordMethod_024, TestSize.Level1) EXPECT_EQ(0, predicates1.GetJoinCount()); EXPECT_EQ(true, predicates1.GetJoinConditions().empty()); EXPECT_EQ(true, predicates1.GetJoinTypes().empty()); - EXPECT_EQ("AllDataType", predicates1.GetJoinClause()); + EXPECT_EQ("", predicates1.GetJoinClause()); EXPECT_EQ(true, predicates1.GetOrder().empty()); EXPECT_EQ(false, predicates1.IsDistinct()); } diff --git a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp index 2c144c7dc1c4ac2e1093388270dd7c047b72e7fd..4bccb1d73e0b1cb7fdbb0dd254f362eab84bd4ae 100644 --- a/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_step_result_set_test.cpp @@ -26,7 +26,8 @@ using namespace testing::ext; using namespace OHOS::NativeRdb; - +namespace OHOS { +namespace NativeRdb { struct ResultSetData { std::string strValue; int iValue; @@ -34,11 +35,6 @@ struct ResultSetData { std::vector blobValue; }; -ResultSetData g_resultSetData[3] = { - {"2", -5, 2.5, std::vector{}}, - {"hello", 10, 1.0, std::vector{ 66 }}, - {"hello world", 3, 1.8, std::vector{}} -}; class RdbStepResultSetTest : public testing::Test { public: @@ -55,10 +51,16 @@ public: static const std::string DATABASE_NAME; static std::shared_ptr store; + static ResultSetData g_resultSetData[3]; }; const std::string RdbStepResultSetTest::DATABASE_NAME = RDB_TEST_PATH + "stepResultSet_test.db"; std::shared_ptr RdbStepResultSetTest::store = nullptr; +ResultSetData RdbStepResultSetTest::g_resultSetData[3] = { + {"2", -5, 2.5, std::vector{}}, + {"hello", 10, 1.0, std::vector{ 66 }}, + {"hello world", 3, 1.8, std::vector{}} +}; class RdbStepResultSetOpenCallback : public RdbOpenCallback { public: @@ -1434,6 +1436,8 @@ HWTEST_F(RdbStepResultSetTest, testSqlStep017, TestSize.Level1) std::vector columns = {"data1", "data2"}; std::string outSql; - int errCode = SqliteSqlBuilder::BuildQueryString(false, "", columns, "", "", "", "", 0, 0, outSql); + int errCode = SqliteSqlBuilder::BuildQueryString(false, "", "", columns, "", "", "", "", 0, 0, outSql); EXPECT_EQ(E_EMPTY_TABLE_NAME, errCode); -} \ No newline at end of file +} +} // namespace NativeRdb +} // namespace OHOS diff --git a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp index e7a68a822fb6f624f3d0f3eefe78c5af93d8090e..226136f1e8e06bf4a09f33f61b7b2248e95e26d1 100644 --- a/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_store_impl_test.cpp @@ -24,6 +24,8 @@ #include "rdb_open_callback.h" #include "rdb_store_impl.h" #include "sqlite_connection.h" +#include "relational_store_manager.h" +#include "relational_store_delegate.h" using namespace testing::ext; using namespace OHOS::NativeRdb; @@ -142,6 +144,47 @@ HWTEST_F(RdbStoreImplTest, GetModifyTimeByRowIdTest_002, TestSize.Level2) RdbStoreImplTest::store->ExecuteSql("DROP TABLE IF EXISTS naturalbase_rdb_aux_rdbstoreimpltest_integer_log"); } + + +/* * + * @tc.name: GetModifyTimeByRowIdTest_002 + * @tc.desc: Abnormal testCase for GetModifyTime, get timestamp by id, + * resultSet is empty or table name is not exist + * @tc.type: FUNC + */ +HWTEST_F(RdbStoreImplTest, GetModifyTimeByRowIdTest_003, TestSize.Level2) +{ + RdbStoreImplTest::store->ExecuteSql("CREATE TABLE naturalbase_rdb_aux_rdbstoreimpltest_integer_log " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + int errorCode = RdbStoreImplTest::store->Insert(rowId, + "naturalbase_rdb_aux_rdbstoreimpltest_integer_log", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + + std::vector PKey = { 1 }; + std::map resultMap = + RdbStoreImplTest::store->GetModifyTime("rdbstoreimpltest_integer", "ROWID", PKey); + EXPECT_EQ(1, resultMap.size()); + + std::shared_ptr resultPtr = + RdbStoreImplTest::store->GetModifyTime("rdbstoreimpltest_integer", "ROWID", PKey); + int count = 0; + resultPtr->GetRowCount(count); + EXPECT_EQ(1, count); + + RdbStore::ModifyTime result = + RdbStoreImplTest::store->GetModifyTime("rdbstoreimpltest_integer", "ROWID", PKey); + RdbStore::PRIKey key = result.GetOriginKey(std::vector{}); + RdbStore::PRIKey monostate = std::monostate(); + EXPECT_EQ(monostate, key); + + RdbStoreImplTest::store->ExecuteSql("DROP TABLE IF EXISTS naturalbase_rdb_aux_rdbstoreimpltest_integer_log"); +} + /* * * @tc.name: GetModifyTime_001 * @tc.desc: Abnormal testCase for GetModifyTime, tablename columnName, keys is empty, @@ -484,3 +527,103 @@ HWTEST_F(RdbStoreImplTest, Rdb_SqlitConnectionPoolTest_0023, TestSize.Level2) delete connectionPool; } + +HWTEST_F(RdbStoreImplTest, NotifyDataChangeTest_001, TestSize.Level2) +{ + const std::string DATABASE_NAME = RDB_TEST_PATH + "SqlitConnectionOpenTest.db"; + int errCode = E_OK; + RdbStoreConfig config(DATABASE_NAME); + config.SetReadOnly(false); + config.SetPageSize(1024); + SqliteConnection* connection = SqliteConnection::Open(config, true, errCode); + EXPECT_NE(nullptr, connection); + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(nullptr, store); +} + +HWTEST_F(RdbStoreImplTest, NotifyDataChangeTest_002, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetPageSize(1024); + config.SetBundleName("callback.test2"); + config.SetSearchable(true); + config.SetStorageMode(StorageMode::MODE_DISK); + // register callback + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + EXPECT_NE(nullptr, store); + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t2;"); + store->ExecuteSql("CREATE TABLE if not exists test_callback_t2 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + // set TrackerTable + DistributedDB::TrackerSchema tracker; + tracker.tableName = "test_callback_t2"; + tracker.extendColName = ""; + tracker.trackerColNames = {"id", "timestamp"}; + DistributedDB::RelationalStoreManager rStoreManager("test_app", "test_user_id", 0); + DistributedDB::RelationalStoreDelegate::Option option; + DistributedDB::RelationalStoreDelegate *g_delegate = nullptr; + EXPECT_EQ(RdbStoreImplTest::DATABASE_NAME, "/data/test/stepResultSet_impl_test.db"); + int status = rStoreManager.OpenStore(RdbStoreImplTest::DATABASE_NAME, "test_callback_t2", option, g_delegate); + EXPECT_EQ(E_OK, status); + int setStatus = g_delegate->SetTrackerTable(tracker); + EXPECT_EQ(E_OK, setStatus); + + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + valuesBucket.PutInt("timestamp", ValueObject(1000000000)); + int errorCode = store->Insert(rowId, "test_callback_t2", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t2;"); +} + +HWTEST_F(RdbStoreImplTest, NotifyDataChangeTest_003, TestSize.Level2) +{ + int errCode = E_OK; + RdbStoreConfig config(RdbStoreImplTest::DATABASE_NAME); + config.SetReadOnly(false); + config.SetPageSize(1024); + config.SetBundleName("callback.test3"); + config.SetSearchable(true); + config.SetStorageMode(StorageMode::MODE_DISK); + + RdbStoreImplTestOpenCallback helper; + std::shared_ptr store = RdbHelper::GetRdbStore(config, 1, helper, errCode); + + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t3;"); + + store->ExecuteSql("CREATE TABLE if not exists test_callback_t3 " + "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " + "data3 FLOAT, data4 BLOB, data5 BOOLEAN);"); + // set TrackerTable + DistributedDB::TrackerSchema tracker; + tracker.tableName = "test_callback_t3"; + tracker.extendColName = ""; + tracker.trackerColNames = {"id", "timestamp"}; + DistributedDB::RelationalStoreManager rStoreManager("test_app", "test_user_id", 0); + DistributedDB::RelationalStoreDelegate::Option option; + DistributedDB::RelationalStoreDelegate *g_delegate = nullptr; + EXPECT_EQ(RdbStoreImplTest::DATABASE_NAME, "/data/test/stepResultSet_impl_test.db"); + int status = rStoreManager.OpenStore(RdbStoreImplTest::DATABASE_NAME, "test_callback_t3", option, g_delegate); + EXPECT_EQ(E_OK, status); + int setStatus = g_delegate->SetTrackerTable(tracker); + EXPECT_EQ(E_OK, setStatus); + + int64_t rowId; + ValuesBucket valuesBucket; + valuesBucket.PutInt("data_key", ValueObject(1)); + valuesBucket.PutInt("timestamp", ValueObject(1000000000)); + int errorCode = store->Insert(rowId, "test_callback_t3", valuesBucket); + EXPECT_EQ(E_OK, errorCode); + EXPECT_EQ(1, rowId); + errorCode = store->ExecuteSql("UPDATE test_callback_t3 SET timestamp = 100 WHERE id = 1;"); + EXPECT_EQ(E_OK, errorCode); + + store->ExecuteSql("DROP TABLE IF EXISTS test_callback_t3;"); +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp b/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp index 105f5b9b2c49330652032b8ec423697cac12a5e8..d4ce489f0f0f18cb8c473dbd9e9acbbef908d7d3 100644 --- a/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_transaction_test.cpp @@ -89,30 +89,6 @@ void RdbTransactionTest::TearDown(void) { } -struct RowData { - int id; - string name; - int age; - double salary; - std::vector blobType; -}; - -static RowData g_rowData[3] = { - {1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 }}, - {2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 }}, - {3, "wangyjing", 20, 300.5, std::vector{ 7, 8, 9 }} -}; - -static ValuesBucket InsertRowData(const RowData &rowData) -{ - ValuesBucket value; - value.PutInt("id", rowData.id); - value.PutString("name", rowData.name); - value.PutInt("age", rowData.age); - value.PutDouble("salary", rowData.salary); - value.PutBlob("blobType", rowData.blobType); - return value; -} /** * @tc.name: RdbStore_Transaction_001 @@ -127,15 +103,15 @@ HWTEST_F(RdbTransactionTest, RdbStore_Transaction_001, TestSize.Level1) int ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[0])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", InsertRowData(g_rowData[1])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - ret = store->Insert(id, "test", InsertRowData(g_rowData[2])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); @@ -166,15 +142,15 @@ HWTEST_F(RdbTransactionTest, RdbStore_Transaction_002, TestSize.Level1) int ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[0])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", InsertRowData(g_rowData[1])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - ret = store->Insert(id, "test", InsertRowData(g_rowData[2])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); @@ -213,15 +189,15 @@ HWTEST_F(RdbTransactionTest, RdbStore_Transaction_003, TestSize.Level1) int ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[0])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - ret = store->Insert(id, "test", InsertRowData(g_rowData[1])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); - ret = store->Insert(id, "test", InsertRowData(g_rowData[2])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); @@ -258,19 +234,19 @@ HWTEST_F(RdbTransactionTest, RdbStore_NestedTransaction_001, TestSize.Level1) int ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[0])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[1])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); ret = store->Commit(); // not commit EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[2])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); @@ -308,13 +284,13 @@ HWTEST_F(RdbTransactionTest, RdbStore_NestedTransaction_002, TestSize.Level1) int ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[0])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[1])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); ret = store->Commit(); @@ -322,7 +298,7 @@ HWTEST_F(RdbTransactionTest, RdbStore_NestedTransaction_002, TestSize.Level1) ret = store->Commit(); // commit EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[2])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); @@ -357,19 +333,19 @@ HWTEST_F(RdbTransactionTest, RdbStore_NestedTransaction_003, TestSize.Level1) int ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[0])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[1])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); ret = store->Commit(); // not commit EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[2])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); @@ -407,19 +383,19 @@ HWTEST_F(RdbTransactionTest, RdbStore_NestedTransaction_004, TestSize.Level1) int ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[0])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); ret = store->BeginTransaction(); EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[1])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); ret = store->Commit(); // commit EXPECT_EQ(ret, E_OK); - ret = store->Insert(id, "test", InsertRowData(g_rowData[2])); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[2])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(3, id); @@ -536,7 +512,7 @@ HWTEST_F(RdbTransactionTest, RdbStore_BatchInsert_003, TestSize.Level1) std::vector valuesBuckets; for (int i = 0; i < 100; i++) { RowData rowData1 = {id + i, name, age + i, salary + i, blob}; - ValuesBucket values = InsertRowData(rowData1); + ValuesBucket values = UTUtils::SetRowData(rowData1); valuesBuckets.push_back(std::move(values)); } @@ -553,7 +529,7 @@ HWTEST_F(RdbTransactionTest, RdbStore_BatchInsert_003, TestSize.Level1) valuesBuckets.clear(); for (int i = 50; i < 100; i++) { RowData rowData2 = {id + i, name, age + i, salary + i, blob}; - ValuesBucket values = InsertRowData(rowData2); + ValuesBucket values = UTUtils::SetRowData(rowData2); valuesBuckets.push_back(std::move(values)); } diff --git a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp index e01fd8cc60db12c9f24268fef7fb3b29114eadc3..04d8b46a756b9c0881ad749698d11d570d248439 100644 --- a/relational_store/test/native/rdb/unittest/rdb_update_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_update_test.cpp @@ -31,6 +31,8 @@ class RdbStoreUpdateTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); + static void ExpectValue(const std::shared_ptr &resultSet, + const RowData &expect); void SetUp(); void TearDown(); @@ -102,16 +104,11 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) { std::shared_ptr &store = RdbStoreUpdateTest::store; - int64_t id; ValuesBucket values; int changedRows; + int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); @@ -121,54 +118,17 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_Update_001, TestSize.Level1) values.PutInt("age", 20); values.PutDouble("salary", 200.5); values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Update(changedRows, "test", values, "id = ?", std::vector{ "1" }); + ret = store->Update(changedRows, "test", values, "id = ?", + std::vector{ "1" }); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToFirstRow(); EXPECT_EQ(ret, E_OK); - - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, intVal); - - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("lisi", strVal); - - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(20, intVal); - - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(200.5, dVal); - - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(4, blob[0]); - EXPECT_EQ(5, blob[1]); - EXPECT_EQ(6, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{2, "lisi", 20, 200.5, std::vector{ 4, 5, 6 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -190,22 +150,11 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_Update_002, TestSize.Level1) ValuesBucket values; int changedRows; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 20); - values.PutDouble("salary", 200.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - ret = store->Insert(id, "test", values); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); @@ -219,76 +168,13 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_Update_002, TestSize.Level1) std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(18, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(300.5, dVal); - - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(4, blob[0]); - EXPECT_EQ(5, blob[1]); - EXPECT_EQ(6, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{1, "zhangsan", 18, 300.5, std::vector{ 4, 5, 6 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("lisi", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(20, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(300.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(4, blob[0]); - EXPECT_EQ(5, blob[1]); - EXPECT_EQ(6, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{2, "lisi", 19, 300.5, std::vector{ 4, 5, 6 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -353,31 +239,19 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize { std::shared_ptr &store = RdbStoreUpdateTest::store; - int64_t id; ValuesBucket values; int changedRows; + int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 19); - values.PutDouble("salary", 200.5); - values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); // update lisi age=19 to wangjing age=20 - values.Clear(); values.PutInt("id", 3); values.PutString("name", std::string("wangjing")); values.PutInt("age", 20); @@ -390,73 +264,13 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_001, TestSize std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(18, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(100.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(1, blob[0]); - EXPECT_EQ(2, blob[1]); - EXPECT_EQ(3, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("wangjing", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(20, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(300.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(7, blob[0]); - EXPECT_EQ(8, blob[1]); - EXPECT_EQ(9, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{3, "wangjing", 20, 300.5, std::vector{ 7, 8, 9 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -474,110 +288,38 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_002, TestSize { std::shared_ptr &store = RdbStoreUpdateTest::store; - int64_t id; ValuesBucket values; int changedRows; + int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 19); - values.PutDouble("salary", 200.5); - values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); // update lisi age=19 to zhangsan age=20 - values.Clear(); values.PutInt("id", 3); values.PutString("name", std::string("zhangsan")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, - ConflictResolution::ON_CONFLICT_NONE); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", + std::vector{ "19" }, ConflictResolution::ON_CONFLICT_NONE); EXPECT_EQ(ret, RdbStoreUpdateTest::E_SQLITE_CONSTRAINT); std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(18, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(100.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(1, blob[0]); - EXPECT_EQ(2, blob[1]); - EXPECT_EQ(3, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("lisi", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(19, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(200.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(4, blob[0]); - EXPECT_EQ(5, blob[1]); - EXPECT_EQ(6, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -595,111 +337,39 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_003, TestSize { std::shared_ptr &store = RdbStoreUpdateTest::store; - int64_t id; ValuesBucket values; int changedRows; + int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 19); - values.PutDouble("salary", 200.5); - values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); // update lisi age=19 to wangjing age=20 - values.Clear(); values.PutInt("id", 3); values.PutString("name", std::string("wangjing")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, - ConflictResolution::ON_CONFLICT_ROLLBACK); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", + std::vector{ "19" }, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(18, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(100.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(1, blob[0]); - EXPECT_EQ(2, blob[1]); - EXPECT_EQ(3, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("wangjing", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(20, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(300.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(7, blob[0]); - EXPECT_EQ(8, blob[1]); - EXPECT_EQ(9, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{3, "wangjing", 20, 300.5, std::vector{ 7, 8, 9 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -717,110 +387,38 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_004, TestSize { std::shared_ptr &store = RdbStoreUpdateTest::store; - int64_t id; ValuesBucket values; int changedRows; + int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 19); - values.PutDouble("salary", 200.5); - values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); // update lisi age=19 to zhangsan age=20 - values.Clear(); values.PutInt("id", 3); values.PutString("name", std::string("zhangsan")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, - ConflictResolution::ON_CONFLICT_ROLLBACK); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", + std::vector{ "19" }, ConflictResolution::ON_CONFLICT_ROLLBACK); EXPECT_EQ(ret, RdbStoreUpdateTest::E_SQLITE_CONSTRAINT); std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(18, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(100.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(1, blob[0]); - EXPECT_EQ(2, blob[1]); - EXPECT_EQ(3, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("lisi", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(19, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(200.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(4, blob[0]); - EXPECT_EQ(5, blob[1]); - EXPECT_EQ(6, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{2, "lisi", 19, 200.5, std::vector{ 4, 5, 6 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -838,111 +436,39 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_005, TestSize { std::shared_ptr &store = RdbStoreUpdateTest::store; - int64_t id; ValuesBucket values; int changedRows; + int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 19); - values.PutDouble("salary", 200.5); - values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); // update lisi age=19 to wangjing age=20 - values.Clear(); values.PutInt("id", 3); values.PutString("name", std::string("wangjing")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); values.PutBlob("blobType", std::vector{ 7, 8, 9 }); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, - ConflictResolution::ON_CONFLICT_REPLACE); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", + std::vector{ "19" }, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, changedRows); std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(1, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(18, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(100.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(1, blob[0]); - EXPECT_EQ(2, blob[1]); - EXPECT_EQ(3, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{1, "zhangsan", 18, 100.5, std::vector{ 1, 2, 3 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("wangjing", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(20, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(300.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(7, blob[0]); - EXPECT_EQ(8, blob[1]); - EXPECT_EQ(9, blob[2]); + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{3, "wangjing", 20, 300.5, std::vector{ 7, 8, 9 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -960,78 +486,34 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateWithConflictResolution_006, TestSize { std::shared_ptr &store = RdbStoreUpdateTest::store; - int64_t id; ValuesBucket values; int changedRows; + int64_t id; - values.PutInt("id", 1); - values.PutString("name", std::string("zhangsan")); - values.PutInt("age", 18); - values.PutDouble("salary", 100.5); - values.PutBlob("blobType", std::vector{ 1, 2, 3 }); - int ret = store->Insert(id, "test", values); + int ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[0])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(1, id); - values.Clear(); - values.PutInt("id", 2); - values.PutString("name", std::string("lisi")); - values.PutInt("age", 19); - values.PutDouble("salary", 200.5); - values.PutBlob("blobType", std::vector{ 4, 5, 6 }); - ret = store->Insert(id, "test", values); + ret = store->Insert(id, "test", UTUtils::SetRowData(UTUtils::g_rowData[1])); EXPECT_EQ(ret, E_OK); EXPECT_EQ(2, id); // update lisi age=19 to zhangsan age=20 - values.Clear(); values.PutString("name", std::string("zhangsan")); values.PutInt("age", 20); values.PutDouble("salary", 300.5); - ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", std::vector{ "19" }, - ConflictResolution::ON_CONFLICT_REPLACE); + ret = store->UpdateWithConflictResolution(changedRows, "test", values, "age = ?", + std::vector{ "19" }, ConflictResolution::ON_CONFLICT_REPLACE); EXPECT_EQ(ret, E_OK); EXPECT_EQ(changedRows, 1); std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); - int columnIndex; - int intVal; - std::string strVal; - double dVal; - std::vector blob; - ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); - ret = resultSet->GetColumnIndex("id", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(2, intVal); - ret = resultSet->GetColumnIndex("name", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetString(columnIndex, strVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ("zhangsan", strVal); - ret = resultSet->GetColumnIndex("age", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetInt(columnIndex, intVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(20, intVal); - ret = resultSet->GetColumnIndex("salary", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetDouble(columnIndex, dVal); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(300.5, dVal); - ret = resultSet->GetColumnIndex("blobType", columnIndex); - EXPECT_EQ(ret, E_OK); - ret = resultSet->GetBlob(columnIndex, blob); - EXPECT_EQ(ret, E_OK); - EXPECT_EQ(3, static_cast(blob.size())); - EXPECT_EQ(4, blob[0]); - EXPECT_EQ(5, blob[1]); - EXPECT_EQ(6, blob[2]); + + RdbStoreUpdateTest::ExpectValue(resultSet, RowData{2, "zhangsan", 20, 300.5, std::vector{ 4, 5, 6 }}); ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_ERROR); @@ -1061,3 +543,54 @@ HWTEST_F(RdbStoreUpdateTest, RdbStore_UpdateSqlBuilder_001, TestSize.Level1) "", "", "", "", INT_MIN, INT_MIN, bindArgs, ConflictResolution::ON_CONFLICT_NONE); EXPECT_EQ(updateSql, "UPDATE test SET age=?,name=?,salary=?"); } + +void RdbStoreUpdateTest::ExpectValue(const std::shared_ptr &resultSet, + const RowData &expect) +{ + EXPECT_NE(nullptr, resultSet); + int columnIndex; + int intVal; + std::string strVal; + double dVal; + std::vector blob; + int ret; + + if (expect.id != -1) { + ret = resultSet->GetColumnIndex("id", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.id, intVal); + } + if (expect.name != "") { + ret = resultSet->GetColumnIndex("name", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetString(columnIndex, strVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.name, strVal); + } + if (expect.age != -1) { + ret = resultSet->GetColumnIndex("age", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetInt(columnIndex, intVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.age, intVal); + } + if (expect.salary != -1) { + ret = resultSet->GetColumnIndex("salary", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetDouble(columnIndex, dVal); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.salary, dVal); + } + if (expect.blobType.size() != 0) { + ret = resultSet->GetColumnIndex("blobType", columnIndex); + EXPECT_EQ(ret, E_OK); + ret = resultSet->GetBlob(columnIndex, blob); + EXPECT_EQ(ret, E_OK); + EXPECT_EQ(expect.blobType.size(), static_cast(blob.size())); + for (int i = 0; i < expect.blobType.size(); i++) { + EXPECT_EQ(expect.blobType[i], blob[i]); + } + } +} \ No newline at end of file diff --git a/relational_store/test/native/rdb/unittest/rdb_upgrade_test.cpp b/relational_store/test/native/rdb/unittest/rdb_upgrade_test.cpp index 9dee69ff79a32cb3c090bd16672520407f1da633..85ceefd8ed7d5fc488f7b0bd4d750a1c34a9dee6 100644 --- a/relational_store/test/native/rdb/unittest/rdb_upgrade_test.cpp +++ b/relational_store/test/native/rdb/unittest/rdb_upgrade_test.cpp @@ -113,11 +113,9 @@ void RdbUpgradeTest::TearDown(void) */ HWTEST_F(RdbUpgradeTest, RdbStore_Upgrade_001, TestSize.Level1) { - std::shared_ptr &store = RdbUpgradeTest::store; + RdbUpgradeTest::InsertValues(RdbUpgradeTest::store); - RdbUpgradeTest::InsertValues(store); - - std::shared_ptr resultSet = store->QuerySql("SELECT * FROM test"); + std::shared_ptr resultSet = RdbUpgradeTest::store->QuerySql("SELECT * FROM test"); EXPECT_NE(resultSet, nullptr); int ret = resultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); @@ -156,7 +154,6 @@ HWTEST_F(RdbUpgradeTest, RdbStore_Upgrade_001, TestSize.Level1) EXPECT_EQ(ret, E_OK); ret = upgradeResultSet->GetColumnIndex("address", columnIndex); EXPECT_EQ(ret, E_OK); - EXPECT_EQ(columnIndex, 5); ret = upgradeResultSet->GoToNextRow(); EXPECT_EQ(ret, E_OK); ret = upgradeResultSet->GoToNextRow(); diff --git a/relational_store/test/ndk/unittest/rdb_cursor_test.cpp b/relational_store/test/ndk/unittest/rdb_cursor_test.cpp index 41aa1140c4b3c35776b54e1a24eee493662cde57..9cbf4c6b6bada4ed10c78e2b6a31fc839f7c6be2 100644 --- a/relational_store/test/ndk/unittest/rdb_cursor_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_cursor_test.cpp @@ -405,8 +405,26 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_005, TestSize.Level1) errCode = cursor->getText(cursor, 0, data1Value, 0); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_ARGS); + predicates->destroy(predicates); + cursor->destroy(cursor); +} + +/** + * @tc.name: RDB_Native_cursor_test_006 + * @tc.desc: Normal testCase of cursor for anomalous branch. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_006, TestSize.Level1) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + + const char *columnNames[] = {"data1", "data2", "data3", "data4"}; + int len = sizeof(columnNames) / sizeof(columnNames[0]); + OH_Cursor *cursor = OH_Rdb_Query(cursorTestRdbStore_, predicates, columnNames, len); + EXPECT_NE(cursor, NULL); + int64_t data2Value; - errCode = cursor->getInt64(nullptr, 1, &data2Value); + int errCode = cursor->getInt64(nullptr, 1, &data2Value); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_ARGS); errCode = cursor->getInt64(cursor, 1, nullptr); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_ARGS); @@ -417,6 +435,7 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_005, TestSize.Level1) errCode = cursor->getReal(cursor, 2, nullptr); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_ARGS); + size_t size = 0; unsigned char data4Value[size]; errCode = cursor->getBlob(nullptr, 3, data4Value, size); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_ARGS); @@ -439,11 +458,11 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_005, TestSize.Level1) } /** - * @tc.name: RDB_Native_cursor_test_005 + * @tc.name: RDB_Native_cursor_test_007 * @tc.desc: Normal testCase of cursor for anomalous branch. * @tc.type: FUNC */ -HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_006, TestSize.Level1) +HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_007, TestSize.Level1) { int errCode = 0; OH_Predicates *predicates = OH_Rdb_CreatePredicates("asset_table"); @@ -467,11 +486,11 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_006, TestSize.Level1) } /** - * @tc.name: RDB_Native_cursor_test_005 + * @tc.name: RDB_Native_cursor_test_008 * @tc.desc: Normal testCase of cursor for anomalous branch. * @tc.type: FUNC */ -HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_007, TestSize.Level1) +HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_008, TestSize.Level1) { int errCode = 0; OH_Predicates *predicates = OH_Rdb_CreatePredicates("asset_table"); @@ -529,11 +548,11 @@ HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_007, TestSize.Level1) } /** - * @tc.name: RDB_Native_cursor_test_008 + * @tc.name: RDB_Native_cursor_test_009 * @tc.desc: Normal testCase of cursor for getAssets. * @tc.type: FUNC */ -HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_008, TestSize.Level1) +HWTEST_F(RdbNativeCursorTest, RDB_Native_cursor_test_009, TestSize.Level1) { int errCode = 0; OH_Predicates *predicates = OH_Rdb_CreatePredicates("asset_table"); diff --git a/relational_store/test/ndk/unittest/rdb_predicates_test.cpp b/relational_store/test/ndk/unittest/rdb_predicates_test.cpp index 2ae34ab7a45851dc489a9cd9336dc362103609c6..968c43822c0f98ad01b7f0510638509446338650 100644 --- a/relational_store/test/ndk/unittest/rdb_predicates_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_predicates_test.cpp @@ -187,7 +187,6 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_003, TestSize.Level EXPECT_EQ(rowCount, 2); cursor->goToNextRow(cursor); - int columnCount = 0; cursor->getColumnCount(cursor, &columnCount); EXPECT_EQ(columnCount, 6); @@ -220,29 +219,9 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_003, TestSize.Level EXPECT_EQ(strcmp(data5Value_1, "ABCDEFGH"), 0); cursor->goToNextRow(cursor); - cursor->getInt64(cursor, 0, &id); EXPECT_EQ(id, 3); - cursor->getSize(cursor, 1, &size); - char data1Value_1[size + 1]; - cursor->getText(cursor, 1, data1Value_1, size + 1); - EXPECT_EQ(strcmp(data1Value_1, "wangWu"), 0); - - cursor->getInt64(cursor, 2, &data2Value); - EXPECT_EQ(data2Value, 14800); - - cursor->getReal(cursor, 3, &data3Value); - EXPECT_EQ(data3Value, 300.1); - - cursor->isNull(cursor, 4, &isNull); - EXPECT_EQ(isNull, true); - - cursor->getSize(cursor, 5, &size); - char data5Value_2[size + 1]; - cursor->getText(cursor, 5, data5Value_2, size + 1); - EXPECT_EQ(strcmp(data5Value_2, "ABCDEFGHI"), 0); - valueObject->destroy(valueObject); predicates->destroy(predicates); cursor->destroy(cursor); @@ -684,6 +663,24 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_019, TestSize.Level predicates->between(predicates, "data2", valueObject); predicates->notBetween(predicates, "data2", valueObject); + valueObject->destroy(valueObject); + predicates->destroy(predicates); +} + +/** + * @tc.name: RDB_Native_predicates_test_020 + * @tc.desc: Normal testCase of Predicates for anomalous branch. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_020, TestSize.Level1) +{ + OH_Predicates *predicates = OH_Rdb_CreatePredicates("test"); + EXPECT_NE(predicates, NULL); + + OH_VObject *valueObject = OH_Rdb_CreateValueObject(); + const char *data1Value = "zhangSan"; + valueObject->putText(valueObject, data1Value); + const char *data5Value = "ABCDEFG"; valueObject->putText(valueObject, data5Value); predicates->greaterThan(nullptr, "data5", valueObject); @@ -707,7 +704,7 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_019, TestSize.Level predicates->offset(nullptr, 1); const char *columnNames[] = {"data1", "data2"}; - len = sizeof(columnNames) / sizeof(columnNames[0]); + uint32_t len = sizeof(columnNames) / sizeof(columnNames[0]); predicates->groupBy(nullptr, columnNames, len); predicates->groupBy(predicates, nullptr, len); predicates->groupBy(predicates, columnNames, 0); @@ -730,11 +727,11 @@ HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_019, TestSize.Level } /** - * @tc.name: RDB_Native_predicates_test_020 + * @tc.name: RDB_Native_predicates_test_021 * @tc.desc: Normal testCase of RelationalPredicatesObjects for anomalous branch. * @tc.type: FUNC */ -HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_020, TestSize.Level1) +HWTEST_F(RdbNativePredicatesTest, RDB_Native_predicates_test_021, TestSize.Level1) { OH_VObject *valueObject = OH_Rdb_CreateValueObject(); int64_t data2Value[] = {12000, 13000}; diff --git a/relational_store/test/ndk/unittest/rdb_store_test.cpp b/relational_store/test/ndk/unittest/rdb_store_test.cpp index 91285ba3ce69f2c9d92be643cd4c539f29f86eb1..8bf48ea763896d6fee0a07f0342af353320422d8 100644 --- a/relational_store/test/ndk/unittest/rdb_store_test.cpp +++ b/relational_store/test/ndk/unittest/rdb_store_test.cpp @@ -102,6 +102,27 @@ void RdbNativeStoreTest::SetUp(void) "data3 FLOAT, data4 BLOB, data5 TEXT);"; int errCode = OH_Rdb_Execute(storeTestRdbStore_, createTableSql); EXPECT_EQ(errCode, 0); + + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putInt64(valueBucket, "id", 1); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + valueBucket->putInt64(valueBucket, "data2", 12800); + valueBucket->putReal(valueBucket, "data3", 100.1); + uint8_t arr[] = { 1, 2, 3, 4, 5 }; + int len = sizeof(arr) / sizeof(arr[0]); + valueBucket->putBlob(valueBucket, "data4", arr, len); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); + errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); + EXPECT_EQ(errCode, 1); + + char querySql[] = "SELECT * FROM store_test"; + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); + + int rowCount = 0; + cursor->getRowCount(cursor, &rowCount); + EXPECT_EQ(rowCount, 1); + cursor->destroy(cursor); + valueBucket->destroy(valueBucket); } void RdbNativeStoreTest::TearDown(void) @@ -123,25 +144,13 @@ void CloudSyncCallback(Rdb_ProgressDetails *progressDetails) } /** * @tc.name: RDB_Native_store_test_001 - * @tc.desc: Normal testCase of store for Insert、Update、Query. + * @tc.desc: Normal testCase of store for Update、Query. * @tc.type: FUNC */ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_001, TestSize.Level1) { int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putInt64(valueBucket, "id", 1); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - - valueBucket->clear(valueBucket); + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); valueBucket->putText(valueBucket, "data1", "liSi"); valueBucket->putInt64(valueBucket, "data2", 13800); valueBucket->putReal(valueBucket, "data3", 200.1); @@ -204,19 +213,7 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_001, TestSize.Level1) HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_002, TestSize.Level1) { int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putInt64(valueBucket, "id", 1); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - - valueBucket->clear(valueBucket); + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); valueBucket->putInt64(valueBucket, "id", 2); valueBucket->putText(valueBucket, "data1", "liSi"); valueBucket->putInt64(valueBucket, "data2", 13800); @@ -282,19 +279,7 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_003, TestSize.Level1) OH_Rdb_BeginTransaction(storeTestRdbStore_); int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putInt64(valueBucket, "id", 1); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - - valueBucket->clear(valueBucket); + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); valueBucket->putInt64(valueBucket, "id", 2); valueBucket->putText(valueBucket, "data1", "liSi"); valueBucket->putInt64(valueBucket, "data2", 13800); @@ -326,19 +311,7 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_004, TestSize.Level1) OH_Rdb_BeginTransaction(storeTestRdbStore_); int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putInt64(valueBucket, "id", 1); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - - valueBucket->clear(valueBucket); + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); valueBucket->putInt64(valueBucket, "id", 2); valueBucket->putText(valueBucket, "data1", "liSi"); valueBucket->putInt64(valueBucket, "data2", 13800); @@ -354,7 +327,7 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_004, TestSize.Level1) int rowCount = 0; cursor->getRowCount(cursor, &rowCount); - EXPECT_EQ(rowCount, 0); + EXPECT_EQ(rowCount, 1); // 回退至函数之前的状态 valueBucket->destroy(valueBucket); cursor->destroy(cursor); @@ -367,28 +340,13 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_004, TestSize.Level1) */ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_005, TestSize.Level1) { - int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); valueBucket->putText(valueBucket, "data1", "zhangSan"); valueBucket->putInt64(valueBucket, "data2", 12800); valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - - char querySql[] = "SELECT * FROM store_test"; - OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); - - int rowCount = 0; - cursor->getRowCount(cursor, &rowCount); - EXPECT_EQ(rowCount, 1); - cursor->destroy(cursor); std::string backupPath1 = RDB_TEST_PATH + std::string("a.db"); - errCode = OH_Rdb_Backup(storeTestRdbStore_, backupPath1.c_str()); + int errCode = OH_Rdb_Backup(storeTestRdbStore_, backupPath1.c_str()); EXPECT_EQ(errCode, 0); errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); @@ -411,7 +369,9 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_005, TestSize.Level1) errCode = OH_Rdb_Restore(storeTestRdbStore_, backupPath1.c_str()); EXPECT_EQ(errCode, 0); - cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); + char querySql[] = "SELECT * FROM store_test"; + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); + int rowCount = 0; cursor->getRowCount(cursor, &rowCount); EXPECT_EQ(rowCount, 1); cursor->destroy(cursor); @@ -449,17 +409,6 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_005, TestSize.Level1) HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_006, TestSize.Level1) { int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - char querySql[] = "SELECT * FROM store_test"; OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); @@ -481,15 +430,37 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_006, TestSize.Level1) std::string restorePath = "error.db"; errCode = OH_Rdb_Restore(storeTestRdbStore_, restorePath.c_str()); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_FILE_PATH); +} + + +/** + * @tc.name: RDB_Native_store_test_007 + * @tc.desc: Normal testCase of store for Backup、Restore. + * @tc.type: FUNC + */ +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_007, TestSize.Level1) +{ + int errCode = 0; + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); + valueBucket->putText(valueBucket, "data1", "zhangSan"); + valueBucket->putInt64(valueBucket, "data2", 12800); + valueBucket->putReal(valueBucket, "data3", 100.1); + uint8_t arr[] = {1, 2, 3, 4, 5}; + int len = sizeof(arr) / sizeof(arr[0]); + valueBucket->putBlob(valueBucket, "data4", arr, len); + valueBucket->putText(valueBucket, "data5", "ABCDEFG"); errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); EXPECT_EQ(errCode, 2); - backupPath = " "; + std::string backupPath = " "; errCode = OH_Rdb_Backup(storeTestRdbStore_, backupPath.c_str()); EXPECT_EQ(errCode, 0); errCode = OH_Rdb_Restore(storeTestRdbStore_, backupPath.c_str()); EXPECT_EQ(errCode, 0); - cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); + char querySql[] = "SELECT * FROM store_test"; + OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); + + int rowCount = 0; cursor->getRowCount(cursor, &rowCount); EXPECT_EQ(rowCount, 2); cursor->destroy(cursor); @@ -506,7 +477,7 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_006, TestSize.Level1) errCode = OH_Rdb_Backup(storeTestRdbStore_, backupPath.c_str()); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_FILE_PATH); - restorePath = RDB_TEST_PATH; + std::string restorePath = RDB_TEST_PATH; errCode = OH_Rdb_Restore(storeTestRdbStore_, restorePath.c_str()); EXPECT_EQ(errCode, OH_Rdb_ErrCode::RDB_E_INVALID_FILE_PATH); @@ -514,11 +485,11 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_006, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_007 + * @tc.name: RDB_Native_store_test_008 * @tc.desc: Normal testCase of store for GetVersion、SetVersion. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_007, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_008, TestSize.Level1) { int errCode = 0; int version = 0; @@ -534,26 +505,14 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_007, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_008 + * @tc.name: RDB_Native_store_test_009 * @tc.desc: Normal testCase of store for Insert with wrong table name or table is NULL. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_008, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_009, TestSize.Level1) { int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putInt64(valueBucket, "id", 1); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - - valueBucket->clear(valueBucket); + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); valueBucket->putInt64(valueBucket, "id", 2); valueBucket->putText(valueBucket, "data1", "liSi"); valueBucket->putInt64(valueBucket, "data2", 13800); @@ -584,30 +543,16 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_008, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_009 + * @tc.name: RDB_Native_store_test_0010 * @tc.desc: Normal testCase of store for Update with wrong table or table is NULL. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_009, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_0010, TestSize.Level1) { int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putInt64(valueBucket, "id", 1); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - - valueBucket->clear(valueBucket); + OH_VBucket* valueBucket = OH_Rdb_CreateValuesBucket(); valueBucket->putText(valueBucket, "data1", "liSi"); valueBucket->putInt64(valueBucket, "data2", 13800); - valueBucket->putReal(valueBucket, "data3", 200.1); - valueBucket->putNull(valueBucket, "data5"); OH_Predicates *predicates = OH_Rdb_CreatePredicates("wrong"); OH_VObject *valueObject = OH_Rdb_CreateValueObject(); @@ -654,11 +599,6 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_009, TestSize.Level1) EXPECT_EQ(data4Value[0], 1); EXPECT_EQ(data4Value[1], 2); - cursor->getSize(cursor, 5, &size); - char data5Value[size + 1]; - cursor->getText(cursor, 5, data5Value, size + 1); - EXPECT_EQ(strcmp(data5Value, "ABCDEFG"), 0); - valueObject->destroy(valueObject); predicates->destroy(predicates); predicates2->destroy(predicates2); @@ -667,38 +607,23 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_009, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_010 + * @tc.name: RDB_Native_store_test_011 * @tc.desc: Normal testCase of store for querysql is NULL. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_010, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_011, TestSize.Level1) { - int errCode = 0; - OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); - valueBucket->putInt64(valueBucket, "id", 1); - valueBucket->putText(valueBucket, "data1", "zhangSan"); - valueBucket->putInt64(valueBucket, "data2", 12800); - valueBucket->putReal(valueBucket, "data3", 100.1); - uint8_t arr[] = { 1, 2, 3, 4, 5 }; - int len = sizeof(arr) / sizeof(arr[0]); - valueBucket->putBlob(valueBucket, "data4", arr, len); - valueBucket->putText(valueBucket, "data5", "ABCDEFG"); - errCode = OH_Rdb_Insert(storeTestRdbStore_, "store_test", valueBucket); - EXPECT_EQ(errCode, 1); - char *querySql = NULL; OH_Cursor *cursor = OH_Rdb_ExecuteQuery(storeTestRdbStore_, querySql); EXPECT_EQ(cursor, NULL); - - valueBucket->destroy(valueBucket); } /** - * @tc.name: RDB_Native_store_test_011 + * @tc.name: RDB_Native_store_test_012 * @tc.desc: Normal testCase of RelationalValuesBucket for anomalous branch. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_011, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_012, TestSize.Level1) { OH_VBucket *valueBucket = OH_Rdb_CreateValuesBucket(); uint8_t arr[] = { 1, 2, 3, 4, 5 }; @@ -718,11 +643,11 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_011, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_012 + * @tc.name: RDB_Native_store_test_013 * @tc.desc: Normal testCase of store for CloudSync. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_012, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_013, TestSize.Level1) { EXPECT_NE(storeTestRdbStore_, nullptr); constexpr int TABLE_COUNT = 1; @@ -748,11 +673,11 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_012, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_013 + * @tc.name: RDB_Native_store_test_014 * @tc.desc: Abnormal testCase of store for SetDistributedTables. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_013, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_014, TestSize.Level1) { EXPECT_NE(storeTestRdbStore_, nullptr); Rdb_DistributedConfig config{ .version = 0, .isAutoSync = true }; @@ -769,11 +694,11 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_013, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_014 + * @tc.name: RDB_Native_store_test_015 * @tc.desc: Normal testCase of store for CloudSync. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_014, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_015, TestSize.Level1) { EXPECT_NE(storeTestRdbStore_, nullptr); constexpr int TABLE_COUNT = 1; @@ -794,11 +719,11 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_014, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_015 + * @tc.name: RDB_Native_store_test_016 * @tc.desc: Abnormal testCase of store for CloudSync. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_015, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_016, TestSize.Level1) { EXPECT_NE(storeTestRdbStore_, nullptr); constexpr int TABLE_COUNT = 1; @@ -813,11 +738,11 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_015, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_016 + * @tc.name: RDB_Native_store_test_017 * @tc.desc: Normal testCase for GetModifyTime. * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_016, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_017, TestSize.Level1) { char createLogTableSql[] = "CREATE TABLE if not exists naturalbase_rdb_aux_rdbstoreimpltest_integer_log " "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " @@ -857,12 +782,12 @@ HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_016, TestSize.Level1) } /** - * @tc.name: RDB_Native_store_test_017 + * @tc.name: RDB_Native_store_test_018 * @tc.desc: Abnormal testCase for GetModifyTime, tablename columnName, keys is empty, * and resultSet is null or empty * @tc.type: FUNC */ -HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_017, TestSize.Level1) +HWTEST_F(RdbNativeStoreTest, RDB_Native_store_test_018, TestSize.Level1) { char createLogTableSql[] = "CREATE TABLE if not exists naturalbase_rdb_aux_rdbstoreimpltest_integer_log " "(id INTEGER PRIMARY KEY AUTOINCREMENT, timestamp INTEGER, data_key INTEGER, " diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7e58aea4265144e6cab5659cf29cfec79f7f7730..730a2c065182a4caa1eaa5e4a86f776faef96e13 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -142,6 +142,7 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../udmf/framework/innerkitsimpl add_executable(UdmfTest ${UdmfTestSrc} ${mainSrc} ${serviceSrc}) target_link_libraries(UdmfTest ${links} gtest_main gcov udmf) target_include_directories(UdmfTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../udmf/framework/common) +target_include_directories(UdmfTest PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../udmf/framework/innerkitsimpl/data) #************************************************UdmfTest end************************************************# aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/../datamgr_service/services/distributeddataservice/service/test/mock CloudTestSrc) diff --git a/test/service/load_service.cpp b/test/service/load_service.cpp index 7022eaaa6763d4b5481a45a23e565a2d8b29dc52..5cc248624d96b3df62288598e9566003db4344d7 100644 --- a/test/service/load_service.cpp +++ b/test/service/load_service.cpp @@ -15,11 +15,11 @@ #include "../load_service.h" //#include "store_factory.h" -#include "uninstaller/uninstaller.h" +#include "installer/installer.h" LoadService::LoadService() { // OHOS::DistributedKv::StoreFactory::GetInstance(); - OHOS::DistributedKv::Uninstaller::GetInstance(); + OHOS::DistributedKv::Installer::GetInstance(); } LoadService::~LoadService() { diff --git a/udmf/CMakeLists.txt b/udmf/CMakeLists.txt index 1108af541335c4acf93e4d92deb9c3f05a96982f..5186b532babf335890743296849ffbfb042ec745 100644 --- a/udmf/CMakeLists.txt +++ b/udmf/CMakeLists.txt @@ -15,13 +15,15 @@ aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/common udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/client udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/common udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/data udmf_src) +aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/service udmf_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/common udmf_channel_src) aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/jskitsimpl/data udmf_channel_src) list(REMOVE_ITEM udmf_channel_src "${CMAKE_CURRENT_SOURCE_DIR}/frameworks/jskitsimpl/data/uniform_type_descriptor_napi.cpp") aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/framework/service udmf_src) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/common) -include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/service) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/service) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/framework/innerkitsimpl/data) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/jskits/common) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/interfaces/jskits/data) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../kv_store/frameworks/common) diff --git a/udmf/README_zh.md b/udmf/README_zh.md index 24cd95f3f9394bf9d3ee53f7f11855472cbb0def..19153e83c8253eb6dcfd27ae9b3d3a943f5671b5 100644 --- a/udmf/README_zh.md +++ b/udmf/README_zh.md @@ -68,12 +68,12 @@ foundation/distributeddatamgr/udmf # udmf统一数据管理部件 │ │ ├── client # native客户端 │ │ ├── common # native接口公共工具类 │ │ ├── data # 数据结构定义 +│ │ ├── service # 服务模块 │ │ └── test # 测试目录 │ ├── jskitsimpl # js接口具体实现 │ │ ├── common # js接口公共工具类 │ │ |── data # 统一数据公共接口实现 | | └── unittest # js单元测试目录 -│ └── service # 服务模块 ├── interfaces # udmf对外接口声明 │ ├── innerkits # nativie接口声明 │ │ ├── client # client接口声明 diff --git a/udmf/bundle.json b/udmf/bundle.json index 6e27f3c85ca9cdc5f87c46f7560193926dda4ca7..3b168f9bfc992a32d3475461ec9aa150fa1acaba 100644 --- a/udmf/bundle.json +++ b/udmf/bundle.json @@ -38,6 +38,7 @@ ], "third_party": [ "bounds_checking_function", + "cJSON", "googletest" ] }, @@ -50,7 +51,8 @@ "name": "//foundation/distributeddatamgr/udmf/interfaces/innerkits:udmf_client", "header": { "header_files": [ - "udmf_client.h" + "udmf_client.h", + "utd_client.h" ], "header_base":"//foundation/distributeddatamgr/udmf/interfaces/innerkits/client" } @@ -85,6 +87,7 @@ "system_defined_pixelmap.h", "system_defined_record.h", "text.h", + "type_descriptor.h", "unified_data.h", "unified_record.h", "video.h" diff --git a/udmf/framework/common/custom_utd_json_parser.cpp b/udmf/framework/common/custom_utd_json_parser.cpp new file mode 100644 index 0000000000000000000000000000000000000000..21ec78e716ac18dd588040af40377527285296c5 --- /dev/null +++ b/udmf/framework/common/custom_utd_json_parser.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "custom_utd_json_parser.h" +#include +#include +#include "error_code.h" +#include "logger.h" +namespace OHOS { +namespace UDMF { +constexpr const char* TYPEID = "typeId"; +constexpr const char* BELONGINGTOTYPES = "belongingToTypes"; +constexpr const char* FILE_NAME_EXTENSTENSIONS = "filenameExtensions"; +constexpr const char* MIME_TYPES = "mimeTypes"; +constexpr const char* DESCRIPTION = "description"; +constexpr const char* REFERENCE_URL = "referenceURL"; +constexpr const char* ICON_FILE = "iconFile"; +constexpr const char* OWNER = "ownerBundle"; +constexpr const char* INSTALLERS = "installerBundles"; + +CustomUtdJsonParser::CustomUtdJsonParser() +{ +} + +CustomUtdJsonParser::~CustomUtdJsonParser() +{ +} + +bool CustomUtdJsonParser::ParseStoredCustomUtdJson(const std::string &jsonData, + std::vector &typesCfg) +{ + if (jsonData.empty()) { + return false; + } + + cJSON* jsonRoot = cJSON_Parse(jsonData.c_str()); + if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { + GetTypeDescriptors(*jsonRoot, UTD_CUSTOM, typesCfg); + } + cJSON_Delete(jsonRoot); + return true; +} + +bool CustomUtdJsonParser::ParseUserCustomUtdJson(const std::string &jsonData, + std::vector &typesDeclarations, + std::vector &typesReference) +{ + if (jsonData.empty()) { + return false; + } + // parse utd-adt.json to TypeDescriptorCfg obj + cJSON* jsonRoot = cJSON_Parse(jsonData.c_str()); + if (jsonRoot != NULL && cJSON_IsObject(jsonRoot)) { + GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_DECLAEEARION, typesDeclarations); + GetTypeDescriptors(*jsonRoot, UTD_CUSTOM_REFERENCE, typesReference); + } + cJSON_Delete(jsonRoot); + return true; +} + +bool CustomUtdJsonParser::ConvertUtdCfgsToJson(std::vector &typesCfg, std::string &jsonData) +{ + json* root = cJSON_CreateObject(); + json* CustomUTDs = cJSON_CreateArray(); + for (auto utdTypeCfg : typesCfg) { + json* jsonItem = cJSON_CreateObject(); + cJSON_AddStringToObject(jsonItem, TYPEID, utdTypeCfg.typeId.c_str()); + std::vector belongingToTypes(utdTypeCfg.belongingToTypes.begin(), + utdTypeCfg.belongingToTypes.end()); + AddJsonStringArray(belongingToTypes, BELONGINGTOTYPES, *jsonItem); + AddJsonStringArray(utdTypeCfg.filenameExtensions, FILE_NAME_EXTENSTENSIONS, *jsonItem); + AddJsonStringArray(utdTypeCfg.mimeTypes, MIME_TYPES, *jsonItem); + cJSON_AddStringToObject(jsonItem, DESCRIPTION, utdTypeCfg.description.c_str()); + cJSON_AddStringToObject(jsonItem, REFERENCE_URL, utdTypeCfg.referenceURL.c_str()); + cJSON_AddStringToObject(jsonItem, ICON_FILE, utdTypeCfg.iconFile.c_str()); + cJSON_AddStringToObject(jsonItem, OWNER, utdTypeCfg.ownerBundle.c_str()); + std::vector installerBundles(utdTypeCfg.installerBundles.begin(), + utdTypeCfg.installerBundles.end()); + AddJsonStringArray(installerBundles, INSTALLERS, *jsonItem); + + cJSON_AddItemToArray(CustomUTDs, jsonItem); + } + cJSON_AddItemToObject(root, UTD_CUSTOM, CustomUTDs); + + jsonData = cJSON_Print(root); + LOG_DEBUG(UDMF_CLIENT, "ConvertUtdCfgsToJson, jsonData size: %{public}zu.", jsonData.length()); + return true; +} + +bool CustomUtdJsonParser::AddJsonStringArray(std::vector &datas, const std::string &nodeName, json &node) +{ + json *arrayNode = cJSON_AddArrayToObject(&node, nodeName.c_str()); + for (const auto &data : datas) { + json* item = cJSON_CreateString(data.c_str()); + cJSON_AddItemToArray(arrayNode, item); + } + return true; +} + +bool CustomUtdJsonParser::GetTypeDescriptors(const json &jsonRoot, const std::string &nodeName, + std::vector &typesCfgs) +{ + if (cJSON_HasObjectItem(&jsonRoot, nodeName.c_str())) { + cJSON *subNode = cJSON_GetObjectItem(&jsonRoot, nodeName.c_str()); + int itemNum = cJSON_GetArraySize(subNode); + for (int i = 0; i < itemNum; i++) { + cJSON *node = cJSON_GetArrayItem(subNode, i); + TypeDescriptorCfg typeCfg; + typeCfg.typeId = GetStringValue(*node, TYPEID); + std::vector belongingToTypes = GetStringArrayValue(*node, BELONGINGTOTYPES); + typeCfg.belongingToTypes.insert(belongingToTypes.begin(), belongingToTypes.end()); + typeCfg.filenameExtensions = GetStringArrayValue(*node, FILE_NAME_EXTENSTENSIONS); + typeCfg.mimeTypes = GetStringArrayValue(*node, MIME_TYPES); + typeCfg.description = GetStringValue(*node, DESCRIPTION); + typeCfg.referenceURL = GetStringValue(*node, REFERENCE_URL); + typeCfg.iconFile = GetStringValue(*node, ICON_FILE); + typeCfg.ownerBundle = GetStringValue(*node, OWNER); + std::vector installerBundles = GetStringArrayValue(*node, INSTALLERS); + typeCfg.installerBundles.insert(installerBundles.begin(), installerBundles.end()); + typesCfgs.push_back(typeCfg); + } + } + return true; +} + +std::string CustomUtdJsonParser::GetStringValue(const json &node, const std::string &nodeName) +{ + std::string value; + if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) { + cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str()); + if (cJSON_IsString(subNode)) { + value = cJSON_GetStringValue(subNode); + } + } + return value; +} + +std::vector CustomUtdJsonParser::GetStringArrayValue(const json &node, const std::string &nodeName) +{ + std::vector values; + if (!cJSON_IsNull(&node) && cJSON_IsObject(&node) && cJSON_HasObjectItem(&node, nodeName.c_str())) { + cJSON *subNode = cJSON_GetObjectItem(&node, nodeName.c_str()); + if (cJSON_IsNull(subNode) || !cJSON_IsArray(subNode)) { + return values; + } + for (int i = 0; i < cJSON_GetArraySize(subNode); i++) { + json *item = cJSON_GetArrayItem(subNode, i); + if (cJSON_IsString(item)) { + values.emplace_back(cJSON_GetStringValue(item)); + } + } + } + return values; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/custom_utd_json_parser.h b/udmf/framework/common/custom_utd_json_parser.h new file mode 100644 index 0000000000000000000000000000000000000000..2ce4eeb22545a427916e140633e23f5ab42ab188 --- /dev/null +++ b/udmf/framework/common/custom_utd_json_parser.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_CUSTOM_UTD_JSON_PARSER_H +#define UDMF_CUSTOM_UTD_JSON_PARSER_H +#include +#include +#include +#include +#include +#include "visibility.h" +#include "cJSON.h" +#include "utd_common.h" +namespace OHOS { +namespace UDMF { +class CustomUtdJsonParser { +public: + using json = cJSON; + CustomUtdJsonParser(); + ~CustomUtdJsonParser(); + bool ParseStoredCustomUtdJson(const std::string &jsonData, std::vector &typesCfg); + bool ParseUserCustomUtdJson(const std::string &jsonData, std::vector &typesDeclarations, + std::vector &typesReference); + bool ConvertUtdCfgsToJson(std::vector &typesCfg, std::string &jsonData); + +private: + bool AddJsonStringArray(std::vector &datas, const std::string &nodeName, json &node); + bool GetTypeDescriptors(const json &jsonRoot, const std::string &nodeName, + std::vector &typesCfg); + std::string GetStringValue(const json &subNode, const std::string &nodeName); + std::vector GetStringArrayValue(const json &node, const std::string &nodeName); +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_CUSTOM_UTD_JSON_PARSER_H \ No newline at end of file diff --git a/udmf/framework/common/custom_utd_store.cpp b/udmf/framework/common/custom_utd_store.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3b7388977ceeca4cebf75a414c1cc1bfaa22df50 --- /dev/null +++ b/udmf/framework/common/custom_utd_store.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "custom_utd_store.h" +#include +#include +#include +#include "unistd.h" +#include "logger.h" +namespace OHOS { +namespace UDMF { +constexpr const char* UTD_CFG_FILE = "utd-adt.json"; + +CustomUtdStore::CustomUtdStore() +{ +} + +CustomUtdStore::~CustomUtdStore() +{ +} + +CustomUtdStore &CustomUtdStore::GetInstance() +{ + static CustomUtdStore utdCustomPersistence; + return utdCustomPersistence; +} + +std::vector CustomUtdStore::GetTypeCfgs(const std::string &cfgFilePath) +{ + LOG_DEBUG(UDMF_CLIENT, "get utdcustom from cfg, Path:%{public}s.", cfgFilePath.c_str()); + std::string jsonStr; + std::ifstream fin(cfgFilePath); + while (fin.good()) { + std::string line; + std::getline(fin, line); + jsonStr += line; + } + std::vector customUtdTypes; + utdJsonParser_.ParseStoredCustomUtdJson(jsonStr, customUtdTypes); + LOG_DEBUG(UDMF_CLIENT, "GetTypeCfgs, customUtdTypes total:%{public}zu.", customUtdTypes.size()); + return customUtdTypes; +} + +int32_t CustomUtdStore::SaveTypeCfgs(std::vector &customUtdTypes, const std::string &cfgFilePath) +{ + std::string jsonData; + std::string cfgFileName = UTD_CFG_FILE; + std::string cfgFileDir = cfgFilePath.substr(0, cfgFilePath.length() - cfgFileName.length()); + if (utdJsonParser_.ConvertUtdCfgsToJson(customUtdTypes, jsonData) && CreateDirectory(cfgFileDir)) { + SavaCfgFile(jsonData, cfgFilePath); + } + return 0; +} + +int32_t CustomUtdStore::SavaCfgFile(const std::string &jsonData, const std::string cfgFilePath) +{ + std::ofstream ofs; + LOG_DEBUG(UDMF_CLIENT, "set cfg start, path:%{public}s ", cfgFilePath.c_str()); + ofs.open(cfgFilePath, std::ios_base::ate); + LOG_DEBUG(UDMF_CLIENT, "set cfg, is_open= %{public}d", ofs.is_open()); + ofs << jsonData << std::endl; + ofs.close(); + LOG_DEBUG(UDMF_CLIENT, "set cfg end."); + return 0; +} + +bool CustomUtdStore::CreateDirectory(const std::string &path) const +{ + LOG_DEBUG(UDMF_CLIENT, "CreateDirectory start, path:%{public}s ", path.c_str()); + if (access(path.c_str(), F_OK) == 0) { + return true; + } + + std::string::size_type index = 0; + do { + std::string subPath; + index = path.find('/', index + 1); + if (index == std::string::npos) { + subPath = path; + } else { + subPath = path.substr(0, index); + } + + if (access(subPath.c_str(), F_OK) != 0) { + if (mkdir(subPath.c_str(), (S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) != 0) { + LOG_WARN(UDMF_CLIENT, "CreateDirectory, fail. path:%{public}s, subPath:%{public}s.", + path.c_str(), subPath.c_str()); + return false; + } + } + } while (index != std::string::npos); + + return access(path.c_str(), F_OK) == 0; +} +} // namespace UDMF +} // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/common/custom_utd_store.h b/udmf/framework/common/custom_utd_store.h new file mode 100644 index 0000000000000000000000000000000000000000..6e6dad41b75cc439c7cdefb261ebac7d27880525 --- /dev/null +++ b/udmf/framework/common/custom_utd_store.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_CUSTOM_UTD_STORE_H +#define UDMF_CUSTOM_UTD_STORE_H +#include +#include +#include +#include +#include +#include "visibility.h" +#include "utd_common.h" +#include "custom_utd_json_parser.h" +namespace OHOS { +namespace UDMF { +class CustomUtdStore { +public: + static CustomUtdStore &GetInstance(); + std::vector GetTypeCfgs(const std::string &cfgFilePath); + int32_t SaveTypeCfgs(std::vector &customUtdTypes, const std::string &cfgFilePath); + +private: + CustomUtdStore(); + ~CustomUtdStore(); + int32_t SavaCfgFile(const std::string &jsonData, const std::string cfgFilePath); + bool CreateDirectory(const std::string &path) const; + + CustomUtdJsonParser utdJsonParser_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_CUSTOM_UTD_STORE_H \ No newline at end of file diff --git a/udmf/framework/common/graph.cpp b/udmf/framework/common/graph.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e9d740fc888a4f83310f0d4299720a2458b6bf02 --- /dev/null +++ b/udmf/framework/common/graph.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include "graph.h" +namespace OHOS { +namespace UDMF { +Graph::Graph(uint32_t vertexNum):vertexNum_(vertexNum) +{ + for (uint32_t node = 0; node < vertexNum_; node++) { + adjList_.push_back({node, nullptr}); + } + visited_.resize(vertexNum_); + fill(visited_.begin(), visited_.end(), 0); +} + +void Graph::AddEdge(uint32_t start, uint32_t end) +{ + EdgeNode *edge = new EdgeNode; // add new edge + edge->adjIndex = end; + edge->next = adjList_[start].firstEdge; + adjList_[start].firstEdge = edge; +} + +bool Graph::Dfs(uint32_t startNode, Action action, bool isInit) +{ + if (isInit) { + visited_.resize(vertexNum_); + fill(visited_.begin(), visited_.end(), 0); + } + std::stack nodes; + EdgeNode *edge = nullptr; + visited_[startNode] = 1; + nodes.push(startNode); + result_.push_back(startNode); + if (action(adjList_[startNode].value)) { + return true; + } + while (!nodes.empty()) { + edge = adjList_[nodes.top()].firstEdge; + while (edge) { + if (visited_[edge->adjIndex] == 0) { + visited_[edge->adjIndex] = 1; + if (adjList_[edge->adjIndex].firstEdge != nullptr) { + auto iter = find(result_.begin(), result_.end(), adjList_[edge->adjIndex].firstEdge->adjIndex); + if (iter != result_.end() && visited_[adjList_[edge->adjIndex].firstEdge->adjIndex] == 1) { + return false; // current node, iscycle + } + } + if (action(adjList_[edge->adjIndex].value)) { + return true; + } + result_.push_back(startNode); + nodes.push(edge->adjIndex); + edge = adjList_[edge->adjIndex].firstEdge; + } else { + edge = edge->next; + } + } + if (edge == nullptr) { + visited_[nodes.top()] = 2; // 2: all edge of the adj is visited. + nodes.pop(); + } + } + return true; +} + +bool Graph::DfsUnconnectedGraph(Action action) +{ + visited_.resize(vertexNum_); + fill(visited_.begin(), visited_.end(), 0); + result_.clear(); + for (uint32_t node = 0; node < vertexNum_; node++) { + if (!visited_[node]) { + if (!Dfs(node, action, false)) { + return false; + } + } + } + return true; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/common/graph.h b/udmf/framework/common/graph.h new file mode 100644 index 0000000000000000000000000000000000000000..39b58f5c258bdb90535428dfec9cdb8d45ceb026 --- /dev/null +++ b/udmf/framework/common/graph.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_GRAPH_H +#define UDMF_GRAPH_H + +#include +#include +#include +#include +#include + +namespace OHOS { +namespace UDMF { +struct EdgeNode { + uint32_t adjIndex; + EdgeNode* next; +}; + +struct VertexNode { + uint32_t value; + EdgeNode* firstEdge; +}; +class Graph { +public: + explicit Graph(uint32_t vertexNum); + using Action = std::function; + void AddEdge(uint32_t start, uint32_t end); + bool Dfs(uint32_t startNode, Action action, bool isInit = true); + bool DfsUnconnectedGraph(Action action); +private: + uint32_t vertexNum_; + std::vector adjList_; // Adjacency List + std::vector visited_; // Determine whether the vertex has been accessed, index=vertex value + std::vector result_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_GRAPH_H diff --git a/udmf/framework/common/tlv_util.cpp b/udmf/framework/common/tlv_util.cpp index f70232917a7c8baaff3223d3f9459d36b381d32c..65a630538247a2d4e2ee12f72ca1f35eebb1a12c 100644 --- a/udmf/framework/common/tlv_util.cpp +++ b/udmf/framework/common/tlv_util.cpp @@ -390,7 +390,7 @@ bool Reading(UDType &output, TLVObject &data) if (!Reading(type, data)) { return false; } - if (type < UDType::TEXT || type >= UDType::UD_BUTT) { + if (type < UDType::ENTITY || type >= UDType::UD_BUTT) { return false; } output = static_cast(type); diff --git a/udmf/framework/common/udmf_types_util.cpp b/udmf/framework/common/udmf_types_util.cpp index 261eb14300ce7e51d0e2f590392f2d9feab80222..1288cf358fb964e546154e2d89e822883128e7ff 100644 --- a/udmf/framework/common/udmf_types_util.cpp +++ b/udmf/framework/common/udmf_types_util.cpp @@ -164,7 +164,7 @@ bool Unmarshalling(UDType &output, MessageParcel &parcel) LOG_ERROR(UDMF_FRAMEWORK, "Unmarshal UDType failed!"); return false; } - if (type < TEXT || type >= UD_BUTT) { + if (type < ENTITY || type >= UD_BUTT) { LOG_ERROR(UDMF_FRAMEWORK, "invalid UDType!"); return false; } diff --git a/udmf/framework/common/utd_cfgs_checker.cpp b/udmf/framework/common/utd_cfgs_checker.cpp new file mode 100644 index 0000000000000000000000000000000000000000..57457544d12be23dbabbb37aee19023905888833 --- /dev/null +++ b/udmf/framework/common/utd_cfgs_checker.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "utd_cfgs_checker.h" + +#include +#include +#include "utd_graph.h" +#include "logger.h" + +namespace OHOS { +namespace UDMF { +constexpr const char *TYPE_ID_REGEX = "[A_za-z0-9_.]+$"; +constexpr const char FILE_EXTENSION_PREFIX = '.'; + +UtdCfgsChecker::UtdCfgsChecker() +{ +} + +UtdCfgsChecker::~UtdCfgsChecker() +{ +} + +UtdCfgsChecker &UtdCfgsChecker::GetInstance() +{ + static auto instance = new UtdCfgsChecker(); + return *instance; +} + +bool UtdCfgsChecker::CheckTypeDescriptors(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, + const std::vector &customCfgs, const std::string &bundleName) +{ + if (!CheckTypesFormat(typeCfgs, bundleName)) { + LOG_ERROR(UDMF_CLIENT, "CheckTypesFormat not pass, bundleName: %{public}s.", bundleName.c_str()); + return false; + } + if (!CheckTypesRelation(typeCfgs, presetCfgs, customCfgs)) { + LOG_ERROR(UDMF_CLIENT, "CheckTypesRelation not pass, bundleName: %{public}s.", bundleName.c_str()); + return false; + } + return true; +} + +bool UtdCfgsChecker::CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string &bundleName) +{ + for (auto declarationType: typeCfgs.first) { + if (!std::regex_match(declarationType.typeId, std::regex(bundleName + TYPE_ID_REGEX))) { + LOG_ERROR(UDMF_CLIENT, "Declaration typeId check failed, id: %{public}s, bundleName: %{public}s.", + declarationType.typeId.c_str(), bundleName.c_str()); + return false; + } + } + for (auto referenceTypes: typeCfgs.second) { + if (!std::regex_match(referenceTypes.typeId, std::regex(TYPE_ID_REGEX))) { + LOG_ERROR(UDMF_CLIENT, "Reference typeId check failed, id: %{public}s, bundleName: %{public}s.", + referenceTypes.typeId.c_str(), bundleName.c_str()); + return false; + } + } + std::vector inputTypeCfgs; + if (!typeCfgs.first.empty()) { + inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.first.begin(), typeCfgs.first.end()); + } + if (!typeCfgs.second.empty()) { + inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.second.begin(), typeCfgs.second.end()); + } + for (TypeDescriptorCfg &typeCfg : inputTypeCfgs) { + for (std::string filenames : typeCfg.filenameExtensions) { + if (!(filenames[0] == FILE_EXTENSION_PREFIX)) { + LOG_ERROR(UDMF_CLIENT, "Extension not valid, extension: %{public}s, bundleName: %{public}s.", + filenames.c_str(), bundleName.c_str()); + return false; + } + } + if (typeCfg.belongingToTypes.empty()) { + LOG_ERROR(UDMF_CLIENT, "BelongingToTypes can not be empty, bundleName: %{public}s.", bundleName.c_str()); + return false; + } + } + return true; +} + +bool UtdCfgsChecker::CheckTypesRelation(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, + const std::vector &customCfgs) +{ + std::vector inputTypeCfgs; + if (!typeCfgs.first.empty()) { + inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.first.begin(), typeCfgs.first.end()); + } + if (!typeCfgs.second.empty()) { + inputTypeCfgs.insert(inputTypeCfgs.end(), typeCfgs.second.begin(), typeCfgs.second.end()); + } + std::vector typeIds; + for (auto &inputTypeCfg: inputTypeCfgs) { + typeIds.push_back(inputTypeCfg.typeId); + } + for (auto &presetCfg: presetCfgs) { + typeIds.push_back(presetCfg.typeId); + } + if (std::set(typeIds.begin(), typeIds.end()).size() != typeIds.size()) { + LOG_ERROR(UDMF_CLIENT, "Find duplicated typeIds."); + return false; + } + if (!CheckBelongingToTypes(inputTypeCfgs, presetCfgs)) { + LOG_ERROR(UDMF_CLIENT, "BelongingToType check failed."); + return false; + } + if (!CanConstructDAG(typeCfgs, presetCfgs, customCfgs)) { + LOG_ERROR(UDMF_CLIENT, "Can not construct DAG."); + return false; + } + return true; +} + +bool UtdCfgsChecker::CheckBelongingToTypes(const std::vector &typeCfgs, + const std::vector &presetCfgs) +{ + std::vector typeIds; + for (auto &typeCfg: typeCfgs) { + typeIds.push_back(typeCfg.typeId); + } + for (auto &presetCfg: presetCfgs) { + typeIds.push_back(presetCfg.typeId); + } + for (auto &inputCfg : typeCfgs) { + for (std::string belongingToType : inputCfg.belongingToTypes) { + if (inputCfg.typeId == belongingToType) { + LOG_ERROR(UDMF_CLIENT, "TypeId cannot equals belongingToType, typeId: %{public}s.", + inputCfg.typeId.c_str()); + return false; + } + if (find(typeIds.begin(), typeIds.end(), belongingToType) == typeIds.end()) { + LOG_ERROR(UDMF_CLIENT, "BelongingToType can not find in typeids, belongingToType: %{public}s.", + belongingToType.c_str()); + return false; + } + } + } + return true; +} + +bool UtdCfgsChecker::CanConstructDAG(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, + const std::vector &customCfgs) +{ + std::vector allTypeCfgs; + if (!customCfgs.empty()) { + allTypeCfgs.insert(allTypeCfgs.end(), customCfgs.begin(), customCfgs.end()); + } + for (TypeDescriptorCfg &declarationType : typeCfgs.first) { + for (auto iter = allTypeCfgs.begin(); iter != allTypeCfgs.end();) { + if (iter->typeId == declarationType.typeId) { + iter = allTypeCfgs.erase(iter); + } else { + iter ++; + } + } + allTypeCfgs.push_back(declarationType); + } + for (TypeDescriptorCfg &referenceTypes : typeCfgs.second) { + bool found = false; + for (auto &typeCfg : allTypeCfgs) { + if (typeCfg.typeId == referenceTypes.typeId) { + found = true; + break; + } + } + if (!found) { + allTypeCfgs.push_back(referenceTypes); + } + } + if (!presetCfgs.empty()) { + allTypeCfgs.insert(allTypeCfgs.end(), presetCfgs.begin(), presetCfgs.end()); + } + if (!allTypeCfgs.empty()) { + UtdGraph::GetInstance().InitUtdGraph(allTypeCfgs); + if (UtdGraph::GetInstance().IsDAG()) { + return true; + } + } + return false; +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/common/utd_cfgs_checker.h b/udmf/framework/common/utd_cfgs_checker.h new file mode 100644 index 0000000000000000000000000000000000000000..404ffd3ef69fa4c76011b59e3c01ec41fcc4a9c6 --- /dev/null +++ b/udmf/framework/common/utd_cfgs_checker.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_UTD_CFGS_CHERCKER_H +#define UDMF_UTD_CFGS_CHERCKER_H +#include "utd_common.h" +namespace OHOS { +namespace UDMF { +class UtdCfgsChecker { +public: + using CustomUtdCfgs = std::pair, std::vector>; + + static UtdCfgsChecker &GetInstance(); + bool CheckTypeDescriptors(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, + const std::vector &customCfgs, const std::string &bundleName); + bool CheckBelongingToTypes(const std::vector &typeCfgs, + const std::vector &presetCfgs); + +private: + UtdCfgsChecker(); + ~UtdCfgsChecker(); + UtdCfgsChecker(const UtdCfgsChecker &obj) = delete; + UtdCfgsChecker &operator=(const UtdCfgsChecker &obj) = delete; + bool CheckTypesFormat(CustomUtdCfgs &typeCfgs, const std::string &bundleName); + bool CheckTypesRelation(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, + const std::vector &customCfgs); + bool CanConstructDAG(CustomUtdCfgs &typeCfgs, const std::vector &presetCfgs, + const std::vector &customCfgs); +}; +} +} +#endif // UDMF_UTD_CFGS_CHERCKER_H diff --git a/udmf/framework/common/utd_common.h b/udmf/framework/common/utd_common.h new file mode 100644 index 0000000000000000000000000000000000000000..5b7316233e9c48dedba8344ac1d5c891b06da1b3 --- /dev/null +++ b/udmf/framework/common/utd_common.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef UDMF_UTD_TYPE +#define UDMF_UTD_TYPE +#include +#include +#include +#include "error_code.h" + +namespace OHOS { +namespace UDMF { +struct TypeDescriptorCfg { + std::string typeId; + std::set belongingToTypes; + std::vector filenameExtensions; + std::vector mimeTypes; + std::string description; + std::string referenceURL; + std::string iconFile; + std::string ownerBundle; + std::set installerBundles; + + bool operator==(const TypeDescriptorCfg &typeDescriptor) const + { + return typeDescriptor.typeId == typeId; + } +}; + +// UTD data category +constexpr const char* UTD_CUSTOM_DECLAEEARION = "UniformDataTypeDeclarations"; +constexpr const char* UTD_CUSTOM_REFERENCE = "ReferenceUniformDataTypeDeclarations"; + +constexpr const char* UTD_CUSTOM = "CustomUTDs"; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UTD_TYPE diff --git a/udmf/framework/common/utd_graph.cpp b/udmf/framework/common/utd_graph.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9ef595e00143d55f34ee956de2e6d70dc13c88d2 --- /dev/null +++ b/udmf/framework/common/utd_graph.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "utd_graph.h" +#include "logger.h" +namespace OHOS { +namespace UDMF { +UtdGraph::UtdGraph() +{ + LOG_INFO(UDMF_CLIENT, "construct UtdGraph sucess."); +} + +UtdGraph::~UtdGraph() +{ +} + +UtdGraph &UtdGraph::GetInstance() +{ + static auto instance = new UtdGraph(); + return *instance; +} + +bool UtdGraph::IsValidType(const std::string &node) +{ + if (typeIdIndex_.find(node) == typeIdIndex_.end()) { + LOG_ERROR(UDMF_CLIENT, "invalid typeId. typeId:%{public}s ", node.c_str()); + return false; + } + return true; +} + +int32_t UtdGraph::GetIndex(const std::string &node) +{ + auto idx = typeIdIndex_.find(node); + if (idx == typeIdIndex_.end()) { + return -1; + } + return idx->second; +} + +void UtdGraph::InitUtdGraph(const std::vector &descriptorCfgs) +{ + uint32_t descriptorsNum = static_cast(descriptorCfgs.size()); + std::unique_lock Lock(graphMutex_); + graph_ = new Graph(descriptorsNum); + for (uint32_t i = 0; i < descriptorsNum; i++) { + typeIdIndex_.insert(std::make_pair(descriptorCfgs[i].typeId, i)); + } + for (const auto &descriptorCfg : descriptorCfgs) { + std::set belongsTo = descriptorCfg.belongingToTypes; + for (auto belongsToType : belongsTo) { + AddEdge(belongsToType, descriptorCfg.typeId); + } + } + LOG_INFO(UDMF_CLIENT, "InitUtdGraph success, descriptorsNum:%{public}u. ", descriptorsNum); +} + +void UtdGraph::AddEdge(const std::string &startNode, const std::string &endNode) +{ + int32_t start = GetIndex(startNode); + int32_t end = GetIndex(endNode); + if (start < 0 || end < 0) { + LOG_WARN(UDMF_CLIENT, "abnormal edge, startNode:%{public}s, endNode:%{public}s. ", + startNode.c_str(), endNode.c_str()); + return; + } + graph_->AddEdge(start, end); +} + +bool UtdGraph::IsLowerLevelType(const std::string &lowerLevelType, const std::string &heigitLevelType) +{ + bool isFind = false; + uint32_t start = GetIndex(lowerLevelType); + uint32_t end = GetIndex(heigitLevelType); + std::shared_lock Lock(graphMutex_); + graph_->Dfs(start, [&isFind, &end](uint32_t currNode)-> bool { + if (end == currNode) { + isFind = true; + return true; + } + return false; + }); + return isFind; +} + +bool UtdGraph::IsDAG() +{ + std::shared_lock Lock(graphMutex_); + return graph_->DfsUnconnectedGraph([&](uint32_t currNode) -> bool {return false; }); +} +} // namespace UDMF +} // namespace OHOS diff --git a/udmf/framework/common/utd_graph.h b/udmf/framework/common/utd_graph.h new file mode 100644 index 0000000000000000000000000000000000000000..877487c1720602fafa34386dc918430a565c36a9 --- /dev/null +++ b/udmf/framework/common/utd_graph.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UDMF_UTD_GRAPH_H +#define UDMF_UTD_GRAPH_H + +#include +#include +#include +#include +#include +#include "graph.h" +#include "utd_common.h" +#include "preset_type_descriptors.h" + +namespace OHOS { +namespace UDMF { +class UtdGraph { +public: + static UtdGraph &GetInstance(); + bool IsValidType(const std::string &node); + void InitUtdGraph(const std::vector &descriptorCfgs); + bool IsLowerLevelType(const std::string &lowerLevelType, const std::string &heigitLevelType); + bool IsDAG(); +private: + UtdGraph(); + ~UtdGraph(); + UtdGraph(const UtdGraph &obj) = delete; + UtdGraph &operator=(const UtdGraph &obj) = delete; + int32_t GetIndex(const std::string &node); + void AddEdge(const std::string &startNode, const std::string &endNode); + mutable std::shared_mutex graphMutex_; + Graph *graph_ = nullptr; + std::map typeIdIndex_; +}; +} // namespace UDMF +} // namespace OHOS +#endif // UDMF_UTD_GRAPH_H diff --git a/udmf/framework/innerkitsimpl/client/utd_client.cpp b/udmf/framework/innerkitsimpl/client/utd_client.cpp index c6e09cc11c4fb0938cbac3014b18fd7cb2db9e40..5ef9f3e58e781c7e6f49c5d6c9ef8751f3dddb79 100644 --- a/udmf/framework/innerkitsimpl/client/utd_client.cpp +++ b/udmf/framework/innerkitsimpl/client/utd_client.cpp @@ -15,12 +15,14 @@ #include "utd_client.h" #include "logger.h" -#include "preset_type_descriptors.h" - +#include "utd_graph.h" +#include "custom_utd_store.h" namespace OHOS { namespace UDMF { +constexpr const char* CUSTOM_TYPE_CFG_PATH = "/data/utd/utd-adt.json"; UtdClient::UtdClient() { + Init(); LOG_INFO(UDMF_CLIENT, "construct UtdClient sucess."); } @@ -30,21 +32,80 @@ UtdClient::~UtdClient() UtdClient &UtdClient::GetInstance() { - static auto instance_ = new UtdClient(); - return *instance_; + static auto instance = new UtdClient(); + return *instance; +} + +void UtdClient::Init() +{ + descriptorCfgs_ = PresetTypeDescriptors::GetInstance().GetPresetTypes(); + std::vector customTypes = + CustomUtdStore::GetInstance().GetTypeCfgs(CUSTOM_TYPE_CFG_PATH); + if (!customTypes.empty()) { + descriptorCfgs_.insert(descriptorCfgs_.end(), customTypes.begin(), customTypes.end()); + } + UtdGraph::GetInstance().InitUtdGraph(descriptorCfgs_); } Status UtdClient::GetTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor) { - descriptors_ = PresetTypeDescriptors::GetInstance().GetTypeDescriptors(); - for (const auto &utdType : descriptors_) { - if (utdType.GetTypeId() == typeId) { - descriptor = std::make_shared(utdType); + for (const auto &utdTypeCfg : descriptorCfgs_) { + if (utdTypeCfg.typeId == typeId) { + descriptor = std::make_shared(utdTypeCfg); LOG_DEBUG(UDMF_CLIENT, "get descriptor success. %{public}s ", typeId.c_str()); + return Status::E_OK; } } + return Status::E_OK; +} + +Status UtdClient::GetUniformDataTypeByFilenameExtension(const std::string &fileExtension, std::string &typeId, + std::string belongsTo) +{ + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. fileExtension:%{public}s, belongsTo:%{public}s ", + fileExtension.c_str(), belongsTo.c_str()); + return Status::E_INVALID_PARAMETERS; + } + for (const auto &utdTypeCfg : descriptorCfgs_) { + std::vector fileExtensions = utdTypeCfg.filenameExtensions; + if (find(fileExtensions.begin(), fileExtensions.end(), fileExtension) != fileExtensions.end()) { + typeId = utdTypeCfg.typeId; + break; + } + } + + // the find typeId is not belongsTo to the belongsTo. + if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + typeId = ""; + } + return Status::E_OK; +} + +Status UtdClient::GetUniformDataTypeByMIMEType(const std::string &mimeType, std::string &typeId, + std::string belongsTo) +{ + if (belongsTo != DEFAULT_TYPE_ID && !UtdGraph::GetInstance().IsValidType(belongsTo)) { + LOG_ERROR(UDMF_CLIENT, "invalid belongsTo. mimeType:%{public}s, belongsTo:%{public}s ", + mimeType.c_str(), belongsTo.c_str()); + return Status::E_INVALID_PARAMETERS; + } + + for (const auto &utdTypeCfg : descriptorCfgs_) { + std::vector mimeTypes = utdTypeCfg.mimeTypes; + if (find(mimeTypes.begin(), mimeTypes.end(), mimeType) != mimeTypes.end()) { + typeId = utdTypeCfg.typeId; + break; + } + } + // the find typeId is not belongsTo to the belongsTo. + if (!typeId.empty() && belongsTo != DEFAULT_TYPE_ID && belongsTo != typeId && + !UtdGraph::GetInstance().IsLowerLevelType(belongsTo, typeId)) { + typeId = ""; + } return Status::E_OK; } } // namespace UDMF -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/common/unified_meta.cpp b/udmf/framework/innerkitsimpl/common/unified_meta.cpp index 6bad218c5444fa15e35a8992da1cc018135608a2..5c9e3f7f644fd07decc6d3db4be5ec9539df280a 100644 --- a/udmf/framework/innerkitsimpl/common/unified_meta.cpp +++ b/udmf/framework/innerkitsimpl/common/unified_meta.cpp @@ -21,7 +21,7 @@ namespace OHOS { namespace UDMF { bool UnifiedDataUtils::IsValidType(int32_t value) { - return value >= TEXT && value < UD_BUTT; + return value >= ENTITY && value < UD_BUTT; } bool UnifiedDataUtils::IsValidIntention(int32_t value) diff --git a/udmf/framework/common/preset_type_descriptors.cpp b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp similarity index 75% rename from udmf/framework/common/preset_type_descriptors.cpp rename to udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp index 88994e0732131a2911e06c8b796cfdcf3c8e1f8d..6b78eaea89efa794aa4b94678d6d3d2177e3eba3 100644 --- a/udmf/framework/common/preset_type_descriptors.cpp +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.cpp @@ -15,6 +15,9 @@ #include "preset_type_descriptors.h" namespace OHOS { namespace UDMF { +constexpr const char *REFERENCE_URL = "https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/"\ + "apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype"; + PresetTypeDescriptors::PresetTypeDescriptors() { InitDescriptors(); @@ -26,11 +29,11 @@ PresetTypeDescriptors::~PresetTypeDescriptors() PresetTypeDescriptors &PresetTypeDescriptors::GetInstance() { - static auto instance_ = new PresetTypeDescriptors(); - return *instance_; + static auto instance = new PresetTypeDescriptors(); + return *instance; } -std::vector &PresetTypeDescriptors::GetTypeDescriptors() +std::vector &PresetTypeDescriptors::GetPresetTypes() { return typeDescriptors_; } @@ -38,623 +41,658 @@ std::vector &PresetTypeDescriptors::GetTypeDescriptors() void PresetTypeDescriptors::InitDescriptors() { typeDescriptors_ = { - {"general.database", - {}, - {}, - {}, - "Base type for databases.", - "", - ""}, - {"general.message", + {"general.entity", {}, {}, {}, - "Base type for messages (email, IM, and so on).", - "", + "Base type for physical hierarchy.", + REFERENCE_URL, ""}, - {"general.contact", - {}, - {}, - {}, - "Base type for contact information.", - "", - ""}, - {"general.archive", + {"general.object", {}, {}, {}, - "Base type for an archive of files and directories.", - "", - ""}, - {"general.disk-image", - {"general.archive"}, - {}, - {}, - "Base type for items mountable as a volume.", - "", - ""}, - {"general.text", - {}, - {}, - {}, - "Base type for all text, including text with markup information (HTML, RTF, and so on).", - "", - ""}, - {"general.plain-text", - {"general.text"}, - {".txt"}, - {"text/plain"}, - "Text of unspecified encoding, with no markup. Equivalent to the MIME type text/plain", - "", - ""}, - {"general.html", - {"general.text"}, - {".html", ".htm"}, - {"text/html"}, - "HTML text.", - "", - ""}, - {"general.xml", - {"general.text"}, - {".xml"}, - {"text/xml"}, - "XML text.", - "", + "Base type for logical hierarchy.", + REFERENCE_URL, ""}, - {"general.source-code", - {"general.plain-text"}, + {"general.file", + {"general.entity"}, {}, {}, - "Generic source code.", - "", + "Base type for file.", + REFERENCE_URL, ""}, - {"general.c-source", - {"general.source-code"}, - {".c"}, + {"general.directory", + {"general.entity"}, {}, - "C source code.", - "", - ""}, - {"general.c-plus-plus-source", - {"general.source-code"}, - {".cp", ".cpp", ".c++", ".cc", ".cxx"}, {}, - "C++ source code.", - "", + "Base type for directory.", + REFERENCE_URL, ""}, - {"general.c-header", - {"general.source-code"}, - {".h"}, + {"general.folder", + {"general.directory"}, {}, - "C header file.", - "", - ""}, - {"general.c-plus-plus-header", - {"general.source-code"}, - {".hpp", ".h++", ".hxx"}, {}, - "C++ header file.", - "", + "Base type for folder.", + REFERENCE_URL, ""}, - {"general.script", - {"general.source-code"}, + {"general.symlink", + {"general.entity"}, {}, {}, - "Base type for scripting language source code.", - "", + "Base type for symlink.", + REFERENCE_URL, ""}, - {"general.shell-script", - {"general.script"}, - {".sh", ".command"}, + {"general.composite-object", + {"general.object"}, {}, - "Shell script.", - "", - ""}, - {"general.csh-script", - {"general.shell-script"}, - {".csh"}, {}, - "C-shell script.", - "", - ""}, - {"general.perl-script", - {"general.shell-script"}, - {".pl", ".pm"}, - {"text/x-perl-script"}, - "Perl script.", - "", + "Base type for mixed object. For example, a PDF file contains both text and special formatting data.", + REFERENCE_URL, ""}, - {"general.python-script", - {"general.shell-script"}, - {".py"}, - {"text/x-python-script"}, - "Python script.", - "", - ""}, - {"general.ruby-script", - {"general.shell-script"}, - {".rb", ".rbw"}, - {"text/ruby-script"}, - "Ruby script.", - "", - ""}, - {"general.php-script", - {"general.shell-script"}, - {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, - {"text/x-php-script, text/php, application/php"}, - "PHP script.", - "", - ""}, - {"general.tar-archive", - {"general.archive"}, - {".tar"}, - {"application/x-tar, application/tar"}, - "Tar archive.", - "", - ""}, - {"general.vcard", - {}, + {"general.media", + {"general.object"}, {}, {}, - "Base type for electronic business card.", - "", + "Base type for media.", + REFERENCE_URL, ""}, {"general.image", {"general.media"}, {}, {}, "Base type for images.", - "", + REFERENCE_URL, + ""}, + {"general.png", + {"general.image"}, + {".png"}, + {"image/png"}, + "PNG image.", + REFERENCE_URL, ""}, {"general.jpeg", {"general.image"}, {".jpg", ".jpeg"}, {"image/jpeg"}, "JPEG image.", - "", + REFERENCE_URL, ""}, {"general.tiff", {"general.image"}, {".tif", ".tiff"}, {"image/tiff"}, "TIFF image.", - "", + REFERENCE_URL, ""}, {"general.raw-image", {"general.image"}, {}, {}, "Base type for digital camera raw image formats.", - "", - ""}, - {"general.png", - {"general.image"}, - {".png"}, - {"image/png"}, - "PNG image", - "", + REFERENCE_URL, ""}, {"general.video", {"general.media"}, {}, {}, "Base type for video.", - "", + REFERENCE_URL, ""}, {"general.avi", {"general.video"}, {".avi", ".vfw"}, {"video/avi", "video/msvideo", "video/x-msvideo"}, "AVI video.", - "", + REFERENCE_URL, ""}, {"general.mpeg", {"general.video"}, - {".mpg", ".mpeg"}, + {".mpg", ".mpeg", ".m75", ".m15"}, {"video/mpg", "video/mpeg", "video/x-mpg", "video/x-mpeg"}, "MPEG-1 or MPEG-2 video.", - "", + REFERENCE_URL, ""}, {"general.mpeg-4", {"general.video"}, {".mp4"}, {"video/mp4", "video/mp4v"}, "MPEG-4 video.", - "", + REFERENCE_URL, ""}, {"general.3gpp", {"general.video"}, {".3gp", ".3gpp"}, {"video/3gpp"}, "3GPP video.", - "", + REFERENCE_URL, ""}, {"general.3gpp2", {"general.video"}, {".3g2", ".3gp2"}, {"video/3gpp2"}, "3GPP2 video.", - "", + REFERENCE_URL, ""}, {"general.audio", {"general.media"}, {}, {}, "Base type for audio.", - "", + REFERENCE_URL, ""}, - {"general.mp3", - {"general.audio"}, - {".mp3,"}, - {"audio/mp3"}, - "MPEG-3 audio.", - "", - ""}, - {"general.aac", + {"general.ogg", {"general.audio"}, - {".aac"}, - {"audio/aac"}, - "AAC audio.", - "", + {".ogg"}, + {"audio/ogg"}, + "OGG audio.", + REFERENCE_URL, ""}, {"general.aiff", {"general.audio"}, {".aiff"}, {"audio/aiff"}, "AIFF audio.", - "", + REFERENCE_URL, + ""}, + {"general.pcm", + {"general.audio"}, + {".pcm"}, + {"audio/pcm"}, + "PCM audio.", + REFERENCE_URL, + ""}, + {"general.flac", + {"general.audio"}, + {".flac"}, + {"audio/flac"}, + "FLAC audio.", + REFERENCE_URL, ""}, {"general.alac", {"general.audio"}, {".alac"}, {"audio/alac"}, "ALAC audio.", - "", + REFERENCE_URL, + ""}, + {"general.mp3", + {"general.audio"}, + {".mp3"}, + {"audio/mp3"}, + "MPEG-3 audio.", + REFERENCE_URL, + ""}, + {"general.aac", + {"general.audio"}, + {".aac"}, + {"audio/aac"}, + "AAC audio.", + REFERENCE_URL, + ""}, + {"general.archive", + {"general.object"}, + {}, + {}, + "Base type for an archive of files and directories.", + REFERENCE_URL, + ""}, + {"general.tar-archive", + {"general.archive"}, + {".tar"}, + {"application/x-tar, application/tar"}, + "Tar archive.", + REFERENCE_URL, + ""}, + {"general.zip-archive", + {"general.archive"}, + {".zip"}, + {"application/zip"}, + "Zip archive.", + REFERENCE_URL, + ""}, + {"general.disk-image", + {"general.archive"}, + {}, + {}, + "Base type for items mountable as a volume.", + REFERENCE_URL, ""}, {"general.bz2-archive", {"general.archive"}, {".bz2"}, {"application/x-bzip2"}, "BZip2 archive.", - "", + REFERENCE_URL, ""}, - {"general.calendar", - {}, - {}, - {}, - "Base type for scheduled events.", - "", - ""}, - {"general.ebook", - {}, + {"general.text", + {"general.object"}, {}, {}, - "Base type for ebook.", - "", - ""}, - {"general.epub", - {"general.ebook"}, - {".epub"}, - {"application/epub+zip"}, - "Electronic publication (EPUB) format.", - "", + "Base type for all text.", + REFERENCE_URL, ""}, - {"general.flac", - {"general.audio"}, - {".flac"}, - {"audio/flac"}, - "FLAC audio.", - "", + {"general.plain-text", + {"general.text"}, + {".txt"}, + {"text/plain"}, + "Text of unspecified encoding, with no markup.", + REFERENCE_URL, ""}, - {"general.java-script", - {"general.source-code"}, - {".js", ".jscript", ".javascript"}, - {"text/javascript"}, - "", - "", + {"general.html", + {"general.text"}, + {".html", ".htm"}, + {"text/html"}, + "HTML text.", + REFERENCE_URL, ""}, - {"general.java-source", - {"general.source-code"}, - {".java", ".jav"}, + {"general.hyperlink", + {"general.text"}, {}, - "Java source code.", - "", + {}, + "Hyperlink.", + REFERENCE_URL, ""}, - {"general.location", - {"general.navigation"}, + {"general.xml", + {"general.text"}, + {".xml"}, + {"text/xml"}, + "XML text.", + REFERENCE_URL, + ""}, + {"general.source-code", + {"general.plain-text"}, {}, {}, - "Navigation location.", - "", + "Generic source code.", + REFERENCE_URL, ""}, - {"general.media", - {}, + {"general.script", + {"general.source-code"}, {}, {}, - "Base type for media.", - "", + "Base type for scripting language source code.", + REFERENCE_URL, ""}, - {"general.navigation", - {}, + {"general.shell-script", + {"general.script"}, + {".sh", ".command"}, {}, + "Shell script.", + REFERENCE_URL, + ""}, + {"general.csh-script", + {"general.shell-script"}, + {".csh"}, {}, - "Base type for navigation.", - "", + "C-shell script.", + REFERENCE_URL, ""}, - {"general.ogg", - {"general.audio"}, - {".ogg"}, - {"audio/ogg"}, - "OGG audio.", - "", + {"general.perl-script", + {"general.shell-script"}, + {".pl", ".pm"}, + {"text/x-perl-script"}, + "Perl script.", + REFERENCE_URL, ""}, - {"general.pcm", - {"general.audio"}, - {".pcm"}, - {"audio/pcm"}, - "PCM audio.", - "", + {"general.python-script", + {"general.shell-script"}, + {".py"}, + {"text/x-python-script"}, + "Python script.", + REFERENCE_URL, + ""}, + {"general.ruby-script", + {"general.shell-script"}, + {".rb", ".rbw"}, + {"text/ruby-script"}, + "Ruby script.", + REFERENCE_URL, + ""}, + {"general.php-script", + {"general.shell-script"}, + {".php", ".php3", ".php4", ".ph3", ".ph4", ".phtml"}, + {"text/x-php-script, text/php, application/php"}, + "PHP script.", + REFERENCE_URL, ""}, {"general.type-script", {"general.source-code"}, {".ts"}, {}, "TypeScript source code.", - "", + REFERENCE_URL, ""}, - {"general.zip-archive", - {"general.archive"}, - {".zip"}, - {"application/zip"}, - "Zip archive.", - "", + {"general.java-script", + {"general.source-code"}, + {".js", ".jscript", ".javascript"}, + {"text/javascript"}, + "JavaScript source code.", + REFERENCE_URL, ""}, - {"general.hyperlink", - {"general.text"}, - {}, + {"general.c-source", + {"general.source-code"}, + {".c"}, {}, - "Hyperlink.", - "", + "C source code.", + REFERENCE_URL, ""}, - {"general.file", + {"general.c-header", + {"general.source-code"}, + {".h"}, {}, + "C header file.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-source", + {"general.source-code"}, + {".cp", ".cpp", ".c++", ".cc", ".cxx"}, {}, + "C++ source code.", + REFERENCE_URL, + ""}, + {"general.c-plus-plus-header", + {"general.source-code"}, + {".hpp", ".h++", ".hxx"}, {}, - "Base type for file.", - "", + "C++ header file.", + REFERENCE_URL, ""}, - {"general.directory", + {"general.java-source", + {"general.source-code"}, + {".java", ".jav"}, {}, + "Java source code.", + REFERENCE_URL, + ""}, + {"general.ebook", + {"general.composite-object"}, {}, {}, - "Base type for directory.", - "", + "Base type for ebook.", + REFERENCE_URL, ""}, - {"general.folder", - {}, + {"general.epub", + {"general.ebook"}, + {".epub"}, + {"application/epub+zip"}, + "Electronic publication (EPUB) format.", + REFERENCE_URL, + ""}, + {"general.navigation", + {"general.object"}, {}, {}, - "Base type for folder.", - "", + "Base type for navigation.", + REFERENCE_URL, ""}, - {"general.symlink", - {}, + {"general.location", + {"general.navigation"}, {}, {}, - "Base type for symlink.", - "", + "Navigation location.", + REFERENCE_URL, ""}, - {"com.adobe.pdf", + {"general.database", + {"general.object"}, {}, - {".pdf"}, - {"application/pdf"}, - "PDF data.", - "", + {}, + "Base type for databases.", + REFERENCE_URL, ""}, - {"com.adobe.postscript", + {"general.vcard", + {"general.object"}, {}, - {".ps"}, - {"application/postscript"}, - "PostScript data.", - "", + {}, + "Base type for electronic business card.", + REFERENCE_URL, ""}, - {"com.adobe.encapsulated-postscript", + {"general.calendar", + {"general.object"}, {}, - {".eps"}, {}, - "Encapsulated PostScript.", - "", + "Base type for scheduled events.", + REFERENCE_URL, ""}, - {"com.adobe.photoshop-image", - {"general.image"}, - {".psd"}, - {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, - "Adobe Photoshop document.", - "", + {"general.message", + {"general.object"}, + {}, + {}, + "Base type for messages.", + REFERENCE_URL, ""}, - {"com.adobe.illustrator.ai-image", - {"general.image"}, - {".ai"}, + {"general.contact", + {"general.object"}, {}, - "Adobe Illustrator document.", - "", + {}, + "Base type for contact information.", + REFERENCE_URL, ""}, {"com.microsoft.bmp", {"general.image"}, {".bmp"}, {}, "Windows bitmap image.", - "", + REFERENCE_URL, ""}, {"com.microsoft.ico", {"general.image"}, {".ico"}, {}, "Windows icon image.", - "", + REFERENCE_URL, ""}, {"com.microsoft.word.doc", - {}, + {"general.composite-object"}, {".doc"}, {"application/msword"}, "Microsoft Word data.", - "", + REFERENCE_URL, ""}, {"com.microsoft.excel.xls", - {}, + {"general.composite-object"}, {".xls"}, {"application/vnd.ms-excel"}, "Microsoft Excel data.", - "", + REFERENCE_URL, ""}, {"com.microsoft.powerpoint.ppt", - {}, + {"general.composite-object"}, {".ppt"}, {"application/mspowerpoint"}, "Microsoft PowerPoint presentation.", - "", + REFERENCE_URL, ""}, {"com.microsoft.waveform-audio", {"general.audio"}, - {".wav", ".wave", ".WAV"}, + {".wav", ".wave"}, {"audio/wav", "audio/wave"}, "Waveform audio.", - "", + REFERENCE_URL, ""}, {"com.microsoft.windows-media-wm", {"general.video"}, {".wm"}, {"video/x-ms-wm"}, "Windows WM video.", - "", + REFERENCE_URL, ""}, {"com.microsoft.windows-media-wmv", {"general.video"}, {".wmv"}, {"video/x-ms-wmv"}, "Windows WMV video.", - "", + REFERENCE_URL, ""}, {"com.microsoft.windows-media-wmp", {"general.video"}, {".wmp"}, {"video/x-ms-wmp"}, "Windows WMP video.", - "", + REFERENCE_URL, ""}, {"com.microsoft.windows-media-wma", {"general.audio"}, {".wma"}, {"video/x-ms-wma"}, "Windows WMA audio.", - "", + REFERENCE_URL, ""}, {"com.microsoft.windows-media-wmx", {"general.audio"}, {".wmx"}, {"video/x-ms-wmx"}, "Windows WMX audio.", - "", + REFERENCE_URL, ""}, {"com.microsoft.windows-media-wvx", {"general.audio"}, {".wvx"}, {"video/x-ms-wvx"}, "Windows WVX audio.", - "", + REFERENCE_URL, ""}, {"com.microsoft.windows-media-wax", {"general.audio"}, {".wax"}, {"video/x-ms-wax"}, "Windows WAX audio.", - "", + REFERENCE_URL, ""}, - {"com.amazon.azw", - {"general.ebook"}, - {".azw"}, - {"application/vnd.amazon.ebook"}, - "AZW ebook.", - "", + {"com.adobe.pdf", + {"general.composite-object"}, + {".pdf"}, + {"application/pdf"}, + "PDF data.", + REFERENCE_URL, ""}, - {"com.amazon.azw3", - {"general.ebook"}, - {".azw3"}, - {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, - "AZW3 ebook.", - "", + {"com.adobe.postscript", + {"general.composite-object"}, + {".ps"}, + {"application/postscript"}, + "PostScript data.", + REFERENCE_URL, ""}, - {"com.amazon.kfx", - {"general.ebook"}, - {".kfx"}, + {"com.adobe.encapsulated-postscript", + {"com.adobe.postscript"}, + {".eps"}, {}, - "KFX ebook.", - "", + "Encapsulated PostScript.", + REFERENCE_URL, ""}, - {"com.amazon.mobi", - {"general.ebook"}, - {".mobi"}, - {"application/x-mobipocket-ebook"}, - "MOBI ebook.", - "", + {"com.adobe.photoshop-image", + {"general.image"}, + {".psd"}, + {"image/x-photoshop", "image/photoshop", "image/psd", "application/photoshop"}, + "Adobe Photoshop document.", + REFERENCE_URL, + ""}, + {"com.adobe.illustrator.ai-image", + {"general.image"}, + {".ai"}, + {}, + "Adobe Illustrator document.", + REFERENCE_URL, ""}, {"com.sun.java-archive", {"general.archive"}, {".jar"}, {"application/java-archive"}, "Java archive.", - "", + REFERENCE_URL, ""}, {"org.gnu.gnu-tar-archive", {"general.archive"}, {".gtar"}, {"application/x-gtar"}, "GNU archive.", - "", + REFERENCE_URL, ""}, {"org.gnu.gnu-zip-archive", {"general.archive"}, {".gz", ".gzip"}, {"application/x-gzip", "application/gzip"}, "Gzip archive.", - "", + REFERENCE_URL, ""}, {"org.gnu.gnu-zip-tar-archive", {"general.archive"}, {".tgz"}, {}, "Gzip tar archive.", - "", + REFERENCE_URL, ""}, - {"openharmony.form", + {"com.amazon.azw", + {"general.ebook"}, + {".azw"}, + {"application/vnd.amazon.ebook"}, + "AZW ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.azw3", + {"general.ebook"}, + {".azw3"}, + {"application/vnd.amazon.mobi8-ebook", "application/x-mobi8-ebook"}, + "AZW3 ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.kfx", + {"general.ebook"}, + {".kfx"}, {}, + "KFX ebook.", + REFERENCE_URL, + ""}, + {"com.amazon.mobi", + {"general.ebook"}, + {".mobi"}, + {"application/x-mobipocket-ebook"}, + "MOBI ebook.", + REFERENCE_URL, + ""}, + {"openharmony.form", + {"general.object"}, {}, {}, "OpenHarmony system defined form.", - "", + REFERENCE_URL, ""}, {"openharmony.app-item", - {}, + {"general.object"}, {}, {}, "OpenHarmony system defined app item.", - "", + REFERENCE_URL, ""}, {"openharmony.pixel-map", - {}, + {"general.image"}, {}, {}, "OpenHarmony system defined pixel map.", - "", + REFERENCE_URL, ""}, {"openharmony.atomic-service", - {}, + {"general.object"}, {}, {}, "OpenHarmony system defined atomic service.", - "", + REFERENCE_URL, + ""}, + {"openharmony.package", + {"general.directory"}, + {}, + {}, + "OpenHarmony system defined package (that is, a directory presented to the user as a file).", + REFERENCE_URL, + ""}, + {"openharmony.hap", + {"openharmony.package"}, + {".hap"}, + {}, + "OpenHarmony system defined ability package.", + REFERENCE_URL, ""} }; } } // namespace UDMF -} // namespace OHOS \ No newline at end of file +} // namespace OHOS diff --git a/udmf/framework/common/preset_type_descriptors.h b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h similarity index 85% rename from udmf/framework/common/preset_type_descriptors.h rename to udmf/framework/innerkitsimpl/data/preset_type_descriptors.h index c2661964596de66e4c8296e9f3fd96c3f7047683..ab69dcafb394fd17efceea4dbf72488a2ec1abd1 100644 --- a/udmf/framework/common/preset_type_descriptors.h +++ b/udmf/framework/innerkitsimpl/data/preset_type_descriptors.h @@ -14,15 +14,16 @@ */ #ifndef UDMF_PRESET_TYPE_DESCRIPTORS #define UDMF_PRESET_TYPE_DESCRIPTORS -#include "type_descriptor.h" +#include #include "error_code.h" +#include "utd_common.h" namespace OHOS { namespace UDMF { class PresetTypeDescriptors { public: static PresetTypeDescriptors &GetInstance(); - std::vector &GetTypeDescriptors(); + std::vector &GetPresetTypes(); private: PresetTypeDescriptors(); ~PresetTypeDescriptors(); @@ -30,7 +31,7 @@ private: PresetTypeDescriptors &operator=(const PresetTypeDescriptors &obj) = delete; void InitDescriptors(); - std::vector typeDescriptors_; + std::vector typeDescriptors_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/framework/innerkitsimpl/data/type_descriptor.cpp b/udmf/framework/innerkitsimpl/data/type_descriptor.cpp index d014e8889df034884f75aa9a8d548ad125c376ab..f9d7985fb1b8530503eddf99e3948eb8b97f80f7 100644 --- a/udmf/framework/innerkitsimpl/data/type_descriptor.cpp +++ b/udmf/framework/innerkitsimpl/data/type_descriptor.cpp @@ -14,8 +14,8 @@ */ #include "type_descriptor.h" - #include "logger.h" +#include "utd_graph.h" namespace OHOS { namespace UDMF { @@ -27,13 +27,65 @@ TypeDescriptor::TypeDescriptor(const std::string &typeId, const std::set descriptor) { - return descriptor->GetTypeId() == this->GetTypeId(); + return descriptor->GetTypeId() == this->GetTypeId(); } const std::string& TypeDescriptor::GetTypeId() const diff --git a/udmf/framework/innerkitsimpl/data/unified_record.cpp b/udmf/framework/innerkitsimpl/data/unified_record.cpp index a6d7eb08953329fb38f63cc283ea08135b6d4cb2..449cb8362786bb5a8c43762050d6df1112473539 100644 --- a/udmf/framework/innerkitsimpl/data/unified_record.cpp +++ b/udmf/framework/innerkitsimpl/data/unified_record.cpp @@ -24,7 +24,7 @@ UnifiedRecord::UnifiedRecord() UnifiedRecord::UnifiedRecord(UDType type) { - if (type < TEXT || type > UD_BUTT) { + if (type < ENTITY || type > UD_BUTT) { dataType_ = UD_BUTT; } dataType_ = type; diff --git a/udmf/framework/service/distributeddata_udmf_ipc_interface_code.h b/udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h similarity index 100% rename from udmf/framework/service/distributeddata_udmf_ipc_interface_code.h rename to udmf/framework/innerkitsimpl/service/distributeddata_udmf_ipc_interface_code.h diff --git a/udmf/framework/service/udmf_service.h b/udmf/framework/innerkitsimpl/service/udmf_service.h similarity index 100% rename from udmf/framework/service/udmf_service.h rename to udmf/framework/innerkitsimpl/service/udmf_service.h diff --git a/udmf/framework/service/udmf_service_client.cpp b/udmf/framework/innerkitsimpl/service/udmf_service_client.cpp similarity index 100% rename from udmf/framework/service/udmf_service_client.cpp rename to udmf/framework/innerkitsimpl/service/udmf_service_client.cpp diff --git a/udmf/framework/service/udmf_service_client.h b/udmf/framework/innerkitsimpl/service/udmf_service_client.h similarity index 100% rename from udmf/framework/service/udmf_service_client.h rename to udmf/framework/innerkitsimpl/service/udmf_service_client.h diff --git a/udmf/framework/service/udmf_service_proxy.cpp b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp similarity index 100% rename from udmf/framework/service/udmf_service_proxy.cpp rename to udmf/framework/innerkitsimpl/service/udmf_service_proxy.cpp diff --git a/udmf/framework/service/udmf_service_proxy.h b/udmf/framework/innerkitsimpl/service/udmf_service_proxy.h similarity index 100% rename from udmf/framework/service/udmf_service_proxy.h rename to udmf/framework/innerkitsimpl/service/udmf_service_proxy.h diff --git a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn index c35490fbd1e2ea36afcd27f39ada8edd91f4c751..d6aec47eb862a595ce0158cbc59bd928043489f4 100644 --- a/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/fuzztest/udmfclient_fuzzer/BUILD.gn @@ -25,7 +25,7 @@ ohos_fuzztest("UdmfClientFuzzTest") { "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", "${udmf_framework_path}/common", - "${udmf_framework_path}/service", + "${udmf_framework_path}/innerkits/service", ] fuzz_config_file = diff --git a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn index fae602a03a471b6aa7cdf14a59a039f2fbc30a84..de9ec6db9e4ebed11c983cc16c42b33d6a1718ee 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn +++ b/udmf/framework/innerkitsimpl/test/unittest/BUILD.gn @@ -22,7 +22,7 @@ config("module_private_config") { "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", "${udmf_framework_path}/common", - "${udmf_framework_path}/service", + "${udmf_framework_path}/innerkits/service", ] } @@ -43,7 +43,13 @@ common_external_deps = [ ohos_unittest("UdmfClientTest") { module_out_path = module_output_path - sources = [ "udmf_client_test.cpp" ] + sources = [ + "custom_utd_json_parser_test.cpp", + "custom_utd_store_test.cpp", + "graph_test.cpp", + "udmf_client_test.cpp", + "utd_client_test.cpp", + ] configs = [ ":module_private_config" ] diff --git a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_json_parser_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_json_parser_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..81ccb03bf7f609ed7f16b35b5d452083997c1aef --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_json_parser_test.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "logger.h" +#include "utd_common.h" +#include "custom_utd_json_parser.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +constexpr const char* TEST_DATA1 = "{\ + \"UniformDataTypeDeclarations\": [{\ + \"typeId\": \"com.example.utdtest.document\",\ + \"belongingToTypes\": [\"com.example.utdtest2.document\"],\ + \"FilenameExtensions\": [\".mydocument\", \".mydoc\"],\ + \"mimeTypes\": [\"application/my-document\", \"application/my-doc\"],\ + \"description\": \"My document.\",\ + \"referenceURL\": \"http://www.mycompany.com/my-document.html\",\ + \"iconFile\": \"resources/my-document.png\"\ + }],\ + \"ReferenceUniformDataTypeDeclarations\": [{\ + \"typeId\": \"com.example.utdtest2.document\",\ + \"belongingToTypes\": [\"general.object\"],\ + \"FilenameExtensions\": [\".mydocument2\", \".mydoc2\"],\ + \"mimeTypes\": [\"application/my-document2\", \"application/my-doc2\"],\ + \"description\": \"My document 2.\",\ + \"referenceURL\": \"http://www.mycompany.com/my-document2.html\",\ + \"iconFile\": \"resources/my-document2.png\"\ + }]}"; + +class CustomUtdJsonParserTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void CustomUtdJsonParserTest::SetUpTestCase() +{ +} + +void CustomUtdJsonParserTest::TearDownTestCase() +{ +} + +void CustomUtdJsonParserTest::SetUp() +{ +} + +void CustomUtdJsonParserTest::TearDown() +{ +} + +/** +* @tc.name: ParseJsonData001 +* @tc.desc: ParseJson +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdJsonParserTest, ParseJsonData001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "ParseJsonData001 begin."); + std::vector typesCfg1; + std::vector typesCfg2; + CustomUtdJsonParser parser; + parser.ParseUserCustomUtdJson(TEST_DATA1, typesCfg1, typesCfg2); + TypeDescriptorCfg type1 = *(typesCfg1.begin()); + + EXPECT_EQ(type1.typeId, "com.example.utdtest.document"); + EXPECT_EQ(*(type1.belongingToTypes.begin()), "com.example.utdtest2.document"); + EXPECT_EQ(*(type1.filenameExtensions.begin()), ".mydocument"); + EXPECT_EQ(*(type1.mimeTypes.begin()), "application/my-document"); + EXPECT_EQ(type1.description, "My document."); + EXPECT_EQ(type1.referenceURL, "http://www.mycompany.com/my-document.html"); + EXPECT_EQ(type1.iconFile, "resources/my-document.png"); + + TypeDescriptorCfg type2 = *(typesCfg2.begin()); + EXPECT_EQ(type2.typeId, "com.example.utdtest2.document"); + EXPECT_EQ(*(type2.belongingToTypes.begin()), "general.object"); + EXPECT_EQ(*(type2.filenameExtensions.begin()), ".mydocument2"); + EXPECT_EQ(*(type2.mimeTypes.begin()), "application/my-document2"); + EXPECT_EQ(type2.description, "My document 2."); + EXPECT_EQ(type2.referenceURL, "http://www.mycompany.com/my-document2.html"); + EXPECT_EQ(type2.iconFile, "resources/my-document2.png"); + + LOG_INFO(UDMF_TEST, "ParseJsonData001 end."); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd5520d279f65f1ca06ae840cf0393e264c016fc --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/custom_utd_store_test.cpp @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#include "logger.h" +#include "custom_utd_store.h" +#include "utd_common.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +constexpr const char* TEST_CFG_FILE = "/data/100-test/utd-adt.json"; +constexpr const char* TEST_CFG_DIR = "/data/100-test/"; + +constexpr const char* TEST_DATA2 = "{\ + \"CustomUTDs\": [{\ + \"typeId\": \"com.example.utdtest.document\",\ + \"belongingToTypes\": [\"com.example.utdtest2.document\"],\ + \"FilenameExtensions\": [\".mydocument\", \".mydoc\"],\ + \"mimeTypes\": [\"application/my-document\", \"application/my-doc\"],\ + \"description\": \"My document.\",\ + \"referenceURL\": \"http://www.mycompany.com/my-document.html\",\ + \"iconFile\": \"resources/my-document.png\",\ + \"installerBundles\":[\"com.example.utdtest\"],\ + \"ownerBundle\":\"com.example.utdtest\"\ + }, {\ + \"typeId\": \"com.example.utdtest2.document\",\ + \"belongingToTypes\": [\"general.object\"],\ + \"FilenameExtensions\": [\".mydocument2\", \".mydoc2\"],\ + \"mimeTypes\": [\"application/my-document2\", \"application/my-doc2\"],\ + \"description\": \"My document 2.\",\ + \"referenceURL\": \"hhttp://www.mycompany.com/my-document2.html\",\ + \"iconFile\": \"resources/my-document2.png\",\ + \"installerBundles\":[\"com.example.utdtest2\", \"com.example.utdtest\"],\ + \"ownerBundle\":\"com.example.utdtest2\"\ + }]}"; + +class CustomUtdStoreTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void CustomUtdStoreTest::SetUpTestCase() +{ +} + +void CustomUtdStoreTest::TearDownTestCase() +{ +} + +void CustomUtdStoreTest::SetUp() +{ +} + +void CustomUtdStoreTest::TearDown() +{ + if (remove(TEST_CFG_FILE) == 0) { + rmdir(TEST_CFG_DIR); + LOG_INFO(UDMF_TEST, "Removed file success, %{public}s.", TEST_CFG_FILE); + } else { + LOG_INFO(UDMF_TEST, "Failed to remove the file., %{public}s.", TEST_CFG_FILE); + } +} + +/** +* @tc.name: SaveTypeCfgs001 +* @tc.desc: SaveTypeCfgs +* @tc.type: FUNC +*/ +HWTEST_F(CustomUtdStoreTest, SaveTypeCfgs001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "SaveTypeCfgs001 begin."); + std::vector typesCfg; + CustomUtdJsonParser parser; + parser.ParseStoredCustomUtdJson(TEST_DATA2, typesCfg); + auto status = CustomUtdStore::GetInstance().SaveTypeCfgs(typesCfg, TEST_CFG_FILE); + EXPECT_EQ(status, E_OK); + + typesCfg.clear(); + typesCfg = CustomUtdStore::GetInstance().GetTypeCfgs(TEST_CFG_FILE); + TypeDescriptorCfg type1 = *(typesCfg.begin()); + EXPECT_EQ(type1.typeId, "com.example.utdtest.document"); + EXPECT_EQ(*(type1.belongingToTypes.begin()), "com.example.utdtest2.document"); + EXPECT_EQ(*(type1.filenameExtensions.begin()), ".mydocument"); + EXPECT_EQ(*(type1.mimeTypes.begin()), "application/my-document"); + EXPECT_EQ(type1.description, "My document."); + EXPECT_EQ(type1.referenceURL, "http://www.mycompany.com/my-document.html"); + EXPECT_EQ(type1.iconFile, "resources/my-document.png"); + EXPECT_EQ(*(type1.installerBundles.begin()), "com.example.utdtest"); + EXPECT_EQ(type1.ownerBundle, "com.example.utdtest"); + + LOG_INFO(UDMF_TEST, "SaveTypeCfgs001 end."); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d071b5998148e08b7a08e972b8b3d489fdb9a0eb --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/graph_test.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "logger.h" +#include "utd_common.h" +#include "graph.h" + +using namespace testing::ext; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +enum TestNodes : uint32_t { + POINT_A = 0, + POINT_B, + POINT_C, + POINT_D, + POINT_E, + POINT_F, + POINT_G, + POINT_H +}; +class GraphTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void GraphTest::SetUpTestCase() +{ +} + +void GraphTest::TearDownTestCase() +{ +} + +void GraphTest::SetUp() +{ +} + +void GraphTest::TearDown() +{ +} + +/** +* @tc.name: DfsUnconnectedGraph001 +* @tc.desc: DfsUnconnectedGraph +* @tc.type: FUNC +*/ +HWTEST_F(GraphTest, DfsUnconnectedGraph001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DfsUnconnectedGraph001 begin."); + uint32_t vextexNum = 3; // total point + vector> edges={{TestNodes::POINT_A, TestNodes::POINT_B}, + {TestNodes::POINT_B, TestNodes::POINT_C}, + {TestNodes::POINT_C, TestNodes::POINT_A} + }; + Graph graph(vextexNum); + for (uint32_t i = 0; i < edges.size(); i++) { + graph.AddEdge(edges[i][0], edges[i][1]); + } + bool isDAGFlag = graph.DfsUnconnectedGraph([&](uint32_t currNode) -> bool + { return false; }); + EXPECT_EQ(isDAGFlag, false); + LOG_INFO(UDMF_TEST, "DfsUnconnectedGraph001 end."); +} + +HWTEST_F(GraphTest, DfsUnconnectedGraph002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DfsUnconnectedGraph002 begin."); + uint32_t vextexNum = 2; + vector> edges={{TestNodes::POINT_A, TestNodes::POINT_B}, + {TestNodes::POINT_B, TestNodes::POINT_A}, + }; + Graph graph(vextexNum); + for (uint32_t i = 0; i < edges.size(); i++) { + graph.AddEdge(edges[i][0], edges[i][1]); + } + bool isDAGFlag = graph.DfsUnconnectedGraph([&](uint32_t currNode) -> bool + { return false; }); + EXPECT_EQ(isDAGFlag, false); + LOG_INFO(UDMF_TEST, "DfsUnconnectedGraph002 end."); +} + +HWTEST_F(GraphTest, DfsUnconnectedGraph003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "DfsUnconnectedGraph003 begin."); + uint32_t vextexNum =8; + vector> edges = { + {TestNodes::POINT_A, TestNodes::POINT_B}, + {TestNodes::POINT_B, TestNodes::POINT_C}, + {TestNodes::POINT_C, TestNodes::POINT_D}, + {TestNodes::POINT_D, TestNodes::POINT_E}, + {TestNodes::POINT_D, TestNodes::POINT_E}, + {TestNodes::POINT_E, TestNodes::POINT_F}, + {TestNodes::POINT_E, TestNodes::POINT_G}, + {TestNodes::POINT_G, TestNodes::POINT_H}, + {TestNodes::POINT_H, TestNodes::POINT_E}, + }; + Graph graph(vextexNum); + for (uint32_t i = 0; i < edges.size(); i++) { + graph.AddEdge(edges[i][0], edges[i][1]); + } + bool isDAGFlag = graph.DfsUnconnectedGraph([&](uint32_t currNode) -> bool + { return false; }); + EXPECT_EQ(isDAGFlag, true); + LOG_INFO(UDMF_TEST, "DfsUnconnectedGraph003 end."); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp index 24d20d489430f1a2b27de16c83336551b2129352..f779d78448b883139bd75a11ab844a6304969c75 100644 --- a/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp +++ b/udmf/framework/innerkitsimpl/test/unittest/udmf_client_test.cpp @@ -50,7 +50,7 @@ public: void SetUp() override; void TearDown() override; - void SetNativeToken(); + void SetNativeToken(const std::string &processName); static void AllocHapToken1(); static void AllocHapToken2(); void SetHapToken1(); @@ -87,9 +87,9 @@ void UdmfClientTest::TearDown() { } -void UdmfClientTest::SetNativeToken() +void UdmfClientTest::SetNativeToken(const std::string &processName) { - auto tokenId = AccessTokenKit::GetNativeTokenId("msdp_sa"); + auto tokenId = AccessTokenKit::GetNativeTokenId(processName); SetSelfTokenID(tokenId); } @@ -187,7 +187,7 @@ void UdmfClientTest::AddPrivilege(QueryOption &option) privilege.tokenId = AccessTokenKit::GetHapTokenID(USER_ID, "ohos.test.demo2", INST_INDEX); privilege.readPermission = "readPermission"; privilege.writePermission = "writePermission"; - SetNativeToken(); + SetNativeToken("msdp_sa"); auto status = UdmfClient::GetInstance().AddPrivilege(option, privilege); ASSERT_EQ(status, E_OK); } @@ -1310,7 +1310,7 @@ HWTEST_F(UdmfClientTest, AddPrivilege001, TestSize.Level1) privilege.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo2", 0); privilege.readPermission = "readPermission"; privilege.writePermission = "writePermission"; - SetNativeToken(); + SetNativeToken("msdp_sa"); status = UdmfClient::GetInstance().AddPrivilege(option2, privilege); ASSERT_EQ(status, E_OK); @@ -1366,6 +1366,72 @@ HWTEST_F(UdmfClientTest, AddPrivilege002, TestSize.Level1) LOG_INFO(UDMF_FRAMEWORK, "AddPrivilege002 end."); } +/** +* @tc.name: AddPrivilege003 +* @tc.desc: Add privilege with invalid intention +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, AddPrivilege003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege003 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DATA_HUB }; + UnifiedData data; + Text text; + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text.SetDetails(details); + std::shared_ptr record = std::make_shared(text); + data.AddRecord(record); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + Privilege privilege; + SetHapToken2(); + privilege.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo2", 0); + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + SetNativeToken("msdp_sa"); + status = UdmfClient::GetInstance().AddPrivilege(option2, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege003 end."); +} + +/** +* @tc.name: AddPrivilege004 +* @tc.desc: Add privilege for unauthorized process with valid params +* @tc.type: FUNC +*/ +HWTEST_F(UdmfClientTest, AddPrivilege004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "AddPrivilege004 begin."); + + CustomOption option1 = { .intention = Intention::UD_INTENTION_DRAG }; + UnifiedData data; + Text text; + UDDetails details; + details.insert({ "udmf_key", "udmf_value" }); + text.SetDetails(details); + std::shared_ptr record = std::make_shared(text); + data.AddRecord(record); + std::string key; + auto status = UdmfClient::GetInstance().SetData(option1, data, key); + ASSERT_EQ(status, E_OK); + + QueryOption option2 = { .key = key }; + Privilege privilege; + SetHapToken2(); + privilege.tokenId = AccessTokenKit::GetHapTokenID(100, "ohos.test.demo2", 0); + privilege.readPermission = "readPermission"; + privilege.writePermission = "writePermission"; + SetNativeToken("foundation"); + status = UdmfClient::GetInstance().AddPrivilege(option2, privilege); + ASSERT_EQ(status, E_NO_PERMISSION); + LOG_INFO(UDMF_TEST, "AddPrivilege004 end."); +} + /** * @tc.name: GetSelfData001 * @tc.desc: Set File record with valid params and no add privilege and get data by self diff --git a/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a20c4f62206405ae325591a15057a6a9cb9d4ece --- /dev/null +++ b/udmf/framework/innerkitsimpl/test/unittest/utd_client_test.cpp @@ -0,0 +1,694 @@ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +#include "token_setproc.h" +#include "accesstoken_kit.h" +#include "nativetoken_kit.h" + +#include "logger.h" +#include "utd_client.h" +#include "type_descriptor.h" + + +using namespace testing::ext; +using namespace OHOS::Security::AccessToken; +using namespace OHOS::UDMF; +using namespace OHOS; +namespace OHOS::Test { +class UtdClientTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp() override; + void TearDown() override; +}; + +void UtdClientTest::SetUpTestCase() +{ +} + +void UtdClientTest::TearDownTestCase() +{ +} + +void UtdClientTest::SetUp() +{ +} + +void UtdClientTest::TearDown() +{ +} + +/** +* @tc.name: GetTypeDescriptor001 +* @tc.desc: Normal testcase of GetTypeDescriptor +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptor001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptor001 begin."); + + std::shared_ptr descriptor; + std::string typeId = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), typeId); + EXPECT_EQ(*(descriptor->GetBelongingToTypes().begin()), "general.ebook"); + EXPECT_EQ(descriptor->GetDescription(), "AZW3 ebook."); + EXPECT_EQ(descriptor->GetIconFile(), ""); + LOG_INFO(UDMF_TEST, "GetTypeDescriptor001 end."); +} + +/** +* @tc.name: GetTypeDescriptor002 +* @tc.desc: Negative test case, invalid typeId argument, returns nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptor002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptor002 begin."); + + std::shared_ptr descriptor; + std::string typeId = ""; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor, nullptr); + LOG_INFO(UDMF_TEST, "GetTypeDescriptor002 end."); +} + +/** +* @tc.name: GetTypeDescriptor003 +* @tc.desc: Negative test case, invalid typeId argument, returns nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptor003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptor003 begin."); + + std::shared_ptr descriptor; + std::string typeId = "12345"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor, nullptr); + LOG_INFO(UDMF_TEST, "GetTypeDescriptor003 end."); +} + +/** +* @tc.name: GetTypeDescriptor004 +* @tc.desc: Normal testcase of GetTypeDescriptor +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptor004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptor004 begin."); + + std::shared_ptr descriptor; + std::string typeId = "org.gnu.gnu-zip-archive"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), typeId); + EXPECT_EQ(*(descriptor->GetBelongingToTypes().begin()), "general.archive"); + EXPECT_EQ(descriptor->GetDescription(), "Gzip archive."); + EXPECT_EQ(descriptor->GetIconFile(), ""); + LOG_INFO(UDMF_TEST, "GetTypeDescriptor004 end."); +} + +/** +* @tc.name: GetTypeDescriptor005 +* @tc.desc: Negative test case, invalid typeId argument, returns nullptr +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetTypeDescriptor005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetTypeDescriptor005 begin."); + + std::shared_ptr descriptor; + std::string typeId = "..."; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor, nullptr); + LOG_INFO(UDMF_TEST, "GetTypeDescriptor005 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtension001 +* @tc.desc: Normal testcase of GetUniformDataTypeByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtension001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension001 begin."); + std::string filenameExtension = ".azw3"; + std::string blongsToType = "general.ebook"; + std::string currType; + auto status = + UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, "com.amazon.azw3"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtension002 +* @tc.desc: Normal testcase of GetUniformDataTypeByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtension002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension002 begin."); + std::string filenameExtension = ".png"; + std::string blongsToType = "general.image"; + std::string currType; + auto status = + UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, "general.png"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtension003 +* @tc.desc: Normal testcase of GetUniformDataTypeByFilenameExtension +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtension003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension003 begin."); + std::string filenameExtension = ".cpp"; + std::string blongsToType = "general.source-code"; + std::string currType; + auto status = + UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, "general.c-plus-plus-source"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension003 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtension004 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension, return "" +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtension004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension004 begin."); + std::string filenameExtension = ""; + std::string blongsToType = "general.plain-text"; + std::string currType; + auto status = + UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, ""); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension004 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtension005 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension, return invalid parameter +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtension005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension005 begin."); + std::string filenameExtension = ".test"; + std::string blongsToType = "general.test"; + std::string currType; + auto status = + UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, currType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension005 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtension006 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension, return "" +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtension006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension006 begin."); + std::string filenameExtension = ".mp3"; + std::string blongsToType = "general.object"; + std::string currType; + auto status = + UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, ""); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension006 end."); +} + +/** +* @tc.name: GetUniformDataTypeByFilenameExtension007 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByFilenameExtension, return invalid parameter +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByFilenameExtension007, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension007 begin."); + std::string filenameExtension = ".mp3"; + std::string blongsToType = "test"; + std::string currType; + auto status = + UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, currType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByFilenameExtension007 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMEType001 +* @tc.desc: Normal testcase of GetUniformDataTypeByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMEType001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType001 begin."); + std::string mimeType = "application/x-mobi8-ebook"; + std::string blongsToType = "general.ebook"; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, "com.amazon.azw3"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType001 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMEType002 +* @tc.desc: Normal testcase of GetUniformDataTypeByMIMEType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMEType002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType002 begin."); + std::string mimeType = "application/mspowerpoint"; + std::string blongsToType = "general.composite-object"; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, "com.microsoft.powerpoint.ppt"); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType002 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMEType003 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByMIMEType, return invalid parameter +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMEType003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType003 begin."); + std::string mimeType = "test01"; + std::string blongsToType = ""; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType003 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMEType004 +* @tc.desc: BelongsTo is invalid, return invalid parameter +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMEType004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType004 begin."); + std::string mimeType = ""; + std::string blongsToType = "test02"; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType004 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMEType005 +* @tc.desc: BelongsTo is invalid, return invalid parameter +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMEType005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType005 begin."); + std::string mimeType = ".pm"; + std::string blongsToType = "test03"; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType005 end."); +} + +/** +* @tc.name: GetUniformDataTypeByMIMEType006 +* @tc.desc: Abnormal testcase of GetUniformDataTypeByMIMEType, return "" +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, GetUniformDataTypeByMIMEType006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType006 begin."); + std::string mimeType = ""; + std::string blongsToType = "general.entity"; + std::string currType; + auto status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, currType, blongsToType); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(currType, ""); + LOG_INFO(UDMF_TEST, "GetUniformDataTypeByMIMEType006 end."); +} +/** +* @tc.name: BelongsTo001 +* @tc.desc: Normal testcase of BelongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, BelongsTo001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "BelongsTo001 begin."); + std::shared_ptr descriptor; + std::string typeId = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->BelongsTo("general.composite-object", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, true); + LOG_INFO(UDMF_TEST, "BelongsTo001 end."); +} + +/** +* @tc.name: BelongsTo002 +* @tc.desc: Normal testcase of BelongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, BelongsTo002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "BelongsTo002 begin."); + std::shared_ptr descriptor; + std::string typeId = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->BelongsTo(typeId, checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, true); + LOG_INFO(UDMF_TEST, "BelongsTo002 end."); +} + +/** +* @tc.name: BelongsTo003 +* @tc.desc: Normal testcase of BelongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, BelongsTo003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "BelongsTo003 begin."); + std::shared_ptr descriptor; + std::string typeId = "general.tiff"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->BelongsTo("general.media", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, true); + LOG_INFO(UDMF_TEST, "BelongsTo003 end."); +} + +/** +* @tc.name: BelongsTo004 +* @tc.desc: Normal testcase of BelongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, BelongsTo004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "BelongsTo004 begin."); + std::shared_ptr descriptor; + std::string typeId = "general.tiff"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->BelongsTo("general.object", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, true); + LOG_INFO(UDMF_TEST, "BelongsTo004 end."); +} + +/** +* @tc.name: BelongsTo005 +* @tc.desc: Abnormal testcase of BelongsTo +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, BelongsTo005, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "BelongsTo005 begin."); + std::shared_ptr descriptor; + std::string typeId = "general.c-header"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->BelongsTo("general.script", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, false); + LOG_INFO(UDMF_TEST, "BelongsTo005 end."); +} + +/** +* @tc.name: BelongsTo006 +* @tc.desc: BelongsTo is invalid, return invalid parameter +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, BelongsTo006, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "BelongsTo006 begin."); + std::shared_ptr descriptor; + std::string typeId = "general.mpeg"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->BelongsTo("test04", checkRet); + EXPECT_EQ(status, E_INVALID_PARAMETERS); + EXPECT_EQ(checkRet, false); + LOG_INFO(UDMF_TEST, "BelongsTo006 end."); +} + +/** +* @tc.name: IsLowerLevelType001 +* @tc.desc: Normal testcase of IsLowerLevelType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, IsLowerLevelType001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsLowerLevelType001 begin."); + std::shared_ptr descriptor; + std::string typeId = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->IsLowerLevelType("general.composite-object", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, true); + LOG_INFO(UDMF_TEST, "IsLowerLevelType001 end."); +} + +/** +* @tc.name: IsLowerLevelType002 +* @tc.desc: TypeId is "', return invalid parameter +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, IsLowerLevelType002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsLowerLevelType002 begin."); + std::shared_ptr descriptor; + std::string typeId = "general.object"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->IsLowerLevelType("", checkRet); + EXPECT_EQ(status, Status::E_INVALID_PARAMETERS); + EXPECT_EQ(checkRet, false); + LOG_INFO(UDMF_TEST, "IsLowerLevelType002 end."); +} + +/** +* @tc.name: IsLowerLevelType003 +* @tc.desc: Normal testcase of IsLowerLevelType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, IsLowerLevelType003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsLowerLevelType003 begin."); + std::shared_ptr descriptor; + std::string typeId = "com.microsoft.bmp"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->IsLowerLevelType("general.object", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, true); + LOG_INFO(UDMF_TEST, "IsLowerLevelType003 end."); +} + +/** +* @tc.name: IsLowerLevelType004 +* @tc.desc: Abnormal testcase of IsLowerLevelType, the two values are equal +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, IsLowerLevelType004, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsLowerLevelType004 begin."); + std::shared_ptr descriptor; + std::string typeId = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->IsLowerLevelType("com.amazon.azw3", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, false); + LOG_INFO(UDMF_TEST, "IsLowerLevelType004 end."); +} + +/** +* @tc.name: IsHigherLevelType001 +* @tc.desc: Normal testcase of IsHigherLevelType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, IsHigherLevelType001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsHigherLevelType001 begin."); + std::shared_ptr descriptor; + std::string typeId = "general.composite-object"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->IsHigherLevelType("com.amazon.azw3", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, true); + LOG_INFO(UDMF_TEST, "IsHigherLevelType001 end."); +} + +/** +* @tc.name: IsHigherLevelType002 +* @tc.desc: Abnormal testcase of IsHigherLevelType, the two values are equal +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, IsHigherLevelType002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsHigherLevelType002 begin."); + std::shared_ptr descriptor; + std::string typeId = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->IsHigherLevelType("com.amazon.azw3", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, false); + LOG_INFO(UDMF_TEST, "IsHigherLevelType002 end."); +} + +/** +* @tc.name: IsHigherLevelType003 +* @tc.desc: Abnormal testcase of IsHigherLevelType +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, IsHigherLevelType003, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "IsHigherLevelType003 begin."); + std::shared_ptr descriptor; + std::string typeId = "general.image"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + bool checkRet = false; + ASSERT_NE(descriptor, nullptr); + status = descriptor->IsHigherLevelType("general.object", checkRet); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(checkRet, false); + LOG_INFO(UDMF_TEST, "IsHigherLevelType003 end."); +} + +/** +* @tc.name: Equals001 +* @tc.desc: Abnormal testcase of Equals, two values are different +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, Equals001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Equals001 begin."); + std::shared_ptr descriptor1; + std::string typeId1 = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId1, descriptor1); + EXPECT_EQ(status, E_OK); + std::string typeId2 = "general.composite-object"; + std::shared_ptr descriptor2; + status = UtdClient::GetInstance().GetTypeDescriptor(typeId2, descriptor2); + EXPECT_EQ(status, E_OK); + bool ret = descriptor1->Equals(descriptor2); + EXPECT_EQ(ret, false); + LOG_INFO(UDMF_TEST, "Equals001 end."); +} + +/** +* @tc.name: Equals002 +* @tc.desc: Normal testcase of Equals +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, Equals002, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "Equals002 begin."); + std::shared_ptr descriptor1; + std::string typeId1 = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId1, descriptor1); + EXPECT_EQ(status, E_OK); + std::string typeId2 = "com.amazon.azw3"; + std::shared_ptr descriptor2; + status = UtdClient::GetInstance().GetTypeDescriptor(typeId2, descriptor2); + EXPECT_EQ(status, E_OK); + bool ret = descriptor1->Equals(descriptor2); + EXPECT_EQ(ret, true); + LOG_INFO(UDMF_TEST, "Equals002 end."); +} + +/** +* @tc.name: TypeDescriptorGetAttr001 +* @tc.desc: Normal testcase of TypeDescriptorGetAttr +* @tc.type: FUNC +*/ +HWTEST_F(UtdClientTest, TypeDescriptorGetAttr001, TestSize.Level1) +{ + LOG_INFO(UDMF_TEST, "TypeDescriptorGetAttr001 begin."); + std::shared_ptr descriptor; + std::string typeId = "com.amazon.azw3"; + auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); + EXPECT_EQ(status, E_OK); + EXPECT_EQ(descriptor->GetTypeId(), typeId); + EXPECT_EQ(*(descriptor->GetBelongingToTypes().begin()), "general.ebook"); + EXPECT_EQ(descriptor->GetDescription(), "AZW3 ebook."); + EXPECT_EQ(descriptor->GetIconFile(), ""); + EXPECT_EQ(*(descriptor->GetFilenameExtensions().begin()), ".azw3"); + EXPECT_EQ(*(descriptor->GetMimeTypes().begin()), "application/vnd.amazon.mobi8-ebook"); + + LOG_INFO(UDMF_TEST, "TypeDescriptorGetAttr001 end."); +} +} // OHOS::Test \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/common/napi_data_utils.cpp b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp index 3dd0f5eeefef3409b37ebabde0bb4e92a12a10f0..abb2fe0e905f1032e8fba0d871466877d4ce3aed 100644 --- a/udmf/framework/jskitsimpl/common/napi_data_utils.cpp +++ b/udmf/framework/jskitsimpl/common/napi_data_utils.cpp @@ -94,21 +94,24 @@ napi_status NapiDataUtils::SetValue(napi_env env, const double &in, napi_value & /* napi_value <-> std::string */ napi_status NapiDataUtils::GetValue(napi_env env, napi_value in, std::string &out) { + LOG_DEBUG(UDMF_KITS_NAPI, "napi_value <- string"); + napi_valuetype type = napi_undefined; + napi_status status = napi_typeof(env, in, &type); + LOG_ERROR_RETURN((status == napi_ok) && (type == napi_string), "invalid type", napi_invalid_arg); + size_t maxLen = STR_MAX_LENGTH; - napi_status status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen); + status = napi_get_value_string_utf8(env, in, NULL, 0, &maxLen); if (maxLen == 0) { - GET_AND_THROW_LAST_ERROR(env); return status; } char *buf = new (std::nothrow) char[maxLen + STR_TAIL_LENGTH]; if (buf != nullptr) { size_t len = 0; status = napi_get_value_string_utf8(env, in, buf, maxLen + STR_TAIL_LENGTH, &len); - if (status != napi_ok) { - GET_AND_THROW_LAST_ERROR(env); + if (status == napi_ok) { + buf[len] = 0; + out = std::string(buf); } - buf[len] = 0; - out = std::string(buf); delete[] buf; } else { status = napi_generic_failure; diff --git a/udmf/framework/jskitsimpl/data/type_descriptor_napi.cpp b/udmf/framework/jskitsimpl/data/type_descriptor_napi.cpp index 0d916dfa836c739bbbef7fe005ee36b40eaa9a9f..972d15c89f2070052c02ed9cbe8ded44c5956117 100644 --- a/udmf/framework/jskitsimpl/data/type_descriptor_napi.cpp +++ b/udmf/framework/jskitsimpl/data/type_descriptor_napi.cpp @@ -16,6 +16,7 @@ #include "type_descriptor_napi.h" #include "utd_client.h" #include "napi_data_utils.h" +#include "napi_error_utils.h" namespace OHOS { namespace UDMF { @@ -23,7 +24,10 @@ napi_value TypeDescriptorNapi::Constructor(napi_env env) { LOG_DEBUG(UDMF_KITS_NAPI, "typeDescriptorNapi"); napi_property_descriptor properties[] = { - /* UnifiedData properties */ + /* TypeDescriptor properties */ + DECLARE_NAPI_FUNCTION("belongsTo", BelongsTo), + DECLARE_NAPI_FUNCTION("isLowerLevelType", IsLowerLevelType), + DECLARE_NAPI_FUNCTION("isHigherLevelType", IsHigherLevelType), DECLARE_NAPI_FUNCTION("equals", Equals), DECLARE_NAPI_GETTER_SETTER("typeId", GetTypeId, nullptr), DECLARE_NAPI_GETTER_SETTER("belongingToTypes", GetBelongingToTypes, nullptr), @@ -76,6 +80,72 @@ TypeDescriptorNapi *TypeDescriptorNapi::GetDescriptorNapi(napi_env env, napi_cal return static_cast(ctxt->native); } +napi_value TypeDescriptorNapi::BelongsTo(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TypeDescriptorNapi::BelongsTo()"); + auto ctxt = std::make_shared(); + std::string typeId; + auto input = [env, ctxt, &typeId](size_t argc, napi_value* argv) { + // required 1 arguments : descriptor + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], typeId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "invalid arg[0], i.e. invalid arguments!"); + }; + + ctxt->GetCbInfoSync(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "BelongsTo Exit"); + bool checkRet = false; + Status status = reinterpret_cast(ctxt->native)->value_->BelongsTo(typeId, checkRet); + ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); + napi_get_boolean(env, checkRet, &ctxt->output); + return ctxt->output; +} + +napi_value TypeDescriptorNapi::IsLowerLevelType(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TypeDescriptorNapi::IsLowerLevelType()"); + auto ctxt = std::make_shared(); + std::string typeId; + auto input = [env, ctxt, &typeId](size_t argc, napi_value* argv) { + // required 1 arguments : descriptor + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], typeId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "invalid arg[0], i.e. invalid arguments!"); + }; + + ctxt->GetCbInfoSync(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "IsLowerLevelType Exit"); + bool checkRet = false; + Status status = reinterpret_cast(ctxt->native)->value_->IsLowerLevelType(typeId, checkRet); + ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); + napi_get_boolean(env, checkRet, &ctxt->output); + return ctxt->output; +} + +napi_value TypeDescriptorNapi::IsHigherLevelType(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "TypeDescriptorNapi::IsHigherLevelType()"); + auto ctxt = std::make_shared(); + std::string typeId; + auto input = [env, ctxt, &typeId](size_t argc, napi_value* argv) { + // required 1 arguments : descriptor + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], typeId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "invalid arg[0], i.e. invalid arguments!"); + }; + + ctxt->GetCbInfoSync(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "IsHigherLevelType Exit"); + bool checkRet = false; + Status status = reinterpret_cast(ctxt->native)->value_->IsHigherLevelType(typeId, checkRet); + ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); + napi_get_boolean(env, checkRet, &ctxt->output); + return ctxt->output; +} + napi_value TypeDescriptorNapi::Equals(napi_env env, napi_callback_info info) { LOG_DEBUG(UDMF_KITS_NAPI, "TypeDescriptorNapi::Equals()"); @@ -85,10 +155,12 @@ napi_value TypeDescriptorNapi::Equals(napi_env env, napi_callback_info info) // required 1 arguments : descriptor ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); ctxt->status = NapiDataUtils::GetValue(env, argv[0], typeDescriptor); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "invalid arg[0], i.e. invalid arguments!"); }; - ctxt->GetCbInfo(env, info, input); - NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!"); + ctxt->GetCbInfoSync(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "Equals Exit"); bool equalsRet = reinterpret_cast(ctxt->native)->value_->Equals(typeDescriptor); napi_get_boolean(env, equalsRet, &ctxt->output); return ctxt->output; diff --git a/udmf/framework/jskitsimpl/data/uniform_type_descriptor_napi.cpp b/udmf/framework/jskitsimpl/data/uniform_type_descriptor_napi.cpp index 52220a16514ae9c459c6920c52056d1166bb1ce6..66568c1e132b43e765ce8e4906cb583133905040 100644 --- a/udmf/framework/jskitsimpl/data/uniform_type_descriptor_napi.cpp +++ b/udmf/framework/jskitsimpl/data/uniform_type_descriptor_napi.cpp @@ -14,7 +14,6 @@ */ #include "uniform_type_descriptor_napi.h" - #include "napi_data_utils.h" #include "napi_error_utils.h" #include "napi_queue.h" @@ -32,6 +31,8 @@ napi_value UniformTypeDescriptorNapi::UniformTypeDescriptorInit(napi_env env, na napi_property_descriptor desc[] = { DECLARE_NAPI_PROPERTY("UniformDataType", uniformDataType), DECLARE_NAPI_FUNCTION("getTypeDescriptor", GetTypeDescriptor), + DECLARE_NAPI_FUNCTION("getUniformDataTypeByFilenameExtension", GetUniformDataTypeByFilenameExtension), + DECLARE_NAPI_FUNCTION("getUniformDataTypeByMIMEType", GetUniformDataTypeByMIMEType), }; NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc)); @@ -68,19 +69,96 @@ napi_value UniformTypeDescriptorNapi::GetTypeDescriptor(napi_env env, napi_callb auto input = [env, ctxt, &typeId](size_t argc, napi_value* argv) { LOG_DEBUG(UDMF_KITS_NAPI, "GetTypeDescriptor, argc = %{public}zu !", argc); // required 1 arguments : typeId - ASSERT_BUSINESS_ERR(ctxt, argc == 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); ctxt->status = NapiDataUtils::GetValue(env, argv[0], typeId); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "invalid arg[0], i.e. invalid arguments!"); }; ctxt->GetCbInfoSync(env, info, input); - NAPI_ASSERT(env, ctxt->status == napi_ok, "invalid arguments!"); + ASSERT_NULL(!ctxt->isThrowError, "GetTypeDescriptor Exit"); std::shared_ptr descriptor; auto status = UtdClient::GetInstance().GetTypeDescriptor(typeId, descriptor); - ASSERT_ERR(ctxt->env, status == E_OK, Status::E_ERROR, "invalid arguments!"); + ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); TypeDescriptorNapi::NewInstance(env, descriptor, ctxt->output); if (descriptor == nullptr) { // descriptor not found, not exception, need return null object. napi_get_null(env, &ctxt->output); } return ctxt->output; } + +napi_value UniformTypeDescriptorNapi::GetUniformDataTypeByFilenameExtension(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "GetUniformDataTypeByFilenameExtension is called!"); + std::string filenameExtension; + std::string belongsTo; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &filenameExtension, &belongsTo](size_t argc, napi_value* argv) { + LOG_DEBUG(UDMF_KITS_NAPI, "get utd type by fileExtention, argc = %{public}zu !", argc); + // required 1 arguments : typeId + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], filenameExtension); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "invalid arg[0], i.e. invalid arguments!"); + if (argc > 1) { + ctxt->status = NapiDataUtils::GetValue(env, argv[1], belongsTo); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && !belongsTo.empty(), E_INVALID_PARAMETERS, + "invalid arg[1], i.e. invalid arguments!"); + } + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "GetUniformDataTypeByFilenameExtension Exit"); + std::string typeId; + auto status = E_OK; + if (belongsTo.empty()) { + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, typeId); + } else { + status = UtdClient::GetInstance().GetUniformDataTypeByFilenameExtension(filenameExtension, typeId, belongsTo); + } + ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); + if (!typeId.empty()) { + NapiDataUtils::SetValue(env, typeId, ctxt->output); + } else { + napi_get_null(env, &ctxt->output); + } + return ctxt->output; +} + +napi_value UniformTypeDescriptorNapi::GetUniformDataTypeByMIMEType(napi_env env, napi_callback_info info) +{ + LOG_DEBUG(UDMF_KITS_NAPI, "GetUniformDataTypeByMIMEType is called!"); + std::string mimeType; + std::string belongsTo; + auto ctxt = std::make_shared(); + auto input = [env, ctxt, &mimeType, &belongsTo](size_t argc, napi_value* argv) { + LOG_DEBUG(UDMF_KITS_NAPI, "get utd type by MIMEType, argc = %{public}zu !", argc); + // required 1 arguments : typeId + ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::E_INVALID_PARAMETERS, "invalid arguments!"); + ctxt->status = NapiDataUtils::GetValue(env, argv[0], mimeType); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, E_INVALID_PARAMETERS, + "invalid arg[0], i.e. invalid arguments!"); + if (argc > 1) { + ctxt->status = NapiDataUtils::GetValue(env, argv[1], belongsTo); + ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok && !belongsTo.empty(), E_INVALID_PARAMETERS, + "invalid arg[1], i.e. invalid arguments!"); + } + }; + ctxt->GetCbInfoSync(env, info, input); + ASSERT_NULL(!ctxt->isThrowError, "GetUniformDataTypeByMIMEType Exit"); + std::string typeId; + auto status = E_OK; + if (belongsTo.empty()) { + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, typeId); + } else { + status = UtdClient::GetInstance().GetUniformDataTypeByMIMEType(mimeType, typeId, belongsTo); + } + ASSERT_ERR(ctxt->env, status == E_OK, status, "invalid arguments!"); + if (!typeId.empty()) { + NapiDataUtils::SetValue(env, typeId, ctxt->output); + } else { + napi_get_null(env, &ctxt->output); + } + + return ctxt->output; +} } // namespace UDMF } // namespace OHOS \ No newline at end of file diff --git a/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js b/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js index 258369fbf885d23c73c251c91d27656923d9b150..7e6b123b5ce6380f8605e2c13f705e6cf569fcbf 100644 --- a/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js +++ b/udmf/framework/jskitsimpl/unittest/UdmfUtdJsTest.js @@ -17,19 +17,22 @@ import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from import UTD from '@ohos.data.uniformTypeDescriptor'; const ERROR_PARAMETER = '401'; +const INVALID_TYPE1 = 'invalidUtdType'; +const INVALID_TYPE2 = 123456; + describe('UdmfUtdJSTest', function () { /* * @tc.name UdmfTestTypeDescriptor001 - * @tc.desc Test Js Api + * @tc.desc Test Js Api input invalid string * @tc.type: FUNC * @tc.require: issueNumber */ - it('UdmfTestTypeDescriptor001', 0, function () { + it ('UdmfTestTypeDescriptor001', 0, function () { const TAG = 'UdmfTestTypeDescriptor001:'; console.info(TAG, 'start'); - let typeObj = UTD.getTypeDescriptor("general.invallType"); + let typeObj = UTD.getTypeDescriptor('general.invalidType'); console.info(TAG, 'typeDescriptor, ret= ' + typeObj); if (typeObj == null) { console.info(TAG, 'typeDescriptor, typeObj == null is true'); @@ -40,38 +43,46 @@ describe('UdmfUtdJSTest', function () { /* * @tc.name UdmfTestTypeDescriptor002 - * @tc.desc Test Js Api + * @tc.desc Test Js Api * @tc.type: FUNC * @tc.require: issueNumber */ - it('UdmfTestTypeDescriptor002', 0, function () { + it ('UdmfTestTypeDescriptor002', 0, function () { const TAG = 'UdmfTestTypeDescriptor002:'; console.info(TAG, 'start'); - let typeObj = UTD.getTypeDescriptor("com.adobe.photoshop-image"); - console.info(TAG, 'typeDescriptor, typeId ' + typeObj.typeId); - console.info(TAG, 'typeDescriptor, belongingToTypes ' + typeObj.belongingToTypes); - console.info(TAG, 'typeDescriptor, description ' + typeObj.description); - console.info(TAG, 'typeDescriptor, referenceURL ' + typeObj.referenceURL); - console.info(TAG, 'typeDescriptor, iconFile ' + typeObj.iconFile); - expect(typeObj.typeId).assertEqual("com.adobe.photoshop-image"); - expect(typeObj.description).assertEqual("Adobe Photoshop document."); - expect(typeObj.referenceURL).assertEqual(""); - expect(typeObj.iconFile).assertEqual(""); + let typeObj = UTD.getTypeDescriptor('com.adobe.photoshop-image'); + let typeId = typeObj.typeId; + let belonging = typeObj.belongingToTypes; + let description = typeObj.description; + let referenceURL = typeObj.referenceURL; + let iconFile = typeObj.iconFile; + console.info(TAG, ', typeId: ' + typeId + ', ' + Object.prototype.toString.call(typeId) + + ', belongingToTypes: ' + belonging + ', ' + Object.prototype.toString.call(belonging)); + console.info(TAG, 'description: ' + typeObj.description + ', ' + Object.prototype.toString.call(description)); + console.info(TAG, 'referenceURL: ' + referenceURL + ', ' + Object.prototype.toString.call(referenceURL) + + ', iconFile: ' + iconFile + ', ' + Object.prototype.toString.call(iconFile)); + expect(typeObj.typeId).assertEqual(UTD.UniformDataType.PHOTOSHOP_IMAGE); + expect(typeObj.belongingToTypes[0]).assertEqual('general.image'); + expect(typeObj.description).assertEqual('Adobe Photoshop document.'); + let equalStr = 'https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/' + + 'apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype'; + expect(typeObj.referenceURL).assertEqual(equalStr); + expect(typeObj.iconFile).assertEqual(''); console.info(TAG, 'end'); }); /* * @tc.name UdmfTestTypeDescriptor003 - * @tc.desc Test Js Api + * @tc.desc Test Js Api * @tc.type: FUNC * @tc.require: issueNumber */ - it('UdmfTestTypeDescriptor003', 0, function () { + it ('UdmfTestTypeDescriptor003', 0, function () { const TAG = 'UdmfTestTypeDescriptor003:'; console.info(TAG, 'start'); - let typeObj = UTD.getTypeDescriptor("general.type-script"); - let typeObj2 = UTD.getTypeDescriptor("general.python-script"); - let typeObj3 = UTD.getTypeDescriptor("general.python-script"); + let typeObj = UTD.getTypeDescriptor('general.type-script'); + let typeObj2 = UTD.getTypeDescriptor('general.python-script'); + let typeObj3 = UTD.getTypeDescriptor('general.python-script'); console.info(TAG, 'typeDescriptor, ret ' + typeObj); console.info(TAG, 'typeDescriptor, ret ' + typeObj2); let ret = typeObj.equals(typeObj2); @@ -85,31 +96,674 @@ describe('UdmfUtdJSTest', function () { /* * @tc.name UdmfTestTypeDescriptor004 - * @tc.desc Test Js Api + * @tc.desc Test Js Api invalid para type * @tc.type: FUNC * @tc.require: issueNumber */ - it('UdmfTestTypeDescriptor004', 0, function () { + it ('UdmfTestTypeDescriptor004', 0, function () { const TAG = 'UdmfTestTypeDescriptor004:'; console.info(TAG, 'start'); - for (var utdType in UTD.UniformDataType) { - console.info(TAG, 'typeDescriptor, utdType=' + UTD.UniformDataType[utdType] + ", " + - Object.prototype.toString.call(UTD.UniformDataType[utdType])); + try { + let typeObj = UTD.getTypeDescriptor(null); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor005 + * @tc.desc Test Js Api + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor005', 0, function () { + const TAG = 'UdmfTestTypeDescriptor005:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('com.adobe.photoshop-image', INVALID_TYPE1, INVALID_TYPE2); + let typeId = typeObj.typeId; + let belonging = typeObj.belongingToTypes; + let description = typeObj.description; + let referenceURL = typeObj.referenceURL; + let iconFile = typeObj.iconFile; + console.info(TAG, ', typeId: ' + typeId + ', ' + Object.prototype.toString.call(typeId) + + ', belongingToTypes: ' + belonging + ', ' + Object.prototype.toString.call(belonging)); + console.info(TAG, 'description: ' + typeObj.description + ', ' + Object.prototype.toString.call(description)); + console.info(TAG, 'referenceURL: ' + referenceURL + ', ' + Object.prototype.toString.call(referenceURL) + + ', iconFile: ' + iconFile + ', ' + Object.prototype.toString.call(iconFile)); + expect(typeObj.typeId).assertEqual(UTD.UniformDataType.PHOTOSHOP_IMAGE); + expect(typeObj.belongingToTypes[0]).assertEqual('general.image'); + expect(typeObj.description).assertEqual('Adobe Photoshop document.'); + let equalStr = 'https://gitee.com/openharmony/docs/blob/master/en/application-dev/reference/' + + 'apis/js-apis-data-uniformTypeDescriptor.md#uniformdatatype'; + expect(typeObj.referenceURL).assertEqual(equalStr); + expect(typeObj.iconFile).assertEqual(''); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor007 + * @tc.desc Test Js Api foreach all UniformDataType + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor006', 0, function () { + const TAG = 'UdmfTestTypeDescriptor006:'; + console.info(TAG, 'start'); + for (let utdType in UTD.UniformDataType) { let typeObj = UTD.getTypeDescriptor(UTD.UniformDataType[utdType]); if (typeObj != null) { - let typeId = typeObj.typeId; - let belonging = typeObj.belongingToTypes; - let description = typeObj.description; - let referenceURL = typeObj.referenceURL; - let iconFile = typeObj.iconFile; - console.info(TAG, ', typeId: ' + typeId + ", " + Object.prototype.toString.call(typeId) + - ', belongingToTypes: ' + belonging + ", " + Object.prototype.toString.call(belonging)); - console.info(TAG, 'description: ' + ", " + Object.prototype.toString.call(description)); - console.info(TAG, 'referenceURL: ' + referenceURL + ", " + Object.prototype.toString.call(referenceURL) - + ', iconFile: ' + iconFile + ", " + Object.prototype.toString.call(iconFile)); expect(typeObj.typeId).assertEqual(UTD.UniformDataType[utdType]); } } console.info(TAG, 'end'); }); + + /* + * @tc.name UdmfTestTypeDescriptor007 + * @tc.desc Test Js Api getTypeDescriptor no para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor007', 0, function () { + const TAG = 'UdmfTestTypeDescriptor007:'; + console.info(TAG, 'start'); + try{ + let typeObj = UTD.getTypeDescriptor(); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + } catch (e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor008 + * @tc.desc Test Js Api equals invalid para type + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor008', 0, function () { + const TAG = 'UdmfTestTypeDescriptor008:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + try{ + typeObj.equals('1111'); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor009 + * @tc.desc Test Js Api enum value judge part1 + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor009', 0, function () { + const TAG = 'UdmfTestTypeDescriptor009:'; + console.info(TAG, 'start'); + expect(UTD.UniformDataType.TEXT).assertEqual('general.text'); + expect(UTD.UniformDataType.PLAIN_TEXT).assertEqual('general.plain-text'); + expect(UTD.UniformDataType.HTML).assertEqual('general.html'); + expect(UTD.UniformDataType.HYPERLINK).assertEqual('general.hyperlink'); + expect(UTD.UniformDataType.XML).assertEqual('general.xml'); + expect(UTD.UniformDataType.SOURCE_CODE).assertEqual('general.source-code'); + expect(UTD.UniformDataType.SCRIPT).assertEqual('general.script'); + expect(UTD.UniformDataType.SHELL_SCRIPT).assertEqual('general.shell-script'); + expect(UTD.UniformDataType.CSH_SCRIPT).assertEqual('general.csh-script'); + expect(UTD.UniformDataType.PERL_SCRIPT).assertEqual('general.perl-script'); + expect(UTD.UniformDataType.PHP_SCRIPT).assertEqual('general.php-script'); + expect(UTD.UniformDataType.PYTHON_SCRIPT).assertEqual('general.python-script'); + expect(UTD.UniformDataType.RUBY_SCRIPT).assertEqual('general.ruby-script'); + expect(UTD.UniformDataType.TYPE_SCRIPT).assertEqual('general.type-script'); + expect(UTD.UniformDataType.JAVA_SCRIPT).assertEqual('general.java-script'); + expect(UTD.UniformDataType.C_HEADER).assertEqual('general.c-header'); + expect(UTD.UniformDataType.C_SOURCE).assertEqual('general.c-source'); + expect(UTD.UniformDataType.C_PLUS_PLUS_HEADER).assertEqual('general.c-plus-plus-header'); + expect(UTD.UniformDataType.C_PLUS_PLUS_SOURCE).assertEqual('general.c-plus-plus-source'); + expect(UTD.UniformDataType.JAVA_SOURCE).assertEqual('general.java-source'); + expect(UTD.UniformDataType.EBOOK).assertEqual('general.ebook'); + expect(UTD.UniformDataType.EPUB).assertEqual('general.epub'); + expect(UTD.UniformDataType.AZW).assertEqual('com.amazon.azw'); + expect(UTD.UniformDataType.AZW3).assertEqual('com.amazon.azw3'); + expect(UTD.UniformDataType.KFX).assertEqual('com.amazon.kfx'); + expect(UTD.UniformDataType.MOBI).assertEqual('com.amazon.mobi'); + expect(UTD.UniformDataType.MEDIA).assertEqual('general.media'); + expect(UTD.UniformDataType.IMAGE).assertEqual('general.image'); + expect(UTD.UniformDataType.JPEG).assertEqual('general.jpeg'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor010 + * @tc.desc Test Js Api enum value judge part2 + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor010', 0, function () { + const TAG = 'UdmfTestTypeDescriptor010:'; + console.info(TAG, 'start'); + expect(UTD.UniformDataType.PNG).assertEqual('general.png'); + expect(UTD.UniformDataType.RAW_IMAGE).assertEqual('general.raw-image'); + expect(UTD.UniformDataType.TIFF).assertEqual('general.tiff'); + expect(UTD.UniformDataType.BMP).assertEqual('com.microsoft.bmp'); + expect(UTD.UniformDataType.ICO).assertEqual('com.microsoft.ico'); + expect(UTD.UniformDataType.PHOTOSHOP_IMAGE).assertEqual('com.adobe.photoshop-image'); + expect(UTD.UniformDataType.AI_IMAGE).assertEqual('com.adobe.illustrator.ai-image'); + expect(UTD.UniformDataType.WORD_DOC).assertEqual('com.microsoft.word.doc'); + expect(UTD.UniformDataType.EXCEL).assertEqual('com.microsoft.excel.xls'); + expect(UTD.UniformDataType.PPT).assertEqual('com.microsoft.powerpoint.ppt'); + expect(UTD.UniformDataType.PDF).assertEqual('com.adobe.pdf'); + expect(UTD.UniformDataType.POSTSCRIPT).assertEqual('com.adobe.postscript'); + expect(UTD.UniformDataType.ENCAPSULATED_POSTSCRIPT).assertEqual('com.adobe.encapsulated-postscript'); + expect(UTD.UniformDataType.VIDEO).assertEqual('general.video'); + expect(UTD.UniformDataType.AVI).assertEqual('general.avi'); + expect(UTD.UniformDataType.MPEG).assertEqual('general.mpeg'); + expect(UTD.UniformDataType.MPEG4).assertEqual('general.mpeg-4'); + expect(UTD.UniformDataType.VIDEO_3GPP).assertEqual('general.3gpp'); + expect(UTD.UniformDataType.VIDEO_3GPP2).assertEqual('general.3gpp2'); + expect(UTD.UniformDataType.WINDOWS_MEDIA_WM).assertEqual('com.microsoft.windows-media-wm'); + expect(UTD.UniformDataType.WINDOWS_MEDIA_WMV).assertEqual('com.microsoft.windows-media-wmv'); + expect(UTD.UniformDataType.WINDOWS_MEDIA_WMP).assertEqual('com.microsoft.windows-media-wmp'); + expect(UTD.UniformDataType.AUDIO).assertEqual('general.audio'); + expect(UTD.UniformDataType.AAC).assertEqual('general.aac'); + expect(UTD.UniformDataType.AIFF).assertEqual('general.aiff'); + expect(UTD.UniformDataType.ALAC).assertEqual('general.alac'); + expect(UTD.UniformDataType.FLAC).assertEqual('general.flac'); + expect(UTD.UniformDataType.MP3).assertEqual('general.mp3'); + expect(UTD.UniformDataType.OGG).assertEqual('general.ogg'); + expect(UTD.UniformDataType.PCM).assertEqual('general.pcm'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor011 + * @tc.desc Test Js Api enum value judge part3 + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor011', 0, function () { + const TAG = 'UdmfTestTypeDescriptor011:'; + console.info(TAG, 'start'); + expect(UTD.UniformDataType.WINDOWS_MEDIA_WMA).assertEqual('com.microsoft.windows-media-wma'); + expect(UTD.UniformDataType.WAVEFORM_AUDIO).assertEqual('com.microsoft.waveform-audio'); + expect(UTD.UniformDataType.WINDOWS_MEDIA_WMX).assertEqual('com.microsoft.windows-media-wmx'); + expect(UTD.UniformDataType.WINDOWS_MEDIA_WVX).assertEqual('com.microsoft.windows-media-wvx'); + expect(UTD.UniformDataType.WINDOWS_MEDIA_WAX).assertEqual('com.microsoft.windows-media-wax'); + expect(UTD.UniformDataType.FILE).assertEqual('general.file'); + expect(UTD.UniformDataType.DIRECTORY).assertEqual('general.directory'); + expect(UTD.UniformDataType.FOLDER).assertEqual('general.folder'); + expect(UTD.UniformDataType.SYMLINK).assertEqual('general.symlink'); + expect(UTD.UniformDataType.ARCHIVE).assertEqual('general.archive'); + expect(UTD.UniformDataType.BZ2_ARCHIVE).assertEqual('general.bz2-archive'); + expect(UTD.UniformDataType.DISK_IMAGE).assertEqual('general.disk-image'); + expect(UTD.UniformDataType.TAR_ARCHIVE).assertEqual('general.tar-archive'); + expect(UTD.UniformDataType.ZIP_ARCHIVE).assertEqual('general.zip-archive'); + expect(UTD.UniformDataType.JAVA_ARCHIVE).assertEqual('com.sun.java-archive'); + expect(UTD.UniformDataType.GNU_TAR_ARCHIVE).assertEqual('org.gnu.gnu-tar-archive'); + expect(UTD.UniformDataType.GNU_ZIP_ARCHIVE).assertEqual('org.gnu.gnu-zip-archive'); + expect(UTD.UniformDataType.GNU_ZIP_TAR_ARCHIVE).assertEqual('org.gnu.gnu-zip-tar-archive'); + expect(UTD.UniformDataType.CALENDAR).assertEqual('general.calendar'); + expect(UTD.UniformDataType.CONTACT).assertEqual('general.contact'); + expect(UTD.UniformDataType.DATABASE).assertEqual('general.database'); + expect(UTD.UniformDataType.MESSAGE).assertEqual('general.message'); + expect(UTD.UniformDataType.VCARD).assertEqual('general.vcard'); + expect(UTD.UniformDataType.NAVIGATION).assertEqual('general.navigation'); + expect(UTD.UniformDataType.LOCATION).assertEqual('general.location'); + expect(UTD.UniformDataType.OPENHARMONY_FORM).assertEqual('openharmony.form'); + expect(UTD.UniformDataType.OPENHARMONY_APP_ITEM).assertEqual('openharmony.app-item'); + expect(UTD.UniformDataType.OPENHARMONY_PIXEL_MAP).assertEqual('openharmony.pixel-map'); + expect(UTD.UniformDataType.OPENHARMONY_ATOMIC_SERVICE).assertEqual('openharmony.atomic-service'); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor012 + * @tc.desc Test Js Api belongsTo + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor012', 0, function () { + const TAG = 'UdmfTestTypeDescriptor012:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.type-script'); + let ret = typeObj.belongsTo('general.plain-text'); + expect(ret === true).assertTrue(); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor013 + * @tc.desc Test Js Api isLowerLevelType + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor013', 0, function () { + const TAG = 'UdmfTestTypeDescriptor013:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.type-script'); + let ret = typeObj.isLowerLevelType('general.plain-text'); + expect(ret === true).assertTrue(); + console.info(TAG, 'typeDescriptor, ret ' + ret); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor014 + * @tc.desc Test Js Api isLowerLevelType + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor014', 0, function () { + const TAG = 'UdmfTestTypeDescriptor014:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.plain-text'); + let ret = typeObj.isHigherLevelType('general.type-script'); + expect(ret === true).assertTrue(); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor015 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor015', 0, function () { + const TAG = 'UdmfTestTypeDescriptor015:'; + console.info(TAG, 'start'); + let typeId = UTD.getUniformDataTypeByFilenameExtension('.ts', 'general.plain-text'); + expect(typeId === 'general.type-script').assertTrue(); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor016 + * @tc.desc Test Js Api getUniformDataTypeByMIMEType + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it ('UdmfTestTypeDescriptor016', 0, function () { + const TAG = 'UdmfTestTypeDescriptor016:'; + console.info(TAG, 'start'); + let typeId = UTD.getUniformDataTypeByMIMEType('application/vnd.ms-excel', 'general.object'); + expect(typeId === 'com.microsoft.excel.xls').assertTrue(); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor017 + * @tc.desc Test Js Api getUniformDataTypeByMIMEType invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor017', 0, function () { + const TAG = 'UdmfTestTypeDescriptor017:'; + console.info(TAG, 'start'); + try{ + let typeId = UTD.getUniformDataTypeByMIMEType(''); + console.info(TAG, 'getUniformDataTypeByMIMEType, ret ' + typeId); + expect(typeId === null).assertTrue(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect().assertFail(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor018 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor018', 0, function () { + const TAG = 'UdmfTestTypeDescriptor018:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getUniformDataTypeByFilenameExtension(''); + console.info(TAG, 'getUniformDataTypeByFilenameExtension, ret ' + typeId); + expect(typeId === null).assertTrue(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect().assertFail(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor019 + * @tc.desc Test Js Api belongsTo invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor019', 0, function () { + const TAG = 'UdmfTestTypeDescriptor019:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + try { + typeObj.belongsTo('1111'); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor020 + * @tc.desc Test Js Api equals invalid para type + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor020', 0, function () { + const TAG = 'UdmfTestTypeDescriptor020:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + try { + typeObj.isLowerLevelType('1111'); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor021 + * @tc.desc Test Js Api isHigherLevelType invalid para type + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor021', 0, function () { + const TAG = 'UdmfTestTypeDescriptor021:'; + console.info(TAG, 'start'); + let typeObj = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeObj); + try { + typeObj.isHigherLevelType('1111'); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor022 + * @tc.desc Test Js Api belongsTo invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor022', 0, function () { + const TAG = 'UdmfTestTypeDescriptor022:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + typeId.belongsTo(); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor023 + * @tc.desc Test Js Api isLowerLevelType invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor023', 0, function () { + const TAG = 'UdmfTestTypeDescriptor023:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + typeId.isLowerLevelType(); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor024 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor024', 0, function () { + const TAG = 'UdmfTestTypeDescriptor024:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + typeId.isHigherLevelType(); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor025 + * @tc.desc Test Js Api getUniformDataTypeByMIMEType invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor025', 0, function () { + const TAG = 'UdmfTestTypeDescriptor025:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getUniformDataTypeByMIMEType(); + console.info(TAG, 'getUniformDataTypeByMIMEType, ret ' + typeId); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor026 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor026', 0, function () { + const TAG = 'UdmfTestTypeDescriptor026:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getUniformDataTypeByFilenameExtension(); + console.info(TAG, 'getUniformDataTypeByFilenameExtension, ret ' + typeId); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor027 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor027', 0, function () { + const TAG = 'UdmfTestTypeDescriptor027:'; + console.info(TAG, 'start'); + let typeId = UTD.getUniformDataTypeByFilenameExtension('.ts'); + expect(typeId === 'general.type-script').assertTrue(); + console.info(TAG, 'getUniformDataTypeByFilenameExtension, ret ' + typeId); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor028 + * @tc.desc Test Js Api getUniformDataTypeByMIMEType + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor028', 0, function () { + const TAG = 'UdmfTestTypeDescriptor028:'; + console.info(TAG, 'start'); + let typeId = UTD.getUniformDataTypeByMIMEType('application/vnd.ms-excel'); + expect(typeId === 'com.microsoft.excel.xls').assertTrue(); + console.info(TAG, 'getUniformDataTypeByMIMEType, ret ' + typeId); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor029 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor029', 0, function () { + const TAG = 'UdmfTestTypeDescriptor029:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getUniformDataTypeByFilenameExtension('invalidFilenameExtension'); + console.info(TAG, 'getUniformDataTypeByFilenameExtension, ret ' + typeId); + expect(typeId === null).assertTrue(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect().assertFail(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor030 + * @tc.desc Test Js Api getUniformDataTypeByMIMEType + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor030', 0, function () { + const TAG = 'UdmfTestTypeDescriptor030:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getUniformDataTypeByMIMEType('invalidMIMEType'); + console.info(TAG, 'getUniformDataTypeByMIMEType, ret ' + typeId); + expect(typeId === null).assertTrue(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect().assertFail(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor031 + * @tc.desc Test Js Api belongsTo invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor031', 0, function () { + const TAG = 'UdmfTestTypeDescriptor031:'; + console.info(TAG, 'start'); + let typeId = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + let ret = typeId.belongsTo('general.type-script'); + expect(ret === true).assertTrue(); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor032 + * @tc.desc Test Js Api isLowerLevelType invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor032', 0, function () { + const TAG = 'UdmfTestTypeDescriptor032:'; + console.info(TAG, 'start'); + let typeId = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + let ret = typeId.isLowerLevelType('general.type-script'); + expect(ret === false).assertTrue(); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor033 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension invalid para + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor033', 0, function () { + const TAG = 'UdmfTestTypeDescriptor033:'; + console.info(TAG, 'start'); + let typeId = UTD.getTypeDescriptor('general.type-script'); + console.info(TAG, 'typeDescriptor, ret ' + typeId); + let ret = typeId.isHigherLevelType('general.type-script'); + expect(ret === false).assertTrue(); + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor032 + * @tc.desc Test Js Api getUniformDataTypeByFilenameExtension + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor034', 0, function () { + const TAG = 'UdmfTestTypeDescriptor034:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getUniformDataTypeByFilenameExtension('.ts', ''); + console.info(TAG, 'getUniformDataTypeByFilenameExtension, ret ' + typeId); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); + + /* + * @tc.name UdmfTestTypeDescriptor035 + * @tc.desc Test Js Api getUniformDataTypeByMIMEType + * @tc.type: FUNC + * @tc.require: issueNumber + */ + it('UdmfTestTypeDescriptor035', 0, function () { + const TAG = 'UdmfTestTypeDescriptor035:'; + console.info(TAG, 'start'); + try { + let typeId = UTD.getUniformDataTypeByMIMEType('video/3gpp2', ''); + console.info(TAG, 'getUniformDataTypeByMIMEType, ret ' + typeId); + expect().assertFail(); + } catch(e) { + console.error(TAG, `get e. code is ${e.code},message is ${e.message} `); + expect(e.code === ERROR_PARAMETER).assertTrue(); + } + console.info(TAG, 'end'); + }); }); \ No newline at end of file diff --git a/udmf/interfaces/innerkits/BUILD.gn b/udmf/interfaces/innerkits/BUILD.gn index 2f942b89e1441cf3088dd51ed7b16784a1b34011..707f4683f4d4fcc2d1a0c78f62f891d90f6cbf29 100644 --- a/udmf/interfaces/innerkits/BUILD.gn +++ b/udmf/interfaces/innerkits/BUILD.gn @@ -18,9 +18,9 @@ config("udmf_client_config") { "${udmf_interfaces_path}/innerkits/client", "${udmf_interfaces_path}/innerkits/common", "${udmf_interfaces_path}/innerkits/data", - "${udmf_framework_path}/common", - "${udmf_framework_path}/service", + "${udmf_framework_path}/innerkitsimpl/data", + "${udmf_framework_path}/innerkitsimpl/service", "${kv_store_path}/frameworks/common", "//third_party/libuv/include", "//third_party/node/src", @@ -33,9 +33,13 @@ config("udmf_client_config") { ohos_shared_library("udmf_client") { sources = [ - "${udmf_framework_path}/common/preset_type_descriptors.cpp", + "${udmf_framework_path}/common/custom_utd_json_parser.cpp", + "${udmf_framework_path}/common/custom_utd_store.cpp", + "${udmf_framework_path}/common/graph.cpp", "${udmf_framework_path}/common/tlv_util.cpp", "${udmf_framework_path}/common/udmf_types_util.cpp", + "${udmf_framework_path}/common/utd_cfgs_checker.cpp", + "${udmf_framework_path}/common/utd_graph.cpp", "${udmf_framework_path}/innerkitsimpl/client/udmf_client.cpp", "${udmf_framework_path}/innerkitsimpl/client/utd_client.cpp", "${udmf_framework_path}/innerkitsimpl/common/unified_key.cpp", @@ -48,6 +52,7 @@ ohos_shared_library("udmf_client") { "${udmf_framework_path}/innerkitsimpl/data/image.cpp", "${udmf_framework_path}/innerkitsimpl/data/link.cpp", "${udmf_framework_path}/innerkitsimpl/data/plain_text.cpp", + "${udmf_framework_path}/innerkitsimpl/data/preset_type_descriptors.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_appitem.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_form.cpp", "${udmf_framework_path}/innerkitsimpl/data/system_defined_pixelmap.cpp", @@ -57,8 +62,8 @@ ohos_shared_library("udmf_client") { "${udmf_framework_path}/innerkitsimpl/data/unified_data.cpp", "${udmf_framework_path}/innerkitsimpl/data/unified_record.cpp", "${udmf_framework_path}/innerkitsimpl/data/video.cpp", - "${udmf_framework_path}/service/udmf_service_client.cpp", - "${udmf_framework_path}/service/udmf_service_proxy.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_client.cpp", + "${udmf_framework_path}/innerkitsimpl/service/udmf_service_proxy.cpp", ] public_configs = [ ":udmf_client_config" ] @@ -76,6 +81,9 @@ ohos_shared_library("udmf_client") { "samgr:samgr_proxy", ] + public_configs += [ "//third_party/cJSON:cJSON_config" ] + deps = [ "//third_party/cJSON:cjson" ] + innerapi_tags = [ "platformsdk" ] subsystem_name = "distributeddatamgr" diff --git a/udmf/interfaces/innerkits/client/utd_client.h b/udmf/interfaces/innerkits/client/utd_client.h index 6e965007188703fe30f2e43045028ea84508593c..30c5882988f72e1c8ecad9e589b8ea3f25a1a241 100644 --- a/udmf/interfaces/innerkits/client/utd_client.h +++ b/udmf/interfaces/innerkits/client/utd_client.h @@ -19,7 +19,9 @@ #include #include #include - +#include +#include "utd_common.h" +#include "preset_type_descriptors.h" #include "type_descriptor.h" #include "error_code.h" @@ -30,13 +32,19 @@ class UtdClient { public: static UtdClient &GetInstance(); Status GetTypeDescriptor(const std::string &typeId, std::shared_ptr &descriptor); + Status GetUniformDataTypeByFilenameExtension(const std::string &fileExtension, std::string &typeId, + std::string belongsTo = DEFAULT_TYPE_ID); + Status GetUniformDataTypeByMIMEType(const std::string &mimeType, std::string &typeId, + std::string belongsTo = DEFAULT_TYPE_ID); + private: UtdClient(); ~UtdClient(); UtdClient(const UtdClient &obj) = delete; UtdClient &operator=(const UtdClient &obj) = delete; - - std::vector descriptors_; + void Init(); + static constexpr const char* DEFAULT_TYPE_ID = "#default"; + std::vector descriptorCfgs_; }; } // namespace UDMF } // namespace OHOS diff --git a/udmf/interfaces/innerkits/common/error_code.h b/udmf/interfaces/innerkits/common/error_code.h index 22ebbd388e6067a66dc26f235e2384cc263402b9..73ab5265680881708f56dab06ace3c436eebf602 100644 --- a/udmf/interfaces/innerkits/common/error_code.h +++ b/udmf/interfaces/innerkits/common/error_code.h @@ -17,6 +17,7 @@ #define UDMF_ERROR_CODE_H #include + #include #include diff --git a/udmf/interfaces/innerkits/common/unified_meta.h b/udmf/interfaces/innerkits/common/unified_meta.h index fdf1506d1250356a188d5467ffee0b066621513e..67739237a32aa2edbd4c844a7d72136c5c93af5d 100644 --- a/udmf/interfaces/innerkits/common/unified_meta.h +++ b/udmf/interfaces/innerkits/common/unified_meta.h @@ -30,7 +30,10 @@ namespace OHOS { namespace UDMF { enum UDType : int32_t { - TEXT = 0, + ENTITY = 0, + OBJECT, + COMPOSITE_OBJECT, + TEXT, PLAIN_TEXT, HTML, HYPERLINK, @@ -120,10 +123,15 @@ enum UDType : int32_t { SYSTEM_DEFINED_PIXEL_MAP, OPENHARMONY_ATOMIC_SERVICE, APPLICATION_DEFINED_RECORD, + OPENHARMONY_PACKAGE, + OPENHARMONY_HAP, UD_BUTT }; static const std::unordered_map UD_TYPE_MAP { + { ENTITY, "general.entity" }, + { OBJECT, "general.object" }, + { COMPOSITE_OBJECT, "general.composite-object" }, { TEXT, "general.text" }, { PLAIN_TEXT, "general.plain-text" }, { HTML, "general.html" }, @@ -214,10 +222,15 @@ static const std::unordered_map UD_TYPE_MAP { { SYSTEM_DEFINED_PIXEL_MAP, "openharmony.pixel-map" }, { OPENHARMONY_ATOMIC_SERVICE, "openharmony.atomic-service" }, { APPLICATION_DEFINED_RECORD, "ApplicationDefinedType" }, + { OPENHARMONY_PACKAGE, "openharmony.package" }, + { OPENHARMONY_HAP, "openharmony.hap" }, { UD_BUTT, "INVALID"} }; static const std::unordered_map JS_UD_TYPE_NAME_MAP { + { ENTITY, "ENTITY" }, + { OBJECT, "OBJECT" }, + { COMPOSITE_OBJECT, "COMPOSITE_OBJECT" }, { TEXT, "TEXT" }, { PLAIN_TEXT, "PLAIN_TEXT" }, { HTML, "HTML" }, @@ -308,6 +321,8 @@ static const std::unordered_map JS_UD_TYPE_NAME_MAP { { SYSTEM_DEFINED_PIXEL_MAP, "OPENHARMONY_PIXEL_MAP" }, { OPENHARMONY_ATOMIC_SERVICE, "OPENHARMONY_ATOMIC_SERVICE" }, { APPLICATION_DEFINED_RECORD, "APPLICATION_DEFINED_RECORD" }, + { OPENHARMONY_PACKAGE, "OPENHARMONY_PACKAGE" }, + { OPENHARMONY_HAP, "OPENHARMONY_HAP" } }; /* diff --git a/udmf/interfaces/innerkits/data/type_descriptor.h b/udmf/interfaces/innerkits/data/type_descriptor.h index 646b5ce8e6e239e3683cffc9ce03aaca2db41872..d64573c426143110e6d7fd34a6ab1a9ccb50d379 100644 --- a/udmf/interfaces/innerkits/data/type_descriptor.h +++ b/udmf/interfaces/innerkits/data/type_descriptor.h @@ -20,7 +20,9 @@ #include #include #include - +#include +#include "error_code.h" +#include "utd_common.h" namespace OHOS { namespace UDMF { class TypeDescriptor { @@ -28,7 +30,11 @@ public: TypeDescriptor(const std::string &typeId, const std::set &belongingToTypes, const std::vector &filenameExtensions, const std::vector &mimeTypes, const std::string &description, const std::string &referenceURL, const std::string &iconFile); + TypeDescriptor(const TypeDescriptorCfg& typeDescriptorCfg); ~TypeDescriptor(); + Status BelongsTo(const std::string &typeId, bool &checkResult); + Status IsLowerLevelType(const std::string &typeId, bool &checkResult); + Status IsHigherLevelType(const std::string &typeId, bool &checkResult); bool Equals(std::shared_ptr descriptor); const std::string& GetTypeId() const; std::set GetBelongingToTypes(); diff --git a/udmf/interfaces/jskits/BUILD.gn b/udmf/interfaces/jskits/BUILD.gn index f1e1316a9054c6331f222efa8fc7a170133930ff..252d229e6e38ffda40fdc82a72c3dd8ea13e23c7 100644 --- a/udmf/interfaces/jskits/BUILD.gn +++ b/udmf/interfaces/jskits/BUILD.gn @@ -22,7 +22,7 @@ config("udmf_napi_config") { "${udmf_interfaces_path}/jskits/data", "${udmf_framework_path}/common", - "${udmf_framework_path}/service", + "${udmf_framework_path}/innerkits/service", "//third_party/libuv/include", "//third_party/node/src", diff --git a/udmf/interfaces/jskits/data/type_descriptor_napi.h b/udmf/interfaces/jskits/data/type_descriptor_napi.h index ae3103679146748586fdaba11853659e8fe7a1dd..bc6e1ea3e0edefd1c98dd7d7e2c99f1d277bf039 100644 --- a/udmf/interfaces/jskits/data/type_descriptor_napi.h +++ b/udmf/interfaces/jskits/data/type_descriptor_napi.h @@ -28,6 +28,9 @@ namespace UDMF { class TypeDescriptorNapi { public: static void NewInstance(napi_env env, std::shared_ptr in, napi_value &out); + static napi_value BelongsTo(napi_env env, napi_callback_info info); + static napi_value IsLowerLevelType(napi_env env, napi_callback_info info); + static napi_value IsHigherLevelType(napi_env env, napi_callback_info info); static napi_value Equals(napi_env env, napi_callback_info info); static napi_value Constructor(napi_env env); diff --git a/udmf/interfaces/jskits/data/uniform_type_descriptor_napi.h b/udmf/interfaces/jskits/data/uniform_type_descriptor_napi.h index 8e45d827e2ad9cd0bc7bf88732d04b18b1b15aa7..338c845f4932f8b6b0f4d024ea4d5ebdf56a94a6 100644 --- a/udmf/interfaces/jskits/data/uniform_type_descriptor_napi.h +++ b/udmf/interfaces/jskits/data/uniform_type_descriptor_napi.h @@ -27,6 +27,8 @@ class UniformTypeDescriptorNapi { public: static napi_value UniformTypeDescriptorInit(napi_env env, napi_value exports); static napi_value GetTypeDescriptor(napi_env env, napi_callback_info info); + static napi_value GetUniformDataTypeByFilenameExtension(napi_env env, napi_callback_info info); + static napi_value GetUniformDataTypeByMIMEType(napi_env env, napi_callback_info info); private: static napi_value CreateUniformDataType(napi_env env);