diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/json_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/json_common.h index 4494f01e9c1e5d8031e924a67ff0428a36303b34..35f11d8942ba8518661efd58d409815b5cea8ab5 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/json_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/json_common.h @@ -30,18 +30,20 @@ public: ~JsonCommon(); static ValueObject GetValueByFiled(JsonObject &node, const std::string& filed); + static ValueObject GetValueByFiled(JsonObject &node, const std::string& filed, bool &isFiledExist); static bool CheckJsonField(JsonObject &node); static bool CheckProjectionField(JsonObject &node); static int ParseNode(JsonObject &Node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor); static std::vector> ParsePath(const JsonObject &node); - static std::vector GetLeafValue(JsonObject &node); - + static std::vector GetLeafValue(const JsonObject &node); + static bool isValueEqual(const ValueObject &srcValue, const ValueObject &targetValue); static int Append(const JsonObject &src, const JsonObject &add); - + static bool isJsonNodeMatch(const JsonObject &src, const JsonObject &target, int &externErrCode); private: static bool CheckNode(JsonObject &Node, std::set filedSet, bool &errFlag); static bool CheckProjectionNode(JsonObject &Node, std::set filedSet, bool &errFlag, bool isFirstFloor); - static int CheckLeafNode(JsonObject &Node, std::vector &leafValue); + static int CheckLeafNode(const JsonObject &Node, std::vector &leafValue); + static bool isArrayMathch(const JsonObject &src, const JsonObject &target, int &flag); }; } // DocumentDB #endif // JSON_COMMON_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/json_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/json_common.cpp index 47a75e9c19df9005c94aa216b17228b2be4fd734..ab96228392f77c92b184a9e129f00552f435fcb0 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/json_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/json_common.cpp @@ -14,7 +14,6 @@ */ #include #include - #include "json_common.h" #include "doc_errno.h" #include "log_print.h" @@ -37,7 +36,26 @@ ValueObject JsonCommon::GetValueByFiled(JsonObject &node, const std::string& fil return ValueObject(); } -int JsonCommon::CheckLeafNode(JsonObject &node, std::vector &leafValue) +ValueObject JsonCommon::GetValueByFiled(JsonObject &node, const std::string& filed, bool &isFiledExist) +{ + while (!node.IsNull()) { + if (node.GetItemFiled() == filed) { + auto itemValue = node.GetItemValue(); + isFiledExist = true; + return itemValue; + } + if (node.GetNext().IsNull()) { + isFiledExist = false; + return ValueObject(); + } + auto nodeNew = node.GetNext(); + node = nodeNew; + } + isFiledExist = false; + return ValueObject(); +} + +int JsonCommon::CheckLeafNode(const JsonObject &node, std::vector &leafValue) { if (node.GetChild().IsNull()) { auto itemValue = node.GetItemValue(); @@ -54,7 +72,7 @@ int JsonCommon::CheckLeafNode(JsonObject &node, std::vector &leafVa return E_OK; } -std::vector JsonCommon::GetLeafValue(JsonObject &node) +std::vector JsonCommon::GetLeafValue(const JsonObject &node) { std::vector leafValue; CheckLeafNode(node, leafValue); @@ -237,6 +255,27 @@ JsonFieldPath ExpendPath(const JsonFieldPath &path, bool &isCollapse) return splitPath; } +JsonFieldPath ExpendPathForField(const JsonFieldPath &path, bool &isCollapse) +{ + + JsonFieldPath splitPath; + const std::string &str = path[0]; + size_t start = 0; + size_t end = 0; + while ((end = str.find('.', start)) != std::string::npos) { + splitPath.push_back(str.substr(start, end - start)); + start = end + 1; + } + if (start < str.length()) { + splitPath.push_back(str.substr(start)); + } + isCollapse = (splitPath.size() > 1); + for (int i = 1; i < path.size(); i++) { + splitPath.emplace_back(path[i]); + } + return splitPath; +} + void JsonObjectIterator(const JsonObject &obj, JsonFieldPath path, std::function foo) { @@ -251,6 +290,22 @@ void JsonObjectIterator(const JsonObject &obj, JsonFieldPath path, } return; } + +void JsonObjectIterator(const JsonObject &obj, JsonFieldPath path, + std::function foo) +{ + JsonObject child = obj.GetChild(); + while(!child.IsNull()) { + bool isCollapse = false; + JsonFieldPath childPath = path; + childPath.push_back(child.GetItemFiled()); + if (foo != nullptr && foo(childPath, child)) { + JsonObjectIterator(child, childPath, foo); + } + child = child.GetNext(); + } + return; +} } int JsonCommon::Append(const JsonObject &src, const JsonObject &add) @@ -308,4 +363,141 @@ int JsonCommon::Append(const JsonObject &src, const JsonObject &add) }); return externErrCode; } +bool JsonCommon::isValueEqual(const ValueObject &srcValue, const ValueObject &targetValue) +{ + if (srcValue.GetValueType() == targetValue.GetValueType()) { + switch (srcValue.GetValueType()) { + case ValueObject::ValueType::VALUE_NULL: + return true; + break; + case ValueObject::ValueType::VALUE_BOOL: + if (srcValue.GetBoolValue() == targetValue.GetBoolValue()) { + return true; + } + return false; + break; + case ValueObject::ValueType::VALUE_NUMBER: + if (srcValue.GetDoubleValue() == targetValue.GetDoubleValue()) { + return true; + } + return false; + break; + case ValueObject::ValueType::VALUE_STRING: + if (srcValue.GetStringValue() == targetValue.GetStringValue()) { + return true; + } + return false; + break; + } + } + return false; +} + +bool JsonCommon::isArrayMathch(const JsonObject &src, const JsonObject &target, int &flag) { + JsonObject srcChild = src.GetChild(); + JsonObject targetObj = target; + bool isMatch = false; + int errCode = 0; + while (!srcChild.IsNull()) { + if (srcChild.GetType() == JsonObject::Type::JSON_OBJECT && target.GetType() == JsonObject::Type::JSON_OBJECT + && (isJsonNodeMatch(srcChild, target, errCode))) { + isMatch = true; + flag = 1; + break; + } + srcChild = srcChild.GetNext(); + } + return isMatch; +} + +bool JsonCommon::isJsonNodeMatch(const JsonObject &src, const JsonObject &target, int &externErrCode) +{ + externErrCode = E_OK; + int isMatchFlag = true; + JsonObjectIterator(target, {}, + [&src, &isMatchFlag, &externErrCode](JsonFieldPath &path, const JsonObject &item) { + int flag = 0; + bool isCollapse = false; + if (isMatchFlag == false) { + return false; + } + JsonFieldPath itemPath = ExpendPath(path, isCollapse); + int errCode = 0; + if (src.IsFieldExistsIncludeArray(itemPath)) { + JsonObject srcItem = src.FindItemIncludeArray(itemPath, errCode); + auto GranpaPath = itemPath; + auto lastFiledName = GranpaPath.back(); + GranpaPath.pop_back(); + JsonObject GranpaItem = src.FindItemIncludeArray(GranpaPath, errCode); + if (GranpaItem.GetType() == JsonObject::Type::JSON_ARRAY && isCollapse) { + JsonObject FatherItem = GranpaItem.GetChild(); + while (!FatherItem.IsNull()) { + bool isEqual = (FatherItem.GetObjectItem(lastFiledName, errCode).Print() == item.Print()); + if (isEqual) { + GLOGE("Filter value is equal with src"); + isMatchFlag = isEqual; + flag = 1; + } + FatherItem = FatherItem.GetNext(); + } + } + if (errCode != E_OK) { + externErrCode = (externErrCode == E_OK ? errCode : externErrCode); + GLOGE("Find item in source json object failed. %d", errCode); + return false; + } + if (srcItem.GetType() == JsonObject::Type::JSON_LEAF && item.GetType() == JsonObject::Type::JSON_LEAF && !flag) { + bool isEqual = isValueEqual(srcItem.GetItemValue(), item.GetItemValue()); + if (!isEqual) { + GLOGE("Filter value is No equal with src"); + isMatchFlag = isEqual; + } + flag = isMatchFlag; + return false; // Both leaf node, no need iterate + } else if (srcItem.GetType() != item.GetType()) { + if (srcItem.GetType() == JsonObject::Type::JSON_ARRAY) { + GLOGE("Check if there has an object in array"); + bool isEqual = isArrayMathch(srcItem, item, flag); + if (!isEqual) { + isMatchFlag = isEqual; + } + return true; + } + GLOGE("valueType is different,"); + isMatchFlag = false; + return false; // Different node types, overwrite directly, skip child node + } + return true; // Both array or object + } else { + if (isCollapse) { + GLOGE("Match failed, path not exist."); + isMatchFlag = false; + return false; + } + GLOGE("Not match anything"); + if (flag == 0) { + isMatchFlag = false; + } + std::vector ItemLeafValue = GetLeafValue(item); + int isNULLFlag = true; + for (auto ValueItem : ItemLeafValue) { + if (ValueItem.GetValueType() != ValueObject::ValueType::VALUE_NULL) { + GLOGE("leaf value is null"); + isNULLFlag = false; + } + } + if (isNULLFlag == true) { + isMatchFlag = true; // + } + return false; // Source path not exist, if leaf value is null, isMatchFlag become true, else it will become false. + } + }); + return isMatchFlag; +} + + + + + + } // namespace DocumentDB \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.cpp index e8370c8d4435ebfc89b26718fb247078783a09af..7c5ff4658d7c00a23656415caf9b8ba46e02c5f2 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.cpp @@ -88,6 +88,27 @@ int CheckCommon::CheckFilter(JsonObject &filterObj) return E_OK; } +int CheckCommon::CheckFilter(JsonObject &filterObj, bool &isOnlyId) +{ + if (filterObj.GetDeep() > JSON_DEEP_MAX) { + GLOGE("filter's json deep is deeper than JSON_DEEP_MAX"); + return -E_INVALID_ARGS; + } + if (!filterObj.GetChild().GetNext().IsNull()) { + isOnlyId = false; + } + bool isIdExisit; + int ret = CheckIdFormat(filterObj, isIdExisit); + if (ret != E_OK) { + GLOGE("Filter Id format is illegal"); + return ret; + } + if (!isIdExisit) { + isOnlyId = false; + } + return E_OK; +} + int CheckCommon::CheckIdFormat(JsonObject &filterJson) { auto filterObjChild = filterJson.GetChild(); @@ -101,6 +122,23 @@ int CheckCommon::CheckIdFormat(JsonObject &filterJson) return E_OK; } +int CheckCommon::CheckIdFormat(JsonObject &filterJson, bool &isIdExisit) +{ + auto filterObjChild = filterJson.GetChild(); + bool isIdExist = false; + ValueObject idValue = JsonCommon::GetValueByFiled(filterObjChild, KEY_ID, isIdExist); + if ((idValue.GetValueType() == ValueObject::ValueType::VALUE_NULL) && isIdExist == false) { + return E_OK; + } + if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { + return -E_INVALID_ARGS; + } + if (idValue.GetStringValue().length() > MAX_ID_LENS) { + return -E_OVER_LIMIT; + } + return E_OK; +} + int CheckCommon::CheckDocument(JsonObject &documentObj) { if (documentObj.GetDeep() > JSON_DEEP_MAX) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.h index 57769260990a02f236848048ba1e417f175ef46d..9261ca70a1225b6c36db17ed0ac097ac49d5a622 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.h @@ -30,7 +30,9 @@ public: static bool CheckCollectionName(const std::string &collectionName, std::string &lowerCaseName, int &errCode); static int CheckFilter(JsonObject &document); + static int CheckFilter(JsonObject &document, bool &isOnlyId); static int CheckIdFormat(JsonObject &data); + static int CheckIdFormat(JsonObject &data, bool &isIdExisit); static int CheckDocument(JsonObject &document); static bool CheckProjection(JsonObject &projectionObj, std::vector> &path); }; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h index f295af703547409c7359917e9e4d481f8b71adfc..290ecb990e4c5706a39c3a184c8e565231b6ecc8 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/collection.h @@ -30,7 +30,9 @@ public: int PutDocument(const Key &key, const Value &document); int GetDocument(const Key &key, Value &document) const; + int GetFilededDocument(const JsonObject &filterObj, std::vector> &values) const; int DeleteDocument(const Key &key); + int IsCollectionExists(int &errCode); int UpsertDocument(const std::string &id, const std::string &document, bool isReplace = true); bool FindDocument(); int UpdateDocument(const std::string &id, const std::string &document); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/projection_tree.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/projection_tree.h index 15920bd41d178faff1529555bbba0bede7e6e581..d317dd0227391649821a81415a4cce7a3b692323 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/projection_tree.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/projection_tree.h @@ -1,3 +1,17 @@ +/* +* 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 PROJECTION_TREE_H #define PROJECTION_TREE_H diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set.h index dc87115e27b6e9fcdf544c3fea5d0e831f73e130..4e14a4dac5e8c577596ddc10555d50d793595702 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set.h @@ -33,8 +33,10 @@ public: ~ResultSet(); int Init(DocumentStore *store, const std::string collectionName, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType); + int Init(DocumentStore *store, const std::string collectionName, const std::string &filter); int GetNext(); int GetValue(char **value); + int GetKey(std::string &key); int EraseCollection(); private: int CutJsonBranch(std::string &jsonData); @@ -42,12 +44,14 @@ private: DocumentStore *store_ = nullptr; std::string collectionName_; ValueObject key_; + std::string filter_; bool ifShowId_ = false; bool viewType_ = false; + bool ifFiled_ = false; ProjectionTree projectionTree_; std::vector> projectionPath_; int index_ = 0; - std::vector findValue_; + std::vector> matchDatas_; }; } // DocumentDB #endif //RESULTSET_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set_common.h index dfef9c26d88b963d3204ad1f03e0fefafd8278a6..5b23952d31cce808aa27162052c8640015a2298c 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set_common.h @@ -26,6 +26,7 @@ namespace DocumentDB { class ValueObject; int InitResultSet(DocumentStore *store, const std::string collectionName, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType, ResultSet &resultSet); +int InitResultSet(DocumentStore *store, const std::string collectionName, const std::string &filter, ResultSet &resultSet); } // DocumentDB #endif //RESULTSET_COMMON_H diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp index fc9fd3ba7271620d129b2ae9a25610a6b50beb04..2e03c92e944c3426c16a98c5e700eafab095dfc7 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/collection.cpp @@ -61,6 +61,14 @@ int Collection::GetDocument(const Key &key, Value &document) const return executor_->GetData(name_, key, document); } +int Collection::GetFilededDocument(const JsonObject &filterObj, std::vector> &values) const +{ + if (executor_ == nullptr) { + return -E_INVALID_ARGS; + } + return executor_->GetFilededData(name_, filterObj, values); +} + int Collection::DeleteDocument(const Key &key) { if (executor_ == nullptr) { @@ -69,6 +77,10 @@ int Collection::DeleteDocument(const Key &key) return executor_->DelData(name_, key); } +int Collection::IsCollectionExists(int &errCode) { + return executor_->IsCollectionExists(name_, errCode); +} + int Collection::UpsertDocument(const std::string &id, const std::string &document, bool isReplace) { if (executor_ == nullptr) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp index b87e8430bf98e6b4eb0db2d09ad798e4e042e35c..a9ed1effbd19e548e711ee3217fba8093340eb6c 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store.cpp @@ -285,6 +285,9 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri return errCode; } auto coll = Collection(collection, executor_); + if (!coll.IsCollectionExists(errCode)) { + return -E_INVALID_ARGS; + } if (filter.empty()) { GLOGE("Filter is empty"); return -E_INVALID_ARGS; @@ -298,15 +301,29 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri GLOGE("filter Parsed faild"); return errCode; } - errCode = CheckCommon::CheckFilter(filterObj); + bool isOnlyId = true; + errCode = CheckCommon::CheckFilter(filterObj, isOnlyId); if (errCode != E_OK) { return errCode; } - auto filterObjChild = filterObj.GetChild(); - auto idValue = JsonCommon::GetValueByFiled(filterObjChild, KEY_ID); - std::string id = idValue.GetStringValue(); - Key key(id.begin(), id.end()); + if (isOnlyId) { + auto filterObjChild = filterObj.GetChild(); + auto idValue = JsonCommon::GetValueByFiled(filterObjChild, KEY_ID); + std::string id = idValue.GetStringValue(); + Key key(id.begin(), id.end()); + std::lock_guard lock(dbMutex_); + return coll.DeleteDocument(key); + } + ResultSet resultSet; + InitResultSet(this, collection, filter, resultSet); std::lock_guard lock(dbMutex_); + errCode = resultSet.GetNext(); + if (errCode != E_OK) { + return errCode; + } + std::string id; + resultSet.GetKey(id); + Key key(id.begin(), id.end()); return coll.DeleteDocument(key); } KvStoreExecutor *DocumentStore::GetExecutor(int errCode) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/projection_tree.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/projection_tree.cpp index edf6f3568215d97e258f18658f1b67842f093143..ce4f7cfca91599de68f8079620a61863bed4059e 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/projection_tree.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/projection_tree.cpp @@ -1,3 +1,17 @@ +/* +* 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 "projection_tree.h" diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set.cpp index 038ada1d9211182c6fe2b4dfe00834b039f6f803..c2f752efde3666265b83a9b181be10981d03da5d 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set.cpp @@ -45,46 +45,71 @@ int ResultSet::Init(DocumentStore *store, const std::string collectionName, Valu } ifShowId_ = ifShowId; viewType_ = viewType; - findValue_.reserve(1 + 1); return E_OK; } +int ResultSet::Init(DocumentStore *store, const std::string collectionName, const std::string &filter) +{ + ifFiled_ = true; + store_ = store; + collectionName_ = collectionName; + filter_ = filter; + return E_OK; +} + int ResultSet::GetNext() { - index_++; - if (index_ != 1) { - if (findValue_.size() != 0) { - findValue_.pop_back(); + if (!ifFiled_ && index_ == 0) { + std::string idValue = key_.GetStringValue(); + if (idValue.empty()) { + GLOGE("id is empty"); + return -E_NO_DATA; } - return -E_NO_DATA; - } - std::string idValue = key_.GetStringValue(); - if (idValue.empty()) { - GLOGE("id is empty"); - return -E_NO_DATA; + Key key(idValue.begin(), idValue.end()); + Value document; + int errCode = 0; + auto coll = Collection(collectionName_, store_->GetExecutor(errCode)); + errCode = coll.GetDocument(key, document); + if (errCode == -E_NOT_FOUND) { + GLOGE("Cant get value from db"); + return -E_NO_DATA; + } + std::string jsonData(document.begin(), document.end()); + CutJsonBranch(jsonData); + std::vector> values; + values.emplace_back(std::pair(idValue, jsonData)); + matchDatas_ = values; + } else if (index_ == 0) { + int errCode = 0; + auto coll = Collection(collectionName_, store_->GetExecutor(errCode)); + std::vector> values; + JsonObject filterObj = JsonObject::Parse(filter_, errCode, true); + if (errCode != E_OK) { + GLOGE("filter Parsed faild"); + return errCode; + } + errCode = coll.GetFilededDocument(filterObj, values); + if (errCode == -E_NOT_FOUND) { + GLOGE("Cant get value from db"); + return -E_NO_DATA; + } + matchDatas_ = values; } - Key key(idValue.begin(), idValue.end()); - Value document; - int errCode = 0; - auto coll = Collection(collectionName_, store_->GetExecutor(errCode)); - errCode = coll.GetDocument(key, document); - if (errCode == -E_NOT_FOUND) { - GLOGE("Cant get value from db"); + index_++; + if (index_ > matchDatas_.size()) { + GLOGE("No data in The value vector"); return -E_NO_DATA; } - std::string jsonData(document.begin(), document.end()); - CutJsonBranch(jsonData); - findValue_.emplace_back(jsonData); return E_OK; } int ResultSet::GetValue(char **value) { - if (findValue_.size() == 0) { + if (index_ == 0 || (index_ > matchDatas_.size())) { GLOGE("The value vector in resultSet is empty"); return -E_NO_DATA; } - auto jsonData = findValue_.back(); + auto jsonData = matchDatas_[index_ - 1].second; char *jsonstr = new char[jsonData.size() + 1]; if (jsonstr == nullptr) { GLOGE("Memory allocation failed!" ); @@ -100,6 +125,16 @@ int ResultSet::GetValue(char **value) return E_OK; } +int ResultSet::GetKey(std::string &key) +{ + if (index_ == 0 || (index_ > matchDatas_.size())) { + GLOGE("The value vector in resultSet is empty"); + return -E_NO_DATA; + } + key = matchDatas_[index_ - 1].first; + return E_OK; +} + int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePath, std::vector> &allCutPath) { if (node == nullptr) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set_common.cpp index ad195a6b65a6085fa0e97c467631c0f136a3a0ba..78d677093b6ac33858eed24317f16e487340d6b4 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set_common.cpp @@ -26,5 +26,10 @@ int InitResultSet(DocumentStore *store, const std::string collectionName, ValueO { return resultSet.Init(store, collectionName, key, path, ifShowId, viewType); } + +int InitResultSet(DocumentStore *store, const std::string collectionName, const std::string &filter, ResultSet &resultSet) +{ + return resultSet.Init(store, collectionName, filter); +} } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/json_object.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/json_object.h index 12510f1dc5c85f1784a0c0a5c8d29f9651240a6e..ae683fa4ea2acf2d39c538be9efb205b98d3be71 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/json_object.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/json_object.h @@ -61,7 +61,6 @@ using JsonFieldPath = std::vector; class JsonObject { public: static JsonObject Parse(const std::string &jsonStr, int &errCode, bool caseSensitive = false); - ~JsonObject (); std::string Print() const; @@ -83,7 +82,9 @@ public: std::string GetItemFiled(int &errCode) const; bool IsFieldExists(const JsonFieldPath &jsonPath) const; + bool IsFieldExistsIncludeArray(const JsonFieldPath &jsonPath) const; JsonObject FindItem(const JsonFieldPath &jsonPath, int &errCode) const; + JsonObject FindItemIncludeArray(const JsonFieldPath &jsonPath, int &errCode) const; ValueObject GetObjectByPath(const JsonFieldPath &jsonPath, int &errCode) const; int DeleteItemOnTarget(const JsonFieldPath &path); int DeleteItemDeeplyOnTarget(const JsonFieldPath &path); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_executor.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_executor.h index 0f81f5b1f2ac08ca2da726bb2ef8f2f348392742..ec9889ffb7dab1712747d8bf0e457bb14888c7c8 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_executor.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_executor.h @@ -26,6 +26,7 @@ public: virtual int PutData(const std::string &collName, const Key &key, const Value &value) = 0; virtual int GetData(const std::string &collName, const Key &key, Value &value) const = 0; + virtual int GetFilededData(const std::string &collName, const JsonObject &filterObj, std::vector> &values) const = 0; virtual int DelData(const std::string &collName, const Key &key) = 0; virtual int CreateCollection(const std::string &name, bool ignoreExists) = 0; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp index 44bd987950952ac294f0b29966b1ac2cd82c337f..77080bc0e487e5df24561746a7e37ccc337aea27 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/json_object.cpp @@ -412,6 +412,33 @@ cJSON *GetChild(cJSON *cjson, const std::string &field, bool caseSens) return nullptr; } + +cJSON *GetChildIncludeArray(cJSON *cjson, const std::string &field, bool caseSens) +{ + if (cjson->type == cJSON_Object) { + if (caseSens) { + return cJSON_GetObjectItemCaseSensitive(cjson, field.c_str()); + } else { + return cJSON_GetObjectItem(cjson, field.c_str()); + } + } else if (cjson->type == cJSON_Array) { + if (!IsNumber(field)) { + cjson = cjson->child; + while (cjson != nullptr) { + auto resultItem = GetChild(cjson, field, caseSens); + if (resultItem != nullptr) { + return resultItem; + } + cjson = cjson->next; + } + return nullptr; + } + return cJSON_GetArrayItem(cjson, std::stoi(field)); + } + GLOGW("Invalid json field type, expect object or array."); + return nullptr; +} + cJSON *MoveToPath(cJSON *cjson, const JsonFieldPath &jsonPath, bool caseSens) { for (const auto &field : jsonPath) { @@ -423,11 +450,27 @@ cJSON *MoveToPath(cJSON *cjson, const JsonFieldPath &jsonPath, bool caseSens) return cjson; } +cJSON *MoveToPathIncludeArray(cJSON *cjson, const JsonFieldPath &jsonPath, bool caseSens) +{ + for (const auto &field : jsonPath) { + cjson = GetChildIncludeArray(cjson, field, caseSens); + if (cjson == nullptr) { + break; + } + } + return cjson; +} + bool JsonObject::IsFieldExists(const JsonFieldPath &jsonPath) const { return (MoveToPath(cjson_, jsonPath, caseSensitive_) != nullptr); } +bool JsonObject::IsFieldExistsIncludeArray(const JsonFieldPath &jsonPath) const +{ + return (MoveToPathIncludeArray(cjson_, jsonPath, caseSensitive_) != nullptr); +} + JsonObject JsonObject::FindItem(const JsonFieldPath &jsonPath, int &errCode) const { if (jsonPath.empty()) { @@ -452,6 +495,29 @@ JsonObject JsonObject::FindItem(const JsonFieldPath &jsonPath, int &errCode) con return item; } +JsonObject JsonObject::FindItemIncludeArray(const JsonFieldPath &jsonPath, int &errCode) const +{ + if (jsonPath.empty()) { + JsonObject curr = JsonObject(); + curr.cjson_ = cjson_; + curr.caseSensitive_ = caseSensitive_; + curr.isOwner_ = false; + GLOGW("Path empty, return current object"); + return curr; + } + + cJSON *findItem = MoveToPathIncludeArray(cjson_, jsonPath, caseSensitive_); + if (findItem == nullptr) { + GLOGE("Find item failed. json field path not found."); + errCode = -E_JSON_PATH_NOT_EXISTS; + return {}; + } + JsonObject item; + item.caseSensitive_ = caseSensitive_; + item.cjson_ = findItem; + return item; +} + ValueObject JsonObject::GetObjectByPath(const JsonFieldPath &jsonPath, int &errCode) const { JsonObject objGot = FindItem(jsonPath, errCode); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.cpp index 937a2793808080d53f3e5cc69ac4c61d3f5fdf82..f6f2629a4d79544cdf97fcf52c0842796a87216c 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.cpp @@ -127,6 +127,47 @@ int SqliteStoreExecutor::GetData(const std::string &collName, const Key &key, Va return innerErrorCode; } +int SqliteStoreExecutor::GetFilededData(const std::string &collName, const JsonObject &filterObj, std::vector> &values) const +{ + if (dbHandle_ == nullptr) { + GLOGE("Invalid db handle."); + return -E_ERROR; + } + Value keyResult; + Value valueResult; + int innerErrorCode = -E_NOT_FOUND; + std::string sql = "SELECT key, value FROM '" + collName + "';"; + int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [](sqlite3_stmt *stmt) { + return E_OK; + }, [&keyResult, &innerErrorCode, &valueResult, &filterObj, &values](sqlite3_stmt *stmt) { + SQLiteUtils::GetColumnBlobValue(stmt, 0, keyResult); + SQLiteUtils::GetColumnBlobValue(stmt, 1, valueResult); + std::string keyStr(keyResult.begin(), keyResult.end()); + std::string valueStr(valueResult.begin(), valueResult.end()); + int externErrCode; + JsonObject srcObj = JsonObject::Parse(valueStr, externErrCode, true); + if (externErrCode != E_OK) { + GLOGE("srcObj Parsed faild"); + return externErrCode; + } + if (filterObj.GetItemValue().GetValueType() == ValueObject::ValueType::VALUE_NULL) { + values.emplace_back(std::pair(keyStr, valueStr)); + innerErrorCode = E_OK; + return E_OK; + } + if (JsonCommon::isJsonNodeMatch(srcObj, filterObj, externErrCode)) { + values.emplace_back(std::pair(keyStr, valueStr)); + } + innerErrorCode = E_OK; + return E_OK; + }); + if (errCode != SQLITE_OK) { + GLOGE("[sqlite executor] Get data failed. err=%d", errCode); + return errCode; + } + return innerErrorCode; +} + int SqliteStoreExecutor::DelData(const std::string &collName, const Key &key) { if (dbHandle_ == nullptr) { @@ -134,9 +175,6 @@ int SqliteStoreExecutor::DelData(const std::string &collName, const Key &key) return -E_ERROR; } int errCode = 0; - if (!IsCollectionExists(collName, errCode)) { - return -E_INVALID_ARGS; - } Value valueRet; if (GetData(collName, key, valueRet) != E_OK) { return -E_NO_DATA; @@ -256,5 +294,4 @@ int SqliteStoreExecutor::CleanCollectionOption(const std::string &name) Key collOptKey = {collOptKeyStr.begin(), collOptKeyStr.end()}; return DelData("grd_meta", collOptKey); } - } // DocumentDB \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.h index bc6857b83a5263998a700cffb28a55b6b111e672..3cfbf1c69946df6685ca26648c14aa6da7b79a53 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.h @@ -19,6 +19,7 @@ #include "db_config.h" #include "kv_store_executor.h" #include "sqlite3.h" +#include "json_common.h" namespace DocumentDB { class SqliteStoreExecutor : public KvStoreExecutor { @@ -33,6 +34,7 @@ public: int PutData(const std::string &collName, const Key &key, const Value &value) override; int GetData(const std::string &collName, const Key &key, Value &value) const override; + int GetFilededData(const std::string &collName, const JsonObject &filterObj, std::vector> &values) const override; int DelData(const std::string &collName, const Key &key) override; int CreateCollection(const std::string &name, bool ignoreExists) override; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_delete_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_delete_test.cpp index 42d4d2d7463cbb2bed72d0edaac6a18dd3fd0fdd..6ce6906314540efd35bf2a9e716477f54ec81cdc 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_delete_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_delete_test.cpp @@ -71,7 +71,7 @@ void DocumentDeleteApiTest::SetUp(void) \"address\": \"beijing\", \ \"age\" : 15, \ \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"math\", \"English\", \"music\"] \ + \"subject\": [\"math\", \"English\", \"music\", {\"info\" : \"exam\"}] \ }"; const char *document2 = "{ \ @@ -89,7 +89,7 @@ void DocumentDeleteApiTest::SetUp(void) \"address\": \"beijing\", \ \"age\" : 15, \ \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ - \"subject\": [\"math\", \"English\", \"music\"] \ + \"subject\": [\"Sing\", \"Jump\", \"Rap\", \"BasketBall\"] \ }"; DocumentDeleteApiTest::InsertDoc(COLLECTION_NAME, document1); DocumentDeleteApiTest::InsertDoc(COLLECTION_NAME, document2); @@ -143,7 +143,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest001, TestSize.Level1) * @tc.steps:step1. Delete all the document * @tc.expected: step1. GRD_INVALID_ARGS */ - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL_JSON_STR, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL_JSON_STR, 0), 1); } /** @@ -160,7 +160,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest002, TestSize.Level1) * @tc.expected: step1. GRD_INVALID_ARGS */ const char *filter = "{\"age\" : 15}"; - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), 1); } /** @@ -177,7 +177,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest003, TestSize.Level1) * @tc.expected: step1. GRD_INVALID_ARGS */ const char *filter = "{\"_id\" : \"1\", \"age\" : 15}"; - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), 1); } /** @@ -321,6 +321,32 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) } const char *filter = "{\"_id\" : \"1\"}"; EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), 1); - +} + +/** + * @tc.name: DocumentDelete011 + * @tc.desc: + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest011, TestSize.Level1) +{ + /** + * @tc.step1: Create filter with _id and get the record according to filter condition. + * @tc.expected: step1. GRD_OK + */ + const char *filter = "{\"_id\" : \"1\"}"; + const char *filter2 = "{\"subject.info\" : \"exam\"}"; + GRD_ResultSet *resultSet = nullptr; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter2, 0), 1); + /** + * @tc.step2: Invoke GRD_Next to get the next matching value. Release resultSet. + * @tc.expected: step2. Cannot get next record, return GRD_NO_DATA. + */ + EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_find_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_find_test.cpp index 0051493bbfe6176822c3d1b856fc82ca14706dcf..ad3bc55e26da23cb938c92fce0fba8da04dddf69 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_find_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_find_test.cpp @@ -172,16 +172,16 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest002, TestSize.Level1) const char *filter = "{\"_id\" : \"6\", \"name\":\"doc6\"}"; GRD_ResultSet *resultSet = nullptr; Query query = {filter, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); /** * @tc.steps: step2. Invoke GRD_Next to get the next matching value. Release resultSet. * @tc.expected: step2. GRD_GetValue return GRD_INVALID_ARGS and GRD_Next return GRD_INVALID_ARGS. */ - EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); char *value = NULL; - EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); EXPECT_EQ(GRD_FreeValue(value), GRD_OK); - EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } /** @@ -200,82 +200,84 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest004, TestSize.Level1) const char *filter = "{\"name\":\"doc6\"}"; GRD_ResultSet *resultSet = nullptr; Query query = {filter, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); /** * @tc.steps: step2. Invoke GRD_Next to get the next matching value. Release resultSet. * @tc.expected: step2. GRD_GetValue return GRD_INVALID_ARGS and GRD_Next return GRD_INVALID_ARGS. */ char *value = NULL; - EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); EXPECT_EQ(GRD_FreeValue(value), GRD_OK); - EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } -/** - * @tc.name: DocumentFindApiTest005 - * @tc.desc: test filter field with other word. - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentFindApiTest, DocumentFindApiTest005, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create filter with _id and number - * @tc.expected: step1. Faild to get the record, the result is GRD_INVALID_ARGS, - */ - GRD_ResultSet *resultSet1 = nullptr; - const char *filter1 = "{\"_id\" : \"1\", \"info\" : 1}"; - Query query1 = {filter1, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query1, 1, &resultSet1), GRD_INVALID_ARGS); - - /** - * @tc.steps: step2. Create filter with two _id - * @tc.expected: step2. Faild to get the record, the result is GRD_INVALID_ARGS, - */ - GRD_ResultSet *resultSet2 = nullptr; - const char *filter2 = "{\"_id\" : \"1\", \"_id\" : \"2\"}"; - Query query2 = {filter2, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query2, 1, &resultSet2), GRD_INVALID_ARGS); - - /** - * @tc.steps: step3. Create filter with array and _id - * @tc.expected: step3. Faild to get the record, the result is GRD_INVALID_ARGS, - */ - GRD_ResultSet *resultSet3 = nullptr; - const char *filter3 = "{\"_id\" : \"1\", \"info\" : [\"2\", 1]}"; - Query query3 = {filter3, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query3, 1, &resultSet3), GRD_INVALID_ARGS); - - /** - * @tc.steps: step4. Create filter with object and _id - * @tc.expected: step4. Faild to get the record, the result is GRD_INVALID_ARGS, - */ - GRD_ResultSet *resultSet4 = nullptr; - const char *filter4 = "{\"_id\" : \"1\", \"info\" : {\"info_val\" : \"1\"}}"; - Query query4 = {filter4, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query4, 1, &resultSet4), GRD_INVALID_ARGS); - - /** - * @tc.steps: step5. Create filter with bool and _id - * @tc.expected: step5. Faild to get the record, the result is GRD_INVALID_ARGS, - */ - GRD_ResultSet *resultSet5 = nullptr; - const char *filter5 = "{\"_id\" : \"1\", \"info\" : true}"; - Query query5 = {filter5, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query5, 1, &resultSet5), GRD_INVALID_ARGS); - - /** - * @tc.steps: step6. Create filter with null and _id - * @tc.expected: step6. Faild to get the record, the result is GRD_INVALID_ARGS, - */ - GRD_ResultSet *resultSet6 = nullptr; - const char *filter6 = "{\"_id\" : \"1\", \"info\" : null}"; - Query query6 = {filter6, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query6, 1, &resultSet6), GRD_INVALID_ARGS); -} +// /** +// * @tc.name: DocumentFindApiTest005 +// * @tc.desc: test filter field with other word. +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentFindApiTest, DocumentFindApiTest005, TestSize.Level1) +// { +// /** +// * @tc.steps: step1. Create filter with _id and number +// * @tc.expected: step1. Faild to get the record, the result is GRD_INVALID_ARGS, +// */ +// GRD_ResultSet *resultSet1 = nullptr; +// const char *filter1 = "{\"_id\" : \"1\", \"info\" : 1}"; +// Query query1 = {filter1, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query1, 1, &resultSet1), GRD_OK); +// EXPECT_EQ(GRD_FreeResultSet(resultSet1), GRD_OK); + +// /** +// * @tc.steps: step2. Create filter with two _id +// * @tc.expected: step2. Faild to get the record, the result is GRD_INVALID_ARGS, +// */ +// GRD_ResultSet *resultSet2 = nullptr; +// const char *filter2 = "{\"_id\" : \"1\", \"_id\" : \"2\"}"; +// Query query2 = {filter2, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query2, 1, &resultSet2), GRD_INVALID_ARGS); +// EXPECT_EQ(GRD_FreeResultSet(resultSet1), GRD_OK); + +// /** +// * @tc.steps: step3. Create filter with array and _id +// * @tc.expected: step3. Faild to get the record, the result is GRD_INVALID_ARGS, +// */ +// GRD_ResultSet *resultSet3 = nullptr; +// const char *filter3 = "{\"_id\" : \"1\", \"info\" : [\"2\", 1]}"; +// Query query3 = {filter3, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query3, 1, &resultSet3), GRD_OK); + +// /** +// * @tc.steps: step4. Create filter with object and _id +// * @tc.expected: step4. Faild to get the record, the result is GRD_INVALID_ARGS, +// */ +// GRD_ResultSet *resultSet4 = nullptr; +// const char *filter4 = "{\"_id\" : \"1\", \"info\" : {\"info_val\" : \"1\"}}"; +// Query query4 = {filter4, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query4, 1, &resultSet4), GRD_OK); + +// /** +// * @tc.steps: step5. Create filter with bool and _id +// * @tc.expected: step5. Faild to get the record, the result is GRD_INVALID_ARGS, +// */ +// GRD_ResultSet *resultSet5 = nullptr; +// const char *filter5 = "{\"_id\" : \"1\", \"info\" : true}"; +// Query query5 = {filter5, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query5, 1, &resultSet5), GRD_OK); + +// /** +// * @tc.steps: step6. Create filter with null and _id +// * @tc.expected: step6. Faild to get the record, the result is GRD_INVALID_ARGS, +// */ +// GRD_ResultSet *resultSet6 = nullptr; +// const char *filter6 = "{\"_id\" : \"1\", \"info\" : null}"; +// Query query6 = {filter6, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query6, 1, &resultSet6), GRD_OK); +// } /** * @tc.name: DocumentFindApiTest006 @@ -1446,4 +1448,35 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest055, TestSize.Level1) query = {filter.c_str(), projectionInfo}; EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest056 + * @tc.desc: Test findDoc with no _id. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest056, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter with _id and get the record according to filter condition. + * @tc.expected: step1. Succeed to get the record, the matching record is g_document6. + */ + const char *filter = "{\"_id\" : \"1\"}"; + GRD_ResultSet *resultSet = nullptr; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, g_document6); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + /** + * @tc.steps: step2. Invoke GRD_Next to get the next matching value. Release resultSet. + * @tc.expected: step2. Cannot get next record, return GRD_NO_DATA. + */ + EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_NOT_AVAILABLE); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/oh_adapter/documentdb_json_common_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/oh_adapter/documentdb_json_common_test.cpp index 11717fe75652d63513e1ad8b579825b993cdb35b..40969e297a1d760dfd85c6f8903cda5fd73804f7 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/oh_adapter/documentdb_json_common_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/oh_adapter/documentdb_json_common_test.cpp @@ -327,4 +327,213 @@ HWTEST_F(DocumentDBJsonCommonTest, JsonObjectAppendTest015, TestSize.Level0) JsonObject itemCase = src.FindItem({"name", "first", "0"}, errCode); EXPECT_EQ(errCode, E_OK); EXPECT_EQ(itemCase.GetItemValue().GetStringValue(), "GG"); -} \ No newline at end of file +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest001, TestSize.Level0) +{ + std::string document = R""({"name":{"first": {"job" : "it"}}, "t1" : {"second":"Lang"}})""; + std::string filter = R""({"name":{"first": {"job" : "it"}}, "t1" : {"second":"Lang"}})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); + + std::string document2 = R""({"name":{"first": {"job" : "it"}, "t1" : {"second":"Lang"}}})""; + std::string filter2 = R""({"name":{"first": {"job" : "NoEqual"}}, "t1" : {"second":"Lang"}})""; + int errCode2 = E_OK; + JsonObject srcObj2 = JsonObject::Parse(document2, errCode2); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj2 = JsonObject::Parse(filter2, errCode2); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj2, filterObj2, errCode), false); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest002, TestSize.Level0) +{ + std::string document = R""({"item": [{"gender":"girl"}, "GG"], "instock": [{"warehouse":"A", "qty":5}, {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"instock": {"warehouse":"A", "qty":5}})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest003, TestSize.Level0) +{ + std::string document = R""({"item": [{"gender":"girl"}, "GG"], "instock": [{"warehouse":"A", "qty":5}, {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"item": "GG"})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), false); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest004, TestSize.Level0) +{ + std::string document = R""({"item": [{"gender":"girl"}, "GG"], "instock": [{"warehouse":"A", "qty":5}, {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"item": "GG"})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), false); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest005, TestSize.Level0) +{ + std::string document = R""({"item": ["GG", "AA"], "instock": [{"warehouse":"A", "qty":5}, {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"item": ["GG", "AA"]})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest006, TestSize.Level0) +{ + std::string document = R""({"item": ["GG", {"gender":"girl"}], "instock": [{"warehouse":"A", "qty":5}, {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"item.0": "GG"})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest007, TestSize.Level0) +{ + std::string document = R""({"item": ["GG", {"gender":"girl"}], "instock": [{"warehouse":"A", "qty":5}, {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"item": ["GG", {"gender":"girl"}]})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest008, TestSize.Level0) +{ + std::string document = R""({"item": ["GG", {"gender":"girl", "hobby" : "IT"}], "instock": [{"warehouse":"A", "qty":5}, {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"item": {"gender":"girl"}})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest009, TestSize.Level0) +{ + std::string document = R""({"item": ["GG", {"gender":"girl", "hobby" : "IT"}], "instock": [{"qty" : 16, "warehouse":"A"}, + {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"instock.warehouse": "A"})"";; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest010, TestSize.Level0) +{ + std::string document = R""({"item": ["GG", {"gender":"girl", "hobby" : "IT"}], "instock": [{"warehouse":"A"}, + {"warehouse":"C", "qty":15}]})""; + std::string filter = R""({"instock.warehouse": "C"})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest011, TestSize.Level0) +{ + std::string document = R""({"item" : "journal", "instock" : [{"warehose" : "A", "qty" : 5}, {"warehose" : "C", "qty" : 15}]})""; + std::string filter = R""({"instock" : {"warehose" : "A", "qty" : 5}})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest012, TestSize.Level0) +{ + std::string document = R""({"item" : "journal", "instock" : [{"warehose" : "A", "qty" : 5}, {"warehose" : "C", "qty" : 15}]})""; + std::string filter = R""({"instock" : {"warehose" : "A", "bad" : "2" ,"qty" : 5}})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), false); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest013, TestSize.Level0) +{ + std::string document = R""({"item" : "journal", "instock" : [{"warehose" : "A", "qty" : 5}, {"warehose" : "C", "qty" : 15}]})""; + std::string filter = R""({"instock.qty" : 15})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest014, TestSize.Level0) +{ + std::string document = R""({"item" : "journal", "instock" : [{"warehose" : "A", "qty" : 5}, {"warehose" : "C", "qty" : 15}]})""; + std::string filter = R""({"instock.1.qty" : 15})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest015, TestSize.Level0) +{ + std::string document = R""({"item" : "journal", "qty" : 25, "tags" : ["blank", "red"], "dim_cm" : [14, 21]})""; + std::string filter = R""({"tags" : ["blank", "red"]})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest016, TestSize.Level0) +{ + std::string document = R""({"item" : "journal", "qty" : 25, "tags" : {"value" : null}, "dim_cm" : [14, 21]})""; + std::string filter = R""({"tags" : {"value" : null}})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest017, TestSize.Level0) +{ + std::string document = R""({"item" : "journal", "qty" : 25, "dim_cm" : [14, 21]})""; + std::string filter = R""({"tags" : {"value" : null}})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +} + +HWTEST_F(DocumentDBJsonCommonTest, JsonObjectisFilterCheckTest018, TestSize.Level0) +{ + std::string document = "{\"_id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"personInfo\":\ + [1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; + std::string filter = R""({"_id" : "2"})""; + int errCode = E_OK; + JsonObject srcObj = JsonObject::Parse(document, errCode); + EXPECT_EQ(errCode, E_OK); + JsonObject filterObj = JsonObject::Parse(filter, errCode); + EXPECT_EQ(JsonCommon::isJsonNodeMatch(srcObj, filterObj, errCode), true); +}