From 1335c407066515d6150b2f3cc843c21db7b2cef6 Mon Sep 17 00:00:00 2001 From: mazhao Date: Mon, 3 Apr 2023 07:55:47 +0000 Subject: [PATCH 01/18] Optimize the format checking function Signed-off-by: mazhao --- .../src/common/include/doc_common.h | 12 +++---- .../src/common/include/json_common.h | 2 +- .../src/common/src/doc_common.cpp | 32 +++++++++---------- .../src/common/src/json_common.cpp | 8 ++--- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h index 24065eda..ce782916 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h @@ -22,16 +22,16 @@ class JsonCommon; namespace DocumentDB { -class CheckCommon +class DocCommon { public: - CheckCommon() = default; - ~CheckCommon(); + DocCommon() = default; + ~DocCommon(); static bool CheckCollectionName(const std::string &collectionName); - static bool CheckFilter(const std::string &filter); - static bool CheckIdFormat(const std::string &data); - static bool CheckDocument(const std::string &document); + static bool CheckFilter(JsonObject *filterObj); + static bool CheckIdFormat(JsonObject *filter_json); + static bool CheckDocument(JsonObject *documentObj); }; using Key = std::vector; using Value = std::vector; 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 745718c1..86bbce07 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 @@ -29,7 +29,7 @@ public: ~JsonCommon(); static ResultValue GetValueByFiled(JsonObject *node, const std::string& filed); - static bool CheckJsonField(const std::string &data); + static bool CheckJsonField(JsonObject *jsonObj); static int ParseNode(JsonObject *Node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor); static std::vector> ParsePath(JsonObject* node); static std::vector GetLeafValue(JsonObject *node); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp index fa39bd34..0da62195 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp @@ -13,14 +13,14 @@ * limitations under the License. */ #include - #include "doc_common.h" #include "doc_errno.h" #include "log_print.h" #include "securec.h" +#include "json_object.h" namespace DocumentDB { -bool CheckCommon::CheckCollectionName(const std::string &collectionName) +bool DocCommon::CheckCollectionName(const std::string &collectionName) { if (collectionName.empty()) { return false; @@ -34,34 +34,32 @@ bool CheckCommon::CheckCollectionName(const std::string &collectionName) return true; } -bool CheckCommon::CheckFilter(const std::string &filter) +bool DocCommon::CheckFilter(JsonObject *filterObj) { - if (JsonCommon::CheckIsJson(filter) == false) { - return false; - } - if (JsonCommon::GetJsonDeep(filter) > 4) { - return false; - } - if (CheckIdFormat(filter) == false) { + if (CheckIdFormat(filterObj) == false) { return false; } return true; } -bool CheckCommon::CheckIdFormat(const std::string &data) +bool DocCommon::CheckIdFormat(JsonObject *filter_json) { - CjsonObject filter_json; - filter_json.Parse(data); - std::vector id; - if (JsonCommon::GetIdValue(&filter_json, id) == E_ERROR) { + auto filterObj_child = filter_json->GetChild(); + auto resultValue = JsonCommon::GetValueByFiled(&filterObj_child, "_id"); + if (resultValue.valueType != ResultValue::ValueType::VALUE_STRING) { return false; } return true; } -bool CheckCommon::CheckDocument(const std::string &document) +bool DocCommon::CheckDocument(JsonObject *documentObj) { + if (CheckIdFormat(documentObj) == false) { + return false; + } + if (JsonCommon::CheckJsonField(documentObj) == false) { + return false; + } return true; } - } // namespace DocumentDB \ 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 a87c0570..7514d328 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 @@ -97,14 +97,10 @@ bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, boo return errFlag; } -bool JsonCommon::CheckJsonField(const std::string &data) { - JsonObject jsonObj; - if (jsonObj.Init(data) != E_OK) { - return false; - } +bool JsonCommon::CheckJsonField(JsonObject *jsonObj) { std::set filedSet; bool errFlag = true; - return CheckNode(&jsonObj, filedSet, errFlag); + return CheckNode(jsonObj, filedSet, errFlag); } int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor) -- Gitee From fe2d9526c659bbf3a5e064b9f65d828c0bfdb7f0 Mon Sep 17 00:00:00 2001 From: mazhao Date: Thu, 6 Apr 2023 06:21:55 +0000 Subject: [PATCH 02/18] fix some bugs after ut check Signed-off-by: mazhao --- .../src/common/include/doc_common.h | 3 +- .../src/common/src/doc_common.cpp | 13 +- .../src/common/src/json_common.cpp | 29 +- .../src/executor/base/grd_resultset_api.cpp | 62 ++ .../executor/document/grd_document_api.cpp | 48 ++ .../src/executor/include/grd_format_config.h | 32 + .../src/executor/include/grd_type_inner.h | 4 + .../src/interface/include/collection.h | 1 + .../src/interface/include/doc_errno.h | 3 + .../src/interface/include/document_store.h | 9 +- .../src/interface/include/projection_tree.h | 36 + .../src/interface/include/result_set.h | 52 ++ .../src/interface/src/collection.cpp | 12 +- .../src/interface/src/document_store.cpp | 164 ++++- .../src/interface/src/projection_tree.cpp | 58 ++ .../src/interface/src/result_set.cpp | 114 ++++ .../src/oh_adapter/include/json_object.h | 3 +- .../oh_adapter/include/kv_store_executor.h | 2 + .../src/oh_adapter/src/json_object.cpp | 33 +- .../src/sqlite_store_executor_impl.cpp | 39 +- .../src/sqlite_store_executor_impl.h | 2 +- .../unittest/api/ documentdb_delete_test.cpp | 81 +++ .../unittest/api/ documentdb_find_test.cpp | 95 +++ .../unittest/api/ documentdb_insert_test.cpp | 619 ++++++++++++++++++ 24 files changed, 1485 insertions(+), 29 deletions(-) create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_format_config.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/projection_tree.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/projection_tree.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_delete_test.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_find_test.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h index ce782916..6301da76 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h @@ -20,6 +20,7 @@ #include #include "json_common.h" + class JsonCommon; namespace DocumentDB { class DocCommon @@ -30,7 +31,7 @@ public: static bool CheckCollectionName(const std::string &collectionName); static bool CheckFilter(JsonObject *filterObj); - static bool CheckIdFormat(JsonObject *filter_json); + static bool CheckIdFormat(JsonObject *filterJson); static bool CheckDocument(JsonObject *documentObj); }; using Key = std::vector; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp index 0da62195..e519eefd 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp @@ -18,6 +18,7 @@ #include "log_print.h" #include "securec.h" #include "json_object.h" +#include "grd_format_config.h" namespace DocumentDB { bool DocCommon::CheckCollectionName(const std::string &collectionName) @@ -42,10 +43,10 @@ bool DocCommon::CheckFilter(JsonObject *filterObj) return true; } -bool DocCommon::CheckIdFormat(JsonObject *filter_json) +bool DocCommon::CheckIdFormat(JsonObject *filterJson) { - auto filterObj_child = filter_json->GetChild(); - auto resultValue = JsonCommon::GetValueByFiled(&filterObj_child, "_id"); + auto filterObjChild = filterJson->GetChild(); + auto resultValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); if (resultValue.valueType != ResultValue::ValueType::VALUE_STRING) { return false; } @@ -57,7 +58,11 @@ bool DocCommon::CheckDocument(JsonObject *documentObj) if (CheckIdFormat(documentObj) == false) { return false; } - if (JsonCommon::CheckJsonField(documentObj) == false) { + JsonObject documentObjChild; + if (documentObj->GetChild().IsNull() != true) { + documentObjChild = documentObj->GetChild(); + } + if (JsonCommon::CheckJsonField(&documentObjChild) == false) { return false; } return true; 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 7514d328..fce10484 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 @@ -26,7 +26,8 @@ ResultValue JsonCommon::GetValueByFiled(JsonObject *node, const std::string& fil return ResultValue(); } while (node != nullptr) { - if (node->GetItemFiled() == filed) + int ret; + if (node->GetItemFiled(ret) == filed) { auto itemValue = node->GetItemValue(); return itemValue; @@ -69,10 +70,17 @@ bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, boo return false; } std::string fieldName; - if (node->GetItemValue().valueType != ResultValue::ValueType::VALUE_NULL) { - fieldName = node->GetItemFiled(); + if (node->IsNull() != true) { + int ret; + fieldName = node->GetItemFiled(ret); if (filedSet.find(fieldName) == filedSet.end()) { - filedSet.insert(fieldName); + if (ret == E_OK) { + filedSet.insert(fieldName); + } + if (ret == E_OK && fieldName == "") { + errFlag = false; + return false; + } } else { errFlag = false; @@ -83,6 +91,10 @@ bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, boo errFlag = false; return false; } + if (i == 0 && ('0'<=fieldName[i] && fieldName[i]<='9')) { + errFlag = false; + return false; + } } } if (node->GetChild().IsNull() != true) { @@ -109,7 +121,8 @@ int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, if (isFirstFloor) { std::string tempParseName; std::vector allFiledsName; - std::string priFieldName = node->GetItemFiled(); + int ret; + std::string priFieldName = node->GetItemFiled(ret); for (int j = 0; j < priFieldName.size(); j++) { if (priFieldName[j] != '.') { tempParseName = tempParseName + priFieldName[j]; @@ -123,11 +136,13 @@ int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, singlePath.insert(singlePath.end(), allFiledsName.begin(), allFiledsName.end()); } else { std::vector allFiledsName; - allFiledsName.emplace_back(node->GetItemFiled()); + int ret; + allFiledsName.emplace_back(node->GetItemFiled(ret)); fatherPath = singlePath; singlePath.insert(singlePath.end(), allFiledsName.begin(), allFiledsName.end()); } - if (node->GetChild().IsNull() != true && node->GetChild().GetItemFiled() != "") { + int ret; + if (node->GetChild().IsNull() != true && node->GetChild().GetItemFiled(ret) != "") { auto nodeNew = node->GetChild(); ParseNode(&nodeNew, singlePath, resultPath, false); } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp new file mode 100644 index 00000000..f99b084a --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp @@ -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. +*/ + +#include "grd_base/grd_error.h" +#include "doc_errno.h" +#include "grd_base/grd_error.h" +#include "grd_type_inner.h" +#include "grd_base/grd_resultset_api.h" +#include "log_print.h" + +using namespace DocumentDB; + +int GRD_Next(GRD_ResultSet *resultSet) +{ + resultSet->resultSet_->GetNext(); + return E_OK; +} + +int GRD_GetValue(GRD_ResultSet *resultSet, char **value) +{ + resultSet->resultSet_->GetValue(value); + return E_OK; +} + +int GRD_FreeValue(char *value) +{ + GLOGE("value is ==============>%s", value); + if (value == nullptr) { + return E_OK; + } + delete[] value; + value = nullptr;//为什么调用delete后,value的指针不为空捏。 + if (value != nullptr) { + GLOGE("delete fail"); + } + return E_OK; +} + +int GRD_FreeResultSet(GRD_ResultSet *resultSet) +{ + if (resultSet == nullptr) { + return E_OK; + } + delete[] resultSet; + resultSet = nullptr; + if (resultSet != nullptr) { + GLOGE("delete fail"); + } + return E_OK; +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index dc5ccf46..6d8733a1 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -16,6 +16,27 @@ #include "grd_document/grd_document_api.h" #include "grd_base/grd_error.h" #include "grd_type_inner.h" +#include "doc_errno.h" + +int TrasnferDocErrSecond(int err) +{ + switch (err) { + case DocumentDB::E_OK: + return GRD_OK; + case DocumentDB::E_ERROR: + return GRD_INNER_ERR; + case DocumentDB::E_INVALID_ARGS: + return GRD_INVALID_ARGS; + case DocumentDB::E_DATA_CONFLICT: + return GRD_DATA_CONFLICT; + case DocumentDB::E_INVALID_FORMAT: + return GRD_INVALID_FORMAT; + case DocumentDB::E_OVER_LIMIT: + return GRD_OVER_LIMIT; + default: + return GRD_INNER_ERR; + } +} int GRD_CreateCollection(GRD_DB *db, const char *collectionName, const char *optionStr, unsigned int flags) { @@ -48,3 +69,30 @@ int GRD_UpSertDoc(GRD_DB *db, const char *collectionName, const char *filter, co } return db->store_->UpsertDocument(collectionName, filter, document, flags); } + +int GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, unsigned int flags) +{ + if (db == nullptr || db->store_ == nullptr || collectionName == nullptr) { + return GRD_INVALID_ARGS; + } + int ret = db->store_->InsertDocument(collectionName, document, flags); + return TrasnferDocErrSecond(ret); +} + +int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, unsigned int flags) +{ + if (db == nullptr || db->store_ == nullptr) { + return GRD_INVALID_ARGS; + } + int ret = db->store_->DeleteDocument(collectionName, filter, flags); + return TrasnferDocErrSecond(ret); +} + +int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned int flags, GRD_ResultSet **resultSet) +{ + if (db == nullptr || db->store_ == nullptr) { + return GRD_INVALID_ARGS; + } + int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, resultSet[0]->resultSet_); + return TrasnferDocErrSecond(ret); +} diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_format_config.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_format_config.h new file mode 100644 index 00000000..06e7bbee --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_format_config.h @@ -0,0 +1,32 @@ +/* +* 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 GRD_FORMAT_CONFIG_H +#define GRD_FORMAT_CONFIG_H + + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#define COLLECTION_LENS_MAX (512 * 1024) +#define JSON_LENS_MAX (512 * 1024) +#define JSON_DEEP_MAX (4) +#define KEY_ID ("_id") + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // GRD_FORMAT_CONFIG_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h index afc300ec..d46324ff 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h @@ -22,4 +22,8 @@ typedef struct GRD_DB { DocumentDB::DocumentStore *store_ = nullptr; } GRD_DB; +typedef struct GRD_ResultSet { + DocumentDB::ResultSet *resultSet_ = new DocumentDB::ResultSet(); +} GRD_ResultSet; + #endif // GRD_TYPE_INNER_H \ No newline at end of file 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 6dba77c9..519d50a4 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 @@ -24,6 +24,7 @@ namespace DocumentDB { class Collection { public: Collection(std::string name, KvStoreExecutor *executor); + Collection(const Collection& collection); ~Collection(); int PutDocument(const Key &key, const Value &document); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h index c481c573..c69b700d 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h @@ -22,6 +22,9 @@ constexpr int E_OK = 0; constexpr int E_BASE = 1000; constexpr int E_ERROR = E_BASE + 1; constexpr int E_INVALID_ARGS = E_BASE + 2; +constexpr int E_OVER_LIMIT = E_BASE + 3; +constexpr int E_DATA_CONFLICT = E_BASE + 4; +constexpr int E_INVALID_FORMAT = E_BASE + 5; constexpr int E_UNFINISHED = E_BASE + 7; constexpr int E_OUT_OF_MEMORY = E_BASE + 8; constexpr int E_SECUREC_ERROR = E_BASE + 9; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h index 93925e55..af3a389e 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h @@ -21,6 +21,9 @@ #include "collection.h" #include "kv_store_executor.h" +#include "result_set.h" +#include "projection_tree.h" +#include "json_common.h" namespace DocumentDB { class DocumentStore { @@ -30,11 +33,13 @@ public: int CreateCollection(const std::string &name, const std::string &option, int flag); int DropCollection(const std::string &name, int flag); - int UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update, int flag); int UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flag); - + int InsertDocument(const std::string &collection, const std::string &document, int flag); + int DeleteDocument(const std::string &collection, const std::string &document, int flag); + int FindDocument(GRD_DB* db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet); private: + int GetViewType(JsonObject *jsonObj, bool &viewType); KvStoreExecutor *executor_ = nullptr; std::map collections_; }; 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 new file mode 100644 index 00000000..625066b0 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/projection_tree.h @@ -0,0 +1,36 @@ +#ifndef PROJECTION_TREE_H +#define PROJECTION_TREE_H + +#include +#include +#include +#include "doc_errno.h" +#include "json_common.h" +#include "log_print.h" + +namespace DocumentDB { +struct ProjectionNode { + std::unordered_map SonNode; + bool isDeepest; + int Deep; + int ViewType; + ProjectionNode() { + Deep = 1; + isDeepest = true; + } +}; +class ProjectionTree { +public: + ProjectionTree(); + ~ProjectionTree(); + + void Init() { + root_ = new ProjectionNode(); + } + int ParseTree(std::vector> &path); + bool SerchTree(std::vector &singlePath, int &index); +private: + ProjectionNode *root_; +}; +} // DocumentDB +#endif // PROJECTION_TREE_H \ No newline at end of file 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 new file mode 100644 index 00000000..e5edea96 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set.h @@ -0,0 +1,52 @@ +/* +* 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 RESULTSET_H +#define RESULTSET_H + +#include +#include "grd_base/grd_type_export.h" +#include "projection_tree.h" +#include "vector" +#include "doc_errno.h" +#include "json_object.h" +#include "securec.h" +#include "collection.h" +#include "doc_common.h" + + +namespace DocumentDB { + +class ResultSet { +public: + ResultSet() = default; + ~ResultSet(); + + int Init(Collection &coll, const std::string &key, std::vector> &path, bool ifShowId, bool viewType); + int GetNext(); + int GetValue(char **value); +private: + int CutString(std::string &jsonData); + int CheckCutNode(JsonObject *node, std::vector singlePath, std::vector> &allPath); + Collection* coll_; + std::string key_; + bool ifShowId_; + bool viewType_; + ProjectionTree* projectionTree_; + std::vector> path_; + int index_; +}; +} // DocumentDB +#endif //RESULTSET_H \ No newline at end of file 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 3e2562b1..0f66ca62 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 @@ -15,12 +15,19 @@ #include "collection.h" #include "doc_errno.h" +#include "log_print.h" namespace DocumentDB { Collection::Collection(std::string name, KvStoreExecutor *executor) : name_(name), executor_(executor) { } +Collection::Collection(const Collection& collection) +{ + name_ = collection.name_; + executor_ = collection.executor_; +} + Collection::~Collection() { executor_ = nullptr; @@ -36,7 +43,10 @@ int Collection::PutDocument(const Key &key, const Value &document) int Collection::GetDocument(const Key &key, Value &document) const { - return E_OK; + if (executor_ == nullptr) { + return -E_INVALID_ARGS; + } + return executor_->GetData(name_, key, document); } int Collection::DeleteDocument(const Key &key) 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 6fd1f679..97a2b529 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 @@ -15,6 +15,11 @@ #include "document_store.h" #include "doc_errno.h" +#include "json_common.h" +#include "json_object.h" +#include "log_print.h" +#include "doc_common.h" +#include "grd_format_config.h" namespace DocumentDB { DocumentStore::DocumentStore(KvStoreExecutor *executor) : executor_(executor) @@ -54,4 +59,161 @@ int DocumentStore::UpsertDocument(const std::string &collection, const std::stri return coll.PutDocument(key, value); } -} // namespace DocumentDB \ No newline at end of file + +int DocumentStore::InsertDocument(const std::string &collection, const std::string &document, int flag) +{ + auto coll = Collection(collection, executor_); + if (document.length() + 1 > JSON_LENS_MAX) { + return E_OVER_LIMIT; + } + JsonObject documentObj; + int ret = documentObj.Init(document); + if (ret != E_OK) { + return ret; + } + if (!DocCommon::CheckDocument(&documentObj) || flag != 0) { + return E_INVALID_ARGS; + } + auto documentObjChild = documentObj.GetChild(); + auto idValue = JsonCommon::GetValueByFiled(&documentObjChild, KEY_ID); + if (idValue.valueType != ResultValue::ValueType::VALUE_STRING) { + return E_INVALID_ARGS; + } + std::string id = idValue.valueString; + Key key(id.begin(), id.end()); + Value value(document.begin(), document.end()); + return coll.PutDocument(key, value); +} + +int DocumentStore::DeleteDocument(const std::string &collection, const std::string &filter, int flag) +{ + auto coll = Collection(collection, executor_); + JsonObject filterObj; + if (filterObj.Init(filter) != E_OK) { + return E_INVALID_ARGS; + } + if (!DocCommon::CheckFilter(&filterObj) || !DocCommon::CheckCollectionName(collection) || flag != 0) { + return E_INVALID_ARGS; + } + auto filterObjChild = filterObj.GetChild(); + auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); + if (idValue.valueType != ResultValue::ValueType::VALUE_STRING) { + return E_INVALID_ARGS; + } + std::string id = idValue.valueString; + Key key(id.begin(), id.end()); + return coll.DeleteDocument(key); +} + +int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet) +{ + JsonObject filterObj; + if (filterObj.Init(filter) != E_OK) { + return E_INVALID_ARGS; + } + if (!DocCommon::CheckFilter(&filterObj) || !DocCommon::CheckCollectionName(collection)) { + return E_INVALID_ARGS; + } + auto filterObjChild = filterObj.GetChild(); + auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); + if (idValue.valueType != ResultValue::ValueType::VALUE_STRING) { + return E_INVALID_ARGS; + } + std::string filterId = idValue.valueString; + JsonObject projectionObj; + if (projectionObj.Init(projection) != E_OK) { + return E_INVALID_ARGS; + } + bool viewType = false; + if (GetViewType(&projectionObj, viewType) != E_OK) { + return E_INVALID_ARGS; + } + bool ifShowId = false; + auto projectionObjChild = projectionObj.GetChild(); + auto projectionId = JsonCommon::GetValueByFiled(&projectionObjChild, KEY_ID); + if (flags == GRD_DOC_ID_DISPLAY) { + if (projectionId.valueString == "" && viewType == true) { + ifShowId = false; + } + else { + ifShowId = true; + } + } + auto allPath = JsonCommon::ParsePath(&projectionObj); + Collection coll = Collection(collection, executor_); + resultSet->Init(coll, filterId, allPath, ifShowId, viewType); + return E_OK; +} + +int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { + auto leafValue = JsonCommon::GetLeafValue(jsonObj); + if (leafValue.size() == 0) { + return E_INVALID_ARGS; + } + switch (leafValue[0].valueType) { + case ResultValue::ValueType::VALUE_TRUE: + viewType = true; + break; + case ResultValue::ValueType::VALUE_FALSE: + viewType = false; + break; + case ResultValue::ValueType::VALUE_STRING: + if (leafValue[0].valueString == "") { + viewType = true; + } + else { + return E_INVALID_ARGS; + } + break; + case ResultValue::ValueType::VALUE_NUMBER: + if (leafValue[0].valueNumber == 0) { + viewType = false; + } + else { + viewType = true; + } + break; + default: + return E_INVALID_ARGS; + } + for (int i = 1; i < leafValue.size(); i++) { + switch (leafValue[i].valueType) { + case ResultValue::ValueType::VALUE_TRUE: + if (viewType != true) { + return E_INVALID_ARGS; + } + break; + case ResultValue::ValueType::VALUE_FALSE: + if (viewType != false) { + return E_INVALID_ARGS; + } + break; + case ResultValue::ValueType::VALUE_STRING: + if (leafValue[i].valueString == "") { + if (viewType != false) { + return E_INVALID_ARGS; + } + } + else { + return E_INVALID_ARGS; + } + break; + case ResultValue::ValueType::VALUE_NUMBER: + if (leafValue[i].valueNumber == 0) { + if (viewType != false) { + return E_INVALID_ARGS; + } + } + else { + if (viewType != true) { + return E_INVALID_ARGS; + } + } + break; + default: + return E_INVALID_ARGS; + } + } + return E_OK; +} +} // namespace DocumentDB 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 new file mode 100644 index 00000000..3e076914 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/projection_tree.cpp @@ -0,0 +1,58 @@ +#include +#include "projection_tree.h" + + +namespace DocumentDB { + +ProjectionTree::ProjectionTree() { +} + +ProjectionTree::~ProjectionTree() { + GLOGE("ProjectionTree free2222"); +} + +int ProjectionTree::ParseTree(std::vector> &path) { + ProjectionNode *node = root_; + if (node == NULL) { + return E_OK; + } + for (int i = 0; i < path.size(); i++) { + node = root_; + for (int j = 0; j < path[i].size(); j++) { + if (node->SonNode[path[i][j]] != nullptr) { + node = node->SonNode[path[i][j]]; + if (j < path[i].size() - 1 && node->isDeepest == true) { + return E_INVALID_ARGS; + } + if (j == path[i].size() - 1 && node->isDeepest == false) { + return E_INVALID_ARGS; + } + } + else { + auto tempNode = new ProjectionNode; + tempNode->Deep = node->Deep + 1; + node->isDeepest = false; + node->SonNode[path[i][j]] = tempNode; + node = node->SonNode[path[i][j]]; + } + } + } + return E_OK; +} + +bool ProjectionTree::SerchTree(std::vector &singlePath, int &index) { + ProjectionNode *node = root_; + for (int i = 0; i < singlePath.size(); i++) { + if (node->isDeepest) { + index = i; + } + if (node->SonNode[singlePath[i]] != nullptr) { + node = node->SonNode[singlePath[i]]; + } + else { + return false; + } + } + return true; +} +} // namespace DocumentDB \ No newline at end of file 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 new file mode 100644 index 00000000..cf9890d6 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set.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 "result_set.h" +#include "log_print.h" +#include "grd_format_config.h" + +namespace DocumentDB { + +ResultSet::~ResultSet() +{ + GLOGE("delte ResultSet"); +} +int ResultSet::Init(Collection &coll, const std::string &key, std::vector> &path, bool ifShowId, bool viewType) +{ + coll_ = new Collection(coll); + key_ = key; + path_ = path; + ProjectionTree* projectionTree = new ProjectionTree(); + projectionTree->Init(); + if (projectionTree->ParseTree(path) == E_INVALID_ARGS) { + return E_INVALID_ARGS; + } + projectionTree_ = projectionTree; + ifShowId_ = ifShowId; + viewType_ = viewType; +} + +int ResultSet::GetNext() +{ + index_++; + return E_OK; +} + +int ResultSet::GetValue(char **value) +{ + if (index_ != 1) { + return E_OK; + } + if (projectionTree_ == nullptr) { + GLOGE("======>projectionTree_ is null"); + return E_INVALID_ARGS; + } + Value document; + Key key(key_.begin(), key_.end()); + coll_->GetDocument(key, document); + std::string jsonData(document.begin(), document.end()); + CutString(jsonData); + errno_t err = strcpy_s(value[0], jsonData.size() + 1, jsonData.c_str()); + if (err != 0) { + GLOGE("strcpy_s failed"); + } + return E_OK; +} + +int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePath, std::vector> &allPath) +{ + if (node == nullptr) { + return E_OK; + } + int ret; + singlePath.emplace_back(node->GetItemFiled(ret)); + int index = 0; + if (projectionTree_->SerchTree(singlePath, index) == false && index == 0) { + allPath.emplace_back(singlePath); + } + if (node->GetChild().IsNull() != true) { + auto nodeNew = node->GetChild(); + CheckCutNode(&nodeNew, singlePath, allPath); + } + if (node->GetNext().IsNull() != true) { + singlePath.pop_back(); + auto nodeNew = node->GetNext(); + CheckCutNode(&nodeNew, singlePath, allPath); + } + return E_OK; +} +int ResultSet::CutString(std::string &jsonData) +{ + JsonObject cjsonObj; + cjsonObj.Init(jsonData); + std::vector> allPath; + if (viewType_ == true) { + std::vector singlePath; + auto cjsonObjChild = cjsonObj.GetChild(); + CheckCutNode(&cjsonObjChild, singlePath, allPath); + for (int i = 0; i < allPath.size(); i++) { + if (ifShowId_ == false || allPath[i][0] != KEY_ID) { + cjsonObj.DeleteItemOnTarget(allPath[i]); + } + } + } + if (viewType_ == false) { + for (int i = 0; i < path_[0].size() - 1; i++) { + if (ifShowId_ == false || path_[i][0] != KEY_ID) { + cjsonObj.DeleteItemOnTarget(path_[i]); + } + } + } + jsonData = cjsonObj.Print(); + return E_OK; +} +} // namespace DocumentDB 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 9b1c4119..33fce535 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 @@ -62,12 +62,13 @@ public: JsonObject GetChild(); int DeleteItemFromObject(const std::string &field); ResultValue GetItemValue(); - std::string GetItemFiled(); + std::string GetItemFiled(int &errCode); JsonObject FindItem(const std::vector jsonPath); int DeleteItemOnTarget(std::vector &path); bool IsNull(); private: int GetDeep(cJSON *cjson, int deep, int &maxDeep); + int CheckNumber(cJSON *cjson, int &errCode); cJSON *cjson_; bool isClone_ = false; }; 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 f1d21444..2c3fc197 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 @@ -27,9 +27,11 @@ 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 DeleteData(const std::string &collName, const Key &key) = 0; virtual int CreateCollection(const std::string &name, int flag) = 0; virtual int DropCollection(const std::string &name, int flag) = 0; + }; } // DocumentDB #endif // KV_STORE_EXECUTOR_H \ No newline at end of file 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 19a75a55..6fe749a5 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 @@ -18,7 +18,6 @@ #include "grd_format_config.h" #include "json_object.h" - namespace DocumentDB { JsonObject::JsonObject() @@ -64,15 +63,17 @@ int JsonObject::GetDeep(cJSON *cjson, int deep, int &maxDeep) int JsonObject::Init(const std::string &str) { - if (str.length() + 1 > JSON_LENS_MAX) { - return E_INVALID_ARGS; - } const char *end = NULL; cjson_ = cJSON_ParseWithOpts(str.c_str(), &end, true); if (cjson_ == nullptr) { - return E_INVALID_ARGS; + return E_INVALID_FORMAT; } if (cjson_->type != cJSON_Object) { + return E_INVALID_FORMAT; + } + int ret; + CheckNumber(cjson_, ret); + if (ret == E_INVALID_ARGS) { return E_INVALID_ARGS; } int deep = 0; @@ -84,6 +85,23 @@ int JsonObject::Init(const std::string &str) return E_OK; } +int JsonObject::CheckNumber(cJSON *item, int &errCode) +{ + if (item != NULL && cJSON_IsNumber(item)) { + double value = cJSON_GetNumberValue(item); + if (value > __DBL_MAX__ || value < -__DBL_MAX__) { + errCode = E_INVALID_ARGS; + } + } + if (item->child != nullptr) { + CheckNumber(item->child, errCode); + } + if (item->next != nullptr) { + CheckNumber(item->next, errCode); + } + return E_OK; +} + std::string JsonObject::Print() { if (cjson_ == nullptr) { @@ -217,14 +235,17 @@ ResultValue JsonObject::GetItemValue() return value; } -std::string JsonObject::GetItemFiled() +std::string JsonObject::GetItemFiled(int &errCode) { if (cjson_ == nullptr) { + errCode = E_INVALID_ARGS; return ""; } if (cjson_->string == nullptr) { + errCode = E_INVALID_ARGS; return ""; } + errCode = E_OK; return cjson_->string; } 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 9f091ca1..b4c6838a 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 @@ -30,11 +30,11 @@ SqliteStoreExecutor::~SqliteStoreExecutor() int SqliteStoreExecutor::PutData(const std::string &collName, const Key &key, const Value &value) { + std::string key_value (key.begin(), key.end()); if (dbHandle_ == nullptr) { return -E_ERROR; } - - std::string sql = "INSERT OR REPLACE INTO '" + collName + "' VALUES (?,?);"; + std::string sql = "INSERT INTO '" + collName + "' VALUES (?,?);"; int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key, value](sqlite3_stmt *stmt) { SQLiteUtils::BindBlobToStatement(stmt, 1, key); SQLiteUtils::BindBlobToStatement(stmt, 2, value); @@ -42,8 +42,13 @@ int SqliteStoreExecutor::PutData(const std::string &collName, const Key &key, co }, nullptr); if (errCode != SQLITE_OK) { GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); - return errCode; - } + if (errCode == 19) { + return E_DATA_CONFLICT; + } + if (errCode == 1) { + return E_INVALID_ARGS; + } + }//要改 return E_OK; } @@ -52,7 +57,10 @@ int SqliteStoreExecutor::GetData(const std::string &collName, const Key &key, Va if (dbHandle_ == nullptr) { return -E_ERROR; } - + std::string key_value (key.begin(), key.end()); + if (dbHandle_ == nullptr) { + return -E_ERROR; + } std::string sql = "SELECT value FROM '" + collName + "' WHERE key=?;"; int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key](sqlite3_stmt *stmt) { SQLiteUtils::BindBlobToStatement(stmt, 1, key); @@ -65,6 +73,10 @@ int SqliteStoreExecutor::GetData(const std::string &collName, const Key &key, Va GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); return errCode; } + std::string ret_value (value.begin(), value.end()); + if (dbHandle_ == nullptr) { + return -E_ERROR; + } return E_OK; } @@ -97,4 +109,21 @@ int SqliteStoreExecutor::DropCollection(const std::string &name, int flag) } return E_OK; } + +int SqliteStoreExecutor::DeleteData(const std::string &collName, const Key &key) +{ + std::string key_value (key.begin(), key.end()); + sqlite3 *db = dbHandle_; + const std::string sql_delete = "DELETE FROM '" + collName + "' WHERE key = ?;"; + const std::function &bindCallback = [&](sqlite3_stmt *stmt) -> int { + SQLiteUtils::BindBlobToStatement(stmt, 1, key); + return E_OK; + }; + int errCode = SQLiteUtils::ExecSql(db, sql_delete, bindCallback, nullptr); + if (errCode != SQLITE_OK) { + GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); + return errCode; + } + return E_OK; +} } // 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 ab15f02d..d4301bac 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 @@ -30,7 +30,7 @@ public: int CreateCollection(const std::string &name, int flag) override; int DropCollection(const std::string &name, int flag) override; - + int DeleteData(const std::string &collName, const Key &key) override; private: sqlite3 *dbHandle_ = nullptr; }; 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 new file mode 100644 index 00000000..a934fce2 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_delete_test.cpp @@ -0,0 +1,81 @@ +/* +* 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 "grd_base/grd_db_api.h" +#include "grd_document/grd_document_api.h" +#include "grd_base/grd_error.h" +using namespace testing::ext; +namespace { + +std::string path = "./document.db"; +GRD_DB *g_db = nullptr; +} + +class DocumentDeleteApiTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void InsertDoc(const char *collectionName, const char *document); +}; +void DocumentDeleteApiTest::SetUpTestCase(void) +{ + GRD_DBOpen(path.c_str(), nullptr, 0, &g_db); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); + EXPECT_NE(g_db, nullptr); +} + +void DocumentDeleteApiTest::TearDownTestCase(void) +{ + EXPECT_EQ(GRD_DBClose(g_db, 0), GRD_OK); + remove(path.c_str()); +} + +void DocumentDeleteApiTest::SetUp(void) +{ +} + +void DocumentDeleteApiTest::TearDown(void) +{ +} + +static void chkDeleteResWithFilter(const char *filter) +{ +} + +void DocumentDeleteApiTest::InsertDoc(const char *collectionName, const char *document) +{ + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, document, 0), GRD_OK); +} + +/** + * @tc.name: DocumentDelete001 + * @tc.desc: Test Insert document db + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ + +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest001, TestSize.Level1) +{ + const char *collectionName = "student"; + const char *document = "{\"_id\":\"12345\", \"name\":\"jack\"}"; + const char *filter = "{\"_id\":\"12345\", \"name\":\"jack\"}"; + InsertDoc(collectionName, document); + EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName, filter, 0), GRD_OK); +} \ No newline at end of file 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 new file mode 100644 index 00000000..b94966ad --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_find_test.cpp @@ -0,0 +1,95 @@ +/* +* 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 "grd_base/grd_db_api.h" +#include "grd_document/grd_document_api.h" +#include "grd_base/grd_error.h" +#include "grd_base/grd_type_export.h" +#include "grd_type_inner.h" +#include "grd_base/grd_resultset_api.h" +using namespace testing::ext; +namespace { +std::string path = "./document.db"; +GRD_DB *g_db = nullptr; +} + +class DocumentFindApiTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + void InsertDoc(const char *collectionName, const char *document); +}; +void DocumentFindApiTest::SetUpTestCase(void) +{ + GRD_DBOpen(path.c_str(), nullptr, 0, &g_db); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); + EXPECT_NE(g_db, nullptr); +} + +void DocumentFindApiTest::TearDownTestCase(void) +{ + EXPECT_EQ(GRD_DBClose(g_db, 0), GRD_OK); + remove(path.c_str()); +} + +void DocumentFindApiTest::SetUp(void) +{ +} + +void DocumentFindApiTest::TearDown(void) +{ +} + + +void DocumentFindApiTest::InsertDoc(const char *collectionName, const char *document) +{ + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, document, 0), GRD_OK); +} + +/** + * @tc.name: DocumentDelete001 + * @tc.desc: Test Insert document db + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ + +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest, TestSize.Level1) +{ + const char *collectionName = "student"; + const char *document = "{\"_id\" : \"12345\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [1,2]}"; + // EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK);; + InsertDoc(collectionName, document); + const char *filter = "{\"_id\":\"12345\", \"name\":\"jack\", \"friend\" : {\"name\" : \"lucy\", \"country\" : \"Englis\", \"age\" : 19}}"; + const char *projection = "{\"friend.t1\":{\"t2\":0, \"t5\":0}}"; + Query query; + query.filter = filter; + query.projection = projection; + GRD_ResultSet **resultSet; + resultSet = new GRD_ResultSet *[1]; + resultSet[0] = new GRD_ResultSet; + EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, GRD_DOC_ID_DISPLAY, resultSet), GRD_OK); + char **test; + test = new char*[1]; + test[0] = new char[521 + 1]; + GRD_Next(resultSet[0]); + GRD_GetValue(resultSet[0], test); + GRD_FreeValue(test[0]); + // GRD_FreeResultSet(resultSet[0]); +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp new file mode 100644 index 00000000..efe734a3 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp @@ -0,0 +1,619 @@ +/* +* 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 "grd_base/grd_db_api.h" +#include "grd_document/grd_document_api.h" +#include "grd_base/grd_error.h" +using namespace testing::ext; +namespace { +std::string path = "./document.db"; +GRD_DB *g_db = nullptr; +const char *right_collectionName = "student"; +const char *no_exsit_collectionName = "no_exisit"; +const int int_max = 2147483647; +const int int_min = -2147483648; +const int max_collection_lens = 511; + +static void TestInsertDocIntoCertainColl(const char *collectionName, const char *projection, int expectedResult) +{ + /** + * @tc.steps: step1. Create Collection + * @tc.expected: step1. GRD_OK + */ + EXPECT_EQ(GRD_CreateCollection(g_db, collectionName, "", 0), expectedResult); + /** + * @tc.steps: step2. Insert projection into colloction. + * @tc.expected: step2. GRD_OK + */ + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, projection, 0), expectedResult); + /** + * @tc.steps: step3. Call GRD_DroCollection to drop the collection. + * @tc.expected: step3. GRD_OK + */ + EXPECT_EQ(GRD_DropCollection(g_db, collectionName, 0), expectedResult); +} + +const char* SetRandomDocument(int i) +{ + string document1 = "{\"_id\" : "; + string document2 = "\""; + string document3 = {'2','6'}; + string document4 = "\""; + string document5 = ", \"name\" : \"Ori\"}"; + string document = document1 + document2 + document3 + document4 + document5; + return document.c_str(); +} +} + +class DocumentInsertApiTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; +void DocumentInsertApiTest::SetUpTestCase(void) +{ + GRD_DBOpen(path.c_str(), nullptr, 0, &g_db); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); + EXPECT_NE(g_db, nullptr); +} + +void DocumentInsertApiTest::TearDownTestCase(void) +{ + EXPECT_EQ(GRD_DBClose(g_db, 0), GRD_OK); + remove(path.c_str()); +} + +void DocumentInsertApiTest::SetUp(void) +{ +} + +void DocumentInsertApiTest::TearDown(void) +{ +} + + +/** + * @tc.name: DocumentInsertApiTest001 + * @tc.desc: Insert documents into collection which dose not exist + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert document into collection which dose not exist + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"1\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, no_exsit_collectionName, document1, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest002 + * @tc.desc: Insert documents into collection which _id is not string + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a document whose _id is integer + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : 2, \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is bool + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document2 = "{\"_id\" : true, \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is NULL + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document3 = "{\"_id\" : null, \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is ARRAY + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document4 = "{\"_id\" : [\"2\"], \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is OBJECT + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document5 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_INVALID_ARGS); +} + + +/** + * @tc.name: DocumentInsertApiTest003 + * @tc.desc: Insert a document whose _id has appeared before + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a document whose _id is string + * @tc.expected:step1.GRD_OK + */ + const char *document1 = "{\"_id\" : \"3\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + + /** + * @tc.steps:step2.Insert a document whose _id has appeared before + * @tc.expected:step2.GRD_DATA_CONFLICT + */ + const char *document2 = "{\"_id\" : \"3\", \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_DATA_CONFLICT); +} + +/** + * @tc.name: DocumentInsertApiTest004 + * @tc.desc: Test Insert with null parameter. parameter db is NULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1.step1.parameter db is NULL + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"4\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(NULL, right_collectionName, document1, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest005 + * @tc.desc: Test insert with null parameter. parameter collectionName is NULL. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest005, TestSize.Level1) +{ + /** + * @tc.steps:step1.Parameter collectionName is NULL + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"5\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, NULL, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Parameter collectionName is empty string + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document2 = "{\"_id\" : \"5\", \"name\" : \"Chuang\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, "", document2, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest006 + * @tc.desc: parameter flags is not zero + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest006, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter flags is not zero + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"6\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 1), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest007 + * @tc.desc: parameter flags is INT_MAX + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest007, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter flags is int_max + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"7\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_max), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest008 + * @tc.desc: parameter flags is int_min + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest008, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter flags is int_min + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"8\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_min), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest009 + * @tc.desc: parameter collectionName and document is NULL or invalid + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter collectionName and document is NULL; + * @tc.expected:step1.GRD_INVALID_ARGS + */ + EXPECT_EQ(GRD_InsertDoc(g_db, NULL, NULL, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.parameter collectionName is larger than max_collectionName_lens; + * @tc.expected:step2.GRD_OVER_LIMIT + */ + // std::string collectionName2(max_collection_lens + 1, 'a'); + // EXPECT_EQ(GRD_InsertDoc(g_db, collectionName2.c_str(), JSON_STR_HASID, 0), GRD_OVER_LIMIT); +} + +/** + * @tc.name: DocumentInsertApiTest010 + * @tc.desc: parameter collectionName contains irregular charactor + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest010, TestSize.Level1) +{ + /** + * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor + * @tc.expected:step1.GRD_OK + */ + const char *collectionName = "collction@!#"; + const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName, document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest011 + * @tc.desc: parameter collectionName is longer than 256 charactors + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest011, TestSize.Level1) +{ + /** + * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor + * @tc.expected:step1.GRD_OK + */ + string collectionName(257, 'k'); + const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest014 + * @tc.desc: Inserted document's JSON depth is larger than 4, which is 5. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) +{ + /** + * @tc.steps:step1.document's JSON depth is larger than 4, which is 5. + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}}, \"level3_2\" : \"level3_2_val\"\ + }},\"_id\":\"14\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step1.document's JSON depth is larger than 4, which is 5.But with array type. + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document2 = "{\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"level5_1val\", \"level5_2\":\ + \"level5_2_val\"}, \"level4_val1\",\"level4_val2\"], \"level3_2\" : \"level3_2_val\"\ + }},\"_id\":\"14\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step1.document's JSON depth is 4 + * @tc.expected:step1.GRD_OK + */ + const char *document3 = "{\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"level5_1val\"}, \"level3_2\" : \"level3_2_val\"\ + }},\"_id\":\"14\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest015 + * @tc.desc: Inserted document with all kinds of size + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) +{ + /** + * @tc.steps:step1.document's JSON is bigger than 512k - 1 + * @tc.expected:step1.GRD_INVALID_ARGS + */ + string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; + string documentPart2 = "\" }"; + string jsonVal = string(512 * 1024 - documentPart1.size() - documentPart2.size(), 'k'); + string document = documentPart1 + jsonVal + documentPart2; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OVER_LIMIT); + /** + * @tc.steps:step2.Insert document's JSON is a large data but lower than 512k - 1 + * @tc.expected:step2.GRD_OK + */ + string jsonVal2 = string(512 * 1024 - 1 - documentPart1.size() - documentPart2.size(), 'k'); + string document2 = documentPart1 + jsonVal2 + documentPart2; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2.c_str(), 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest016 + * @tc.desc: document JSON string contains irregular char + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest016, TestSize.Level1) +{ + /** + * @tc.steps:step1.document JSON string contains irregular char. + * @tc.expected:step1.GRD_OK + */ + const char *document1 = "{\"_id\" : \"16\", \"name\" : \"!@#Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest017 + * @tc.desc: document JSON string contains invalid value type such as BLOB type + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) +{ + /** + * @tc.steps:step1.document JSON string contains invalid value type such as BLOB type. + * @tc.expected:step1.GRD_INVALID_FORMAT. + */ + const char *document = "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : x'1234'\ + } } }, \"level1_2\" : \"level1_2Val\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); +} + +/** + * @tc.name: DocumentInsertApiTest018 + * @tc.desc: The Inserted document is not JSON format + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest018, TestSize.Level1) +{ + /** + * @tc.steps:step1.The Inserted document is not JSON format + * @tc.expected:step1.GRD_INVALID_FORMAT. + */ + const char *document = "some random string not JSON format"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); +} + +/** + * @tc.name: DocumentInsertApiTest019 + * @tc.desc: Insert a normal documents + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest019, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a normal documents which _id is in the end of the string + * @tc.expected:step1.GRD_OK. + */ + const char *document1 = "{\"name\" : \"Jack\", \"age\" : 18, \"friend\" : {\"name\" : \" lucy\"}, \"_id\" : \"19\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest022 + * @tc.desc: parameter collectionName is equal to 256 charactors + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest022, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter collectionName is equal to 256 charactors + * @tc.expected:step1.GRD_OK. + */ + string collectionName = string(256, 'k'); + const char *document1 = "{\"_id\" : \"22\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest023 + * @tc.desc: parameter collectionName contains upper & lower case charactors, + * numbers and underline + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter collectionName contains upper & lower case charactors, + * numbers and underline + * @tc.expected:step1.GRD_OK. + */ + string collectionName = "Aads_sd__23Asb_"; + const char *document1 = "{\"_id\" : \"23\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest025 + * @tc.desc: Insert document whose depth is 4, which is allowed + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) +{ + /** + * @tc.steps:step1.documents JSON depth is 4, which is allowed. + * @tc.expected:step1.GRD_OK. + */ + const char *document1 = "{\"_id\" : \"25_0\", \"level1\" : { \"level2\" : {\"level3\" :\ + {\"level4\" : \"level4Val\" } } } , \"level1_2\" : \"level1_2Val\" }"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + /** + * @tc.steps:step2.documents JSON depth is exactly 4. + * @tc.expected:step2.GRD_OK. + */ + const char *document2 = "{\"_id\" : \"25_1\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ + \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\"] }]}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK); + /** + * @tc.steps:step3.documents JSON depth is exactly 4, but the last field in array contains leading number + * @tc.expected:step3.GRD_INVALID_ARGS. + */ + const char *document3 = "{\"_id\" : \"25_2\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ + \"age\" : 18, \"sex\" : \"男\"}, [\"qw\", \"dr\", 0, \"ab\", {\"0ab\" : null}]]}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step4.documents JSON depth is exactly 5. + * @tc.expected:step4.GRD_INVALID_ARGS. + */ + const char *document4 = "{\"_id\" : \"25_3\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ + \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\", {\"level5\" : 1}] }]}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest026 + * @tc.desc: Insert 100 normal documents continuously + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert 100 normal documents continuously + * @tc.expected:step1.GRD_OK. + */ + string document1 = "{\"_id\" : "; + string document2 = "\""; + string document4 = "\""; + string document5 = ", \"name\" : \"Ori\"}"; + for (int i = 0; i < 5; i++) { + string document_midlle = {'2','6' + i}; + string document = document1 + document2 + document_midlle + document4 + document5; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OK); + } +} + +/** + * @tc.name: DocumentInsertApiTest036 + * @tc.desc: Insert a document whose value contains + * string, number, bool, null, array and object type + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a document whose value contains + * string, number, bool, null, array and object type + * @tc.expected:step1.GRD_OK. + */ + const char *document1 = "{\"_id\" : \"36_0\", \"stringType\" : \"stringVal\", \"numType\" : 1, \"BoolType\" : true,\ + \"nullType\" : null, \"arrayType\" : [1, 2, 3, 4], \"objectType\" : {\"A\" : 3}}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest038 + * @tc.desc: Insert document whose value is over the range of double + * string, number, bool, null, array and object type + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest038, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert document whose value is over the range of double + * @tc.expected:step1.GRD_INVALID_ARGS. + */ + const char *document1 = R"({"_id" : "38_0", "field2" : 1.79769313486232e308})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert document whose value is over the range of double + * @tc.expected:step2.GRD_INVALID_ARGS. + */ + const char *document2 = R"({"_id" : "38_1", "t1" : {"field2" : 1.79769313486232e308}})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step3.Insert document whose value is over the range of double + * @tc.expected:step3.GRD_INVALID_ARGS. + */ + const char *document3 = R"({"_id" : "38_2", "t1" : [1, 2, 1.79769313486232e308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step4.Insert document whose value is over the range of double + * @tc.expected:step4.GRD_INVALID_ARGS. + */ + const char *document4 = R"({"_id" : "38_3", "t1" : [1, 2, -1.7976931348623167E+308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step5.Insert document with minimum double value + * @tc.expected:step5.GRD_INVALID_ARGS. + */ + const char *document5 = R"({"_id" : "38_4", "t1" : [1, 2, -1.79769313486231570E+308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_OK); + /** + * @tc.steps:step6.Insert document with maxium double value + * @tc.expected:step6.GRD_INVALID_ARGS. + */ + const char *document6 = R"({"_id" : "38_5", "t1" : [1, 2, 1.79769313486231570E+308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document6, 0), GRD_OK); +} \ No newline at end of file -- Gitee From 70addc548065ac5846baa188eabe650892b94878 Mon Sep 17 00:00:00 2001 From: mazhao Date: Fri, 7 Apr 2023 03:16:09 +0000 Subject: [PATCH 03/18] Complete deleting use cases and fixing bugs Signed-off-by: mazhao --- .../src/common/src/doc_common.cpp | 3 + .../src/executor/base/grd_resultset_api.cpp | 40 ++- .../executor/document/grd_document_api.cpp | 2 +- .../src/interface/include/doc_errno.h | 1 + .../src/interface/include/result_set.h | 1 + .../src/interface/src/collection.cpp | 5 +- .../src/interface/src/document_store.cpp | 11 +- .../src/interface/src/result_set.cpp | 44 +++- .../src/sqlite_store_executor_impl.cpp | 9 +- .../unittest/api/ documentdb_delete_test.cpp | 247 +++++++++++++++++- .../unittest/api/ documentdb_find_test.cpp | 17 +- 11 files changed, 327 insertions(+), 53 deletions(-) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp index e519eefd..931e8cde 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp @@ -40,6 +40,9 @@ bool DocCommon::CheckFilter(JsonObject *filterObj) if (CheckIdFormat(filterObj) == false) { return false; } + if (filterObj->GetChild().GetNext().IsNull() != true) { + return false; + } return true; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp index f99b084a..f4ce8118 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp @@ -22,41 +22,63 @@ using namespace DocumentDB; +int TrasnferDocErrThird(int err) +{ + switch (err) { + case DocumentDB::E_OK: + return GRD_OK; + case DocumentDB::E_ERROR: + return GRD_INNER_ERR; + case DocumentDB::E_INVALID_ARGS: + return GRD_INVALID_ARGS; + case DocumentDB::E_DATA_CONFLICT: + return GRD_DATA_CONFLICT; + case DocumentDB::E_INVALID_FORMAT: + return GRD_INVALID_FORMAT; + case DocumentDB::E_OVER_LIMIT: + return GRD_OVER_LIMIT; + case DocumentDB::E_NO_DATA: + return GRD_NO_DATA; + default: + return GRD_INNER_ERR; + } +} + int GRD_Next(GRD_ResultSet *resultSet) { - resultSet->resultSet_->GetNext(); - return E_OK; + int ret = resultSet->resultSet_->GetNext(); + return TrasnferDocErrThird(ret); } int GRD_GetValue(GRD_ResultSet *resultSet, char **value) { - resultSet->resultSet_->GetValue(value); - return E_OK; + int ret = resultSet->resultSet_->GetValue(value); + return TrasnferDocErrThird(ret); } int GRD_FreeValue(char *value) { GLOGE("value is ==============>%s", value); if (value == nullptr) { - return E_OK; + return GRD_OK; } delete[] value; - value = nullptr;//为什么调用delete后,value的指针不为空捏。 + value = nullptr;//为什么调用delete后,value的指针不为空。 if (value != nullptr) { GLOGE("delete fail"); } - return E_OK; + return GRD_OK; } int GRD_FreeResultSet(GRD_ResultSet *resultSet) { if (resultSet == nullptr) { - return E_OK; + return GRD_OK; } delete[] resultSet; resultSet = nullptr; if (resultSet != nullptr) { GLOGE("delete fail"); } - return E_OK; + return GRD_OK; } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 6d8733a1..295e3d33 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -81,7 +81,7 @@ int GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, unsigned int flags) { - if (db == nullptr || db->store_ == nullptr) { + if (db == nullptr || db->store_ == nullptr || filter == nullptr) { return GRD_INVALID_ARGS; } int ret = db->store_->DeleteDocument(collectionName, filter, flags); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h index c69b700d..d821fa6c 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h @@ -25,6 +25,7 @@ constexpr int E_INVALID_ARGS = E_BASE + 2; constexpr int E_OVER_LIMIT = E_BASE + 3; constexpr int E_DATA_CONFLICT = E_BASE + 4; constexpr int E_INVALID_FORMAT = E_BASE + 5; +constexpr int E_NO_DATA = E_BASE + 6; constexpr int E_UNFINISHED = E_BASE + 7; constexpr int E_OUT_OF_MEMORY = E_BASE + 8; constexpr int E_SECUREC_ERROR = E_BASE + 9; 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 e5edea96..a266f983 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 @@ -47,6 +47,7 @@ private: ProjectionTree* projectionTree_; std::vector> path_; int index_; + std::vector findValue_; }; } // DocumentDB #endif //RESULTSET_H \ No newline at end of file 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 0f66ca62..4c6b2944 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 @@ -51,7 +51,10 @@ int Collection::GetDocument(const Key &key, Value &document) const int Collection::DeleteDocument(const Key &key) { - return E_OK; + if (executor_ == nullptr) { + return -E_INVALID_ARGS; + } + return executor_->DeleteData(name_, key); } int Collection::UpsertDocument(const Key &key, Value &document) 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 97a2b529..99a92647 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 @@ -92,7 +92,7 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri if (filterObj.Init(filter) != E_OK) { return E_INVALID_ARGS; } - if (!DocCommon::CheckFilter(&filterObj) || !DocCommon::CheckCollectionName(collection) || flag != 0) { + if (!DocCommon::CheckFilter(&filterObj) || flag != 0) { return E_INVALID_ARGS; } auto filterObjChild = filterObj.GetChild(); @@ -125,19 +125,14 @@ int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const return E_INVALID_ARGS; } bool viewType = false; - if (GetViewType(&projectionObj, viewType) != E_OK) { + if (GetViewType(&projectionObj, viewType) != E_OK && projection != "{}") { return E_INVALID_ARGS; } bool ifShowId = false; auto projectionObjChild = projectionObj.GetChild(); auto projectionId = JsonCommon::GetValueByFiled(&projectionObjChild, KEY_ID); if (flags == GRD_DOC_ID_DISPLAY) { - if (projectionId.valueString == "" && viewType == true) { - ifShowId = false; - } - else { - ifShowId = true; - } + ifShowId = true; } auto allPath = JsonCommon::ParsePath(&projectionObj); Collection coll = Collection(collection, executor_); 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 cf9890d6..cd7a86cc 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 @@ -35,28 +35,36 @@ int ResultSet::Init(Collection &coll, const std::string &key, std::vectorprojectionTree_ is null"); - return E_INVALID_ARGS; - } Value document; + if (key_ == "") { + return E_NO_DATA; + } Key key(key_.begin(), key_.end()); coll_->GetDocument(key, document); + if (document.size() == 0) { + return E_NO_DATA; + } std::string jsonData(document.begin(), document.end()); CutString(jsonData); + findValue_.emplace_back(jsonData); + return E_OK; +} + +int ResultSet::GetValue(char **value) +{ + if (findValue_.size() == 0) { + return E_NO_DATA; + } + auto jsonData = findValue_.back(); errno_t err = strcpy_s(value[0], jsonData.size() + 1, jsonData.c_str()); if (err != 0) { GLOGE("strcpy_s failed"); @@ -72,6 +80,10 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat int ret; singlePath.emplace_back(node->GetItemFiled(ret)); int index = 0; + if (projectionTree_ == nullptr) { + GLOGE("======>projectionTree_ is null"); + return E_OK; + } if (projectionTree_->SerchTree(singlePath, index) == false && index == 0) { allPath.emplace_back(singlePath); } @@ -91,6 +103,7 @@ int ResultSet::CutString(std::string &jsonData) JsonObject cjsonObj; cjsonObj.Init(jsonData); std::vector> allPath; + bool idFlag = false; if (viewType_ == true) { std::vector singlePath; auto cjsonObjChild = cjsonObj.GetChild(); @@ -102,10 +115,13 @@ int ResultSet::CutString(std::string &jsonData) } } if (viewType_ == false) { - for (int i = 0; i < path_[0].size() - 1; i++) { - if (ifShowId_ == false || path_[i][0] != KEY_ID) { - cjsonObj.DeleteItemOnTarget(path_[i]); - } + for (int i = 0; i < path_.size(); i++) { + cjsonObj.DeleteItemOnTarget(path_[i]); + } + if (ifShowId_ == false) { + std::vector idPath; + idPath.emplace_back(KEY_ID); + cjsonObj.DeleteItemOnTarget(idPath); } } jsonData = cjsonObj.Print(); 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 b4c6838a..24317ce3 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 @@ -122,8 +122,13 @@ int SqliteStoreExecutor::DeleteData(const std::string &collName, const Key &key) int errCode = SQLiteUtils::ExecSql(db, sql_delete, bindCallback, nullptr); if (errCode != SQLITE_OK) { GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); - return errCode; - } + if (errCode == 19) { + return E_DATA_CONFLICT; + } + if (errCode == 1) { + return E_INVALID_ARGS; + } + }//要改 return E_OK; } } // DocumentDB \ No newline at end of file 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 a934fce2..4bc5e4b4 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 @@ -18,6 +18,12 @@ #include "grd_base/grd_db_api.h" #include "grd_document/grd_document_api.h" #include "grd_base/grd_error.h" +#include "grd_base/grd_type_export.h" +#include "grd_type_inner.h" +#include "grd_base/grd_resultset_api.h" + +#define COLLECTION_NAME "student" +#define NULL_JSON_STR "{}" using namespace testing::ext; namespace { @@ -36,7 +42,6 @@ public: void DocumentDeleteApiTest::SetUpTestCase(void) { GRD_DBOpen(path.c_str(), nullptr, 0, &g_db); - EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); EXPECT_NE(g_db, nullptr); } @@ -48,14 +53,80 @@ void DocumentDeleteApiTest::TearDownTestCase(void) void DocumentDeleteApiTest::SetUp(void) { + /** + * @tc.steps:step1. Create Collection + * @tc.expected: step1. GRD_OK + */ + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); + /** + * @tc.steps:step2. Insert many document in order to delete + * @tc.expected: step2. GRD_OK + */ + const char *document1 = + "{ \ + \"_id\" : \"1\", \ + \"name\": \"xiaoming\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"math\", \"English\", \"music\"] \ + }"; + const char *document2 = + "{ \ + \"_id\" : \"2\", \ + \"name\": \"ori\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"math\", \"English\", \"music\"] \ + }"; + const char *document3 = + "{ \ + \"_id\" : \"3\", \ + \"name\": \"David\", \ + \"address\": \"beijing\", \ + \"age\" : 15, \ + \"friend\" : {\"name\" : \"David\", \"sex\" : \"female\", \"age\" : 90}, \ + \"subject\": [\"math\", \"English\", \"music\"] \ + }"; + DocumentDeleteApiTest::InsertDoc(COLLECTION_NAME, document1); + DocumentDeleteApiTest::InsertDoc(COLLECTION_NAME, document2); + DocumentDeleteApiTest::InsertDoc(COLLECTION_NAME, document3); } void DocumentDeleteApiTest::TearDown(void) { + /** + * @tc.steps:step1. Call GRD_DropCollection to drop the collection + * @tc.expected: step1. GRD_OK + */ + EXPECT_EQ(GRD_DropCollection(g_db, COLLECTION_NAME, 0), GRD_OK); } -static void chkDeleteResWithFilter(const char *filter) +static void ChkDeleteResWithFilter(const char *filter) { + /** + * @tc.steps:step1. Try to find the deleted document + * @tc.expected: step1. GRD_OK + */ + Query query; + query.filter = filter; + const char *projection = "{}"; + query.projection = projection; + GRD_ResultSet *resultSet; + resultSet = new GRD_ResultSet; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + /** + * @tc.steps:step2. The resultset should be NULL + * @tc.expected: step2. GRD_OK + */ + EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); + char **test; + test = new char*[1]; + test[0] = new char[521 + 1]; + EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); + EXPECT_EQ(GRD_FreeValue(test[0]), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } void DocumentDeleteApiTest::InsertDoc(const char *collectionName, const char *document) @@ -65,17 +136,175 @@ void DocumentDeleteApiTest::InsertDoc(const char *collectionName, const char *do /** * @tc.name: DocumentDelete001 - * @tc.desc: Test Insert document db + * @tc.desc: Delete with NULL filter * @tc.type: FUNC * @tc.require: * @tc.author: mazhao */ - HWTEST_F(DocumentDeleteApiTest, DeleteDBTest001, TestSize.Level1) { - const char *collectionName = "student"; - const char *document = "{\"_id\":\"12345\", \"name\":\"jack\"}"; - const char *filter = "{\"_id\":\"12345\", \"name\":\"jack\"}"; - InsertDoc(collectionName, document); - EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName, filter, 0), GRD_OK); + /** + * @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); +} + +/** + * @tc.name: DocumentDelete002 + * @tc.desc: Delete with filter which has no _id + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1. Delete with filter which has no _id + * @tc.expected: step1. GRD_INVALID_ARGS + */ + const char *filter = "{\"age\" : 15}"; + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentDelete003 + * @tc.desc: Delete with filter which has more than one fileds. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. Delete with filter which has more than one fileds. + * @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); +} + +/** + * @tc.name: DocumentDelete004 + * @tc.desc: Test delete with invalid input + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. Test delete with un-zero flags + * @tc.expected: step1. GRD_INVALID_ARGS + */ + const char *filter1 = "{\"_id\" : \"1\"}"; + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter1, 1), GRD_INVALID_ARGS); + /** + * @tc.steps:step2. Test delete with NULL collection name + * @tc.expected: step2. GRD_INVALID_ARGS + */ + // const char *filter2 = "{\"_id\" : \"1\"}"; + // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step3. Test delete with empty collection name + * @tc.expected: step3. GRD_INVALID_ARGS + */ + // const char *filter1 = "{\"_id\" : \"1\"}"; + // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter1, 1), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentDelete005 + * @tc.desc: Test delete with same collection name + * but one is uppercase(delete) and the other is lowercase(insert) + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest005, TestSize.Level1) +{ + /** + * @tc.step1: Test delete with same collection name + * but one is uppercase(delete) and the other is lowercase(insert) + * @tc.expected: step1. GRD_INVALID_ARGS + */ + const char *filter = "{\"_id\" : \"1\"}"; + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); + /** + * @tc.step2: Check whether doc has been deleted compeletely + * @tc.expected: step2. GRD_OK + */ + ChkDeleteResWithFilter(filter); +} + +/** + * @tc.name: DocumentDelete006 + * @tc.desc: Test delete after calling find interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, 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\"}"; + GRD_ResultSet *resultSet; + resultSet = new GRD_ResultSet; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); + /** + * @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); +} + +/** + * @tc.name: DocumentDelete008 + * @tc.desc: Test delete with invalid NULL input for all parameters. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest008, TestSize.Level1) +{ + /** + * @tc.steps:step1. Delete with filter which has more than one fileds. + * @tc.expected: step1. GRD_INVALID_ARGS + */ + const char *filter = "{\"_id\" : \"1\"}"; + EXPECT_EQ(GRD_DeleteDoc(NULL, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); + // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter, 0), GRD_INVALID_ARGS); + // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentDelete010 + * @tc.desc: Test delete document when filter _id is int and string + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) +{ + /** + * @tc.steps:step1. Test delete document when filter _id is int and string. + * @tc.expected: step1. GRD_INVALID_ARGS + */ + std::vector filterVec = {R"({"_id" : 1})", R"("_id":[1, 2]})", + R"({"_id" : {"t1" : 1}})", R"({"_id":null})", R"({"_id":true})", R"({"_id" : 1.333})", R"({"_id" : -2.0})"}; + for (const auto &item : filterVec) { + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, item.c_str(), 0), GRD_INVALID_ARGS); + } + const char *filter = "{\"_id\" : \"1\"}"; + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); + } \ No newline at end of file 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 b94966ad..b0cd0da1 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 @@ -73,23 +73,22 @@ void DocumentFindApiTest::InsertDoc(const char *collectionName, const char *docu HWTEST_F(DocumentFindApiTest, DocumentFindApiTest, TestSize.Level1) { const char *collectionName = "student"; - const char *document = "{\"_id\" : \"12345\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [1,2]}"; + const char *document = "{\"_id\" : \"12345\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [1,2], \"friend\" : {\"t1\":{\"t2\":1, \"t5\":1}}}"; // EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK);; InsertDoc(collectionName, document); - const char *filter = "{\"_id\":\"12345\", \"name\":\"jack\", \"friend\" : {\"name\" : \"lucy\", \"country\" : \"Englis\", \"age\" : 19}}"; - const char *projection = "{\"friend.t1\":{\"t2\":0, \"t5\":0}}"; + const char *filter = "{\"_id\":\"12345\"}"; + const char *projection = "{}"; Query query; query.filter = filter; query.projection = projection; - GRD_ResultSet **resultSet; - resultSet = new GRD_ResultSet *[1]; - resultSet[0] = new GRD_ResultSet; - EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, GRD_DOC_ID_DISPLAY, resultSet), GRD_OK); + GRD_ResultSet *resultSet; + resultSet = new GRD_ResultSet; + EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 0, &resultSet), GRD_OK); char **test; test = new char*[1]; test[0] = new char[521 + 1]; - GRD_Next(resultSet[0]); - GRD_GetValue(resultSet[0], test); + GRD_Next(resultSet); + EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); GRD_FreeValue(test[0]); // GRD_FreeResultSet(resultSet[0]); } \ No newline at end of file -- Gitee From b0db406fc87a0b3faddd7c1b21d589382dd9c636 Mon Sep 17 00:00:00 2001 From: mazhao Date: Mon, 10 Apr 2023 03:09:31 +0000 Subject: [PATCH 04/18] Version that has not been merged modified Signed-off-by: mazhao --- .../unittest/api/ documentdb_find_test.cpp | 73 +++++++++++++------ 1 file changed, 50 insertions(+), 23 deletions(-) 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 b0cd0da1..4eae25a6 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 @@ -25,6 +25,41 @@ using namespace testing::ext; namespace { std::string path = "./document.db"; GRD_DB *g_db = nullptr; + +static const char *g_document1 = "{\"_id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"personInfo\":\ +{\"school\":\"AB\", \"age\" : 51}}"; +static const char *g_document2 = "{\"_id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"personInfo\":\ +[1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; +static const char *g_document3 = "{\"_id\" : \"3\", \"name\":\"doc3\",\"item\":\"notebook\",\"personInfo\":\ +[{\"school\":\"C\", \"age\" : 5}]}"; +static const char *g_document4 = "{\"_id\" : \"4\", \"name\":\"doc4\",\"item\":\"paper\",\"personInfo\":\ +{\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; +static const char *g_document5 = "{\"_id\" : \"5\", \"name\":\"doc5\",\"item\":\"journal\",\"personInfo\":\ +[{\"sex\" : \"woma\", \"school\" : \"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *g_document6 = "{\"_id\" : \"6\", \"name\":\"doc6\",\"item\":false,\"personInfo\":\ +[{\"school\":\"B\", \"teacher\" : \"mike\",\"age\" : 15}, {\"school\":\"C\", \"teacher\" : \"moon\",\"age\" : 20}]}"; +static const char *g_document7 = "{\"_id\" : \"7\", \"name\":\"doc7\",\"item\":\"fruit\",\"other_Info\":\ +[{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *g_document8 = "{\"_id\" : \"8\", \"name\":\"doc8\",\"item\":true,\"personInfo\":\ +[{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; +static const char *g_document9 = "{\"_id\" : \"9\", \"name\":\"doc9\",\"item\": true}"; +static const char *g_document10 = "{\"_id\" : \"10\", \"name\":\"doc10\", \"parent\" : \"kate\"}"; +static const char *g_document11 = "{\"_id\" : \"11\", \"name\":\"doc11\", \"other\" : \"null\"}"; +static const char *g_document12 = "{\"_id\" : \"12\", \"name\":\"doc12\",\"other\" : null}"; +static const char *g_document13 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"personInfo\":\ +{\"school\":\"AB\", \"age\" : 15}}"; +static const char *g_document14 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"personInfo\":\ +{\"school\":\"AB\", \"age\" : 15}}"; + + +static std::vectorg_data = {g_document1, g_document2, g_document3, g_document4, g_document5, g_document6, g_document7, + g_document8}; + +static void InsertData(GRD_DB *g_db, const char *collectionName) { + for (const auto &item : g_data) { + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, item, 0), GRD_OK); + } +} } class DocumentFindApiTest : public testing::Test { @@ -50,6 +85,7 @@ void DocumentFindApiTest::TearDownTestCase(void) void DocumentFindApiTest::SetUp(void) { + InsertData(g_db, "student"); } void DocumentFindApiTest::TearDown(void) @@ -57,11 +93,6 @@ void DocumentFindApiTest::TearDown(void) } -void DocumentFindApiTest::InsertDoc(const char *collectionName, const char *document) -{ - EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, document, 0), GRD_OK); -} - /** * @tc.name: DocumentDelete001 * @tc.desc: Test Insert document db @@ -72,23 +103,19 @@ void DocumentFindApiTest::InsertDoc(const char *collectionName, const char *docu HWTEST_F(DocumentFindApiTest, DocumentFindApiTest, TestSize.Level1) { - const char *collectionName = "student"; - const char *document = "{\"_id\" : \"12345\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [1,2], \"friend\" : {\"t1\":{\"t2\":1, \"t5\":1}}}"; - // EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK);; - InsertDoc(collectionName, document); - const char *filter = "{\"_id\":\"12345\"}"; - const char *projection = "{}"; - Query query; - query.filter = filter; - query.projection = projection; - GRD_ResultSet *resultSet; - resultSet = new GRD_ResultSet; - EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 0, &resultSet), GRD_OK); - char **test; - test = new char*[1]; - test[0] = new char[521 + 1]; - GRD_Next(resultSet); - EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); - GRD_FreeValue(test[0]); + // const char *filter = "{\"_id\":\"1\"}"; + // const char *projection = "{}"; + // Query query; + // query.filter = filter; + // query.projection = projection; + // GRD_ResultSet *resultSet; + // resultSet = new GRD_ResultSet; + // EXPECT_EQ(GRD_FindDoc(g_db, "student", query, 0, &resultSet), GRD_OK); + // char **test; + // test = new char*[1]; + // test[0] = new char[521 + 1]; + // GRD_Next(resultSet); + // EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); + //GRD_FreeValue(test[0]); // GRD_FreeResultSet(resultSet[0]); } \ No newline at end of file -- Gitee From a139fa4040b7f76f6a43af8035134e2a0f2fb7bb Mon Sep 17 00:00:00 2001 From: mazhao Date: Mon, 10 Apr 2023 11:32:17 +0000 Subject: [PATCH 05/18] The first merged version Signed-off-by: mazhao --- .../include/grd_base/grd_error.h | 2 +- .../include/grd_base/grd_type_export.h | 14 +- .../src/common/include/collection_option.h | 37 + .../src/common/include/db_config.h | 46 + .../src/common/include/doc_common.h | 18 +- .../src/common/include/doc_limit.h | 22 + .../src/common/include/json_common.h | 8 +- .../src/common/src/collection_option.cpp | 85 ++ .../src/common/src/db_config.cpp | 253 ++++ .../src/common/src/doc_common.cpp | 79 +- .../src/common/src/json_common.cpp | 102 +- .../src/common/src/os_api.cpp | 2 + .../src/executor/base/grd_db_api.cpp | 27 +- .../src/executor/base/grd_resultset_api.cpp | 6 +- .../executor/document/grd_document_api.cpp | 56 +- .../src/executor/include/grd_type_inner.h | 3 +- .../src/interface/include/collection.h | 3 +- .../src/interface/include/doc_errno.h | 16 +- .../src/interface/include/document_store.h | 11 +- .../include/document_store_manager.h | 13 +- .../src/interface/src/collection.cpp | 48 +- .../src/interface/src/doc_errno.cpp | 45 + .../src/interface/src/document_store.cpp | 211 +++- .../interface/src/document_store_manager.cpp | 88 +- .../src/interface/src/result_set.cpp | 7 +- .../src/oh_adapter/include/json_object.h | 78 +- .../oh_adapter/include/kv_store_executor.h | 13 +- .../src/oh_adapter/include/kv_store_manager.h | 3 +- .../src/oh_adapter/src/cjson_object.cpp | 211 ++++ .../src/oh_adapter/src/cjson_object.h | 47 + .../src/oh_adapter/src/json_object.cpp | 424 ++++--- .../src/oh_adapter/src/kv_store_manager.cpp | 46 +- .../src/sqlite_store_executor_impl.cpp | 193 +++- .../src/sqlite_store_executor_impl.h | 18 +- .../src/oh_adapter/src/sqlite_utils.cpp | 42 +- .../src/oh_adapter/src/sqlite_utils.h | 3 + .../unittest/api/ documentdb_delete_test.cpp | 286 ++--- .../unittest/api/ documentdb_find_test.cpp | 35 +- .../unittest/api/ documentdb_insert_test.cpp | 1028 ++++++++--------- .../test/unittest/api/documentdb_api_test.cpp | 592 ++++++++++ .../api/documentdb_collection_test.cpp | 202 ++++ .../unittest/api/documentdb_data_test.cpp | 195 ++++ ...est.cpp => documentdb_jsonobject_test.cpp} | 59 +- .../test/unittest/api/documentdb_test_utils.h | 27 + .../unittest/common/documentdb_test_utils.cpp | 24 + .../unittest/common/documentdb_test_utils.h | 27 + 46 files changed, 3513 insertions(+), 1242 deletions(-) create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/collection_option.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp rename services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/{doucumentdb_api_test.cpp => documentdb_jsonobject_test.cpp} (40%) create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_test_utils.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.cpp create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.h diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_error.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_error.h index 16b5eb4b..ecc7c705 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_error.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_error.h @@ -30,7 +30,7 @@ extern "C" { #define GRD_OVER_LIMIT (-2000) #define GRD_INVALID_ARGS (-3000) #define GRD_SYSTEM_ERR (-4000) -#define GRD_FAILED_FILE_FORMAT (-5000) +#define GRD_FAILED_FILE_OPERATION (-5000) #define GRD_INVALID_FILE_FORMAT (-6000) #define GRD_INNER_ERR (-8000) #define GRD_RESOURCE_BUSY (-9000) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h index 0b8ad2c9..64fc1af6 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h @@ -29,7 +29,8 @@ typedef struct GRD_DB GRD_DB; #define GRD_DB_OPEN_CREATE 0x01 #define GRD_DB_OPEN_CHECK_FOR_ABNORMAL 0x02 //check data in database if close abnormally last time, //if data is corrupted, rebuild the database -#define GRD_DB_OPEN_CREATE 0x04//check data in database when open database, if data is corrupted, rebuild the database. +#define GRD_DB_OPEN_CHECK 0x04//check data in database when open database, if data is corrupted, rebuild the database. + /** * @brief Close database config */ @@ -37,8 +38,8 @@ typedef struct GRD_DB GRD_DB; #define GRD_DB_CLOSE_IGNORE_ERROR 0x01 /** - * @brief flush database config -*/ + * @brief flush database config + */ #define GRD_DB_FLUSH_ASYNC 0x00 #define GRD_DB_FLUSH_SYNC 0x01 @@ -52,10 +53,11 @@ typedef struct Query { * @brief Flags for create and drop collection */ #define IGNORE_EXIST_TABLE 1 -#define IGNORE_NOT_EXIST_TABLE 1 +#define IGNORE_NON_EXIST_TABLE 1 + +#define GRD_DOC_APPEND 0 +#define GRD_DOC_REPLACE 1 -#define IGNORE_DOC_APPEND 0 -#define IGNORE_DOC_REPLACE 1 #ifdef __cplusplus } #endif // __cplusplus diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/collection_option.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/collection_option.h new file mode 100644 index 00000000..72759240 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/collection_option.h @@ -0,0 +1,37 @@ +/* +* 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 COLLECTION_OPTION_H +#define COLLECTION_OPTION_H + +#include +#include + +namespace DocumentDB { +class CollectionOption final { +public: + static CollectionOption ReadOption(const std::string &optStr, int &errCode); + + uint32_t GetMaxDoc() const; + std::string ToString() const; + + bool operator==(const CollectionOption &targetOption) const; + bool operator!=(const CollectionOption &targetOption) const; +private: + std::string option_ = "{}"; + uint32_t maxDoc_ = UINT32_MAX; +}; +} // namespace DocumentDB +#endif // COLLECTION_OPTION_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.h new file mode 100644 index 00000000..d3e5b37c --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.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 DB_CONFIG_H +#define DB_CONFIG_H + +#include + +namespace DocumentDB { +class DBConfig final { +public: + static DBConfig ReadConfig(const std::string &confStr, int &errCode); + + ~DBConfig() = default; + std::string ToString() const; + + int32_t GetPageSize() const; + + bool operator==(const DBConfig &targetConfig) const; + bool operator!=(const DBConfig &targetConfig) const; + +private: + DBConfig() = default; + + std::string configStr_ = {}; + int32_t pageSize_ = 4; + uint32_t redoFlushByTrx_ = 0; + uint32_t redoPubBufSize_ = 1024; + int32_t maxConnNum_ = 100; + uint32_t bufferPoolSize_ = 1024; + uint32_t crcCheckEnable_ = 1; +}; +} // namespace DocumentDB +#endif // DB_CONFIG_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h index 6301da76..c6eaccba 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h @@ -20,22 +20,22 @@ #include #include "json_common.h" - -class JsonCommon; namespace DocumentDB { -class DocCommon +class JsonCommon; +class CheckCommon { public: - DocCommon() = default; - ~DocCommon(); - + CheckCommon() = default; + ~CheckCommon(); + static bool CheckCollectionName(const std::string &collectionName); - static bool CheckFilter(JsonObject *filterObj); - static bool CheckIdFormat(JsonObject *filterJson); - static bool CheckDocument(JsonObject *documentObj); + static bool CheckFilter(const JsonObject *document); + static bool CheckIdFormat(const std::string &data); + static bool CheckDocument(const JsonObject *document); }; using Key = std::vector; using Value = std::vector; +constexpr const char *COLL_PREFIX = "GRD_COLL_"; } // DocumentDB #endif // DOC_COMMON_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h new file mode 100644 index 00000000..94d054b6 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h @@ -0,0 +1,22 @@ +/* +* 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 DOC_LIMIT_H +#define DOC_LIMIT_H + +namespace DocumentDB { +constexpr const int MAX_DB_CONFIG_LEN = 512 * 1024; // 512 * 1024: 5k length +} // namespace DocumentDB +#endif // DOC_LIMIT_H \ No newline at end of file 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 86bbce07..cc9d6bdb 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 @@ -27,13 +27,15 @@ class JsonCommon public: JsonCommon() = default; ~JsonCommon(); - + static ResultValue GetValueByFiled(JsonObject *node, const std::string& filed); - static bool CheckJsonField(JsonObject *jsonObj); + static bool CheckJsonField(const std::string &data); static int ParseNode(JsonObject *Node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor); static std::vector> ParsePath(JsonObject* node); static std::vector GetLeafValue(JsonObject *node); -private: + + static JsonObject Append(const JsonObject &src, const JsonObject &add); +private: static bool CheckNode(JsonObject *Node, std::set filedSet, bool &errFlag); static int CheckLeafNode(JsonObject *Node, std::vector &leafValue); }; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp new file mode 100644 index 00000000..1b64a9f1 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp @@ -0,0 +1,85 @@ +/* +* 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 "collection_option.h" + +#include + +#include "doc_errno.h" +#include "json_object.h" +#include "log_print.h" + +namespace DocumentDB { +CollectionOption CollectionOption::ReadOption(const std::string &optStr, int &errCode) +{ + if (optStr.empty()) { + return {}; + } + + JsonObject collOpt = JsonObject::Parse(optStr, errCode); + if (errCode != E_OK) { + GLOGE("Read collection option failed from str. %d", errCode); + return {}; + } + + static const JsonFieldPath maxDocField = {"maxDoc"}; + if (!collOpt.IsFieldExists(maxDocField)) { + return {}; + } + + ValueObject maxDocValue = collOpt.GetObjectByPath(maxDocField, errCode); + if (errCode != E_OK) { + GLOGE("Read collection option failed. %d", errCode); + return {}; + } + + if (maxDocValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { + GLOGE("Check collection option failed, the field type of maxDoc is not NUMBER. %d", errCode); + errCode = -E_INVALID_CONFIG_VALUE; + return {}; + } + + if (maxDocValue.GetIntValue() <= 0 || maxDocValue.GetIntValue() > UINT32_MAX) { + GLOGE("Check collection option failed, invalid maxDoc value."); + errCode = -E_INVALID_CONFIG_VALUE; + return {}; + } + + CollectionOption option; + option.maxDoc_ = static_cast(maxDocValue.GetIntValue()); + option.option_ = optStr; + return option; +} + +uint32_t CollectionOption::GetMaxDoc() const +{ + return maxDoc_; +} + +std::string CollectionOption::ToString() const +{ + return option_; +} + +bool CollectionOption::operator==(const CollectionOption &targetOption) const +{ + return maxDoc_ == targetOption.maxDoc_; +} + +bool CollectionOption::operator!=(const CollectionOption &targetOption) const +{ + return !(*this == targetOption); +} +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp new file mode 100644 index 00000000..242ed1a2 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp @@ -0,0 +1,253 @@ +/* +* 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 "db_config.h" + +#include +#include + +#include "doc_errno.h" +#include "doc_limit.h" +#include "log_print.h" +#include "json_object.h" + +namespace DocumentDB { + +namespace { +bool CheckPageSizeConfig(JsonObject config, int32_t &pageSize, int &errCode) +{ + static const JsonFieldPath pageSizeField = {"pageSize"}; + if (!config.IsFieldExists(pageSizeField)) { + return true; + } + + ValueObject configValue = config.GetObjectByPath(pageSizeField, errCode); // TODO: check return code + if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { + GLOGE("Check DB config failed, the field type of pageSize is not NUMBER. %d", errCode); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + static const std::vector pageSizeValid = {4, 8, 16, 32, 64}; + if (std::find(pageSizeValid.begin(), pageSizeValid.end(), configValue.GetIntValue()) == pageSizeValid.end()) { + GLOGE("Check DB config failed, invalid pageSize value."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + pageSize = static_cast(configValue.GetIntValue()); + return true; +} + +bool CheckRedoFlushConfig(JsonObject config, uint32_t &redoFlush, int &errCode) +{ + static const JsonFieldPath redoFlushField = {"redoFlushByTrx"}; + if (!config.IsFieldExists(redoFlushField)) { + return true; + } + + ValueObject configValue = config.GetObjectByPath(redoFlushField, errCode); // TODO: + if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { + GLOGE("Check DB config failed, the field type of redoFlushByTrx is not NUMBER. %d", errCode); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + if (configValue.GetIntValue() != 0 && configValue.GetIntValue() != 1) { + GLOGE("Check DB config failed, invalid redoFlushByTrx value."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + redoFlush = static_cast(configValue.GetIntValue()); + return true; +} + +bool CheckRedoBufSizeConfig(JsonObject config, uint32_t &redoBufSize, int &errCode) +{ + static const JsonFieldPath redoBufSizeField = {"redoPubBufSize"}; + if (!config.IsFieldExists(redoBufSizeField)) { + return true; + } + + ValueObject configValue = config.GetObjectByPath(redoBufSizeField, errCode); // TODO: + if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { + GLOGE("Check DB config failed, the field type of redoPubBufSize is not NUMBER. %d", errCode); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + if (configValue.GetIntValue() < 256 && configValue.GetIntValue() > 16384) { + GLOGE("Check DB config failed, invalid redoPubBufSize value."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + redoBufSize = static_cast(configValue.GetIntValue()); + return true; +} + +bool CheckMaxConnNumConfig(JsonObject config, int32_t &maxConnNum, int &errCode) +{ + static const JsonFieldPath maxConnNumField = {"maxConnNum"}; + if (!config.IsFieldExists(maxConnNumField)) { + return true; + } + + ValueObject configValue = config.GetObjectByPath(maxConnNumField, errCode); // TODO: + if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { + GLOGE("Check DB config failed, the field type of maxConnNum is not NUMBER. %d", errCode); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + if (configValue.GetIntValue() < 16 || configValue.GetIntValue() > 1024) { + GLOGE("Check DB config failed, invalid maxConnNum value."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + maxConnNum = static_cast(configValue.GetIntValue()); + return true; +} + +bool CheckBufferPoolSizeConfig(JsonObject config, int32_t pageSize, uint32_t &redoBufSize, + int &errCode) +{ + static const JsonFieldPath bufferPoolSizeField = {"bufferPoolSize"}; + if (!config.IsFieldExists(bufferPoolSizeField)) { + return true; + } + + ValueObject configValue = config.GetObjectByPath(bufferPoolSizeField, errCode); // TODO: + if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { + GLOGE("Check DB config failed, the field type of bufferPoolSize is not NUMBER. %d", errCode); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + if (configValue.GetIntValue() < 1024 && configValue.GetIntValue() > 4 * 1024 * 1024 || + configValue.GetIntValue() < pageSize * 33) { + GLOGE("Check DB config failed, invalid bufferPoolSize value."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + redoBufSize = static_cast(configValue.GetIntValue()); + return true; +} + +bool CheckCrcCheckEnableConfig(JsonObject config, uint32_t &crcCheckEnable, int &errCode) +{ + static const JsonFieldPath crcCheckEnableField = {"crcCheckEnable"}; + if (!config.IsFieldExists(crcCheckEnableField)) { + return true; + } + + ValueObject configValue = config.GetObjectByPath(crcCheckEnableField, errCode); // TODO: + if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { + GLOGE("Check DB config failed, the field type of crcCheckEnable is not NUMBER. %d", errCode); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + if (configValue.GetIntValue() != 0 && configValue.GetIntValue() != 1) { + GLOGE("Check DB config failed, invalid crcCheckEnable value."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + + crcCheckEnable = static_cast(configValue.GetIntValue()); + return true; +} + +} + +DBConfig DBConfig::ReadConfig(const std::string &confStr, int &errCode) +{ + if (confStr.empty()) { + return {}; + } + + if (confStr.length() > MAX_DB_CONFIG_LEN) { + GLOGE("Config json string is too long."); + errCode = -E_OVER_LIMIT; + return {}; + } + JsonObject dbConfig = JsonObject::Parse(confStr, errCode); + if (errCode != E_OK) { + GLOGE("Read DB config failed from str. %d", errCode); + return {}; + } + + DBConfig conf; + if (!CheckPageSizeConfig(dbConfig, conf.pageSize_, errCode)) { + GLOGE("Check DB config 'pageSize' failed. %d", errCode); + return {}; + } + + if (!CheckRedoFlushConfig(dbConfig, conf.redoFlushByTrx_, errCode)) { + GLOGE("Check DB config 'redoFlushByTrx' failed. %d", errCode); + return {}; + } + + if (!CheckRedoBufSizeConfig(dbConfig, conf.redoPubBufSize_, errCode)) { + GLOGE("Check DB config 'redoPubBufSize' failed. %d", errCode); + return {}; + } + + if (!CheckMaxConnNumConfig(dbConfig, conf.maxConnNum_, errCode)) { + GLOGE("Check DB config 'maxConnNum' failed. %d", errCode); + return {}; + } + + if (!CheckBufferPoolSizeConfig(dbConfig, conf.pageSize_, conf.bufferPoolSize_, errCode)) { + GLOGE("Check DB config 'bufferPoolSize' failed. %d", errCode); + return {}; + } + + if (!CheckCrcCheckEnableConfig(dbConfig, conf.crcCheckEnable_, errCode)) { + GLOGE("Check DB config 'crcCheckEnable' failed. %d", errCode); + return {}; + } + + conf.configStr_ = confStr; + errCode = E_OK; + return conf; +} + +std::string DBConfig::ToString() const +{ + return configStr_; +} + +int32_t DBConfig::GetPageSize() const +{ + return pageSize_; +} + +bool DBConfig::operator==(const DBConfig &targetConfig) const +{ + return configStr_ == targetConfig.configStr_ && pageSize_ == targetConfig.pageSize_ && + redoFlushByTrx_ == targetConfig.redoFlushByTrx_ && redoPubBufSize_ == targetConfig.redoPubBufSize_ && + maxConnNum_ == targetConfig.maxConnNum_ && bufferPoolSize_ == targetConfig.bufferPoolSize_ && + crcCheckEnable_ == targetConfig.crcCheckEnable_; +} + +bool DBConfig::operator!=(const DBConfig &targetConfig) const +{ + return !(*this == targetConfig); +} +} // namespace DocumentDB \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp index 931e8cde..d01e61d0 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp @@ -13,15 +13,34 @@ * limitations under the License. */ #include + #include "doc_common.h" #include "doc_errno.h" #include "log_print.h" #include "securec.h" -#include "json_object.h" -#include "grd_format_config.h" namespace DocumentDB { -bool DocCommon::CheckCollectionName(const std::string &collectionName) +namespace { +bool CheckCollectionNamePrefix(const std::string &name, const std::string &prefix) +{ + if (name.length() < prefix.length()) { + return false; + } + + auto itPrefix = prefix.begin(); + auto itName = name.begin(); + while (itPrefix != prefix.end()) { + if (std::tolower(*itPrefix) != std::tolower(*itName)) { + return false; + } + itPrefix++; + itName++; + } + return true; +} +} + +bool CheckCommon::CheckCollectionName(const std::string &collectionName) { if (collectionName.empty()) { return false; @@ -29,45 +48,49 @@ bool DocCommon::CheckCollectionName(const std::string &collectionName) if (collectionName.length() > 512) { return false; } - if (collectionName.compare(0, 4, "GRD", 0, 4) == 0 || collectionName.compare(0, 7, "GM_SYS_", 0, 7) == 0) { + if (CheckCollectionNamePrefix(collectionName, "GRD_") || CheckCollectionNamePrefix(collectionName, "GM_SYS_")) { return false; } return true; } -bool DocCommon::CheckFilter(JsonObject *filterObj) +bool CheckCommon::CheckFilter(const JsonObject *document) { - if (CheckIdFormat(filterObj) == false) { - return false; - } - if (filterObj->GetChild().GetNext().IsNull() != true) { - return false; - } + // if (JsonCommon::CheckIsJson(filter) == false) { + // return false; + // } + // if (JsonCommon::GetJsonDeep(filter) > 4) { + // return false; + // } + // if (CheckIdFormat(filter) == false) { + // return false; + // } return true; } -bool DocCommon::CheckIdFormat(JsonObject *filterJson) +bool CheckCommon::CheckIdFormat(const std::string &data) { - auto filterObjChild = filterJson->GetChild(); - auto resultValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); - if (resultValue.valueType != ResultValue::ValueType::VALUE_STRING) { - return false; - } + // CjsonObject filter_json; + // filter_json.Parse(data); + // std::vector id; + // if (JsonCommon::GetIdValue(&filter_json, id) == E_ERROR) { + // return false; + // } return true; } -bool DocCommon::CheckDocument(JsonObject *documentObj) +bool CheckCommon::CheckDocument(const JsonObject *document) { - if (CheckIdFormat(documentObj) == false) { - return false; - } - JsonObject documentObjChild; - if (documentObj->GetChild().IsNull() != true) { - documentObjChild = documentObj->GetChild(); - } - if (JsonCommon::CheckJsonField(&documentObjChild) == false) { - return false; - } + // if (CheckIdFormat(documentObj) == false) { + // return false; + // } + // JsonObject documentObjChild; + // if (documentObj->GetChild().IsNull() != true) { + // documentObjChild = documentObj->GetChild(); + // } + // if (JsonCommon::CheckJsonField(&documentObjChild) == false) { + // return false; + // } return true; } } // namespace DocumentDB \ 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 fce10484..85d155fd 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 @@ -36,6 +36,7 @@ ResultValue JsonCommon::GetValueByFiled(JsonObject *node, const std::string& fil return ResultValue(); } auto nodeNew = node->GetNext(); + nodeNew.Print(); node = &nodeNew; } return ResultValue(); @@ -46,13 +47,15 @@ int JsonCommon::CheckLeafNode(JsonObject *node, std::vector &leafVa if (node->GetChild().IsNull() == true) { auto itemValue = node->GetItemValue(); leafValue.emplace_back(itemValue); - } + } if (node->GetChild().IsNull() != true) { auto nodeNew = node->GetChild(); + nodeNew.Print(); CheckLeafNode(&nodeNew, leafValue); } if (node->GetNext().IsNull() != true) { auto nodeNew = node->GetNext(); + nodeNew.Print(); CheckLeafNode(&nodeNew, leafValue); } return E_OK; @@ -65,55 +68,55 @@ std::vector JsonCommon::GetLeafValue(JsonObject *node) return leafValue; } -bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, bool &errFlag) { - if (errFlag == false) { - return false; - } - std::string fieldName; - if (node->IsNull() != true) { - int ret; - fieldName = node->GetItemFiled(ret); - if (filedSet.find(fieldName) == filedSet.end()) { - if (ret == E_OK) { - filedSet.insert(fieldName); - } - if (ret == E_OK && fieldName == "") { - errFlag = false; - return false; - } - } - else { - errFlag = false; - return false; - } - for (int i = 0; i < fieldName.size(); i++) { - if (!(('a'<=fieldName[i] && fieldName[i]<='z')|| ('A'<=fieldName[i] && fieldName[i]<='Z') || ('0'<=fieldName[i] && fieldName[i]<='9') || '_' == fieldName[i])) { - errFlag = false; - return false; - } - if (i == 0 && ('0'<=fieldName[i] && fieldName[i]<='9')) { - errFlag = false; - return false; - } - } - } - if (node->GetChild().IsNull() != true) { - auto nodeNew = node->GetChild(); - std::set newFiledSet; - CheckNode(&nodeNew, newFiledSet, errFlag); - } - if (node->GetNext().IsNull() != true) { - auto nodeNew = node->GetNext(); - CheckNode(&nodeNew, filedSet, errFlag); - } - return errFlag; -} +// bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, bool &errFlag) { +// if (errFlag == false) { +// return false; +// } +// std::string fieldName; +// if (node->IsNull() != true) { +// int ret; +// fieldName = node->GetItemFiled(ret); +// if (filedSet.find(fieldName) == filedSet.end()) { +// if (ret == E_OK) { +// filedSet.insert(fieldName); +// } +// if (ret == E_OK && fieldName == "") { +// errFlag = false; +// return false; +// } +// } +// else { +// errFlag = false; +// return false; +// } +// for (int i = 0; i < fieldName.size(); i++) { +// if (!(('a'<=fieldName[i] && fieldName[i]<='z')|| ('A'<=fieldName[i] && fieldName[i]<='Z') || ('0'<=fieldName[i] && fieldName[i]<='9') || '_' == fieldName[i])) { +// errFlag = false; +// return false; +// } +// if (i == 0 && ('0'<=fieldName[i] && fieldName[i]<='9')) { +// errFlag = false; +// return false; +// } +// } +// } +// if (node->GetChild().IsNull() != true) { +// auto nodeNew = node->GetChild(); +// std::set newFiledSet; +// CheckNode(&nodeNew, newFiledSet, errFlag); +// } +// if (node->GetNext().IsNull() != true) { +// auto nodeNew = node->GetNext(); +// CheckNode(&nodeNew, filedSet, errFlag); +// } +// return errFlag; +// } -bool JsonCommon::CheckJsonField(JsonObject *jsonObj) { - std::set filedSet; - bool errFlag = true; - return CheckNode(jsonObj, filedSet, errFlag); -} +// bool JsonCommon::CheckJsonField(JsonObject *jsonObj) { +// std::set filedSet; +// bool errFlag = true; +// return CheckNode(jsonObj, filedSet, errFlag); +// } int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor) { @@ -158,6 +161,7 @@ int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, std::vector> JsonCommon::ParsePath(JsonObject* root) { + std::vector> resultPath; auto projectionJson = root->GetChild(); if (projectionJson.IsNull() == true) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp index 13528043..a50c30e0 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp @@ -53,7 +53,9 @@ int GetRealPath(const std::string &inOriPath, std::string &outRealPath) delete []realPath; return -E_SYSTEM_API_FAIL; } + GLOGE("----> realpath: %s, %s", inOriPath.c_str(), realPath); outRealPath = std::string(realPath); + GLOGD("----> outRealPath: %s", outRealPath.c_str()); delete []realPath; return E_OK; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp index f4e3d65f..ca23460b 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp @@ -20,28 +20,16 @@ #include "document_store.h" #include "grd_base/grd_error.h" #include "grd_type_inner.h" +#include "log_print.h" using namespace DocumentDB; -int TrasnferDocErr(int err) -{ - switch (err) { - case E_OK: - return GRD_OK; - case -E_ERROR: - return GRD_INNER_ERR; - case -E_INVALID_ARGS: - return GRD_INVALID_ARGS; - default: - return GRD_INNER_ERR; - } -} - int GRD_DBOpen(const char *dbPath, const char *configStr, unsigned int flags, GRD_DB **db) { std::string path = (dbPath == nullptr ? "" : dbPath); + std::string config = (configStr == nullptr ? "" : configStr); DocumentStore *store = nullptr; - int ret = DocumentStoreManager::GetDocumentStore(path, store); + int ret = DocumentStoreManager::GetDocumentStore(path, config, flags, store); *db = new (std::nothrow) GRD_DB(); (*db)->store_ = store; return TrasnferDocErr(ret); @@ -53,13 +41,12 @@ int GRD_DBClose(GRD_DB *db, unsigned int flags) return GRD_INVALID_ARGS; } - DocumentStoreManager::CloseType closeType = (flags == GRD_DB_CLOSE) ? DocumentStoreManager::CloseType::NORMAL : - DocumentStoreManager::CloseType::IGNORE_ERROR; - int status = DocumentStoreManager::CloseDocumentStore(db->store_, closeType); - if (status != E_OK) { - return GRD_RESOURCE_BUSY; + int ret = DocumentStoreManager::CloseDocumentStore(db->store_, flags); + if (ret != E_OK) { + return TrasnferDocErr(ret); } + db->store_ = nullptr; delete db; return GRD_OK; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp index f4ce8118..cdda85f8 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp @@ -31,9 +31,9 @@ int TrasnferDocErrThird(int err) return GRD_INNER_ERR; case DocumentDB::E_INVALID_ARGS: return GRD_INVALID_ARGS; - case DocumentDB::E_DATA_CONFLICT: - return GRD_DATA_CONFLICT; - case DocumentDB::E_INVALID_FORMAT: + // case DocumentDB::E_DATA_CONFLICT: + // return GRD_DATA_CONFLICT; + case DocumentDB::E_INVALID_JSON_FORMAT: return GRD_INVALID_FORMAT; case DocumentDB::E_OVER_LIMIT: return GRD_OVER_LIMIT; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 295e3d33..ca6aef9f 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -16,34 +16,19 @@ #include "grd_document/grd_document_api.h" #include "grd_base/grd_error.h" #include "grd_type_inner.h" -#include "doc_errno.h" - -int TrasnferDocErrSecond(int err) -{ - switch (err) { - case DocumentDB::E_OK: - return GRD_OK; - case DocumentDB::E_ERROR: - return GRD_INNER_ERR; - case DocumentDB::E_INVALID_ARGS: - return GRD_INVALID_ARGS; - case DocumentDB::E_DATA_CONFLICT: - return GRD_DATA_CONFLICT; - case DocumentDB::E_INVALID_FORMAT: - return GRD_INVALID_FORMAT; - case DocumentDB::E_OVER_LIMIT: - return GRD_OVER_LIMIT; - default: - return GRD_INNER_ERR; - } -} +#include "log_print.h" +using namespace DocumentDB; int GRD_CreateCollection(GRD_DB *db, const char *collectionName, const char *optionStr, unsigned int flags) { if (db == nullptr || db->store_ == nullptr) { return GRD_INVALID_ARGS; } - return db->store_->CreateCollection(collectionName, optionStr, flags); + + std::string name = (collectionName == nullptr ? "" : collectionName); + std::string option = (optionStr == nullptr ? "" : optionStr); + int ret = db->store_->CreateCollection(name, option, flags); + return TrasnferDocErr(ret); } int GRD_DropCollection(GRD_DB *db, const char *collectionName, unsigned int flags) @@ -51,7 +36,10 @@ int GRD_DropCollection(GRD_DB *db, const char *collectionName, unsigned int flag if (db == nullptr || db->store_ == nullptr) { return GRD_INVALID_ARGS; } - return db->store_->DropCollection(collectionName, flags); + + std::string name = (collectionName == nullptr ? "" : collectionName); + int ret = db->store_->DropCollection(name, flags); + return TrasnferDocErr(ret); } int GRD_UpdateDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *update, unsigned int flags) @@ -59,7 +47,12 @@ int GRD_UpdateDoc(GRD_DB *db, const char *collectionName, const char *filter, co if (db == nullptr || db->store_ == nullptr) { return GRD_INVALID_ARGS; } - return db->store_->UpdateDocument(collectionName, filter, update, flags); + + std::string name = (collectionName == nullptr ? "" : collectionName); + std::string filterStr = (filter == nullptr ? "" : filter); + std::string updateStr = (update == nullptr ? "" : update); + int ret = db->store_->UpdateDocument(name, filterStr, updateStr, flags); + return TrasnferDocErr(ret); } int GRD_UpSertDoc(GRD_DB *db, const char *collectionName, const char *filter, const char *document, unsigned int flags) @@ -67,7 +60,12 @@ int GRD_UpSertDoc(GRD_DB *db, const char *collectionName, const char *filter, co if (db == nullptr || db->store_ == nullptr) { return GRD_INVALID_ARGS; } - return db->store_->UpsertDocument(collectionName, filter, document, flags); + + std::string name = (collectionName == nullptr ? "" : collectionName); + std::string filterStr = (filter == nullptr ? "" : filter); + std::string documentStr = (document == nullptr ? "" : document); + int ret = db->store_->UpsertDocument(name, filterStr, documentStr, flags); + return TrasnferDocErr(ret); } int GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, unsigned int flags) @@ -76,7 +74,7 @@ int GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, return GRD_INVALID_ARGS; } int ret = db->store_->InsertDocument(collectionName, document, flags); - return TrasnferDocErrSecond(ret); + return TrasnferDocErr(ret); } int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, unsigned int flags) @@ -85,7 +83,7 @@ int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, un return GRD_INVALID_ARGS; } int ret = db->store_->DeleteDocument(collectionName, filter, flags); - return TrasnferDocErrSecond(ret); + return TrasnferDocErr(ret); } int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned int flags, GRD_ResultSet **resultSet) @@ -94,5 +92,5 @@ int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned in return GRD_INVALID_ARGS; } int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, resultSet[0]->resultSet_); - return TrasnferDocErrSecond(ret); -} + return TrasnferDocErr(ret); +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h index d46324ff..e5cafb2e 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h @@ -17,6 +17,8 @@ #define GRD_TYPE_INNER_H #include "document_store.h" +#include "doc_errno.h" +#include "grd_base/grd_error.h" typedef struct GRD_DB { DocumentDB::DocumentStore *store_ = nullptr; @@ -25,5 +27,4 @@ typedef struct GRD_DB { typedef struct GRD_ResultSet { DocumentDB::ResultSet *resultSet_ = new DocumentDB::ResultSet(); } GRD_ResultSet; - #endif // GRD_TYPE_INNER_H \ No newline at end of file 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 519d50a4..272eee25 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 @@ -24,14 +24,13 @@ namespace DocumentDB { class Collection { public: Collection(std::string name, KvStoreExecutor *executor); - Collection(const Collection& collection); ~Collection(); int PutDocument(const Key &key, const Value &document); int GetDocument(const Key &key, Value &document) const; int DeleteDocument(const Key &key); - int UpsertDocument(const Key &key, Value &document); + int UpsertDocument(const std::string &id, const std::string &document, bool isReplace = true); int UpdateDocument(const Key &key, Value &update); private: std::string name_; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h index d821fa6c..e6ed94b0 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h @@ -16,19 +16,25 @@ #ifndef DOC_ERRNO_H #define DOC_ERRNO_H - namespace DocumentDB { constexpr int E_OK = 0; constexpr int E_BASE = 1000; constexpr int E_ERROR = E_BASE + 1; constexpr int E_INVALID_ARGS = E_BASE + 2; -constexpr int E_OVER_LIMIT = E_BASE + 3; -constexpr int E_DATA_CONFLICT = E_BASE + 4; -constexpr int E_INVALID_FORMAT = E_BASE + 5; -constexpr int E_NO_DATA = E_BASE + 6; constexpr int E_UNFINISHED = E_BASE + 7; constexpr int E_OUT_OF_MEMORY = E_BASE + 8; constexpr int E_SECUREC_ERROR = E_BASE + 9; constexpr int E_SYSTEM_API_FAIL = E_BASE + 10; +constexpr int E_FILE_OPERATION = E_BASE + 11; +constexpr int E_OVER_LIMIT = E_BASE + 12; +constexpr int E_INVALID_CONFIG_VALUE = E_BASE + 13; +constexpr int E_NOT_FOUND = E_BASE + 14; +constexpr int E_COLLECTION_CONFLICT = E_BASE + 15; +constexpr int E_NO_DATA = E_BASE + 16; +constexpr int E_NOT_PERMIT = E_BASE + 17; +constexpr int E_INVALID_JSON_FORMAT = E_BASE + 40; +constexpr int E_JSON_PATH_NOT_EXISTS = E_BASE + 41; + +int TrasnferDocErr(int err); } // DocumentDB #endif // DOC_ERRNO_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h index af3a389e..69cf3c60 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h @@ -22,8 +22,6 @@ #include "collection.h" #include "kv_store_executor.h" #include "result_set.h" -#include "projection_tree.h" -#include "json_common.h" namespace DocumentDB { class DocumentStore { @@ -31,12 +29,13 @@ public: DocumentStore(KvStoreExecutor *); ~DocumentStore(); - int CreateCollection(const std::string &name, const std::string &option, int flag); - int DropCollection(const std::string &name, int flag); + int CreateCollection(const std::string &name, const std::string &option, int flags); + int DropCollection(const std::string &name, int flags); + int UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update, int flag); - int UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flag); + int UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flags); int InsertDocument(const std::string &collection, const std::string &document, int flag); - int DeleteDocument(const std::string &collection, const std::string &document, int flag); + int DeleteDocument(const std::string &collection, const std::string &filter, int flag); int FindDocument(GRD_DB* db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet); private: int GetViewType(JsonObject *jsonObj, bool &viewType); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store_manager.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store_manager.h index acfb64aa..70043162 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store_manager.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store_manager.h @@ -22,17 +22,14 @@ namespace DocumentDB { class DocumentStoreManager { public: - static int GetDocumentStore(const std::string &path, DocumentStore *&store); + static int GetDocumentStore(const std::string &path, const std::string &config, unsigned int flags, + DocumentStore *&store); - enum class CloseType { - NORMAL, - IGNORE_ERROR, - }; - - static int CloseDocumentStore(DocumentStore *store, CloseType type); + static int CloseDocumentStore(DocumentStore *store, unsigned int flags); private: - static bool CheckDBPath(const std::string &path, std::string &canonicalPath); + static bool CheckDBPath(const std::string &path, std::string &canonicalPath, std::string &dbName, int &errCode); + static bool CheckDBConfig(const std::string &config, int &errCode); }; } // DocumentDB #endif // DOCUMENT_STORE_MANAGER_H \ No newline at end of file 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 4c6b2944..e6192c35 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 @@ -14,20 +14,15 @@ */ #include "collection.h" +#include "doc_common.h" #include "doc_errno.h" #include "log_print.h" namespace DocumentDB { -Collection::Collection(std::string name, KvStoreExecutor *executor) : name_(name), executor_(executor) +Collection::Collection(std::string name, KvStoreExecutor *executor) : name_(COLL_PREFIX + name), executor_(executor) { } -Collection::Collection(const Collection& collection) -{ - name_ = collection.name_; - executor_ = collection.executor_; -} - Collection::~Collection() { executor_ = nullptr; @@ -54,15 +49,48 @@ int Collection::DeleteDocument(const Key &key) if (executor_ == nullptr) { return -E_INVALID_ARGS; } - return executor_->DeleteData(name_, key); + return executor_->DelData(name_, key); } -int Collection::UpsertDocument(const Key &key, Value &document) +int Collection::UpsertDocument(const std::string &id, const std::string &document, bool isReplace) { if (executor_ == nullptr) { return -E_INVALID_ARGS; } - return executor_->PutData(name_, key, document); + + int errCode = E_OK; + bool isCollExist = executor_->IsCollectionExists(name_, errCode); + if (errCode != E_OK) { + GLOGE("Check collection failed. %d", errCode); + return -errCode; + } + if (!isCollExist) { + GLOGE("Collection not created."); + return -E_NO_DATA; + } + + Key keyId(id.begin(), id.end()); + Value valSet(document.begin(), document.end()); + + if (!isReplace) { + Value valueGot; + errCode = executor_->GetData(name_, keyId, valueGot); + std::string valueGotStr = std::string(valueGot.begin(), valueGot.end()); + + if (errCode != E_OK && errCode != -E_NOT_FOUND) { + GLOGE("Get original document failed. %d", errCode); + return errCode; + } else if (errCode == E_OK) { // document has been inserted + GLOGD("Document has been inserted, append value."); + JsonObject originValue = JsonObject::Parse(valueGotStr, errCode); + + JsonObject upsertValue = JsonObject::Parse(document, errCode); + + // TOOD:: Join document and update valSet + } + } + + return executor_->PutData(name_, keyId, valSet); } int Collection::UpdateDocument(const Key &key, Value &update) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp new file mode 100644 index 00000000..093c04e1 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp @@ -0,0 +1,45 @@ +/* +* 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 "doc_errno.h" +#include "grd_base/grd_error.h" + +namespace DocumentDB { +int TrasnferDocErr(int err) +{ + switch (err) { + case E_OK: + return GRD_OK; + case -E_ERROR: + return GRD_INNER_ERR; + case -E_INVALID_ARGS: + return GRD_INVALID_ARGS; + case -E_FILE_OPERATION: + return GRD_FAILED_FILE_OPERATION; + case -E_OVER_LIMIT: + return GRD_OVER_LIMIT; + case -E_INVALID_JSON_FORMAT: + return GRD_INVALID_JSON_FORMAT; + case -E_INVALID_CONFIG_VALUE: + return GRD_INVALID_CONFIG_VALUE; + case -E_COLLECTION_CONFLICT: + return GRD_COLLECTION_CONFLICT; + case -E_NO_DATA: + return GRD_NO_DATA; + default: + return GRD_INNER_ERR; + } +} +} \ No newline at end of file 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 99a92647..ca7f8db4 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 @@ -14,12 +14,12 @@ */ #include "document_store.h" +#include "grd_format_config.h" +#include "collection_option.h" +#include "doc_common.h" #include "doc_errno.h" -#include "json_common.h" -#include "json_object.h" +#include "grd_base/grd_type_export.h" #include "log_print.h" -#include "doc_common.h" -#include "grd_format_config.h" namespace DocumentDB { DocumentStore::DocumentStore(KvStoreExecutor *executor) : executor_(executor) @@ -31,16 +31,72 @@ DocumentStore::~DocumentStore() delete executor_; } -int DocumentStore::CreateCollection(const std::string &name, const std::string &option, int flag) +int DocumentStore::CreateCollection(const std::string &name, const std::string &option, int flags) { - executor_->CreateCollection(name, flag); - return E_OK; + if (!CheckCommon::CheckCollectionName(name)) { + GLOGE("Check collection name invalid."); + return -E_INVALID_ARGS; + } + + int errCode = E_OK; + CollectionOption collOption = CollectionOption::ReadOption(option, errCode); + if (errCode != E_OK) { + GLOGE("Read collection option str failed. %d", errCode); + return errCode; + } + + if (flags != 0 && flags != IGNORE_EXIST_TABLE) { + GLOGE("Check flags invalid."); + return -E_INVALID_ARGS; + } + + bool ignoreExists = (flags == IGNORE_EXIST_TABLE); + errCode = executor_->CreateCollection(name, ignoreExists); + if (errCode != E_OK) { + GLOGE("Create collection failed. %d", errCode); + return errCode; + } + std::string oriOptStr; + errCode = executor_->GetCollectionOption(name, oriOptStr); + if (errCode == -E_NOT_FOUND) { + executor_->SetCollectionOption(name, collOption.ToString()); + errCode = E_OK; + } else { + CollectionOption oriOption = CollectionOption::ReadOption(oriOptStr, errCode); + if (collOption != oriOption) { + GLOGE("Create collection failed, option changed."); + return -E_INVALID_CONFIG_VALUE; + } + } + + return errCode; } -int DocumentStore::DropCollection(const std::string &name, int flag) +int DocumentStore::DropCollection(const std::string &name, int flags) { - executor_->DropCollection(name, flag); - return E_OK; + if (!CheckCommon::CheckCollectionName(name)) { + GLOGE("Check collection name invalid."); + return -E_INVALID_ARGS; + } + + if (flags != 0 && flags != IGNORE_NON_EXIST_TABLE) { + GLOGE("Check flags invalid."); + return -E_INVALID_ARGS; + } + + bool ignoreNonExists = (flags == IGNORE_NON_EXIST_TABLE); + int errCode = executor_->DropCollection(name, ignoreNonExists); + if (errCode != E_OK) { + GLOGE("Drop collection failed. %d", errCode); + return errCode; + } + + errCode = executor_->CleanCollectionOption(name); + if (errCode != E_OK) { + GLOGE("Clean collection option failed. %d", errCode); + } + + return errCode; } int DocumentStore::UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update, @@ -50,36 +106,53 @@ int DocumentStore::UpdateDocument(const std::string &collection, const std::stri } int DocumentStore::UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, - int flag) + int flags) { - auto coll = Collection(collection, executor_); + if (!CheckCommon::CheckCollectionName(collection)) { + GLOGE("Check collection name invalid."); + return -E_INVALID_ARGS; + } - Key key(filter.begin(), filter.end()); - Value value(document.begin(), document.end()); + // TODO:: check filter - return coll.PutDocument(key, value); + // TODO:: check document + + if (flags != GRD_DOC_APPEND && flags != GRD_DOC_REPLACE) { + GLOGE("Check flags invalid."); + return -E_INVALID_ARGS; + } + + auto coll = Collection(collection, executor_); + + std::string docId(filter.begin(), filter.end()); + bool isReplace = (flags & GRD_DOC_REPLACE == GRD_DOC_REPLACE); + return coll.UpsertDocument(docId, document, isReplace); } int DocumentStore::InsertDocument(const std::string &collection, const std::string &document, int flag) { + if (!CheckCommon::CheckCollectionName(collection)) { + GLOGE("Check collection name invalid."); + return -E_INVALID_ARGS; + } auto coll = Collection(collection, executor_); if (document.length() + 1 > JSON_LENS_MAX) { return E_OVER_LIMIT; } - JsonObject documentObj; - int ret = documentObj.Init(document); - if (ret != E_OK) { - return ret; + int errCode1; + JsonObject documentObj = JsonObject::Parse(document, errCode1); + if (errCode1 != E_OK) { + return errCode1; } - if (!DocCommon::CheckDocument(&documentObj) || flag != 0) { + if (!CheckCommon::CheckDocument(&documentObj) || flag != 0) { return E_INVALID_ARGS; } auto documentObjChild = documentObj.GetChild(); auto idValue = JsonCommon::GetValueByFiled(&documentObjChild, KEY_ID); - if (idValue.valueType != ResultValue::ValueType::VALUE_STRING) { + if (idValue.GetValueType() != ResultValue::ValueType::VALUE_STRING) { return E_INVALID_ARGS; } - std::string id = idValue.valueString; + std::string id = idValue.GetStringValue(); Key key(id.begin(), id.end()); Value value(document.begin(), document.end()); return coll.PutDocument(key, value); @@ -87,54 +160,66 @@ int DocumentStore::InsertDocument(const std::string &collection, const std::stri int DocumentStore::DeleteDocument(const std::string &collection, const std::string &filter, int flag) { + if (!CheckCommon::CheckCollectionName(collection)) { + GLOGE("Check collection name invalid."); + return -E_INVALID_ARGS; + } auto coll = Collection(collection, executor_); - JsonObject filterObj; - if (filterObj.Init(filter) != E_OK) { - return E_INVALID_ARGS; + int errCode1; + JsonObject filterObj = JsonObject::Parse(filter, errCode1); + if (errCode1 != E_OK) { + return errCode1; } - if (!DocCommon::CheckFilter(&filterObj) || flag != 0) { + if (!CheckCommon::CheckFilter(&filterObj) || flag != 0) { return E_INVALID_ARGS; } auto filterObjChild = filterObj.GetChild(); auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); - if (idValue.valueType != ResultValue::ValueType::VALUE_STRING) { + if (idValue.GetValueType() != ResultValue::ValueType::VALUE_STRING) { return E_INVALID_ARGS; } - std::string id = idValue.valueString; + std::string id = idValue.GetStringValue(); Key key(id.begin(), id.end()); return coll.DeleteDocument(key); } int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet) { - JsonObject filterObj; - if (filterObj.Init(filter) != E_OK) { - return E_INVALID_ARGS; + if (!CheckCommon::CheckCollectionName(collection)) { + GLOGE("Check collection name invalid."); + return -E_INVALID_ARGS; } - if (!DocCommon::CheckFilter(&filterObj) || !DocCommon::CheckCollectionName(collection)) { + int errCode1; + JsonObject filterObj = JsonObject::Parse(filter, errCode1); + if (errCode1 != E_OK) { + return errCode1; + } + if (!CheckCommon::CheckFilter(&filterObj)) { return E_INVALID_ARGS; } auto filterObjChild = filterObj.GetChild(); auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); - if (idValue.valueType != ResultValue::ValueType::VALUE_STRING) { + if (idValue.GetValueType() != ResultValue::ValueType::VALUE_STRING) { return E_INVALID_ARGS; } - std::string filterId = idValue.valueString; - JsonObject projectionObj; - if (projectionObj.Init(projection) != E_OK) { - return E_INVALID_ARGS; + std::string filterId = idValue.GetStringValue(); + int errCode2; + JsonObject projectionObj = JsonObject::Parse(projection, errCode2); + if (errCode2 != E_OK) { + return errCode2; } bool viewType = false; - if (GetViewType(&projectionObj, viewType) != E_OK && projection != "{}") { - return E_INVALID_ARGS; + std::vector> allPath; + if (projection != "{}") { + if (GetViewType(&projectionObj, viewType) != E_OK) { + return E_INVALID_ARGS; + } + allPath = JsonCommon::ParsePath(&projectionObj); } bool ifShowId = false; - auto projectionObjChild = projectionObj.GetChild(); - auto projectionId = JsonCommon::GetValueByFiled(&projectionObjChild, KEY_ID); if (flags == GRD_DOC_ID_DISPLAY) { ifShowId = true; } - auto allPath = JsonCommon::ParsePath(&projectionObj); Collection coll = Collection(collection, executor_); resultSet->Init(coll, filterId, allPath, ifShowId, viewType); return E_OK; @@ -145,15 +230,17 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { if (leafValue.size() == 0) { return E_INVALID_ARGS; } - switch (leafValue[0].valueType) { - case ResultValue::ValueType::VALUE_TRUE: - viewType = true; - break; - case ResultValue::ValueType::VALUE_FALSE: - viewType = false; + switch (leafValue[0].GetValueType()) { + case ResultValue::ValueType::VALUE_BOOL: + if (leafValue[0].GetBoolValue()) { + viewType = true; + } + else { + viewType = false; + } break; case ResultValue::ValueType::VALUE_STRING: - if (leafValue[0].valueString == "") { + if (leafValue[0].GetStringValue() == "") { viewType = true; } else { @@ -161,7 +248,7 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { } break; case ResultValue::ValueType::VALUE_NUMBER: - if (leafValue[0].valueNumber == 0) { + if (leafValue[0].GetIntValue() == 0) { viewType = false; } else { @@ -172,19 +259,21 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { return E_INVALID_ARGS; } for (int i = 1; i < leafValue.size(); i++) { - switch (leafValue[i].valueType) { - case ResultValue::ValueType::VALUE_TRUE: - if (viewType != true) { - return E_INVALID_ARGS; + switch (leafValue[i].GetValueType()) { + case ResultValue::ValueType::VALUE_BOOL: + if (leafValue[i].GetBoolValue()) { + if (viewType != true) { + return E_INVALID_ARGS; + } } - break; - case ResultValue::ValueType::VALUE_FALSE: - if (viewType != false) { - return E_INVALID_ARGS; + else { + if (viewType != false) { + return E_INVALID_ARGS; + } } break; case ResultValue::ValueType::VALUE_STRING: - if (leafValue[i].valueString == "") { + if (leafValue[i].GetStringValue() == "") { if (viewType != false) { return E_INVALID_ARGS; } @@ -194,7 +283,7 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { } break; case ResultValue::ValueType::VALUE_NUMBER: - if (leafValue[i].valueNumber == 0) { + if (leafValue[i].GetIntValue() == 0) { if (viewType != false) { return E_INVALID_ARGS; } @@ -211,4 +300,4 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { } return E_OK; } -} // namespace DocumentDB +} // namespace DocumentDB \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp index b386b44d..7078536b 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp @@ -13,6 +13,7 @@ * limitations under the License. */ +#include "db_config.h" #include "document_store_manager.h" #include "doc_errno.h" #include "grd_base/grd_type_export.h" @@ -21,43 +22,100 @@ #include "os_api.h" namespace DocumentDB { -int DocumentStoreManager::GetDocumentStore(const std::string &path, DocumentStore *&store) +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 invalidOpt = (GRD_DB_OPEN_CHECK_FOR_ABNORMAL | GRD_DB_OPEN_CHECK); + return ((flag & mask) == 0x00) && ((flag & invalidOpt) != invalidOpt); +} + +bool CheckDBCloseFlag(unsigned int flag) +{ + return (flag == GRD_DB_CLOSE) || (flag == GRD_DB_CLOSE_IGNORE_ERROR); +} +} + +int DocumentStoreManager::GetDocumentStore(const std::string &path, const std::string &config, unsigned int flags, + DocumentStore *&store) +{ + std::string canonicalPath; + std::string dbName; + int errCode = E_OK; + if (!CheckDBPath(path, canonicalPath, dbName, errCode)) { + GLOGE("Check document db file path failed."); + return errCode; + } + + DBConfig dbConfig = DBConfig::ReadConfig(config, errCode); + if (errCode != E_OK) { + GLOGE("Read db config str failed. %d", errCode); + return errCode; + } + + if (!CheckDBOpenFlag(flags)) { + GLOGE("Check document db open flags failed."); + return -E_INVALID_ARGS; + } + KvStoreExecutor *executor = nullptr; - KvStoreManager::GetKvStore(path, executor); + errCode = KvStoreManager::GetKvStore(canonicalPath + "/" + dbName, dbConfig, executor); + if (errCode != E_OK) { + GLOGE("Open document store failed. %d", errCode); + return errCode; + } + store = new (std::nothrow) DocumentStore(executor); - return E_OK; + if (store == nullptr) { + return -E_OUT_OF_MEMORY; + } + + return errCode; } -int DocumentStoreManager::CloseDocumentStore(DocumentStore *store, CloseType type) +int DocumentStoreManager::CloseDocumentStore(DocumentStore *store, unsigned int flags) { - if (type == CloseType::NORMAL) { - // TODO: check result set + if (!CheckDBCloseFlag(flags)) { + GLOGE("Check document db close flags failed."); + return -E_INVALID_ARGS; } delete store; return E_OK; } -bool DocumentStoreManager::CheckDBPath(const std::string &path, std::string &canonicalPath) +bool DocumentStoreManager::CheckDBPath(const std::string &path, std::string &canonicalPath, std::string &dbName, + int &errCode) { if (path.empty()) { - GLOGE("invalid path empty"); - return -E_INVALID_ARGS; + GLOGE("Invalid path empty"); + errCode = -E_INVALID_ARGS; + return false; } if (path.back() == '/') { - GLOGE("invalid path end with slash"); - return -E_INVALID_ARGS; + GLOGE("Invalid path end with slash"); + errCode = -E_INVALID_ARGS; + return false; } - std::string canonicalDir; - int errCode = OSAPI::GetRealPath(path, canonicalDir); - if (errCode == E_OK) { + std::string dirPath; + OSAPI::SplitFilePath(path, dirPath, dbName); + + int innerErrCode = OSAPI::GetRealPath(dirPath, canonicalPath); + if (innerErrCode != E_OK) { GLOGE("Get real path failed. %d", errCode); - return errCode; + errCode = -E_FILE_OPERATION; + return false; } + GLOGD("----> path: %s, dirPath: %s, dbName: %s, canonicalPath: %s", path.c_str(), dirPath.c_str(), dbName.c_str(), + canonicalPath.c_str()); + return true; +} +bool DocumentStoreManager::CheckDBConfig(const std::string &config, int &errCode) +{ + return true; } } // DocumentDB \ No newline at end of file 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 cd7a86cc..67412a02 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 @@ -100,8 +100,11 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat } int ResultSet::CutString(std::string &jsonData) { - JsonObject cjsonObj; - cjsonObj.Init(jsonData); + int errCode; + JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode); + if (errCode != E_OK) { + return errCode; + } std::vector> allPath; bool idFlag = false; if (viewType_ == true) { 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 33fce535..02a7262b 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 @@ -16,6 +16,7 @@ #ifndef JSON_OBJECT_H #define JSON_OBJECT_H +#include #include #include #include @@ -23,54 +24,77 @@ #include "cJSON.h" namespace DocumentDB { -class JsonObject; -class ResultValue { +class ValueObject { public: - ResultValue() {}; - ResultValue(const ResultValue& newValue) { - valueNumber = newValue.valueNumber; - valueString = newValue.valueString; - valueType = newValue.valueType; - valueObject = newValue.valueObject; - } enum class ValueType { - VALUE_FALSE, - VALUE_TRUE, - VALUE_NULL, + // VALUE_INVALID = -1, + VALUE_NULL = 0, + VALUE_BOOL, VALUE_NUMBER, VALUE_STRING, - VALUE_ARRAY, - VALUE_OBJECT }; - int valueNumber; - std::string valueString; + + ValueObject() = default; + explicit ValueObject(bool val); + explicit ValueObject(double val); + explicit ValueObject(const char *val); + explicit ValueObject(const std::string &val); + + ValueType GetValueType() const; + bool GetBoolValue() const; + int GetIntValue() const; + double GetDoubleValue() const; + std::string GetStringValue() const; + +private: ValueType valueType = ValueType::VALUE_NULL; - JsonObject *valueObject = nullptr; + union { + bool boolValue; + double doubleValue; + }; + std::string stringValue; }; +using ResultValue = ValueObject; +using JsonFieldPath = std::vector; + class JsonObject { public: - JsonObject(); - JsonObject(const JsonObject& newObj); + static JsonObject Parse(const std::string &jsonStr, int &errCode, bool caseSensitive = false); + + //JsonObject(const JsonObject &obj); ~JsonObject (); int Init(const std::string &str); + std::string Print(); - JsonObject GetObjectItem(const std::string &field, bool caseSensitive); - JsonObject GetArrayItem(const int index); + + JsonObject GetObjectItem(const std::string &field, int &errCode); + JsonObject GetArrayItem(int index, int &errCode); + JsonObject GetNext(); JsonObject GetChild(); + int DeleteItemFromObject(const std::string &field); - ResultValue GetItemValue(); - std::string GetItemFiled(int &errCode); - JsonObject FindItem(const std::vector jsonPath); - int DeleteItemOnTarget(std::vector &path); + + ValueObject GetItemValue() const; + std::string GetItemFiled(int &errCode) const; + + bool IsFieldExists(const JsonFieldPath &jsonPath) const; + JsonObject FindItem(const JsonFieldPath &jsonPath, int &errCode) const; + ValueObject GetObjectByPath(const JsonFieldPath &jsonPath, int &errCode) const; + int DeleteItemOnTarget(const JsonFieldPath &path); bool IsNull(); + private: - int GetDeep(cJSON *cjson, int deep, int &maxDeep); + JsonObject(); + + int GetDeep(cJSON *cjson); int CheckNumber(cJSON *cjson, int &errCode); + cJSON *cjson_; - bool isClone_ = false; + bool isOwner_ = false; + bool caseSensitive_ = false; }; } // DocumentDB #endif // JSON_OBJECT_H 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 2c3fc197..8037fc6b 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 @@ -25,13 +25,16 @@ public: virtual ~KvStoreExecutor() = default; 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 DeleteData(const std::string &collName, const Key &key) = 0; + virtual int DelData(const std::string &collName, const Key &key) = 0; + + virtual int CreateCollection(const std::string &name, bool ignoreExists) = 0; + virtual int DropCollection(const std::string &name, bool ignoreNonExists) = 0; + virtual bool IsCollectionExists(const std::string &name, int &errCode) = 0; - virtual int CreateCollection(const std::string &name, int flag) = 0; - virtual int DropCollection(const std::string &name, int flag) = 0; - + virtual int GetCollectionOption(const std::string &name, std::string &option) = 0; + virtual int SetCollectionOption(const std::string &name, const std::string &option) = 0; + virtual int CleanCollectionOption(const std::string &name) = 0; }; } // DocumentDB #endif // KV_STORE_EXECUTOR_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h index 6c82e983..97b79f64 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h @@ -17,13 +17,14 @@ #define KV_STORE_MANAGER_H #include +#include "db_config.h" #include "doc_common.h" #include "kv_store_executor.h" namespace DocumentDB { class KvStoreManager { public: - static int GetKvStore(const std::string &path, KvStoreExecutor *&executor); + static int GetKvStore(const std::string &path, const DBConfig &config, KvStoreExecutor *&executor); }; } // DocumentDB #endif // KV_STORE_MANAGER_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.cpp new file mode 100644 index 00000000..5841c2dc --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.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. +// */ + +// #include "doc_errno.h" +// #include "cjson_object.h" +// #include "log_print.h" + +// namespace DocumentDB { +// int CjsonObject::Parse(const std::string &str) +// { +// cjson_ = cJSON_Parse(str.c_str()); +// if (cjson_ == nullptr) { +// GLOGE("json parse failed."); +// return -E_INVALID_JSON_FORMAT; +// } +// return E_OK; +// } + +// std::string CjsonObject::Print() +// { +// if (cjson_ == nullptr) { +// GLOGE("======================>NULL"); +// return ""; +// } +// char *ret = cJSON_Print(cjson_); +// std::string str = ret; +// free(ret); +// GLOGE("======================>%s", str.c_str()); +// return str; +// } + +// CjsonObject* CjsonObject::GetObjectItem(const std::string &field) +// { +// if (cjson_ == nullptr) { +// return nullptr; +// } +// CjsonObject *item = new CjsonObject(); +// auto cjson_item = cJSON_GetObjectItem(cjson_, field.c_str()); +// if (cjson_item == nullptr) { +// return item; +// } +// item->cjson_ = cjson_item; +// return item; +// } + +// CjsonObject* CjsonObject::GetArrayItem(const int index) +// { +// if (cjson_ == nullptr) { +// return nullptr; +// } +// CjsonObject *item = new CjsonObject(); +// auto cjson_item = cJSON_GetArrayItem(cjson_, index); +// if (cjson_item == nullptr) { +// return item; +// } +// item->cjson_ = cjson_item; +// return item; +// } + +// CjsonObject* CjsonObject::GetNext() +// { +// if (cjson_ == nullptr) { +// return nullptr; +// } +// CjsonObject *next = new CjsonObject(); +// if (cjson_->next == nullptr) { +// return next; +// } +// next->cjson_ = cjson_->next; +// return next; +// } + +// CjsonObject* CjsonObject::GetChild() +// { +// if (cjson_ == nullptr) { +// return nullptr; +// } +// CjsonObject *child = new CjsonObject(); +// if (cjson_->child == nullptr) { +// return child; +// } +// child->cjson_ = cjson_->child; +// return child; +// } + +// int CjsonObject::DeleteItemFromObject(const std::string &field) +// { +// if (field == "") { +// return E_OK; +// } +// cJSON_DeleteItemFromObject(cjson_, field.c_str()); +// return E_OK; +// } + +// ResultValue* CjsonObject::GetItemValue() +// { +// if (cjson_ == nullptr) { +// return nullptr; +// } +// ResultValue* value = new ResultValue(); +// switch (cjson_->type) +// { +// case cJSON_False: +// { +// value->value_type = ResultValue::ValueType::VALUE_FALSE; +// } +// break; +// case cJSON_True: +// { +// value->value_type = ResultValue::ValueType::VALUE_TRUE; +// } +// break; +// case cJSON_NULL: +// { +// value->value_type = ResultValue::ValueType::VALUE_NULL; +// } +// break; +// case cJSON_Number: +// { +// value->value_type = ResultValue::ValueType::VALUE_NUMBER; +// value->value_number = cjson_->valuedouble; +// } +// break; +// case cJSON_String: +// { +// value->value_type = ResultValue::ValueType::VALUE_STRING; +// value->value_string = cjson_->valuestring; +// } +// break; +// case cJSON_Array: +// { +// value->value_type = ResultValue::ValueType::VALUE_ARRAY; +// value->value_Object = GetChild(); +// } +// break; +// case cJSON_Object: +// { +// value->value_type = ResultValue::ValueType::VALUE_OBJECT; +// value->value_Object = GetChild(); +// } +// break; +// default: +// break; +// } +// return value; +// } + +// std::string CjsonObject::GetItemFiled() +// { +// if (cjson_ == nullptr) { +// GLOGE("cjson is null"); +// return ""; +// } +// if (cjson_->string == nullptr) { +// GLOGE("cjson string is null"); +// return ""; +// } +// return cjson_->string; +// } + +// int CjsonObject::Delete() +// { +// if (cjson_ != nullptr) { +// cJSON_Delete(cjson_); +// } +// return E_OK; +// } + +// bool CjsonObject::IsFieldExists(const JsonFieldPath &path) +// { +// cJSON *item = cjson_; +// for (const auto &field : path) { +// item = cJSON_GetObjectItem(item, field.c_str()); // TODO: parse array +// if (item == nullptr) { +// return false; +// } +// } +// return true; +// } + +// int CjsonObject::GetObjectByPath(const JsonFieldPath &path, ValueObject &obj) +// { +// cJSON *item = cjson_; +// for (const auto &field : path) { +// item = cJSON_GetObjectItem(item, field.c_str()); // TODO: parse array +// if (item == nullptr) { +// GLOGE("Invalid json field path. %s", field.c_str()); +// return -E_JSON_PATH_NOT_EXISTS; +// } +// } + +// if (item->type == cJSON_Number) { +// obj.valueType = ValueObject::ValueType::VALUE_NUMBER; +// obj.intValue = item->valueint; +// } + +// return E_OK; +// } +// } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.h new file mode 100644 index 00000000..398e45dd --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.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 CJSON_OBJECT_H +// #define CJSON_OBJECT_H + +// #include +// #include "cJSON.h" +// #include "json_object.h" + +// namespace DocumentDB { +// class CjsonObject : public JsonObject{ +// public: +// CjsonObject () = default; +// virtual ~CjsonObject () = default; + +// int Parse(const std::string &str) override; +// std::string Print() override; +// CjsonObject* GetObjectItem(const std::string &field) override; +// CjsonObject* GetArrayItem(const int index) override; +// CjsonObject* GetNext(); +// CjsonObject* GetChild(); +// int DeleteItemFromObject(const std::string &field) override; +// ResultValue* GetItemValue() override; +// std::string GetItemFiled() override; +// int Delete() override; + +// bool IsFieldExists(const JsonFieldPath &path) override; +// int GetObjectByPath(const JsonFieldPath &path, ValueObject &obj) override; +// private: +// cJSON *cjson_; +// }; +// } // DocumentDB +// #endif // CJSON_OBJECT_H + 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 6fe749a5..c72237e0 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 @@ -13,28 +13,92 @@ * limitations under the License. */ +#include "json_object.h" +#include #include "doc_errno.h" #include "log_print.h" -#include "grd_format_config.h" -#include "json_object.h" +// #include "grd_format_config.h" namespace DocumentDB { -JsonObject::JsonObject() +namespace { +#define COLLECTION_LENS_MAX (512) +#define JSON_LENS_MAX (512) +#define JSON_DEEP_MAX (4) +} + +ValueObject::ValueObject(bool val) { - cjson_ = nullptr; - isClone_ = true; + 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::ValueObject(const std::string &val) +{ + valueType = ValueType::VALUE_STRING; + stringValue = val; +} + +ValueObject::ValueType ValueObject::GetValueType() const +{ + return valueType; +} + +bool ValueObject::GetBoolValue() const +{ + return boolValue; +} + +int ValueObject::GetIntValue() const +{ + return static_cast(doubleValue + 0.5); +} + +double ValueObject::GetDoubleValue() const +{ + return doubleValue; +} + +std::string ValueObject::GetStringValue() const +{ + return stringValue; +} + +JsonObject JsonObject::Parse(const std::string &jsonStr, int &errCode, bool caseSensitive) +{ + JsonObject obj; + errCode = obj.Init(jsonStr); + obj.caseSensitive_ = caseSensitive; + return obj; } -JsonObject::JsonObject(const JsonObject& newObj) +JsonObject::JsonObject() { - cjson_ = newObj.cjson_; - isClone_ = true; + cjson_ = nullptr; } +// JsonObject::JsonObject(const JsonObject &obj) +// { +// this->cjson_ = cJSON_Duplicate(obj.cjson_, true); +// this->isOwner_ = true; +// this->caseSensitive_ = obj.caseSensitive_; +// } + JsonObject::~JsonObject() { - if (isClone_ == false) { + if (isOwner_ == true) { cJSON_Delete(cjson_); } } @@ -47,42 +111,19 @@ bool JsonObject::IsNull() return false; } -int JsonObject::GetDeep(cJSON *cjson, int deep, int &maxDeep) +int JsonObject::GetDeep(cJSON *cjson) { if (cjson->child == nullptr) { - maxDeep = std::max(deep, maxDeep); - } - if (cjson->child != nullptr) { - GetDeep(cjson->child, deep + 1, maxDeep); + return 1; // leaf node } - if (cjson->next != nullptr) { - GetDeep(cjson->next, deep, maxDeep); - } - return E_OK; -} -int JsonObject::Init(const std::string &str) -{ - const char *end = NULL; - cjson_ = cJSON_ParseWithOpts(str.c_str(), &end, true); - if (cjson_ == nullptr) { - return E_INVALID_FORMAT; - } - if (cjson_->type != cJSON_Object) { - return E_INVALID_FORMAT; - } - int ret; - CheckNumber(cjson_, ret); - if (ret == E_INVALID_ARGS) { - return E_INVALID_ARGS; + int depth = -1; + cJSON *child = cjson->child; + while (child != nullptr) { + depth = std::max(depth, GetDeep(child) + 1); + child = child->next; } - int deep = 0; - GetDeep(cjson_, 0, deep); - if (deep > JSON_DEEP_MAX) { - return E_INVALID_ARGS; - } - isClone_ = false; - return E_OK; + return depth; } int JsonObject::CheckNumber(cJSON *item, int &errCode) @@ -102,6 +143,31 @@ int JsonObject::CheckNumber(cJSON *item, int &errCode) return E_OK; } +int JsonObject::Init(const std::string &str) +{ + if (str.length() + 1 > JSON_LENS_MAX) { + return -E_INVALID_ARGS; + } + const char *end = NULL; + isOwner_ = true; + cjson_ = cJSON_ParseWithOpts(str.c_str(), &end, true); + if (cjson_ == nullptr) { + return -E_INVALID_ARGS; + } + if (cjson_->type != cJSON_Object) { + return -E_INVALID_ARGS; + } + if (GetDeep(cjson_) > JSON_DEEP_MAX) { + return -E_INVALID_ARGS; + } + int ret; + CheckNumber(cjson_, ret); + if (ret == E_INVALID_ARGS) { + return E_INVALID_ARGS; + } + return E_OK; +} + std::string JsonObject::Print() { if (cjson_ == nullptr) { @@ -109,36 +175,43 @@ std::string JsonObject::Print() } char *ret = cJSON_PrintUnformatted(cjson_); std::string str = ret; - free(ret); + free(ret); return str; } -JsonObject JsonObject::GetObjectItem(const std::string &field, bool caseSensitive) +JsonObject JsonObject::GetObjectItem(const std::string &field, int &errCode) { - if (cjson_ == nullptr) { + if (cjson_ == nullptr || (cjson_->type & cJSON_Object) != cJSON_Object) { + errCode = -E_INVALID_ARGS; return JsonObject(); } + JsonObject item; - if (caseSensitive) { - cJSON *cjsonItem = cJSON_GetObjectItemCaseSensitive(cjson_, field.c_str()); + item.caseSensitive_ = caseSensitive_; + if (caseSensitive_) { + item.cjson_ = cJSON_GetObjectItemCaseSensitive(cjson_, field.c_str()); } else { - cJSON *cjsonItem = cJSON_GetObjectItem(cjson_, field.c_str()); - item.cjson_ = cjsonItem; + item.cjson_ = cJSON_GetObjectItem(cjson_, field.c_str()); + } + if (item.cjson_ == nullptr) { + errCode = -E_NOT_FOUND; } return item; } -JsonObject JsonObject::GetArrayItem(const int index) +JsonObject JsonObject::GetArrayItem(int index, int &errCode) { - if (cjson_ == nullptr) { + if (cjson_ == nullptr || (cjson_->type & cJSON_Array) != cJSON_Array) { + errCode = -E_INVALID_ARGS; return JsonObject(); } + JsonObject item; - auto cjsonItem = cJSON_GetArrayItem(cjson_, index); - if (cjsonItem == nullptr) { - return item; + item.caseSensitive_ = caseSensitive_; + item.cjson_ = cJSON_GetArrayItem(cjson_, index); + if (item.cjson_ == nullptr) { + errCode = -E_NOT_FOUND; } - item.cjson_ = cjsonItem; return item; } @@ -148,19 +221,21 @@ JsonObject JsonObject::GetNext() return JsonObject(); } JsonObject next; + next.caseSensitive_ = caseSensitive_; if (cjson_->next == nullptr) { return JsonObject(); } next.cjson_ = cjson_->next; return next; } - + JsonObject JsonObject::GetChild() { if (cjson_ == nullptr) { return JsonObject(); } JsonObject child; + child.caseSensitive_ = caseSensitive_; if (cjson_->child == nullptr) { return JsonObject(); } @@ -177,65 +252,34 @@ int JsonObject::DeleteItemFromObject(const std::string &field) return E_OK; } -ResultValue JsonObject::GetItemValue() +ValueObject JsonObject::GetItemValue() const { if (cjson_ == nullptr) { - return ResultValue(); + return ValueObject(); } - ResultValue value; + + ValueObject value; switch (cjson_->type) { - case cJSON_False: { - value.valueType = ResultValue::ValueType::VALUE_FALSE; - } - break; - case cJSON_True: - { - value.valueType = ResultValue::ValueType::VALUE_TRUE; - } - break; - case cJSON_NULL: - { - value.valueType = ResultValue::ValueType::VALUE_NULL; - } - break; - case cJSON_Number: - { - value.valueType = ResultValue::ValueType::VALUE_NUMBER; - value.valueNumber = cjson_->valuedouble; - } - break; - case cJSON_String: - { - value.valueType = ResultValue::ValueType::VALUE_STRING; - value.valueString = cjson_->valuestring; - } - break; - case cJSON_Array: - { - value.valueType = ResultValue::ValueType::VALUE_ARRAY; - if (GetChild().IsNull() != true) { - auto item = GetChild(); - value.valueObject = &item; - } - } - break; - case cJSON_Object: - { - value.valueType = ResultValue::ValueType::VALUE_OBJECT; - if (GetChild().IsNull() != true) { - auto item = GetChild(); - value.valueObject = &item; - } - } - break; + case cJSON_False: + case cJSON_True: + return ValueObject(cjson_->type == cJSON_True); + case cJSON_NULL: + return ValueObject(); + case cJSON_Number: + return ValueObject(cjson_->valuedouble); + case cJSON_String: + return ValueObject(cjson_->valuestring); + case cJSON_Array: + case cJSON_Object: default: + GLOGW("Invalid json type: %d", cjson_->type); break; } return value; } -std::string JsonObject::GetItemFiled(int &errCode) +std::string JsonObject::GetItemFiled(int &errCode) const { if (cjson_ == nullptr) { errCode = E_INVALID_ARGS; @@ -249,101 +293,111 @@ std::string JsonObject::GetItemFiled(int &errCode) return cjson_->string; } -JsonObject JsonObject::FindItem(const std::vector jsonPath) + +namespace { +bool IsNumber(const std::string &str) { + return std::all_of(str.begin(), str.end(), [](char c) { + return std::isdigit(c); + }); +} + +cJSON *GetChild(cJSON *cjson, const std::string &field, bool caseSens) { - cJSON *cJsondataItem = cjson_; - if (jsonPath.size() != 0 && jsonPath[0] == "") { - return JsonObject(); - } - for (int i = 0; i < jsonPath.size(); i++) { - if (cJsondataItem->type == cJSON_Object) { - if (cJSON_GetObjectItem(cJsondataItem,jsonPath[i].c_str()) == nullptr) { - return JsonObject(); - } - cJSON *cJsondataTemp; - cJsondataTemp = cJSON_GetObjectItem(cJsondataItem,jsonPath[i].c_str()); - cJsondataItem = cJsondataTemp; + if (cjson->type == cJSON_Object) { + if (caseSens) { + return cJSON_GetObjectItemCaseSensitive(cjson, field.c_str()); + } else { + return cJSON_GetObjectItem(cjson, field.c_str()); } - if (cJsondataItem->type == cJSON_Array) { - int nums = 0; - for (int j = 0; j < jsonPath[i].size(); j++) { - if (jsonPath[i][j]-'0' > 9 || jsonPath[i][j] - '0' < 0 || - jsonPath[i][j] - '0' > cJSON_GetArraySize(cJsondataItem)) { - break; - } - auto GetArrayRet = cJSON_GetArrayItem(cJsondataItem, jsonPath[i][j]-'0'); - if (typeid(GetArrayRet) == typeid(cJSON*)) { - cJsondataItem = GetArrayRet; - } - else { - if ( i != jsonPath.size() - 1) { - GLOGD("[cjson_object]=====>Patharg wrong"); - } - else { - return JsonObject(); - } - } - } + } else if (cjson->type == cJSON_Array) { + if (!IsNumber(field)) { + GLOGW("Invalid json field path, expect array index."); + 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) { + cjson = GetChild(cjson, field, caseSens); + if (cjson == nullptr) { + GLOGW("Invalid json field path, no such field."); + } + } + return cjson; +} +} + + +bool JsonObject::IsFieldExists(const JsonFieldPath &jsonPath) const +{ + return (MoveToPath(cjson_, jsonPath, caseSensitive_) == nullptr); +} + +JsonObject JsonObject::FindItem(const JsonFieldPath &jsonPath, int &errCode) const +{ + if (jsonPath.empty()) { + return JsonObject(); + } + + cJSON *findItem = MoveToPath(cjson_, jsonPath, caseSensitive_); + if (findItem == nullptr) { + GLOGE("Find item failed. json field path not found."); + errCode = -E_JSON_PATH_NOT_EXISTS; + } + JsonObject item; - item.cjson_ = cJsondataItem; + item.caseSensitive_ = caseSensitive_; + item.cjson_ = findItem; return item; } -int JsonObject::DeleteItemOnTarget(std::vector &path) +ValueObject JsonObject::GetObjectByPath(const JsonFieldPath &jsonPath, int &errCode) const { - cJSON *nodeFather; - cJSON *cJsondataRoot; - std::string lastString; - if (path.size()>0) { - lastString = path.back(); - path.pop_back(); - if (path.size() == 0) { - std::vector emptyPath; - auto cjsonObj = FindItem(emptyPath); - if (cjsonObj.IsNull() == true) { - return E_OK; - } - nodeFather = cjsonObj.cjson_; - cJsondataRoot = cjsonObj.cjson_; - path.emplace_back(lastString); - } - else { - std::vector fatherPath; - for (int i = 0; i < path.size() - 1; i++) { - fatherPath.emplace_back(path[i]); - } - auto foreObj = FindItem(fatherPath); - if (foreObj.IsNull() == true) { - return E_OK; - } - cJsondataRoot = foreObj.cjson_; - auto cjsonObj = FindItem(path); - if (cjsonObj.IsNull() == true) { - return E_OK; - } - nodeFather = cjsonObj.cjson_; - path.emplace_back(lastString); - } + JsonObject objGot = FindItem(jsonPath, errCode); + if (errCode != E_OK) { + GLOGE("Get json value object failed. %d", errCode); + return {}; } - if (nodeFather->type == cJSON_Object) { - if (cJSON_GetObjectItem(nodeFather, lastString.c_str()) != nullptr) { - cJSON_DeleteItemFromObject(nodeFather, lastString.c_str()); - } - else { - GLOGE("no item that can be deleted"); - } + return objGot.GetItemValue(); +} + +int JsonObject::DeleteItemOnTarget(const JsonFieldPath &path) +{ + if (path.empty()) { + return -E_INVALID_ARGS; } - if (nodeFather->type == cJSON_Array) { - if (cJSON_GetArrayItem(nodeFather, lastString[0] - '0') != nullptr) { - cJSON_DeleteItemFromArray(nodeFather, lastString[0] - '0'); + + std::string fieldName = path.back(); + JsonFieldPath patherPath = path; + patherPath.pop_back(); + + int errCode = E_OK; + cJSON *nodeFather = MoveToPath(cjson_, patherPath, caseSensitive_); + if (nodeFather == nullptr) { + GLOGE("Delete item failed, json field path not found."); + return -E_JSON_PATH_NOT_EXISTS; + } + + if (nodeFather->type == cJSON_Object) { + if (caseSensitive_) { + cJSON_DeleteItemFromObjectCaseSensitive(nodeFather, fieldName.c_str()); + } else { + cJSON_DeleteItemFromObject(nodeFather, fieldName.c_str()); } - else { - GLOGE("no item that can be deleted"); + } else if (nodeFather->type == cJSON_Array) { + if (!IsNumber(fieldName)) { + GLOGW("Invalid json field path, expect array index."); + return -E_JSON_PATH_NOT_EXISTS; } + cJSON_DeleteItemFromArray(nodeFather, std::stoi(fieldName)); } - return E_OK; + + return E_OK; +} } -} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp index ca9b2788..d22d47cf 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp @@ -15,6 +15,7 @@ #include "doc_errno.h" #include "kv_store_manager.h" +#include "log_print.h" #include "sqlite_store_executor_impl.h" #include "sqlite_utils.h" @@ -23,15 +24,50 @@ constexpr const char *APP_ID = "APP_ID"; constexpr const char *USER_ID = "USER_ID"; constexpr const char *STORE_ID = "STORE_ID"; -int KvStoreManager::GetKvStore(const std::string &path, KvStoreExecutor *&executor) +int KvStoreManager::GetKvStore(const std::string &path, const DBConfig &config, KvStoreExecutor *&executor) { + if (executor != nullptr) { + return -E_INVALID_ARGS; + } + sqlite3 *db = nullptr; - int errCode = SQLiteUtils::CreateDataBase(path, 0, db); - if (errCode != E_OK || db == nullptr) { - return -E_ERROR; + int errCode = SqliteStoreExecutor::CreateDatabase(path, config, db); + if (errCode != E_OK) { + GLOGE("Get kv store failed. %d", errCode); + return errCode; + } + + auto *sqliteExecutor = new (std::nothrow) SqliteStoreExecutor(db); + if (sqliteExecutor == nullptr) { + return -E_OUT_OF_MEMORY; } - executor = new (std::nothrow) SqliteStoreExecutor(db); + std::string oriConfigStr; + errCode = sqliteExecutor->GetDBConfig(oriConfigStr); + GLOGD("----> Get original db config: [%s] %d", oriConfigStr.c_str(), errCode); + if (errCode == -E_NOT_FOUND) { + errCode = sqliteExecutor->SetDBConfig(config.ToString()); + } else if (errCode != E_OK) { + goto END; + } else { + DBConfig oriDbConfig = DBConfig::ReadConfig(oriConfigStr, errCode); + if (errCode != E_OK) { + GLOGE("Read db config failed. %d", errCode); + goto END; + } + if (config != oriDbConfig) { + errCode = -E_INVALID_CONFIG_VALUE; + GLOGE("Get kv store failed, db config changed. %d", errCode); + goto END; + } + } + + executor = sqliteExecutor; return E_OK; + +END: + delete sqliteExecutor; + sqliteExecutor = nullptr; + return errCode; } } \ 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.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_store_executor_impl.cpp index 24317ce3..b50872b1 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 @@ -12,12 +12,47 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include "doc_common.h" #include "doc_errno.h" #include "log_print.h" #include "sqlite_utils.h" #include "sqlite_store_executor_impl.h" namespace DocumentDB { +int SqliteStoreExecutor::CreateDatabase(const std::string &path, const DBConfig &config, sqlite3 *&db) +{ + if (db != nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = SQLiteUtils::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); + if (errCode != E_OK) { + GLOGE("Set db page size failed. %d", errCode); + goto END; + } + + errCode = SQLiteUtils::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; + } + + return E_OK; + +END: + sqlite3_close_v2(db); + db = nullptr; + return errCode; +} + SqliteStoreExecutor::SqliteStoreExecutor(sqlite3 *handle) : dbHandle_(handle) { } @@ -28,107 +63,181 @@ SqliteStoreExecutor::~SqliteStoreExecutor() dbHandle_ = nullptr; } +int SqliteStoreExecutor::GetDBConfig(std::string &config) +{ + std::string dbConfigKeyStr = "DB_CONFIG"; + Key dbConfigKey = {dbConfigKeyStr.begin(), dbConfigKeyStr.end()}; + Value dbConfigVal; + int errCode = GetData("grd_meta", dbConfigKey, dbConfigVal); + config.assign(dbConfigVal.begin(), dbConfigVal.end()); + return errCode; +} + +int SqliteStoreExecutor::SetDBConfig(const std::string &config) +{ + std::string dbConfigKeyStr = "DB_CONFIG"; + Key dbConfigKey = {dbConfigKeyStr.begin(), dbConfigKeyStr.end()}; + Value dbConfigVal = {config.begin(), config.end()}; + return PutData("grd_meta", dbConfigKey, dbConfigVal); +} + int SqliteStoreExecutor::PutData(const std::string &collName, const Key &key, const Value &value) { - std::string key_value (key.begin(), key.end()); if (dbHandle_ == nullptr) { return -E_ERROR; } - std::string sql = "INSERT INTO '" + collName + "' VALUES (?,?);"; + + std::string sql = "INSERT OR REPLACE INTO '" + collName + "' VALUES (?,?);"; int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key, value](sqlite3_stmt *stmt) { SQLiteUtils::BindBlobToStatement(stmt, 1, key); SQLiteUtils::BindBlobToStatement(stmt, 2, value); return E_OK; }, nullptr); if (errCode != SQLITE_OK) { - GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); - if (errCode == 19) { - return E_DATA_CONFLICT; - } - if (errCode == 1) { - return E_INVALID_ARGS; - } - }//要改 + GLOGE("[sqlite executor] Put data failed. err=%d", errCode); + return errCode; + } return E_OK; } int SqliteStoreExecutor::GetData(const std::string &collName, const Key &key, Value &value) const { if (dbHandle_ == nullptr) { + GLOGE("Invalid db handle."); return -E_ERROR; } - std::string key_value (key.begin(), key.end()); - if (dbHandle_ == nullptr) { - return -E_ERROR; - } + int innerErrorCode = -E_NOT_FOUND; std::string sql = "SELECT value FROM '" + collName + "' WHERE key=?;"; int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key](sqlite3_stmt *stmt) { SQLiteUtils::BindBlobToStatement(stmt, 1, key); return E_OK; - }, [&value](sqlite3_stmt *stmt) { + }, [&value, &innerErrorCode](sqlite3_stmt *stmt) { SQLiteUtils::GetColumnBlobValue(stmt, 0, value); + innerErrorCode = E_OK; return E_OK; }); if (errCode != SQLITE_OK) { - GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); + GLOGE("[sqlite executor] Get data failed. err=%d", errCode); return errCode; } - std::string ret_value (value.begin(), value.end()); + return innerErrorCode; +} + +int SqliteStoreExecutor::DelData(const std::string &collName, const Key &key) +{ if (dbHandle_ == nullptr) { + GLOGE("Invalid db handle."); return -E_ERROR; } - return E_OK; + std::string sql = "DELETE FROM '" + collName + "' WHERE key=?;"; + int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key](sqlite3_stmt *stmt) { + SQLiteUtils::BindBlobToStatement(stmt, 1, key); + return E_OK; + }, nullptr); + + if (errCode != SQLITE_OK) { + GLOGE("[sqlite executor] Delete data failed. err=%d", errCode); + } + return errCode; } -int SqliteStoreExecutor::CreateCollection(const std::string &name, int flag) +int SqliteStoreExecutor::CreateCollection(const std::string &name, bool ignoreExists) { if (dbHandle_ == nullptr) { return -E_ERROR; } + std::string collName = COLL_PREFIX + name; + if (!ignoreExists) { + int errCode = E_OK; + bool isExists = IsCollectionExists(collName, errCode); + if (errCode != E_OK) { + return errCode; + } + if (isExists) { + GLOGE("[sqlite executor] Create collectoin failed, collection already exists."); + return -E_COLLECTION_CONFLICT; + } + } - std::string sql = "CREATE TABLE IF NOT EXISTS '" + name + "' (key BLOB PRIMARY KEY, value BLOB);"; + std::string sql = "CREATE TABLE IF NOT EXISTS '" + collName + "' (key BLOB PRIMARY KEY, value BLOB);"; int errCode = SQLiteUtils::ExecSql(dbHandle_, sql); if (errCode != SQLITE_OK) { - GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); + GLOGE("[sqlite executor] Create collectoin failed. err=%d", errCode); return errCode; } return E_OK; } -int SqliteStoreExecutor::DropCollection(const std::string &name, int flag) +int SqliteStoreExecutor::DropCollection(const std::string &name, bool ignoreNonExists) { if (dbHandle_ == nullptr) { return -E_ERROR; } - std::string sql = "DROP TABLE IF EXISTS '" + name + "';"; + std::string collName = COLL_PREFIX + name; + if (!ignoreNonExists) { + int errCode = E_OK; + bool isExists = IsCollectionExists(collName, errCode); + if (errCode != E_OK) { + return errCode; + } + if (!isExists) { + GLOGE("[sqlite executor] Drop collectoin failed, collection not exists."); + return -E_NO_DATA; + } + } + + std::string sql = "DROP TABLE IF EXISTS '" + collName + "';"; int errCode = SQLiteUtils::ExecSql(dbHandle_, sql); if (errCode != SQLITE_OK) { - GLOGE("[sqlite executor] drop collectoin failed. err=%d", errCode); + GLOGE("[sqlite executor] Drop collectoin failed. err=%d", errCode); return errCode; } return E_OK; } -int SqliteStoreExecutor::DeleteData(const std::string &collName, const Key &key) +bool SqliteStoreExecutor::IsCollectionExists(const std::string &name, int &errCode) { - std::string key_value (key.begin(), key.end()); - sqlite3 *db = dbHandle_; - const std::string sql_delete = "DELETE FROM '" + collName + "' WHERE key = ?;"; - const std::function &bindCallback = [&](sqlite3_stmt *stmt) -> int { - SQLiteUtils::BindBlobToStatement(stmt, 1, key); + bool isExists = false; + std::string sql = "SELECT tbl_name FROM sqlite_master WHERE tbl_name=?;"; + + errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [name](sqlite3_stmt *stmt) { + SQLiteUtils::BindTextToStatement(stmt, 1, name); return E_OK; - }; - int errCode = SQLiteUtils::ExecSql(db, sql_delete, bindCallback, nullptr); - if (errCode != SQLITE_OK) { - GLOGE("[sqlite executor] create collectoin failed. err=%d", errCode); - if (errCode == 19) { - return E_DATA_CONFLICT; - } - if (errCode == 1) { - return E_INVALID_ARGS; - } - }//要改 - return E_OK; + }, [&isExists](sqlite3_stmt *stmt) { + isExists = true; + return E_OK; + }); + + if (errCode != E_OK) { + GLOGE("Check collection exist failed. %d", errCode); + } + + return isExists; +} + +int SqliteStoreExecutor::GetCollectionOption(const std::string &name, std::string &option) +{ + std::string collOptKeyStr = "COLLECTION_OPTION_" + name; + Key collOptKey = {collOptKeyStr.begin(), collOptKeyStr.end()}; + Value collOptVal; + int errCode = GetData("grd_meta", collOptKey, collOptVal); + option.assign(collOptVal.begin(), collOptVal.end()); + return errCode; +} + +int SqliteStoreExecutor::SetCollectionOption(const std::string &name, const std::string &option) +{ + std::string collOptKeyStr = "COLLECTION_OPTION_" + name; + Key collOptKey = {collOptKeyStr.begin(), collOptKeyStr.end()}; + Value collOptVal = {option.begin(), option.end()}; + return PutData("grd_meta", collOptKey, collOptVal); +} + +int SqliteStoreExecutor::CleanCollectionOption(const std::string &name) +{ + std::string collOptKeyStr = "COLLECTION_OPTION_" + 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 d4301bac..bc6857b8 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 @@ -16,21 +16,33 @@ #ifndef SQLITE_STORE_EXECUTOR_IMPL_H #define SQLITE_STORE_EXECUTOR_IMPL_H +#include "db_config.h" #include "kv_store_executor.h" #include "sqlite3.h" namespace DocumentDB { class SqliteStoreExecutor : public KvStoreExecutor { public: + static int CreateDatabase(const std::string &path, const DBConfig &config, sqlite3 *&db); + SqliteStoreExecutor(sqlite3 *handle); ~SqliteStoreExecutor() override; + int GetDBConfig(std::string &config); + int SetDBConfig(const std::string &config); + 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 DelData(const std::string &collName, const Key &key) override; + + int CreateCollection(const std::string &name, bool ignoreExists) override; + int DropCollection(const std::string &name, bool ignoreNonExists) override; + bool IsCollectionExists(const std::string &name, int &errCode) override; + + int GetCollectionOption(const std::string &name, std::string &option) override; + int SetCollectionOption(const std::string &name, const std::string &option) override; + int CleanCollectionOption(const std::string &name) override; - int CreateCollection(const std::string &name, int flag) override; - int DropCollection(const std::string &name, int flag) override; - int DeleteData(const std::string &collName, const Key &key) override; private: sqlite3 *dbHandle_ = nullptr; }; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp index 6a1082c5..0c431b1c 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp @@ -19,6 +19,7 @@ namespace DocumentDB { const int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit TODO:: check blob size +const int MAX_TEXT_READ_SIZE = 5 * 1024 * 1024; // 5M limit const std::string BEGIN_SQL = "BEGIN TRANSACTION"; const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION"; const std::string COMMIT_SQL = "COMMIT TRANSACTION"; @@ -31,6 +32,7 @@ void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) int SQLiteUtils::CreateDataBase(const std::string &path, int flag, sqlite3 *&db) { + GLOGD("----> open sqlite: %s", path.c_str()); int errCode = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); if (errCode != SQLITE_OK) { GLOGE("Open database [%s] failed. %d", path.c_str(), errCode); @@ -152,6 +154,44 @@ 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) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int errCode = sqlite3_bind_text(statement, index, value.c_str(), value.length(), SQLITE_TRANSIENT); + if (errCode != SQLITE_OK) { + GLOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode); + return errCode; + } + + return E_OK; +} + +int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value) +{ + if (statement == nullptr) { + return -E_INVALID_ARGS; + } + + int valSize = sqlite3_column_bytes(statement, index); + if (valSize < 0 || valSize > MAX_TEXT_READ_SIZE) { + GLOGW("[SQLiteUtils][Column text] size over limit:%d", valSize); + value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid + return E_OK; // Return OK for continue get data, but value is invalid + } + + const unsigned char *val = sqlite3_column_text(statement, index); + if (valSize == 0 || val == nullptr) { + value = {}; + } else { + value = std::string(reinterpret_cast(val)); + } + + return E_OK; +} + int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type) { if (type == TransactType::IMMEDIATE) { @@ -193,7 +233,7 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::functio if (db == nullptr || sql.empty()) { return -E_INVALID_ARGS; } - + GLOGD("----> execSql: %s", sql.c_str()); bool bindFinish = true; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, sql, stmt); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.h index 9b8e02d3..4dcf5b1b 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.h @@ -39,6 +39,9 @@ public: static int BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector &value); static int GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector &value); + static int BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &value); + static int GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value); + static int BeginTransaction(sqlite3 *db, TransactType type = TransactType::DEFERRED); static int CommitTransaction(sqlite3 *db); static int RollbackTransaction(sqlite3 *db); 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 4bc5e4b4..c647ca0d 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 @@ -134,84 +134,84 @@ void DocumentDeleteApiTest::InsertDoc(const char *collectionName, const char *do EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, document, 0), GRD_OK); } -/** - * @tc.name: DocumentDelete001 - * @tc.desc: Delete with NULL filter - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -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); -} +// /** +// * @tc.name: DocumentDelete001 +// * @tc.desc: Delete with NULL filter +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// 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); +// } -/** - * @tc.name: DocumentDelete002 - * @tc.desc: Delete with filter which has no _id - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentDeleteApiTest, DeleteDBTest002, TestSize.Level1) -{ - /** - * @tc.steps:step1. Delete with filter which has no _id - * @tc.expected: step1. GRD_INVALID_ARGS - */ - const char *filter = "{\"age\" : 15}"; - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); -} +// /** +// * @tc.name: DocumentDelete002 +// * @tc.desc: Delete with filter which has no _id +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest002, TestSize.Level1) +// { +// /** +// * @tc.steps:step1. Delete with filter which has no _id +// * @tc.expected: step1. GRD_INVALID_ARGS +// */ +// const char *filter = "{\"age\" : 15}"; +// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); +// } -/** - * @tc.name: DocumentDelete003 - * @tc.desc: Delete with filter which has more than one fileds. - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentDeleteApiTest, DeleteDBTest003, TestSize.Level1) -{ - /** - * @tc.steps:step1. Delete with filter which has more than one fileds. - * @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); -} +// /** +// * @tc.name: DocumentDelete003 +// * @tc.desc: Delete with filter which has more than one fileds. +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest003, TestSize.Level1) +// { +// /** +// * @tc.steps:step1. Delete with filter which has more than one fileds. +// * @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); +// } -/** - * @tc.name: DocumentDelete004 - * @tc.desc: Test delete with invalid input - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentDeleteApiTest, DeleteDBTest004, TestSize.Level1) -{ - /** - * @tc.steps:step1. Test delete with un-zero flags - * @tc.expected: step1. GRD_INVALID_ARGS - */ - const char *filter1 = "{\"_id\" : \"1\"}"; - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter1, 1), GRD_INVALID_ARGS); - /** - * @tc.steps:step2. Test delete with NULL collection name - * @tc.expected: step2. GRD_INVALID_ARGS - */ - // const char *filter2 = "{\"_id\" : \"1\"}"; - // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter2, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step3. Test delete with empty collection name - * @tc.expected: step3. GRD_INVALID_ARGS - */ - // const char *filter1 = "{\"_id\" : \"1\"}"; - // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter1, 1), GRD_INVALID_ARGS); -} +// /** +// * @tc.name: DocumentDelete004 +// * @tc.desc: Test delete with invalid input +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest004, TestSize.Level1) +// { +// /** +// * @tc.steps:step1. Test delete with un-zero flags +// * @tc.expected: step1. GRD_INVALID_ARGS +// */ +// const char *filter1 = "{\"_id\" : \"1\"}"; +// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter1, 1), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2. Test delete with NULL collection name +// * @tc.expected: step2. GRD_INVALID_ARGS +// */ +// // const char *filter2 = "{\"_id\" : \"1\"}"; +// // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter2, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step3. Test delete with empty collection name +// * @tc.expected: step3. GRD_INVALID_ARGS +// */ +// // const char *filter1 = "{\"_id\" : \"1\"}"; +// // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter1, 1), GRD_INVALID_ARGS); +// } /** * @tc.name: DocumentDelete005 @@ -237,74 +237,74 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest005, TestSize.Level1) ChkDeleteResWithFilter(filter); } -/** - * @tc.name: DocumentDelete006 - * @tc.desc: Test delete after calling find interface - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, 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\"}"; - GRD_ResultSet *resultSet; - resultSet = new GRD_ResultSet; - Query query = {filter, "{}"}; - EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); - /** - * @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); -} +// /** +// * @tc.name: DocumentDelete006 +// * @tc.desc: Test delete after calling find interface +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, 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\"}"; +// GRD_ResultSet *resultSet; +// resultSet = new GRD_ResultSet; +// Query query = {filter, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); +// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); +// /** +// * @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); +// } -/** - * @tc.name: DocumentDelete008 - * @tc.desc: Test delete with invalid NULL input for all parameters. - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentDeleteApiTest, DeleteDBTest008, TestSize.Level1) -{ - /** - * @tc.steps:step1. Delete with filter which has more than one fileds. - * @tc.expected: step1. GRD_INVALID_ARGS - */ - const char *filter = "{\"_id\" : \"1\"}"; - EXPECT_EQ(GRD_DeleteDoc(NULL, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); - // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter, 0), GRD_INVALID_ARGS); - // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter, 0), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), GRD_INVALID_ARGS); -} +// /** +// * @tc.name: DocumentDelete008 +// * @tc.desc: Test delete with invalid NULL input for all parameters. +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest008, TestSize.Level1) +// { +// /** +// * @tc.steps:step1. Delete with filter which has more than one fileds. +// * @tc.expected: step1. GRD_INVALID_ARGS +// */ +// const char *filter = "{\"_id\" : \"1\"}"; +// EXPECT_EQ(GRD_DeleteDoc(NULL, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); +// // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter, 0), GRD_INVALID_ARGS); +// // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter, 0), GRD_INVALID_ARGS); +// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0), GRD_INVALID_ARGS); +// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0), GRD_INVALID_ARGS); +// EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), GRD_INVALID_ARGS); +// } -/** - * @tc.name: DocumentDelete010 - * @tc.desc: Test delete document when filter _id is int and string - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) -{ - /** - * @tc.steps:step1. Test delete document when filter _id is int and string. - * @tc.expected: step1. GRD_INVALID_ARGS - */ - std::vector filterVec = {R"({"_id" : 1})", R"("_id":[1, 2]})", - R"({"_id" : {"t1" : 1}})", R"({"_id":null})", R"({"_id":true})", R"({"_id" : 1.333})", R"({"_id" : -2.0})"}; - for (const auto &item : filterVec) { - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, item.c_str(), 0), GRD_INVALID_ARGS); - } - const char *filter = "{\"_id\" : \"1\"}"; - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); +// /** +// * @tc.name: DocumentDelete010 +// * @tc.desc: Test delete document when filter _id is int and string +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) +// { +// /** +// * @tc.steps:step1. Test delete document when filter _id is int and string. +// * @tc.expected: step1. GRD_INVALID_ARGS +// */ +// std::vector filterVec = {R"({"_id" : 1})", R"("_id":[1, 2]})", +// R"({"_id" : {"t1" : 1}})", R"({"_id":null})", R"({"_id":true})", R"({"_id" : 1.333})", R"({"_id" : -2.0})"}; +// for (const auto &item : filterVec) { +// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, item.c_str(), 0), GRD_INVALID_ARGS); +// } +// const char *filter = "{\"_id\" : \"1\"}"; +// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); -} \ No newline at end of file +// } \ No newline at end of file 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 4eae25a6..30a03191 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 @@ -52,8 +52,9 @@ static const char *g_document14 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\ {\"school\":\"AB\", \"age\" : 15}}"; -static std::vectorg_data = {g_document1, g_document2, g_document3, g_document4, g_document5, g_document6, g_document7, - g_document8}; +// static std::vectorg_data = {g_document1, g_document2, g_document3, g_document4, g_document5, g_document6, g_document7, +// g_document8}; +static std::vectorg_data = {g_document1}; static void InsertData(GRD_DB *g_db, const char *collectionName) { for (const auto &item : g_data) { @@ -103,19 +104,19 @@ void DocumentFindApiTest::TearDown(void) HWTEST_F(DocumentFindApiTest, DocumentFindApiTest, TestSize.Level1) { - // const char *filter = "{\"_id\":\"1\"}"; - // const char *projection = "{}"; - // Query query; - // query.filter = filter; - // query.projection = projection; - // GRD_ResultSet *resultSet; - // resultSet = new GRD_ResultSet; - // EXPECT_EQ(GRD_FindDoc(g_db, "student", query, 0, &resultSet), GRD_OK); - // char **test; - // test = new char*[1]; - // test[0] = new char[521 + 1]; - // GRD_Next(resultSet); - // EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); - //GRD_FreeValue(test[0]); - // GRD_FreeResultSet(resultSet[0]); + const char *filter = "{\"_id\":\"1\"}"; + const char *projection = "{\"item\" : 0, \"personInfo.school\" : 0, \"_id\" : 0}"; + Query query; + query.filter = filter; + query.projection = projection; + GRD_ResultSet *resultSet; + resultSet = new GRD_ResultSet; + EXPECT_EQ(GRD_FindDoc(g_db, "student", query, GRD_DOC_ID_DISPLAY, &resultSet), GRD_OK); + char **test; + test = new char*[1]; + test[0] = new char[521 + 1]; + GRD_Next(resultSet); + EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); + GRD_FreeValue(test[0]); + //GRD_FreeResultSet(resultSet); } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp index efe734a3..a0b44f5f 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp @@ -88,72 +88,72 @@ void DocumentInsertApiTest::TearDown(void) } -/** - * @tc.name: DocumentInsertApiTest001 - * @tc.desc: Insert documents into collection which dose not exist - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest001, TestSize.Level1) -{ - /** - * @tc.steps:step1.Insert document into collection which dose not exist - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"_id\" : \"1\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, no_exsit_collectionName, document1, 0), GRD_INVALID_ARGS); -} - -/** - * @tc.name: DocumentInsertApiTest002 - * @tc.desc: Insert documents into collection which _id is not string - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest002, TestSize.Level1) -{ - /** - * @tc.steps:step1.Insert a document whose _id is integer - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"_id\" : 2, \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step2.Insert a document whose _id is bool - * @tc.expected:step2.GRD_INVALID_ARGS - */ - const char *document2 = "{\"_id\" : true, \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step2.Insert a document whose _id is NULL - * @tc.expected:step2.GRD_INVALID_ARGS - */ - const char *document3 = "{\"_id\" : null, \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step2.Insert a document whose _id is ARRAY - * @tc.expected:step2.GRD_INVALID_ARGS - */ - const char *document4 = "{\"_id\" : [\"2\"], \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step2.Insert a document whose _id is OBJECT - * @tc.expected:step2.GRD_INVALID_ARGS - */ - const char *document5 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_INVALID_ARGS); -} - - -/** - * @tc.name: DocumentInsertApiTest003 - * @tc.desc: Insert a document whose _id has appeared before - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ +// /** +// * @tc.name: DocumentInsertApiTest001 +// * @tc.desc: Insert documents into collection which dose not exist +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest001, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Insert document into collection which dose not exist +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"_id\" : \"1\", \"name\" : \"Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, no_exsit_collectionName, document1, 0), GRD_INVALID_ARGS); +// } + +// /** +// * @tc.name: DocumentInsertApiTest002 +// * @tc.desc: Insert documents into collection which _id is not string +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest002, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Insert a document whose _id is integer +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"_id\" : 2, \"name\" : \"Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2.Insert a document whose _id is bool +// * @tc.expected:step2.GRD_INVALID_ARGS +// */ +// const char *document2 = "{\"_id\" : true, \"name\" : \"Chuan\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2.Insert a document whose _id is NULL +// * @tc.expected:step2.GRD_INVALID_ARGS +// */ +// const char *document3 = "{\"_id\" : null, \"name\" : \"Chuan\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2.Insert a document whose _id is ARRAY +// * @tc.expected:step2.GRD_INVALID_ARGS +// */ +// const char *document4 = "{\"_id\" : [\"2\"], \"name\" : \"Chuan\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2.Insert a document whose _id is OBJECT +// * @tc.expected:step2.GRD_INVALID_ARGS +// */ +// const char *document5 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"Chuan\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_INVALID_ARGS); +// } + + +// /** +// * @tc.name: DocumentInsertApiTest003 +// * @tc.desc: Insert a document whose _id has appeared before +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ HWTEST_F(DocumentInsertApiTest, InsertDBTest003, TestSize.Level1) { /** @@ -167,453 +167,453 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest003, TestSize.Level1) * @tc.steps:step2.Insert a document whose _id has appeared before * @tc.expected:step2.GRD_DATA_CONFLICT */ - const char *document2 = "{\"_id\" : \"3\", \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_DATA_CONFLICT); -} - -/** - * @tc.name: DocumentInsertApiTest004 - * @tc.desc: Test Insert with null parameter. parameter db is NULL - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest004, TestSize.Level1) -{ - /** - * @tc.steps:step1.step1.parameter db is NULL - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"_id\" : \"4\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(NULL, right_collectionName, document1, 0), GRD_INVALID_ARGS); -} - -/** - * @tc.name: DocumentInsertApiTest005 - * @tc.desc: Test insert with null parameter. parameter collectionName is NULL. - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest005, TestSize.Level1) -{ - /** - * @tc.steps:step1.Parameter collectionName is NULL - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"_id\" : \"5\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, NULL, document1, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step2.Parameter collectionName is empty string - * @tc.expected:step2.GRD_INVALID_ARGS - */ - const char *document2 = "{\"_id\" : \"5\", \"name\" : \"Chuang\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, "", document2, 0), GRD_INVALID_ARGS); -} - -/** - * @tc.name: DocumentInsertApiTest006 - * @tc.desc: parameter flags is not zero - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest006, TestSize.Level1) -{ - /** - * @tc.steps:step1.parameter flags is not zero - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"_id\" : \"6\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 1), GRD_INVALID_ARGS); -} - -/** - * @tc.name: DocumentInsertApiTest007 - * @tc.desc: parameter flags is INT_MAX - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest007, TestSize.Level1) -{ - /** - * @tc.steps:step1.parameter flags is int_max - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"_id\" : \"7\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_max), GRD_INVALID_ARGS); -} - -/** - * @tc.name: DocumentInsertApiTest008 - * @tc.desc: parameter flags is int_min - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest008, TestSize.Level1) -{ - /** - * @tc.steps:step1.parameter flags is int_min - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"_id\" : \"8\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_min), GRD_INVALID_ARGS); -} - -/** - * @tc.name: DocumentInsertApiTest009 - * @tc.desc: parameter collectionName and document is NULL or invalid - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) -{ - /** - * @tc.steps:step1.parameter collectionName and document is NULL; - * @tc.expected:step1.GRD_INVALID_ARGS - */ - EXPECT_EQ(GRD_InsertDoc(g_db, NULL, NULL, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step2.parameter collectionName is larger than max_collectionName_lens; - * @tc.expected:step2.GRD_OVER_LIMIT - */ - // std::string collectionName2(max_collection_lens + 1, 'a'); - // EXPECT_EQ(GRD_InsertDoc(g_db, collectionName2.c_str(), JSON_STR_HASID, 0), GRD_OVER_LIMIT); -} - -/** - * @tc.name: DocumentInsertApiTest010 - * @tc.desc: parameter collectionName contains irregular charactor - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest010, TestSize.Level1) -{ - /** - * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor - * @tc.expected:step1.GRD_OK - */ - const char *collectionName = "collction@!#"; - const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; - TestInsertDocIntoCertainColl(collectionName, document1, GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest011 - * @tc.desc: parameter collectionName is longer than 256 charactors - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest011, TestSize.Level1) -{ - /** - * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor - * @tc.expected:step1.GRD_OK - */ - string collectionName(257, 'k'); - const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; - TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest014 - * @tc.desc: Inserted document's JSON depth is larger than 4, which is 5. - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) -{ - /** - * @tc.steps:step1.document's JSON depth is larger than 4, which is 5. - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document1 = "{\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}}, \"level3_2\" : \"level3_2_val\"\ - }},\"_id\":\"14\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step1.document's JSON depth is larger than 4, which is 5.But with array type. - * @tc.expected:step1.GRD_INVALID_ARGS - */ - const char *document2 = "{\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"level5_1val\", \"level5_2\":\ - \"level5_2_val\"}, \"level4_val1\",\"level4_val2\"], \"level3_2\" : \"level3_2_val\"\ - }},\"_id\":\"14\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step1.document's JSON depth is 4 - * @tc.expected:step1.GRD_OK - */ - const char *document3 = "{\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"level5_1val\"}, \"level3_2\" : \"level3_2_val\"\ - }},\"_id\":\"14\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest015 - * @tc.desc: Inserted document with all kinds of size - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) -{ - /** - * @tc.steps:step1.document's JSON is bigger than 512k - 1 - * @tc.expected:step1.GRD_INVALID_ARGS - */ - string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; - string documentPart2 = "\" }"; - string jsonVal = string(512 * 1024 - documentPart1.size() - documentPart2.size(), 'k'); - string document = documentPart1 + jsonVal + documentPart2; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OVER_LIMIT); - /** - * @tc.steps:step2.Insert document's JSON is a large data but lower than 512k - 1 - * @tc.expected:step2.GRD_OK - */ - string jsonVal2 = string(512 * 1024 - 1 - documentPart1.size() - documentPart2.size(), 'k'); - string document2 = documentPart1 + jsonVal2 + documentPart2; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2.c_str(), 0), GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest016 - * @tc.desc: document JSON string contains irregular char - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest016, TestSize.Level1) -{ - /** - * @tc.steps:step1.document JSON string contains irregular char. - * @tc.expected:step1.GRD_OK - */ - const char *document1 = "{\"_id\" : \"16\", \"name\" : \"!@#Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest017 - * @tc.desc: document JSON string contains invalid value type such as BLOB type - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) -{ - /** - * @tc.steps:step1.document JSON string contains invalid value type such as BLOB type. - * @tc.expected:step1.GRD_INVALID_FORMAT. - */ - const char *document = "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : x'1234'\ - } } }, \"level1_2\" : \"level1_2Val\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); -} - -/** - * @tc.name: DocumentInsertApiTest018 - * @tc.desc: The Inserted document is not JSON format - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest018, TestSize.Level1) -{ - /** - * @tc.steps:step1.The Inserted document is not JSON format - * @tc.expected:step1.GRD_INVALID_FORMAT. - */ - const char *document = "some random string not JSON format"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); -} - -/** - * @tc.name: DocumentInsertApiTest019 - * @tc.desc: Insert a normal documents - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest019, TestSize.Level1) -{ - /** - * @tc.steps:step1.Insert a normal documents which _id is in the end of the string - * @tc.expected:step1.GRD_OK. - */ - const char *document1 = "{\"name\" : \"Jack\", \"age\" : 18, \"friend\" : {\"name\" : \" lucy\"}, \"_id\" : \"19\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest022 - * @tc.desc: parameter collectionName is equal to 256 charactors - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest022, TestSize.Level1) -{ - /** - * @tc.steps:step1.parameter collectionName is equal to 256 charactors - * @tc.expected:step1.GRD_OK. - */ - string collectionName = string(256, 'k'); - const char *document1 = "{\"_id\" : \"22\", \"name\" : \"Ori\"}"; - TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); + // const char *document2 = "{\"_id\" : \"3\", \"name\" : \"Chuan\"}"; + // EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_DATA_CONFLICT); } -/** - * @tc.name: DocumentInsertApiTest023 - * @tc.desc: parameter collectionName contains upper & lower case charactors, - * numbers and underline - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) -{ - /** - * @tc.steps:step1.parameter collectionName contains upper & lower case charactors, - * numbers and underline - * @tc.expected:step1.GRD_OK. - */ - string collectionName = "Aads_sd__23Asb_"; - const char *document1 = "{\"_id\" : \"23\", \"name\" : \"Ori\"}"; - TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest025 - * @tc.desc: Insert document whose depth is 4, which is allowed - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) -{ - /** - * @tc.steps:step1.documents JSON depth is 4, which is allowed. - * @tc.expected:step1.GRD_OK. - */ - const char *document1 = "{\"_id\" : \"25_0\", \"level1\" : { \"level2\" : {\"level3\" :\ - {\"level4\" : \"level4Val\" } } } , \"level1_2\" : \"level1_2Val\" }"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); - /** - * @tc.steps:step2.documents JSON depth is exactly 4. - * @tc.expected:step2.GRD_OK. - */ - const char *document2 = "{\"_id\" : \"25_1\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ - \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\"] }]}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK); - /** - * @tc.steps:step3.documents JSON depth is exactly 4, but the last field in array contains leading number - * @tc.expected:step3.GRD_INVALID_ARGS. - */ - const char *document3 = "{\"_id\" : \"25_2\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ - \"age\" : 18, \"sex\" : \"男\"}, [\"qw\", \"dr\", 0, \"ab\", {\"0ab\" : null}]]}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step4.documents JSON depth is exactly 5. - * @tc.expected:step4.GRD_INVALID_ARGS. - */ - const char *document4 = "{\"_id\" : \"25_3\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ - \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\", {\"level5\" : 1}] }]}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); -} - -/** - * @tc.name: DocumentInsertApiTest026 - * @tc.desc: Insert 100 normal documents continuously - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) -{ - /** - * @tc.steps:step1.Insert 100 normal documents continuously - * @tc.expected:step1.GRD_OK. - */ - string document1 = "{\"_id\" : "; - string document2 = "\""; - string document4 = "\""; - string document5 = ", \"name\" : \"Ori\"}"; - for (int i = 0; i < 5; i++) { - string document_midlle = {'2','6' + i}; - string document = document1 + document2 + document_midlle + document4 + document5; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OK); - } -} - -/** - * @tc.name: DocumentInsertApiTest036 - * @tc.desc: Insert a document whose value contains - * string, number, bool, null, array and object type - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) -{ - /** - * @tc.steps:step1.Insert a document whose value contains - * string, number, bool, null, array and object type - * @tc.expected:step1.GRD_OK. - */ - const char *document1 = "{\"_id\" : \"36_0\", \"stringType\" : \"stringVal\", \"numType\" : 1, \"BoolType\" : true,\ - \"nullType\" : null, \"arrayType\" : [1, 2, 3, 4], \"objectType\" : {\"A\" : 3}}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); -} - -/** - * @tc.name: DocumentInsertApiTest038 - * @tc.desc: Insert document whose value is over the range of double - * string, number, bool, null, array and object type - * @tc.type: FUNC - * @tc.require: - * @tc.author: mazhao - */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest038, TestSize.Level1) -{ - /** - * @tc.steps:step1.Insert document whose value is over the range of double - * @tc.expected:step1.GRD_INVALID_ARGS. - */ - const char *document1 = R"({"_id" : "38_0", "field2" : 1.79769313486232e308})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step2.Insert document whose value is over the range of double - * @tc.expected:step2.GRD_INVALID_ARGS. - */ - const char *document2 = R"({"_id" : "38_1", "t1" : {"field2" : 1.79769313486232e308}})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step3.Insert document whose value is over the range of double - * @tc.expected:step3.GRD_INVALID_ARGS. - */ - const char *document3 = R"({"_id" : "38_2", "t1" : [1, 2, 1.79769313486232e308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step4.Insert document whose value is over the range of double - * @tc.expected:step4.GRD_INVALID_ARGS. - */ - const char *document4 = R"({"_id" : "38_3", "t1" : [1, 2, -1.7976931348623167E+308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); - /** - * @tc.steps:step5.Insert document with minimum double value - * @tc.expected:step5.GRD_INVALID_ARGS. - */ - const char *document5 = R"({"_id" : "38_4", "t1" : [1, 2, -1.79769313486231570E+308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_OK); - /** - * @tc.steps:step6.Insert document with maxium double value - * @tc.expected:step6.GRD_INVALID_ARGS. - */ - const char *document6 = R"({"_id" : "38_5", "t1" : [1, 2, 1.79769313486231570E+308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document6, 0), GRD_OK); -} \ No newline at end of file +// /** +// * @tc.name: DocumentInsertApiTest004 +// * @tc.desc: Test Insert with null parameter. parameter db is NULL +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest004, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.step1.parameter db is NULL +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"_id\" : \"4\", \"name\" : \"Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(NULL, right_collectionName, document1, 0), GRD_INVALID_ARGS); +// } + +// /** +// * @tc.name: DocumentInsertApiTest005 +// * @tc.desc: Test insert with null parameter. parameter collectionName is NULL. +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest005, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Parameter collectionName is NULL +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"_id\" : \"5\", \"name\" : \"Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, NULL, document1, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2.Parameter collectionName is empty string +// * @tc.expected:step2.GRD_INVALID_ARGS +// */ +// const char *document2 = "{\"_id\" : \"5\", \"name\" : \"Chuang\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, "", document2, 0), GRD_INVALID_ARGS); +// } + +// /** +// * @tc.name: DocumentInsertApiTest006 +// * @tc.desc: parameter flags is not zero +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest006, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.parameter flags is not zero +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"_id\" : \"6\", \"name\" : \"Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 1), GRD_INVALID_ARGS); +// } + +// /** +// * @tc.name: DocumentInsertApiTest007 +// * @tc.desc: parameter flags is INT_MAX +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest007, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.parameter flags is int_max +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"_id\" : \"7\", \"name\" : \"Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_max), GRD_INVALID_ARGS); +// } + +// /** +// * @tc.name: DocumentInsertApiTest008 +// * @tc.desc: parameter flags is int_min +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest008, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.parameter flags is int_min +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"_id\" : \"8\", \"name\" : \"Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_min), GRD_INVALID_ARGS); +// } + +// /** +// * @tc.name: DocumentInsertApiTest009 +// * @tc.desc: parameter collectionName and document is NULL or invalid +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.parameter collectionName and document is NULL; +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// EXPECT_EQ(GRD_InsertDoc(g_db, NULL, NULL, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2.parameter collectionName is larger than max_collectionName_lens; +// * @tc.expected:step2.GRD_OVER_LIMIT +// */ +// // std::string collectionName2(max_collection_lens + 1, 'a'); +// // EXPECT_EQ(GRD_InsertDoc(g_db, collectionName2.c_str(), JSON_STR_HASID, 0), GRD_OVER_LIMIT); +// } + +// /** +// * @tc.name: DocumentInsertApiTest010 +// * @tc.desc: parameter collectionName contains irregular charactor +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest010, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor +// * @tc.expected:step1.GRD_OK +// */ +// const char *collectionName = "collction@!#"; +// const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; +// TestInsertDocIntoCertainColl(collectionName, document1, GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest011 +// * @tc.desc: parameter collectionName is longer than 256 charactors +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest011, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor +// * @tc.expected:step1.GRD_OK +// */ +// string collectionName(257, 'k'); +// const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; +// TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest014 +// * @tc.desc: Inserted document's JSON depth is larger than 4, which is 5. +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.document's JSON depth is larger than 4, which is 5. +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document1 = "{\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}}, \"level3_2\" : \"level3_2_val\"\ +// }},\"_id\":\"14\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step1.document's JSON depth is larger than 4, which is 5.But with array type. +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// const char *document2 = "{\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"level5_1val\", \"level5_2\":\ +// \"level5_2_val\"}, \"level4_val1\",\"level4_val2\"], \"level3_2\" : \"level3_2_val\"\ +// }},\"_id\":\"14\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step1.document's JSON depth is 4 +// * @tc.expected:step1.GRD_OK +// */ +// const char *document3 = "{\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"level5_1val\"}, \"level3_2\" : \"level3_2_val\"\ +// }},\"_id\":\"14\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest015 +// * @tc.desc: Inserted document with all kinds of size +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.document's JSON is bigger than 512k - 1 +// * @tc.expected:step1.GRD_INVALID_ARGS +// */ +// string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; +// string documentPart2 = "\" }"; +// string jsonVal = string(512 * 1024 - documentPart1.size() - documentPart2.size(), 'k'); +// string document = documentPart1 + jsonVal + documentPart2; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OVER_LIMIT); +// /** +// * @tc.steps:step2.Insert document's JSON is a large data but lower than 512k - 1 +// * @tc.expected:step2.GRD_OK +// */ +// string jsonVal2 = string(512 * 1024 - 1 - documentPart1.size() - documentPart2.size(), 'k'); +// string document2 = documentPart1 + jsonVal2 + documentPart2; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2.c_str(), 0), GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest016 +// * @tc.desc: document JSON string contains irregular char +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest016, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.document JSON string contains irregular char. +// * @tc.expected:step1.GRD_OK +// */ +// const char *document1 = "{\"_id\" : \"16\", \"name\" : \"!@#Ori\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest017 +// * @tc.desc: document JSON string contains invalid value type such as BLOB type +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.document JSON string contains invalid value type such as BLOB type. +// * @tc.expected:step1.GRD_INVALID_FORMAT. +// */ +// const char *document = "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : x'1234'\ +// } } }, \"level1_2\" : \"level1_2Val\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); +// } + +// /** +// * @tc.name: DocumentInsertApiTest018 +// * @tc.desc: The Inserted document is not JSON format +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest018, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.The Inserted document is not JSON format +// * @tc.expected:step1.GRD_INVALID_FORMAT. +// */ +// const char *document = "some random string not JSON format"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); +// } + +// /** +// * @tc.name: DocumentInsertApiTest019 +// * @tc.desc: Insert a normal documents +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest019, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Insert a normal documents which _id is in the end of the string +// * @tc.expected:step1.GRD_OK. +// */ +// const char *document1 = "{\"name\" : \"Jack\", \"age\" : 18, \"friend\" : {\"name\" : \" lucy\"}, \"_id\" : \"19\"}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest022 +// * @tc.desc: parameter collectionName is equal to 256 charactors +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest022, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.parameter collectionName is equal to 256 charactors +// * @tc.expected:step1.GRD_OK. +// */ +// string collectionName = string(256, 'k'); +// const char *document1 = "{\"_id\" : \"22\", \"name\" : \"Ori\"}"; +// TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest023 +// * @tc.desc: parameter collectionName contains upper & lower case charactors, +// * numbers and underline +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.parameter collectionName contains upper & lower case charactors, +// * numbers and underline +// * @tc.expected:step1.GRD_OK. +// */ +// string collectionName = "Aads_sd__23Asb_"; +// const char *document1 = "{\"_id\" : \"23\", \"name\" : \"Ori\"}"; +// TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest025 +// * @tc.desc: Insert document whose depth is 4, which is allowed +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.documents JSON depth is 4, which is allowed. +// * @tc.expected:step1.GRD_OK. +// */ +// const char *document1 = "{\"_id\" : \"25_0\", \"level1\" : { \"level2\" : {\"level3\" :\ +// {\"level4\" : \"level4Val\" } } } , \"level1_2\" : \"level1_2Val\" }"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +// /** +// * @tc.steps:step2.documents JSON depth is exactly 4. +// * @tc.expected:step2.GRD_OK. +// */ +// const char *document2 = "{\"_id\" : \"25_1\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ +// \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\"] }]}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK); +// /** +// * @tc.steps:step3.documents JSON depth is exactly 4, but the last field in array contains leading number +// * @tc.expected:step3.GRD_INVALID_ARGS. +// */ +// const char *document3 = "{\"_id\" : \"25_2\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ +// \"age\" : 18, \"sex\" : \"男\"}, [\"qw\", \"dr\", 0, \"ab\", {\"0ab\" : null}]]}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step4.documents JSON depth is exactly 5. +// * @tc.expected:step4.GRD_INVALID_ARGS. +// */ +// const char *document4 = "{\"_id\" : \"25_3\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ +// \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\", {\"level5\" : 1}] }]}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); +// } + +// /** +// * @tc.name: DocumentInsertApiTest026 +// * @tc.desc: Insert 100 normal documents continuously +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Insert 100 normal documents continuously +// * @tc.expected:step1.GRD_OK. +// */ +// string document1 = "{\"_id\" : "; +// string document2 = "\""; +// string document4 = "\""; +// string document5 = ", \"name\" : \"Ori\"}"; +// for (int i = 0; i < 5; i++) { +// string document_midlle = {'2','6' + i}; +// string document = document1 + document2 + document_midlle + document4 + document5; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OK); +// } +// } + +// /** +// * @tc.name: DocumentInsertApiTest036 +// * @tc.desc: Insert a document whose value contains +// * string, number, bool, null, array and object type +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Insert a document whose value contains +// * string, number, bool, null, array and object type +// * @tc.expected:step1.GRD_OK. +// */ +// const char *document1 = "{\"_id\" : \"36_0\", \"stringType\" : \"stringVal\", \"numType\" : 1, \"BoolType\" : true,\ +// \"nullType\" : null, \"arrayType\" : [1, 2, 3, 4], \"objectType\" : {\"A\" : 3}}"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +// } + +// /** +// * @tc.name: DocumentInsertApiTest038 +// * @tc.desc: Insert document whose value is over the range of double +// * string, number, bool, null, array and object type +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentInsertApiTest, InsertDBTest038, TestSize.Level1) +// { +// /** +// * @tc.steps:step1.Insert document whose value is over the range of double +// * @tc.expected:step1.GRD_INVALID_ARGS. +// */ +// const char *document1 = R"({"_id" : "38_0", "field2" : 1.79769313486232e308})"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step2.Insert document whose value is over the range of double +// * @tc.expected:step2.GRD_INVALID_ARGS. +// */ +// const char *document2 = R"({"_id" : "38_1", "t1" : {"field2" : 1.79769313486232e308}})"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step3.Insert document whose value is over the range of double +// * @tc.expected:step3.GRD_INVALID_ARGS. +// */ +// const char *document3 = R"({"_id" : "38_2", "t1" : [1, 2, 1.79769313486232e308]})"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step4.Insert document whose value is over the range of double +// * @tc.expected:step4.GRD_INVALID_ARGS. +// */ +// const char *document4 = R"({"_id" : "38_3", "t1" : [1, 2, -1.7976931348623167E+308]})"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); +// /** +// * @tc.steps:step5.Insert document with minimum double value +// * @tc.expected:step5.GRD_INVALID_ARGS. +// */ +// const char *document5 = R"({"_id" : "38_4", "t1" : [1, 2, -1.79769313486231570E+308]})"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_OK); +// /** +// * @tc.steps:step6.Insert document with maxium double value +// * @tc.expected:step6.GRD_INVALID_ARGS. +// */ +// const char *document6 = R"({"_id" : "38_5", "t1" : [1, 2, 1.79769313486231570E+308]})"; +// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document6, 0), GRD_OK); +// } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp new file mode 100644 index 00000000..1d9ba8a8 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp @@ -0,0 +1,592 @@ +/* +* 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 "doc_errno.h" +#include "documentdb_test_utils.h" +#include "log_print.h" +#include "grd_base/grd_db_api.h" +#include "grd_base/grd_error.h" +#include "grd_document/grd_document_api.h" +#include "sqlite_utils.h" + +using namespace DocumentDB; +using namespace testing::ext; +using namespace DocumentDBUnitTest; + +class DocumentDBApiTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DocumentDBApiTest::SetUpTestCase(void) +{ +} + +void DocumentDBApiTest::TearDownTestCase(void) +{ +} + +void DocumentDBApiTest::SetUp(void) +{ +} + +void DocumentDBApiTest::TearDown(void) +{ + DocumentDBTestUtils::RemoveTestDbFiles("./document.db"); +} + +/** + * @tc.name: OpenDBTest001 + * @tc.desc: Test open document db + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +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); + 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); + + EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", "{name:\"Tom\",age:23}", 0), GRD_OK); + EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", "{name:\"Tom\",age:24}", 0), GRD_OK); + + EXPECT_EQ(GRD_DropCollection(db, "student", 0), GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: OpenDBPathTest001 + * @tc.desc: Test open document db with NULL path + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBPathTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::vector invalidPath = { + nullptr, + "", + "/a/b/c/" + }; + for (auto path : invalidPath) { + GLOGD("OpenDBPathTest001: open db with path: %s", path); + int status = GRD_DBOpen(path, nullptr, GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_INVALID_ARGS); + } +} + +/** + * @tc.name: OpenDBPathTest002 + * @tc.desc: Test open document db with file no permission + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBPathTest002, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string pathNoPerm = "/root/document.db"; + int status = GRD_DBOpen(pathNoPerm.c_str(), nullptr, GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_FAILED_FILE_OPERATION); +} + +/** + * @tc.name: OpenDBConfigTest001 + * @tc.desc: Test open document db with invalid config option + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + const int MAX_JSON_LEN = 512 * 1024; + std::string configStr = std::string(MAX_JSON_LEN + 1, 'a'); + int status = GRD_DBOpen(path.c_str(), configStr.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OVER_LIMIT); +} + +/** + * @tc.name: OpenDBConfigTest002 + * @tc.desc: Test open document db with invalid config format + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigTest002, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + int status = GRD_DBOpen(path.c_str(), "{aa}", GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_INVALID_JSON_FORMAT); +} + +/** + * @tc.name: OpenDBConfigTest003 + * @tc.desc: Test open document db with config not support + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigTest003, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + int status = GRD_DBOpen(path.c_str(), R""({"notSupport":123})"", GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_NOT_SUPPORT); +} + +/** + * @tc.name: OpenDBConfigMaxConnNumTest001 + * @tc.desc: Test open document db with invalid config item maxConnNum + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + std::vector configList = { + R""({"maxConnNum":0})"", + R""({"maxConnNum":15})"", + R""({"maxConnNum":1025})"", + R""({"maxConnNum":1000000007})"", + R""({"maxConnNum":"16"})"", + R""({"maxConnNum":{"value":17}})"", + R""({"maxConnNum":[16,17,18]})"", + }; + for (const auto &config : configList) { + GLOGD("OpenDBConfigMaxConnNumTest001: test with config:%s", config.c_str()); + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + ASSERT_EQ(status, GRD_INVALID_CONFIG_VALUE); + } +} + +/** + * @tc.name: OpenDBConfigMaxConnNumTest002 + * @tc.desc: Test open document db with valid item maxConnNum + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest002, TestSize.Level1) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + for (int i = 16; i <= 1024; i++) { + std::string config = "{\"maxConnNum\":" + std::to_string(i) + "}"; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + ASSERT_NE(db, nullptr); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + DocumentDBTestUtils::RemoveTestDbFiles(path); + } +} + +/** + * @tc.name: OpenDBConfigMaxConnNumTest003 + * @tc.desc: Test reopen document db with different maxConnNum + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest003, TestSize.Level1) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + std::string config = R""({"maxConnNum":16})""; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + config = R""({"maxConnNum":17})""; + status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: OpenDBConfigMaxConnNumTest004 + * @tc.desc: Test open document db over maxConnNum + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest004, TestSize.Level1) +{ + std::string path= "./document.db"; + + int maxCnt = 16; + std::string config = "{\"maxConnNum\":" + std::to_string(maxCnt) + "}"; + + std::vector dbList; + while (maxCnt--) { + GRD_DB *db = nullptr; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + dbList.push_back(db); + } + + GRD_DB *db = nullptr; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OVER_LIMIT); + EXPECT_EQ(db, nullptr); + + for (auto *it : dbList) { + status = GRD_DBClose(it, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + } + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: OpenDBConfigPageSizeTest001 + * @tc.desc: Test open document db with invalid config item pageSize + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigPageSizeTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + std::vector configList = { + R""({"pageSize":0})"", + R""({"pageSize":5})"", + R""({"pageSize":48})"", + R""({"pageSize":1000000007})"", + R""({"pageSize":"4"})"", + R""({"pageSize":{"value":8}})"", + R""({"pageSize":[16,32,64]})"", + }; + for (const auto &config : configList) { + GLOGD("OpenDBConfigPageSizeTest001: test with config:%s", config.c_str()); + int status = GRD_DBOpen(path.c_str(), config.c_str(), 0, &db); + EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); + } +} + +namespace { +int GetDBPageSize(const std::string &path) +{ + sqlite3 *db = nullptr; + int ret = SQLiteUtils::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) { + pageSize = sqlite3_column_int(stmt, 0); + return E_OK; + }); + + sqlite3_close_v2(db); + return pageSize; +} +} + +/** + * @tc.name: OpenDBConfigPageSizeTest002 + * @tc.desc: Test open document db with valid config item pageSize + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigPageSizeTest002, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + for (int size : {4, 8, 16, 32, 64}) { + std::string config = "{\"pageSize\":" + std::to_string(size) + "}"; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + EXPECT_EQ(GetDBPageSize(path), size * 1024); + DocumentDBTestUtils::RemoveTestDbFiles(path); + } +} + +/** + * @tc.name: OpenDBConfigPageSizeTest003 + * @tc.desc: Test reopen document db with different pageSize + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigPageSizeTest003, TestSize.Level1) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + std::string config = R""({"pageSize":4})""; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + config = R""({"pageSize":8})""; + status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: OpenDBConfigRedoFlushTest001 + * @tc.desc: Test open document db with valid config item redoFlushByTrx + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigRedoFlushTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + for (int flush : {0, 1}) { + std::string config = "{\"redoFlushByTrx\":" + std::to_string(flush) + "}"; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + DocumentDBTestUtils::RemoveTestDbFiles(path); + } +} + +/** + * @tc.name: OpenDBConfigXXXTest001 + * @tc.desc: Test open document db with invalid config item redoFlushByTrx + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBConfigRedoFlushTest002, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + + std::string config = R""({"redoFlushByTrx":3})""; + int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); +} + +/** + * @tc.name: OpenDBFlagTest001 + * @tc.desc: Test open document db with invalid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBFlagTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + std::vector invaldFlag = { + GRD_DB_OPEN_CHECK_FOR_ABNORMAL | GRD_DB_OPEN_CHECK, + GRD_DB_OPEN_CREATE | GRD_DB_OPEN_CHECK_FOR_ABNORMAL | GRD_DB_OPEN_CHECK, + 0x08, + 0xffff, + UINT32_MAX + }; + for (unsigned int flag : invaldFlag) { + GLOGD("OpenDBFlagTest001: open doc db with flag %u", flag); + int status = GRD_DBOpen(path.c_str(), "", flag, &db); + EXPECT_EQ(status, GRD_INVALID_ARGS); + } +} + +/** + * @tc.name: OpenDBFlagTest002 + * @tc.desc: Test open document db with valid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, OpenDBFlagTest002, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CHECK_FOR_ABNORMAL, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CHECK, &db); + EXPECT_EQ(status, GRD_OK); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: CloseDBTest001 + * @tc.desc: Test close document db with invalid db + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, CloseDBTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + int status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_INVALID_ARGS); + + status = GRD_DBClose(db, GRD_DB_CLOSE_IGNORE_ERROR); + EXPECT_EQ(status, GRD_INVALID_ARGS); + db = nullptr; +} + +/** + * @tc.name: CloseDBFlagTest001 + * @tc.desc: Test close document db with valid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, CloseDBFlagTest001, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + ASSERT_NE(db, nullptr); + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: CloseDBFlagTest002 + * @tc.desc: Test close document db with valid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, CloseDBFlagTest002, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + ASSERT_NE(db, nullptr); + + // TODO: open result set + + status = GRD_DBClose(db, GRD_DB_CLOSE_IGNORE_ERROR); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} + +/** + * @tc.name: CloseDBFlagTest003 + * @tc.desc: Test close document db with invalid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBApiTest, CloseDBFlagTest003, TestSize.Level0) +{ + GRD_DB *db = nullptr; + std::string path= "./document.db"; + int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); + EXPECT_EQ(status, GRD_OK); + ASSERT_NE(db, nullptr); + + std::vector invaldFlag = { + 0x02, + 0x03, + 0xffff, + UINT32_MAX + }; + for (unsigned int flag : invaldFlag) { + GLOGD("CloseDBFlagTest003: close doc db with flag %u", flag); + status = GRD_DBClose(db, flag); + EXPECT_EQ(status, GRD_INVALID_ARGS); + } + + status = GRD_DBClose(db, GRD_DB_CLOSE); + EXPECT_EQ(status, GRD_OK); + db = nullptr; + + DocumentDBTestUtils::RemoveTestDbFiles(path); +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp new file mode 100644 index 00000000..22af9ecb --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp @@ -0,0 +1,202 @@ +/* +* 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 "doc_errno.h" +#include "documentdb_test_utils.h" +#include "log_print.h" +#include "grd_base/grd_db_api.h" +#include "grd_base/grd_error.h" +#include "grd_document/grd_document_api.h" +#include "sqlite_utils.h" + +using namespace DocumentDB; +using namespace testing::ext; +using namespace DocumentDBUnitTest; + +namespace { +std::string g_path = "./document.db"; +GRD_DB *g_db = nullptr; +} + +class DocumentDBCollectionTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DocumentDBCollectionTest::SetUpTestCase(void) +{ +} + +void DocumentDBCollectionTest::TearDownTestCase(void) +{ +} + +void DocumentDBCollectionTest::SetUp(void) +{ + EXPECT_EQ(GRD_DBOpen(g_path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &g_db), GRD_OK); + EXPECT_NE(g_db, nullptr); +} + +void DocumentDBCollectionTest::TearDown(void) +{ + if (g_db != nullptr) { + EXPECT_EQ(GRD_DBClose(g_db, GRD_DB_CLOSE), GRD_OK); + g_db = nullptr; + } + DocumentDBTestUtils::RemoveTestDbFiles(g_path); +} + +/** + * @tc.name: CollectionTest001 + * @tc.desc: Test create collection with null db + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest001, TestSize.Level0) +{ + EXPECT_EQ(GRD_CreateCollection(nullptr, "student", "", 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: CollectionTest002 + * @tc.desc: Test create/drop collection with invalid collection name + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest002, TestSize.Level0) +{ + std::vector invalidName = { + nullptr, + "", + "GRD_123", + "grd_123", + "GM_SYS_123", + "gm_sys_123", + }; + + for (auto *it : invalidName) { + GLOGD("CollectionTest002: create collection with name: %s", it); + EXPECT_EQ(GRD_CreateCollection(g_db, it, "", 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DropCollection(g_db, it, 0), GRD_INVALID_ARGS); + } +} + +/** + * @tc.name: CollectionTest003 + * @tc.desc: Test create/drop collection with valid collection name + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest003, TestSize.Level0) +{ + std::vector validName = { + "123", + "&^%@", + "中文字符", + "sqlite_master", + "NULL", + "SELECT" + }; + + for (auto *it : validName) { + GLOGD("CollectionTest003: create collection with name: %s", it); + EXPECT_EQ(GRD_CreateCollection(g_db, it, "", 0), GRD_OK); + EXPECT_EQ(GRD_DropCollection(g_db, it, 0), GRD_OK); + } +} + +/** + * @tc.name: CollectionTest004 + * @tc.desc: Test create collection with ignore flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest004, TestSize.Level0) +{ + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_COLLECTION_CONFLICT); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", IGNORE_EXIST_TABLE), GRD_OK); +} + +/** + * @tc.name: CollectionTest005 + * @tc.desc: Test create collection with invalid option + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest005, TestSize.Level0) +{ + EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({aa})"", 0), GRD_INVALID_JSON_FORMAT); + + std::vector invalidOption = { + // R""({"invalidOption":2})"", + R""({"maxDoc":0})"", + R""({"maxDoc":"123"})"", + R""({"maxDoc":{"value":1024}})"", + R""({"maxDoc":[1,2,4,8]})"", + }; + + for (auto opt : invalidOption) { + GLOGD("CollectionTest005: create collection with option: %s", opt); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", opt, 0), GRD_INVALID_CONFIG_VALUE); + } +} + +/** + * @tc.name: CollectionTest006 + * @tc.desc: Test create/drop collection with valid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest006, TestSize.Level0) +{ + EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({"maxDoc":1024})"", 0), GRD_OK); + + EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({"maxDoc":2048})"", IGNORE_EXIST_TABLE), + GRD_INVALID_CONFIG_VALUE); + + EXPECT_EQ(GRD_DropCollection(g_db, "student", 0), GRD_OK); + EXPECT_EQ(GRD_DropCollection(g_db, "student", 0), GRD_NO_DATA); + EXPECT_EQ(GRD_DropCollection(g_db, "student", IGNORE_NON_EXIST_TABLE), GRD_OK); + + // Create collection with different option returnh OK after drop collection + EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({"maxDoc":2048})"", 0), GRD_OK); +} + +/** + * @tc.name: CollectionTest007 + * @tc.desc: Test create/drop collection with invalid flag + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBCollectionTest, CollectionTest007, TestSize.Level0) +{ + for (int flag : std::vector {2, 4, 8, 1024, UINT32_MAX}) { + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", flag), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DropCollection(g_db, "student", flag), GRD_INVALID_ARGS); + } +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp new file mode 100644 index 00000000..6832993f --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.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 + +#include "doc_errno.h" +#include "documentdb_test_utils.h" +#include "log_print.h" +#include "grd_base/grd_db_api.h" +#include "grd_base/grd_error.h" +#include "grd_document/grd_document_api.h" +#include "sqlite_utils.h" + +using namespace DocumentDB; +using namespace testing::ext; +using namespace DocumentDBUnitTest; + +namespace { +std::string g_path = "./document.db"; +GRD_DB *g_db = nullptr; +const char *g_coll = "student"; +} + +class DocumentDBDataTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DocumentDBDataTest::SetUpTestCase(void) +{ +} + +void DocumentDBDataTest::TearDownTestCase(void) +{ +} + +void DocumentDBDataTest::SetUp(void) +{ + DocumentDBTestUtils::RemoveTestDbFiles(g_path); + EXPECT_EQ(GRD_DBOpen(g_path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &g_db), GRD_OK); + EXPECT_NE(g_db, nullptr); + + EXPECT_EQ(GRD_CreateCollection(g_db, g_coll, "", 0), GRD_OK); +} + +void DocumentDBDataTest::TearDown(void) +{ + if (g_db != nullptr) { + EXPECT_EQ(GRD_DBClose(g_db, GRD_DB_CLOSE), GRD_OK); + g_db = nullptr; + } +} + +/** + * @tc.name: UpsertDataTest001 + * @tc.desc: Test upsert data into collection + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpsertDataTest001, TestSize.Level0) +{ + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, "1234", document.c_str(), GRD_DOC_REPLACE), GRD_OK); +} + +/** + * @tc.name: UpsertDataTest002 + * @tc.desc: Test upsert data with db is nullptr + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpsertDataTest002, TestSize.Level0) +{ + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + EXPECT_EQ(GRD_UpSertDoc(nullptr, g_coll, "1234", document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); +} + +/** + * @tc.name: UpsertDataTest003 + * @tc.desc: Test upsert data with invalid collection name + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpsertDataTest003, TestSize.Level0) +{ + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + std::vector invalidName = { + nullptr, + "", + "GRD_123", + "grd_123", + "GM_SYS_123", + "gm_sys_123", + }; + for (auto name : invalidName) { + GLOGD("UpsertDataTest003: upsert data with collectionname: %s", name); + EXPECT_EQ(GRD_UpSertDoc(g_db, name, "1234", document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); + } +} + +HWTEST_F(DocumentDBDataTest, UpsertDataTest004, TestSize.Level0) +{ + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + std::vector invalidFilter = { + nullptr, + "", + R""({"name":"Tmono"})"", + R""({"value":{"_id":"1234"}})"", + R""({"_id":1234})"", + }; + for (auto filter : invalidFilter) { + EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter, document.c_str(), GRD_DOC_REPLACE), GRD_INVALID_ARGS); + } +} + +HWTEST_F(DocumentDBDataTest, UpsertDataTest005, TestSize.Level0) +{ + std::string filter = R""({"_id":1234})""; + std::vector invalidDocument = { + nullptr, + "", + "GRD_123", + "grd_123", + "GM_SYS_123", + "gm_sys_123", + }; + for (auto document : invalidDocument) { + EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document, GRD_DOC_REPLACE), GRD_INVALID_ARGS); + } +} + +/** + * @tc.name: UpsertDataTest006 + * @tc.desc: Test upsert data with invalid flags + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpsertDataTest006, TestSize.Level0) +{ + std::string filter = R""({"_id":1234})""; + std::string document = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + + for (auto flags : std::vector {2, 4, 8, 64, 1024, UINT32_MAX}) { + EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document.c_str(), flags), GRD_INVALID_ARGS); + } +} + +/** + * @tc.name: UpsertDataTest007 + * @tc.desc: Test upsert data with collection not create + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpsertDataTest007, TestSize.Level0) +{ + std::string val = R""({"name":"Tmono","age":18,"addr":{"city":"shanghai","postal":200001}})""; + EXPECT_EQ(GRD_UpSertDoc(g_db, "collection_not_exists", "1234", val.c_str(), GRD_DOC_REPLACE), GRD_NO_DATA); +} + +/** + * @tc.name: UpsertDataTest008 + * @tc.desc: Test upsert data with different document + * @tc.type: FUNC + * @tc.require: + * @tc.author: lianhuix + */ +HWTEST_F(DocumentDBDataTest, UpsertDataTest008, TestSize.Level0) +{ + std::string filter = R""({"_id":1234})""; + std::string document = R""({"name":"Tmn","age":18,"addr":{"city":"shanghai","postal":200001}})""; + EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document.c_str(), GRD_DOC_REPLACE), GRD_OK); + + std::string updateDoc = R""({"name":"Xue","case":2,"age":28,"addr":{"city":"shenzhen","postal":518000}})""; + EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), updateDoc.c_str(), GRD_DOC_APPEND), GRD_OK); +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/doucumentdb_api_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp similarity index 40% rename from services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/doucumentdb_api_test.cpp rename to services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp index 63ca9cab..fa16a27a 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/doucumentdb_api_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp @@ -14,16 +14,15 @@ */ #include - -#include "log_print.h" -#include "grd_base/grd_db_api.h" -#include "grd_base/grd_error.h" -#include "grd_document/grd_document_api.h" +#include "documentdb_test_utils.h" +#include "doc_errno.h" +#include "json_object.h" using namespace DocumentDB; using namespace testing::ext; +using namespace DocumentDBUnitTest; -class DocumentDBApiTest : public testing::Test { +class DocumentDBJsonObjectTest : public testing::Test { public: static void SetUpTestCase(void); static void TearDownTestCase(void); @@ -31,19 +30,19 @@ public: void TearDown(); }; -void DocumentDBApiTest::SetUpTestCase(void) +void DocumentDBJsonObjectTest::SetUpTestCase(void) { } -void DocumentDBApiTest::TearDownTestCase(void) +void DocumentDBJsonObjectTest::TearDownTestCase(void) { } -void DocumentDBApiTest::SetUp(void) +void DocumentDBJsonObjectTest::SetUp(void) { } -void DocumentDBApiTest::TearDown(void) +void DocumentDBJsonObjectTest::TearDown(void) { } @@ -54,38 +53,16 @@ void DocumentDBApiTest::TearDown(void) * @tc.require: * @tc.author: lianhuix */ -HWTEST_F(DocumentDBApiTest, OpenDBTest001, TestSize.Level1) +HWTEST_F(DocumentDBJsonObjectTest, JsonObjectTest001, TestSize.Level0) { - std::string path = "./document.db"; - GRD_DB *db = nullptr; - int status = GRD_DBOpen(path.c_str(), nullptr, 0, &db); - 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); - - EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", "{name:\"Tom\",age:23}", 0), GRD_OK); - EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", "{name:\"Tom\",age:24}", 0), GRD_OK); + const std::string config = R""({"a":123,"b":{"c":234,"d":"12345"}})""; - EXPECT_EQ(GRD_DropCollection(db, "student", 0), GRD_OK); + int ret = E_OK; + JsonObject conf = JsonObject::Parse(config, ret); + EXPECT_EQ(ret, E_OK); - status = GRD_DBClose(db, 0); - EXPECT_EQ(status, GRD_OK); - db = nullptr; -} + ValueObject obj = conf.GetObjectByPath({"b", "c"}, ret); -/** - * @tc.name: OpenDBTest001 - * @tc.desc: Test open document db with NULL path - * @tc.type: FUNC - * @tc.require: - * @tc.author: lianhuix - */ -HWTEST_F(DocumentDBApiTest, OpenDBTest002, TestSize.Level1) -{ - GRD_DB *db = nullptr; - char *path = nullptr; - int status = GRD_DBOpen(path, nullptr, 0, &db); - EXPECT_EQ(status, GRD_INVALID_ARGS); -} + EXPECT_EQ(obj.GetValueType(), ValueObject::ValueType::VALUE_NUMBER); + EXPECT_EQ(obj.GetIntValue(), 234); +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_test_utils.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_test_utils.h new file mode 100644 index 00000000..a513875e --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_test_utils.h @@ -0,0 +1,27 @@ +/* +* 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 DOCUMENTDB_TEST_UTILS_H +#define DOCUMENTDB_TEST_UTILS_H +#include + + +namespace DocumentDBUnitTest { +class DocumentDBTestUtils { +public: + static int RemoveTestDbFiles(const std::string &dir); +}; +} // namespace DocumentDBUnitTest +#endif // DOCUMENTDB_TEST_UTILS_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.cpp new file mode 100644 index 00000000..f26640ad --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.cpp @@ -0,0 +1,24 @@ +/* +* 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 "documentdb_test_utils.h" + +namespace DocumentDBUnitTest { +int DocumentDBTestUtils::RemoveTestDbFiles(const std::string &dir) +{ + (void)remove(dir.c_str()); // TODO: remove dir or files + return 0; +} +} // namespace DocumentDBUnitTest \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.h new file mode 100644 index 00000000..a513875e --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/common/documentdb_test_utils.h @@ -0,0 +1,27 @@ +/* +* 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 DOCUMENTDB_TEST_UTILS_H +#define DOCUMENTDB_TEST_UTILS_H +#include + + +namespace DocumentDBUnitTest { +class DocumentDBTestUtils { +public: + static int RemoveTestDbFiles(const std::string &dir); +}; +} // namespace DocumentDBUnitTest +#endif // DOCUMENTDB_TEST_UTILS_H \ No newline at end of file -- Gitee From d1936c985eb89d4f8d029dda538a8263812b4c6c Mon Sep 17 00:00:00 2001 From: mazhao Date: Mon, 10 Apr 2023 12:00:52 +0000 Subject: [PATCH 06/18] flush null implementation Signed-off-by: mazhao --- .../src/executor/document/grd_document_api.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index ca6aef9f..14ea8c1d 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -93,4 +93,9 @@ int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned in } int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, resultSet[0]->resultSet_); return TrasnferDocErr(ret); +} + +int GRD_Flush(GRD_DB *db, unsigned int flags) +{ + return GRD_OK; } \ No newline at end of file -- Gitee From 549f2d8b70099b2bc232f1c01a8880158670fea5 Mon Sep 17 00:00:00 2001 From: mazhao Date: Wed, 12 Apr 2023 01:52:00 +0000 Subject: [PATCH 07/18] The second Merge Signed-off-by: mazhao --- .../include/grd_base/grd_type_export.h | 7 +- .../src/common/include/db_config.h | 8 +- .../src/common/include/doc_common.h | 10 +- .../src/common/include/doc_limit.h | 2 +- .../src/common/include/json_common.h | 14 +- .../src/common/include/os_api.h | 2 + .../src/common/src/collection_option.cpp | 41 +- .../src/common/src/db_config.cpp | 107 +- .../src/common/src/doc_common.cpp | 73 +- .../src/common/src/json_common.cpp | 225 ++-- .../src/common/src/os_api.cpp | 7 +- .../src/executor/base/grd_db_api.cpp | 13 + .../src/executor/base/grd_resultset_api.cpp | 45 +- .../executor/document/grd_document_api.cpp | 15 +- .../src/interface/include/collection.h | 2 +- .../src/interface/include/doc_errno.h | 2 + .../src/interface/include/document_store.h | 3 + .../src/interface/include/result_set.h | 10 +- .../src/interface/src/collection.cpp | 28 +- .../src/interface/src/doc_errno.cpp | 41 +- .../src/interface/src/document_store.cpp | 148 ++- .../interface/src/document_store_manager.cpp | 21 +- .../src/interface/src/result_set.cpp | 25 +- .../src/oh_adapter/include/json_object.h | 31 +- .../src/oh_adapter/src/cjson_object.cpp | 211 ---- .../src/oh_adapter/src/cjson_object.h | 47 - .../src/oh_adapter/src/json_object.cpp | 159 ++- .../src/oh_adapter/src/kv_store_manager.cpp | 2 +- .../src/sqlite_store_executor_impl.cpp | 9 + .../src/oh_adapter/src/sqlite_utils.cpp | 24 +- .../unittest/api/ documentdb_delete_test.cpp | 291 ++--- .../unittest/api/ documentdb_find_test.cpp | 23 +- .../unittest/api/ documentdb_insert_test.cpp | 1028 +++++++++-------- .../test/unittest/api/documentdb_api_test.cpp | 4 +- .../api/documentdb_collection_test.cpp | 29 +- .../unittest/api/documentdb_data_test.cpp | 6 +- 36 files changed, 1437 insertions(+), 1276 deletions(-) delete mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.cpp delete mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.h diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h index 64fc1af6..ca6163a2 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/include/grd_base/grd_type_export.h @@ -29,8 +29,7 @@ typedef struct GRD_DB GRD_DB; #define GRD_DB_OPEN_CREATE 0x01 #define GRD_DB_OPEN_CHECK_FOR_ABNORMAL 0x02 //check data in database if close abnormally last time, //if data is corrupted, rebuild the database -#define GRD_DB_OPEN_CHECK 0x04//check data in database when open database, if data is corrupted, rebuild the database. - +#define GRD_DB_OPEN_CHECK 0x04//check data in database when open database, if data is corrupted, rebuild the database. /** * @brief Close database config */ @@ -52,8 +51,8 @@ typedef struct Query { /** * @brief Flags for create and drop collection */ -#define IGNORE_EXIST_TABLE 1 -#define IGNORE_NON_EXIST_TABLE 1 +#define CHK_EXIST_COLLECTION 1 +#define CHK_NON_EXIST_COLLECTION 1 #define GRD_DOC_APPEND 0 #define GRD_DOC_REPLACE 1 diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.h index d3e5b37c..c04116f2 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/db_config.h @@ -35,11 +35,11 @@ private: DBConfig() = default; std::string configStr_ = {}; - int32_t pageSize_ = 4; + int32_t pageSize_ = 4; // 4: default page size k uint32_t redoFlushByTrx_ = 0; - uint32_t redoPubBufSize_ = 1024; - int32_t maxConnNum_ = 100; - uint32_t bufferPoolSize_ = 1024; + uint32_t redoPubBufSize_ = 1024; // 1024: default 1024k buff size + int32_t maxConnNum_ = 100; // 100: default max conn + uint32_t bufferPoolSize_ = 1024; // 100: default 1024k pool size uint32_t crcCheckEnable_ = 1; }; } // namespace DocumentDB diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h index c6eaccba..5ef1dd38 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h @@ -26,12 +26,12 @@ class CheckCommon { public: CheckCommon() = default; - ~CheckCommon(); + ~CheckCommon() = default; - static bool CheckCollectionName(const std::string &collectionName); - static bool CheckFilter(const JsonObject *document); - static bool CheckIdFormat(const std::string &data); - static bool CheckDocument(const JsonObject *document); + static bool CheckCollectionName(const std::string &collectionName, std::string &lowerCaseName, int &errCode); + static bool CheckFilter(JsonObject *document); + static bool CheckIdFormat(JsonObject *data); + static bool CheckDocument(JsonObject *document); }; using Key = std::vector; using Value = std::vector; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h index 94d054b6..38ceb943 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_limit.h @@ -17,6 +17,6 @@ #define DOC_LIMIT_H namespace DocumentDB { -constexpr const int MAX_DB_CONFIG_LEN = 512 * 1024; // 512 * 1024: 5k length +constexpr const int MAX_DB_CONFIG_LEN = 512 * 1024; // 512 * 1024: 512k length } // namespace DocumentDB #endif // DOC_LIMIT_H \ No newline at end of file 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 cc9d6bdb..96813bed 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 @@ -19,6 +19,7 @@ #include #include #include +#include #include "json_object.h" namespace DocumentDB { @@ -28,16 +29,17 @@ public: JsonCommon() = default; ~JsonCommon(); - static ResultValue GetValueByFiled(JsonObject *node, const std::string& filed); - static bool CheckJsonField(const std::string &data); + static ValueObject GetValueByFiled(JsonObject *node, const std::string& filed); + static bool CheckJsonField(JsonObject *node); static int ParseNode(JsonObject *Node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor); - static std::vector> ParsePath(JsonObject* node); - static std::vector GetLeafValue(JsonObject *node); + static std::vector> ParsePath(const JsonObject* const node); + static std::vector GetLeafValue(JsonObject *node); - static JsonObject Append(const JsonObject &src, const JsonObject &add); + static int Append(const JsonObject &src, const JsonObject &add); + private: static bool CheckNode(JsonObject *Node, std::set filedSet, bool &errFlag); - static int CheckLeafNode(JsonObject *Node, std::vector &leafValue); + static int CheckLeafNode(JsonObject *Node, std::vector &leafValue); }; } // DocumentDB #endif // JSON_COMMON_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/os_api.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/os_api.h index e331ab33..6bfbf3bb 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/os_api.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/os_api.h @@ -18,6 +18,8 @@ #define OS_API_H namespace DocumentDB { namespace OSAPI { +bool CheckPermission(const std::string &filePath); + bool CheckPathExistence(const std::string &filePath); int GetRealPath(const std::string &inOriPath, std::string &outRealPath); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp index 1b64a9f1..fcb3da1e 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/collection_option.cpp @@ -16,25 +16,58 @@ #include "collection_option.h" #include +#include #include "doc_errno.h" #include "json_object.h" #include "log_print.h" namespace DocumentDB { +namespace { +const std::string OPT_MAX_DOC = "maxdoc"; +const std::vector DB_CONFIG = { + OPT_MAX_DOC, +}; + +bool CheckConfigSupport(const JsonObject &config, int &errCode) +{ + + JsonObject child = config.GetChild(); + while (!child.IsNull()) { + std::string fieldName = child.GetItemFiled(); + if (std::find(DB_CONFIG.begin(), DB_CONFIG.end(), fieldName) == DB_CONFIG.end()) { + GLOGE("Invalid collection config."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + child = child.GetNext(); + } + return true; +} +} CollectionOption CollectionOption::ReadOption(const std::string &optStr, int &errCode) { if (optStr.empty()) { return {}; } - JsonObject collOpt = JsonObject::Parse(optStr, errCode); + std::string lowerCaseOptStr = optStr; + std::transform(lowerCaseOptStr.begin(), lowerCaseOptStr.end(), lowerCaseOptStr.begin(), [](unsigned char c) { + return std::tolower(c); + }); + + JsonObject collOpt = JsonObject::Parse(lowerCaseOptStr, errCode); if (errCode != E_OK) { GLOGE("Read collection option failed from str. %d", errCode); return {}; } - static const JsonFieldPath maxDocField = {"maxDoc"}; + if (!CheckConfigSupport(collOpt, errCode)) { + GLOGE("Check collection option, not support config item. %d", errCode); + return {}; + } + + static const JsonFieldPath maxDocField = {OPT_MAX_DOC}; if (!collOpt.IsFieldExists(maxDocField)) { return {}; } @@ -46,12 +79,12 @@ CollectionOption CollectionOption::ReadOption(const std::string &optStr, int &er } if (maxDocValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { - GLOGE("Check collection option failed, the field type of maxDoc is not NUMBER. %d", errCode); + GLOGE("Check collection option failed, the field type of maxDoc is not NUMBER."); errCode = -E_INVALID_CONFIG_VALUE; return {}; } - if (maxDocValue.GetIntValue() <= 0 || maxDocValue.GetIntValue() > UINT32_MAX) { + if (maxDocValue.GetIntValue() <= 0 || static_cast(maxDocValue.GetIntValue()) > UINT32_MAX) { GLOGE("Check collection option failed, invalid maxDoc value."); errCode = -E_INVALID_CONFIG_VALUE; return {}; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp index 242ed1a2..b60de5b1 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/db_config.cpp @@ -24,18 +24,40 @@ #include "json_object.h" namespace DocumentDB { - namespace { -bool CheckPageSizeConfig(JsonObject config, int32_t &pageSize, int &errCode) +const int MIN_REDO_BUFFER_SIZE = 256; +const int MAX_REDO_BUFFER_SIZE = 16384; +const int MIN_CONNECTION_NUM = 16; +const int MAX_CONNECTION_NUM = 1024; +const int MIN_BUFFER_POOL_SIZE = 1024; +const int MAX_BUFFER_POOL_SIZE = 4 * 1024 * 1024; + +const std::string DB_CONFIG_PAGESIZE = "pagesize"; +const std::string DB_CONFIG_REDO_FLUSH_BY_TRX = "redoflushbytrx"; +const std::string DB_CONFIG_REDO_PUB_BUFF_SIZE = "redopubbufsize"; +const std::string DB_CONFIG_MAX_CONN_NUM = "maxconnnum"; +const std::string DB_CONFIG_BUFFER_POOL_SIZE = "bufferpoolsize"; +const std::string DB_CONFIG_CRC_CHECK_ENABLE = "crccheckenable"; + +const std::vector 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 +}; + +bool CheckPageSizeConfig(const JsonObject &config, int32_t &pageSize, int &errCode) { - static const JsonFieldPath pageSizeField = {"pageSize"}; + static const JsonFieldPath pageSizeField = {DB_CONFIG_PAGESIZE}; if (!config.IsFieldExists(pageSizeField)) { return true; } - ValueObject configValue = config.GetObjectByPath(pageSizeField, errCode); // TODO: check return code + ValueObject configValue = config.GetObjectByPath(pageSizeField, errCode); if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { - GLOGE("Check DB config failed, the field type of pageSize is not NUMBER. %d", errCode); + GLOGE("Check DB config failed, the field type of pageSize is not NUMBER."); errCode = -E_INVALID_CONFIG_VALUE; return false; } @@ -51,16 +73,16 @@ bool CheckPageSizeConfig(JsonObject config, int32_t &pageSize, int &errCode) return true; } -bool CheckRedoFlushConfig(JsonObject config, uint32_t &redoFlush, int &errCode) +bool CheckRedoFlushConfig(const JsonObject &config, uint32_t &redoFlush, int &errCode) { - static const JsonFieldPath redoFlushField = {"redoFlushByTrx"}; + static const JsonFieldPath redoFlushField = {DB_CONFIG_REDO_FLUSH_BY_TRX}; if (!config.IsFieldExists(redoFlushField)) { return true; } - ValueObject configValue = config.GetObjectByPath(redoFlushField, errCode); // TODO: + ValueObject configValue = config.GetObjectByPath(redoFlushField, errCode); if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { - GLOGE("Check DB config failed, the field type of redoFlushByTrx is not NUMBER. %d", errCode); + GLOGE("Check DB config failed, the field type of redoFlushByTrx is not NUMBER."); errCode = -E_INVALID_CONFIG_VALUE; return false; } @@ -75,21 +97,21 @@ bool CheckRedoFlushConfig(JsonObject config, uint32_t &redoFlush, int &errCode) return true; } -bool CheckRedoBufSizeConfig(JsonObject config, uint32_t &redoBufSize, int &errCode) +bool CheckRedoBufSizeConfig(const JsonObject &config, uint32_t &redoBufSize, int &errCode) { - static const JsonFieldPath redoBufSizeField = {"redoPubBufSize"}; + static const JsonFieldPath redoBufSizeField = {DB_CONFIG_REDO_PUB_BUFF_SIZE}; if (!config.IsFieldExists(redoBufSizeField)) { return true; } - ValueObject configValue = config.GetObjectByPath(redoBufSizeField, errCode); // TODO: + ValueObject configValue = config.GetObjectByPath(redoBufSizeField, errCode); if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { - GLOGE("Check DB config failed, the field type of redoPubBufSize is not NUMBER. %d", errCode); + GLOGE("Check DB config failed, the field type of redoPubBufSize is not NUMBER."); errCode = -E_INVALID_CONFIG_VALUE; return false; } - if (configValue.GetIntValue() < 256 && configValue.GetIntValue() > 16384) { + if (configValue.GetIntValue() < MIN_REDO_BUFFER_SIZE || configValue.GetIntValue() > MAX_REDO_BUFFER_SIZE) { GLOGE("Check DB config failed, invalid redoPubBufSize value."); errCode = -E_INVALID_CONFIG_VALUE; return false; @@ -99,21 +121,21 @@ bool CheckRedoBufSizeConfig(JsonObject config, uint32_t &redoBufSize, int &errCo return true; } -bool CheckMaxConnNumConfig(JsonObject config, int32_t &maxConnNum, int &errCode) +bool CheckMaxConnNumConfig(const JsonObject &config, int32_t &maxConnNum, int &errCode) { - static const JsonFieldPath maxConnNumField = {"maxConnNum"}; + static const JsonFieldPath maxConnNumField = {DB_CONFIG_MAX_CONN_NUM}; if (!config.IsFieldExists(maxConnNumField)) { return true; } - ValueObject configValue = config.GetObjectByPath(maxConnNumField, errCode); // TODO: + ValueObject configValue = config.GetObjectByPath(maxConnNumField, errCode); if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { - GLOGE("Check DB config failed, the field type of maxConnNum is not NUMBER. %d", errCode); + GLOGE("Check DB config failed, the field type of maxConnNum is not NUMBER."); errCode = -E_INVALID_CONFIG_VALUE; return false; } - if (configValue.GetIntValue() < 16 || configValue.GetIntValue() > 1024) { + if (configValue.GetIntValue() < MIN_CONNECTION_NUM || configValue.GetIntValue() > MAX_CONNECTION_NUM) { GLOGE("Check DB config failed, invalid maxConnNum value."); errCode = -E_INVALID_CONFIG_VALUE; return false; @@ -123,22 +145,22 @@ bool CheckMaxConnNumConfig(JsonObject config, int32_t &maxConnNum, int &errCode) return true; } -bool CheckBufferPoolSizeConfig(JsonObject config, int32_t pageSize, uint32_t &redoBufSize, +bool CheckBufferPoolSizeConfig(const JsonObject &config, int32_t pageSize, uint32_t &redoBufSize, int &errCode) { - static const JsonFieldPath bufferPoolSizeField = {"bufferPoolSize"}; + static const JsonFieldPath bufferPoolSizeField = {DB_CONFIG_BUFFER_POOL_SIZE}; if (!config.IsFieldExists(bufferPoolSizeField)) { return true; } - ValueObject configValue = config.GetObjectByPath(bufferPoolSizeField, errCode); // TODO: + ValueObject configValue = config.GetObjectByPath(bufferPoolSizeField, errCode); if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { - GLOGE("Check DB config failed, the field type of bufferPoolSize is not NUMBER. %d", errCode); + GLOGE("Check DB config failed, the field type of bufferPoolSize is not NUMBER."); errCode = -E_INVALID_CONFIG_VALUE; return false; } - if (configValue.GetIntValue() < 1024 && configValue.GetIntValue() > 4 * 1024 * 1024 || + if (configValue.GetIntValue() < MIN_BUFFER_POOL_SIZE || configValue.GetIntValue() > MAX_BUFFER_POOL_SIZE || configValue.GetIntValue() < pageSize * 33) { GLOGE("Check DB config failed, invalid bufferPoolSize value."); errCode = -E_INVALID_CONFIG_VALUE; @@ -149,16 +171,16 @@ bool CheckBufferPoolSizeConfig(JsonObject config, int32_t pageSize, uint32_t &re return true; } -bool CheckCrcCheckEnableConfig(JsonObject config, uint32_t &crcCheckEnable, int &errCode) +bool CheckCrcCheckEnableConfig(const JsonObject &config, uint32_t &crcCheckEnable, int &errCode) { - static const JsonFieldPath crcCheckEnableField = {"crcCheckEnable"}; + static const JsonFieldPath crcCheckEnableField = {DB_CONFIG_CRC_CHECK_ENABLE}; if (!config.IsFieldExists(crcCheckEnableField)) { return true; } - ValueObject configValue = config.GetObjectByPath(crcCheckEnableField, errCode); // TODO: + ValueObject configValue = config.GetObjectByPath(crcCheckEnableField, errCode); if (configValue.GetValueType() != ValueObject::ValueType::VALUE_NUMBER) { - GLOGE("Check DB config failed, the field type of crcCheckEnable is not NUMBER. %d", errCode); + GLOGE("Check DB config failed, the field type of crcCheckEnable is not NUMBER."); errCode = -E_INVALID_CONFIG_VALUE; return false; } @@ -173,6 +195,20 @@ bool CheckCrcCheckEnableConfig(JsonObject config, uint32_t &crcCheckEnable, int return true; } +bool CheckConfigSupport(const JsonObject &config, int &errCode) +{ + JsonObject child = config.GetChild(); + while (!child.IsNull()) { + std::string fieldName = child.GetItemFiled(); + if (std::find(DB_CONFIG.begin(), DB_CONFIG.end(), fieldName) == DB_CONFIG.end()) { + GLOGE("Invalid db config."); + errCode = -E_INVALID_CONFIG_VALUE; + return false; + } + child = child.GetNext(); + } + return true; +} } DBConfig DBConfig::ReadConfig(const std::string &confStr, int &errCode) @@ -181,17 +217,28 @@ DBConfig DBConfig::ReadConfig(const std::string &confStr, int &errCode) return {}; } - if (confStr.length() > MAX_DB_CONFIG_LEN) { + if (confStr.length() + 1 > MAX_DB_CONFIG_LEN) { GLOGE("Config json string is too long."); errCode = -E_OVER_LIMIT; return {}; } - JsonObject dbConfig = JsonObject::Parse(confStr, errCode); + + std::string lowerCaseConfStr = confStr; + std::transform(lowerCaseConfStr.begin(), lowerCaseConfStr.end(), lowerCaseConfStr.begin(), [](unsigned char c) { + return std::tolower(c); + }); + + JsonObject dbConfig = JsonObject::Parse(lowerCaseConfStr, errCode); if (errCode != E_OK) { GLOGE("Read DB config failed from str. %d", errCode); return {}; } + if (!CheckConfigSupport(dbConfig, errCode)) { + GLOGE("Check DB config, not support config item. %d", errCode); + return {}; + } + DBConfig conf; if (!CheckPageSizeConfig(dbConfig, conf.pageSize_, errCode)) { GLOGE("Check DB config 'pageSize' failed. %d", errCode); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp index d01e61d0..d3e4bb6e 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include #include "doc_common.h" @@ -21,6 +22,11 @@ namespace DocumentDB { namespace { +#define KEY_ID "_id" +constexpr const char *COLLECTION_PREFIX_GRD = "GRD_"; +constexpr const char *COLLECTION_PREFIX_GM_SYS = "GM_SYS_"; +const int MAX_COLLECTION_NAME = 512; + bool CheckCollectionNamePrefix(const std::string &name, const std::string &prefix) { if (name.length() < prefix.length()) { @@ -40,57 +46,62 @@ bool CheckCollectionNamePrefix(const std::string &name, const std::string &prefi } } -bool CheckCommon::CheckCollectionName(const std::string &collectionName) +bool CheckCommon::CheckCollectionName(const std::string &collectionName, std::string &lowerCaseName, int &errCode) { if (collectionName.empty()) { + errCode = -E_INVALID_ARGS; return false; } - if (collectionName.length() > 512) { + if (collectionName.length() + 1 > MAX_COLLECTION_NAME) { + errCode = -E_OVER_LIMIT; return false; } - if (CheckCollectionNamePrefix(collectionName, "GRD_") || CheckCollectionNamePrefix(collectionName, "GM_SYS_")) { + if (CheckCollectionNamePrefix(collectionName, COLLECTION_PREFIX_GRD) || + CheckCollectionNamePrefix(collectionName, COLLECTION_PREFIX_GM_SYS)) { + errCode = -E_INVALID_COLL_NAME_FORMAT; return false; } + lowerCaseName = collectionName; + std::transform(lowerCaseName.begin(), lowerCaseName.end(), lowerCaseName.begin(), [](unsigned char c){ + return std::tolower(c); + }); return true; } -bool CheckCommon::CheckFilter(const JsonObject *document) +bool CheckCommon::CheckFilter(JsonObject *filterObj) { - // if (JsonCommon::CheckIsJson(filter) == false) { - // return false; - // } - // if (JsonCommon::GetJsonDeep(filter) > 4) { - // return false; - // } - // if (CheckIdFormat(filter) == false) { - // return false; - // } + if (CheckIdFormat(filterObj) == false) { + return false; + } + if (filterObj->GetChild().GetNext().IsNull() != true) { + return false; + } return true; } -bool CheckCommon::CheckIdFormat(const std::string &data) +bool CheckCommon::CheckIdFormat(JsonObject *filterJson) { - // CjsonObject filter_json; - // filter_json.Parse(data); - // std::vector id; - // if (JsonCommon::GetIdValue(&filter_json, id) == E_ERROR) { - // return false; - // } + auto filterObjChild = filterJson->GetChild(); + auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); + if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { + return false; + } return true; } -bool CheckCommon::CheckDocument(const JsonObject *document) +bool CheckCommon::CheckDocument(JsonObject *documentObj) { - // if (CheckIdFormat(documentObj) == false) { - // return false; - // } - // JsonObject documentObjChild; - // if (documentObj->GetChild().IsNull() != true) { - // documentObjChild = documentObj->GetChild(); - // } - // if (JsonCommon::CheckJsonField(&documentObjChild) == false) { - // return false; - // } + if (CheckIdFormat(documentObj) == false) { + GLOGE("Document Id format is illegal"); + return false; + } + if (documentObj->GetChild().IsNull() != true) { + auto documentObjChild = documentObj->GetChild(); + if (JsonCommon::CheckJsonField(&documentObjChild) == false) { + GLOGE("Document json field format is illegal"); + return false; + } + } return true; } } // namespace DocumentDB \ 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 85d155fd..c775c006 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 @@ -13,6 +13,7 @@ * limitations under the License. */ #include +#include #include "json_common.h" #include "doc_errno.h" @@ -20,103 +21,98 @@ #include "securec.h" namespace DocumentDB { -ResultValue JsonCommon::GetValueByFiled(JsonObject *node, const std::string& filed) +ValueObject JsonCommon::GetValueByFiled(JsonObject *node, const std::string& filed) { if (node == nullptr) { - return ResultValue(); + return ValueObject(); } while (node != nullptr) { - int ret; - if (node->GetItemFiled(ret) == filed) - { + if (node->GetItemFiled() == filed) { auto itemValue = node->GetItemValue(); return itemValue; } if (node->GetNext().IsNull() == true) { - return ResultValue(); + return ValueObject(); } auto nodeNew = node->GetNext(); - nodeNew.Print(); node = &nodeNew; } - return ResultValue(); + return ValueObject(); } -int JsonCommon::CheckLeafNode(JsonObject *node, std::vector &leafValue) -{ +int JsonCommon::CheckLeafNode(JsonObject *node, std::vector &leafValue) +{ if (node->GetChild().IsNull() == true) { auto itemValue = node->GetItemValue(); leafValue.emplace_back(itemValue); } if (node->GetChild().IsNull() != true) { auto nodeNew = node->GetChild(); - nodeNew.Print(); CheckLeafNode(&nodeNew, leafValue); } if (node->GetNext().IsNull() != true) { auto nodeNew = node->GetNext(); - nodeNew.Print(); CheckLeafNode(&nodeNew, leafValue); } return E_OK; } -std::vector JsonCommon::GetLeafValue(JsonObject *node) +std::vector JsonCommon::GetLeafValue(JsonObject *node) { - std::vector leafValue; + std::vector leafValue; CheckLeafNode(node, leafValue); return leafValue; } -// bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, bool &errFlag) { -// if (errFlag == false) { -// return false; -// } -// std::string fieldName; -// if (node->IsNull() != true) { -// int ret; -// fieldName = node->GetItemFiled(ret); -// if (filedSet.find(fieldName) == filedSet.end()) { -// if (ret == E_OK) { -// filedSet.insert(fieldName); -// } -// if (ret == E_OK && fieldName == "") { -// errFlag = false; -// return false; -// } -// } -// else { -// errFlag = false; -// return false; -// } -// for (int i = 0; i < fieldName.size(); i++) { -// if (!(('a'<=fieldName[i] && fieldName[i]<='z')|| ('A'<=fieldName[i] && fieldName[i]<='Z') || ('0'<=fieldName[i] && fieldName[i]<='9') || '_' == fieldName[i])) { -// errFlag = false; -// return false; -// } -// if (i == 0 && ('0'<=fieldName[i] && fieldName[i]<='9')) { -// errFlag = false; -// return false; -// } -// } -// } -// if (node->GetChild().IsNull() != true) { -// auto nodeNew = node->GetChild(); -// std::set newFiledSet; -// CheckNode(&nodeNew, newFiledSet, errFlag); -// } -// if (node->GetNext().IsNull() != true) { -// auto nodeNew = node->GetNext(); -// CheckNode(&nodeNew, filedSet, errFlag); -// } -// return errFlag; -// } +bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, bool &errFlag) { + if (errFlag == false) { + return false; + } + std::string fieldName; + if (node->IsNull() != true) { + int ret; + fieldName = node->GetItemFiled(ret); + if (filedSet.find(fieldName) == filedSet.end()) { + if (ret == E_OK) { + filedSet.insert(fieldName); + } + if (ret == E_OK && fieldName == "") { + errFlag = false; + return false; + } + } + else { + errFlag = false; + return false; + } + for (int i = 0; i < fieldName.size(); i++) { + if (!(('a'<=fieldName[i] && fieldName[i]<='z')|| ('A'<=fieldName[i] && fieldName[i]<='Z') || ('0'<=fieldName[i] && fieldName[i]<='9') || '_' == fieldName[i])) { + errFlag = false; + return false; + } + if (i == 0 && ('0'<=fieldName[i] && fieldName[i]<='9')) { + errFlag = false; + return false; + } + } + } + if (node->GetChild().IsNull() != true) { + auto nodeNew = node->GetChild(); + std::set newFiledSet; + CheckNode(&nodeNew, newFiledSet, errFlag); + } + if (node->GetNext().IsNull() != true) { + auto nodeNew = node->GetNext(); + CheckNode(&nodeNew, filedSet, errFlag); + } + return errFlag; +} -// bool JsonCommon::CheckJsonField(JsonObject *jsonObj) { -// std::set filedSet; -// bool errFlag = true; -// return CheckNode(jsonObj, filedSet, errFlag); -// } +bool JsonCommon::CheckJsonField(JsonObject *jsonObj) { + std::set filedSet; + bool errFlag = true; + return CheckNode(jsonObj, filedSet, errFlag); +} int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor) { @@ -124,8 +120,7 @@ int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, if (isFirstFloor) { std::string tempParseName; std::vector allFiledsName; - int ret; - std::string priFieldName = node->GetItemFiled(ret); + std::string priFieldName = node->GetItemFiled(); for (int j = 0; j < priFieldName.size(); j++) { if (priFieldName[j] != '.') { tempParseName = tempParseName + priFieldName[j]; @@ -139,13 +134,11 @@ int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, singlePath.insert(singlePath.end(), allFiledsName.begin(), allFiledsName.end()); } else { std::vector allFiledsName; - int ret; - allFiledsName.emplace_back(node->GetItemFiled(ret)); + allFiledsName.emplace_back(node->GetItemFiled()); fatherPath = singlePath; singlePath.insert(singlePath.end(), allFiledsName.begin(), allFiledsName.end()); } - int ret; - if (node->GetChild().IsNull() != true && node->GetChild().GetItemFiled(ret) != "") { + if (node->GetChild().IsNull() != true && node->GetChild().GetItemFiled() != "") { auto nodeNew = node->GetChild(); ParseNode(&nodeNew, singlePath, resultPath, false); } @@ -159,9 +152,8 @@ int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, return 0; } -std::vector> JsonCommon::ParsePath(JsonObject* root) +std::vector> JsonCommon::ParsePath(const JsonObject* const root) { - std::vector> resultPath; auto projectionJson = root->GetChild(); if (projectionJson.IsNull() == true) { @@ -171,4 +163,97 @@ std::vector> JsonCommon::ParsePath(JsonObject* root) ParseNode(&projectionJson, singlePath, resultPath, true); return resultPath; } + +namespace { +JsonFieldPath ExpendPath(const JsonFieldPath &path, bool &isCollapse) +{ + if (path.size() > 1) { // only first lever has collapse field + return path; + } + 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); + return splitPath; +} + +void JsonObjectIterator(const JsonObject &obj, JsonFieldPath path, + std::function foo) +{ + JsonObject child = obj.GetChild(); + while(!child.IsNull()) { + JsonFieldPath childPath = path; + childPath.push_back(child.GetItemFiled()); + if (foo != nullptr && foo(childPath, obj, child)) { + JsonObjectIterator(child, childPath, foo); + } + child = child.GetNext(); + } + return; +} +} + +int JsonCommon::Append(const JsonObject &src, const JsonObject &add) +{ + int externErrCode = E_OK; + JsonObjectIterator(add, {}, + [&src, &externErrCode](const JsonFieldPath &path, const JsonObject &father, const JsonObject &item) { + bool isCollapse = false; + JsonFieldPath itemPath = ExpendPath(path, isCollapse); + JsonFieldPath fatherPath = itemPath; + fatherPath.pop_back(); + int errCode = E_OK; + if (src.IsFieldExists(itemPath)) { + JsonObject srcItem = src.FindItem(itemPath, errCode); + 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) { + srcItem.SetItemValue(item.GetItemValue()); + return false; // Both leaf node, no need iterate + } else if (srcItem.GetType() != item.GetType()) { + JsonObject srcFatherItem = src.FindItem(fatherPath, errCode); + if (errCode != E_OK) { + externErrCode = (externErrCode == E_OK ? errCode : externErrCode); + GLOGE("Find father item in source json object failed. %d", errCode); + return false; + } + srcFatherItem.DeleteItemFromObject(itemPath.back()); + srcFatherItem.AddItemToObject(itemPath.back(), item); + return false; // Different node types, overwrite directly, skip child node + } + return true; // Both array or object + } else { + if (isCollapse == true) { + GLOGE("Add collapse item to object failed, path not exist."); + externErrCode = -E_DATA_CONFLICT; + return false; + } + JsonObject srcFatherItem = src.FindItem(fatherPath, errCode); + if (errCode == E_OK) { + errCode = srcFatherItem.AddItemToObject(itemPath.back(), item); + if (errCode != E_OK) { + externErrCode = (externErrCode == E_OK ? errCode : externErrCode); + GLOGE("Add item to object failed. %d", errCode); + return false; + } + } else { + externErrCode = -E_DATA_CONFLICT; + GLOGE("Find father item in source json object failed. %d", errCode); + } + return false; // Source path not exist, overwrite directly, skip child node + } + }); + return externErrCode; +} } // namespace DocumentDB \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp index a50c30e0..31786a74 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/os_api.cpp @@ -26,6 +26,11 @@ namespace { const int ACCESS_MODE_EXISTENCE = 0; } namespace OSAPI { +bool CheckPermission(const std::string &filePath) +{ + return (access(filePath.c_str(), R_OK) == 0) && (access(filePath.c_str(), W_OK) == 0); +} + bool CheckPathExistence(const std::string &filePath) { return (access(filePath.c_str(), ACCESS_MODE_EXISTENCE) == 0); @@ -53,9 +58,7 @@ int GetRealPath(const std::string &inOriPath, std::string &outRealPath) delete []realPath; return -E_SYSTEM_API_FAIL; } - GLOGE("----> realpath: %s, %s", inOriPath.c_str(), realPath); outRealPath = std::string(realPath); - GLOGD("----> outRealPath: %s", outRealPath.c_str()); delete []realPath; return E_OK; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp index ca23460b..e6c954e3 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp @@ -26,11 +26,24 @@ using namespace DocumentDB; int GRD_DBOpen(const char *dbPath, const char *configStr, unsigned int flags, GRD_DB **db) { + if (db == nullptr || (*db) != nullptr) { + return GRD_INVALID_ARGS; + } std::string path = (dbPath == nullptr ? "" : dbPath); std::string config = (configStr == nullptr ? "" : configStr); DocumentStore *store = nullptr; int ret = DocumentStoreManager::GetDocumentStore(path, config, flags, store); + if (ret != E_OK || store == nullptr) { + return TrasnferDocErr(ret); + } + *db = new (std::nothrow) GRD_DB(); + if (*db == nullptr) { + (void)DocumentStoreManager::CloseDocumentStore(store, GRD_DB_CLOSE_IGNORE_ERROR); + store = nullptr; + ret = -E_OUT_OF_MEMORY; + } + (*db)->store_ = store; return TrasnferDocErr(ret); } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp index cdda85f8..bd23a4f5 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "grd_base/grd_error.h" #include "doc_errno.h" @@ -22,51 +23,31 @@ using namespace DocumentDB; -int TrasnferDocErrThird(int err) -{ - switch (err) { - case DocumentDB::E_OK: - return GRD_OK; - case DocumentDB::E_ERROR: - return GRD_INNER_ERR; - case DocumentDB::E_INVALID_ARGS: - return GRD_INVALID_ARGS; - // case DocumentDB::E_DATA_CONFLICT: - // return GRD_DATA_CONFLICT; - case DocumentDB::E_INVALID_JSON_FORMAT: - return GRD_INVALID_FORMAT; - case DocumentDB::E_OVER_LIMIT: - return GRD_OVER_LIMIT; - case DocumentDB::E_NO_DATA: - return GRD_NO_DATA; - default: - return GRD_INNER_ERR; - } -} - int GRD_Next(GRD_ResultSet *resultSet) { + std::mutex dbMutex; + std::lock_guard lock(dbMutex); int ret = resultSet->resultSet_->GetNext(); - return TrasnferDocErrThird(ret); + return TrasnferDocErr(ret); } int GRD_GetValue(GRD_ResultSet *resultSet, char **value) { - int ret = resultSet->resultSet_->GetValue(value); - return TrasnferDocErrThird(ret); + char *val = nullptr; + int ret = resultSet->resultSet_->GetValue(&val); + if (val == nullptr) { + return GRD_NO_DATA; + } + *value = val; + return TrasnferDocErr(ret); } int GRD_FreeValue(char *value) { - GLOGE("value is ==============>%s", value); if (value == nullptr) { return GRD_OK; } delete[] value; - value = nullptr;//为什么调用delete后,value的指针不为空。 - if (value != nullptr) { - GLOGE("delete fail"); - } return GRD_OK; } @@ -76,9 +57,5 @@ int GRD_FreeResultSet(GRD_ResultSet *resultSet) return GRD_OK; } delete[] resultSet; - resultSet = nullptr; - if (resultSet != nullptr) { - GLOGE("delete fail"); - } return GRD_OK; } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 14ea8c1d..f5deac52 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -79,7 +79,7 @@ int GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, unsigned int flags) { - if (db == nullptr || db->store_ == nullptr || filter == nullptr) { + if (db == nullptr || db->store_ == nullptr || filter == nullptr || collectionName == nullptr) { return GRD_INVALID_ARGS; } int ret = db->store_->DeleteDocument(collectionName, filter, flags); @@ -88,11 +88,18 @@ int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, un int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned int flags, GRD_ResultSet **resultSet) { - if (db == nullptr || db->store_ == nullptr) { + if (db == nullptr || db->store_ == nullptr || collectionName == nullptr || resultSet == nullptr) { return GRD_INVALID_ARGS; } - int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, resultSet[0]->resultSet_); - return TrasnferDocErr(ret); + GRD_ResultSet *tmp = new GRD_ResultSet(); + int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, tmp->resultSet_); + if (ret != E_OK) { + delete[] tmp; + return TrasnferDocErr(ret); + } + *resultSet = tmp; + return TrasnferDocErr(ret); + } int GRD_Flush(GRD_DB *db, unsigned int flags) 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 272eee25..b71feaae 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 @@ -23,7 +23,7 @@ namespace DocumentDB { class Collection { public: - Collection(std::string name, KvStoreExecutor *executor); + Collection(const std::string &name, KvStoreExecutor *executor); ~Collection(); int PutDocument(const Key &key, const Value &document); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h index e6ed94b0..6c80c693 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h @@ -32,6 +32,8 @@ constexpr int E_NOT_FOUND = E_BASE + 14; constexpr int E_COLLECTION_CONFLICT = E_BASE + 15; constexpr int E_NO_DATA = E_BASE + 16; constexpr int E_NOT_PERMIT = E_BASE + 17; +constexpr int E_DATA_CONFLICT = E_BASE + 18; +constexpr int E_INVALID_COLL_NAME_FORMAT = E_BASE + 18; constexpr int E_INVALID_JSON_FORMAT = E_BASE + 40; constexpr int E_JSON_PATH_NOT_EXISTS = E_BASE + 41; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h index 69cf3c60..f51a77a1 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h @@ -18,6 +18,7 @@ #include #include +#include #include "collection.h" #include "kv_store_executor.h" @@ -39,6 +40,8 @@ public: int FindDocument(GRD_DB* db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet); private: int GetViewType(JsonObject *jsonObj, bool &viewType); + std::mutex dbMutex_; + KvStoreExecutor *executor_ = nullptr; std::map collections_; }; 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 a266f983..63d7d3fd 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 @@ -40,13 +40,13 @@ public: private: int CutString(std::string &jsonData); int CheckCutNode(JsonObject *node, std::vector singlePath, std::vector> &allPath); - Collection* coll_; + Collection* coll_ = nullptr; std::string key_; - bool ifShowId_; - bool viewType_; - ProjectionTree* projectionTree_; + bool ifShowId_ = false; + bool viewType_ = false; + ProjectionTree* projectionTree_ = nullptr; std::vector> path_; - int index_; + int index_ = 0; std::vector findValue_; }; } // DocumentDB 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 e6192c35..f0f86cf7 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 @@ -14,13 +14,21 @@ */ #include "collection.h" + +#include + #include "doc_common.h" #include "doc_errno.h" #include "log_print.h" namespace DocumentDB { -Collection::Collection(std::string name, KvStoreExecutor *executor) : name_(COLL_PREFIX + name), executor_(executor) +Collection::Collection(const std::string &name, KvStoreExecutor *executor) : executor_(executor) { + std::string lowerCaseName = name; + std::transform(lowerCaseName.begin(), lowerCaseName.end(), lowerCaseName.begin(), [](unsigned char c) { + return std::tolower(c); + }); + name_ = COLL_PREFIX + lowerCaseName; } Collection::~Collection() @@ -69,6 +77,12 @@ int Collection::UpsertDocument(const std::string &id, const std::string &documen return -E_NO_DATA; } + JsonObject upsertValue = JsonObject::Parse(document, errCode); + if (errCode != E_OK) { + GLOGD("Parse upsert value failed. %d", errCode); + return errCode; + } + Key keyId(id.begin(), id.end()); Value valSet(document.begin(), document.end()); @@ -83,10 +97,16 @@ int Collection::UpsertDocument(const std::string &id, const std::string &documen } else if (errCode == E_OK) { // document has been inserted GLOGD("Document has been inserted, append value."); JsonObject originValue = JsonObject::Parse(valueGotStr, errCode); + if (errCode != E_OK) { + GLOGD("Parse original value failed. %d %s", errCode, valueGotStr.c_str()); + return errCode; + } - JsonObject upsertValue = JsonObject::Parse(document, errCode); - - // TOOD:: Join document and update valSet + errCode = JsonCommon::Append(originValue, upsertValue); + if (errCode != E_OK) { + GLOGD("Append value failed. %d", errCode); + return errCode; + } } } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp index 093c04e1..9cedce6a 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp @@ -17,29 +17,52 @@ #include "grd_base/grd_error.h" namespace DocumentDB { +int GetErrorCategory(int errCode) +{ + int categoryCode = errCode % 1000000; + categoryCode /= 1000; + categoryCode *= 1000; + return categoryCode; +} + int TrasnferDocErr(int err) { + int outErr = GRD_OK; switch (err) { case E_OK: return GRD_OK; case -E_ERROR: - return GRD_INNER_ERR; + outErr = GRD_INNER_ERR; + break; case -E_INVALID_ARGS: - return GRD_INVALID_ARGS; + outErr = GRD_INVALID_ARGS; + break; case -E_FILE_OPERATION: - return GRD_FAILED_FILE_OPERATION; + outErr = GRD_FAILED_FILE_OPERATION; + break; case -E_OVER_LIMIT: - return GRD_OVER_LIMIT; + outErr = GRD_OVER_LIMIT; + break; case -E_INVALID_JSON_FORMAT: - return GRD_INVALID_JSON_FORMAT; + outErr = GRD_INVALID_JSON_FORMAT; + break; case -E_INVALID_CONFIG_VALUE: - return GRD_INVALID_CONFIG_VALUE; + outErr = GRD_INVALID_CONFIG_VALUE; + break; case -E_COLLECTION_CONFLICT: - return GRD_COLLECTION_CONFLICT; + outErr = GRD_COLLECTION_CONFLICT; + break; case -E_NO_DATA: - return GRD_NO_DATA; + outErr = GRD_NO_DATA; + break; + case -E_INVALID_COLL_NAME_FORMAT: + outErr = GRD_INVALID_COLLECTION_NAME; + break; default: - return GRD_INNER_ERR; + outErr = GRD_INNER_ERR; + break; } + + return GetErrorCategory(outErr); } } \ No newline at end of file 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 ca7f8db4..02a1459d 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 @@ -14,7 +14,6 @@ */ #include "document_store.h" -#include "grd_format_config.h" #include "collection_option.h" #include "doc_common.h" #include "doc_errno.h" @@ -22,6 +21,10 @@ #include "log_print.h" namespace DocumentDB { +#define COLLECTION_LENS_MAX (512 * 1024) +#define JSON_LENS_MAX (512 * 1024) +#define JSON_DEEP_MAX (4) +#define KEY_ID "_id" DocumentStore::DocumentStore(KvStoreExecutor *executor) : executor_(executor) { } @@ -33,33 +36,36 @@ DocumentStore::~DocumentStore() int DocumentStore::CreateCollection(const std::string &name, const std::string &option, int flags) { - if (!CheckCommon::CheckCollectionName(name)) { - GLOGE("Check collection name invalid."); - return -E_INVALID_ARGS; + std::string lowerCaseName; + int errCode = E_OK; + if (!CheckCommon::CheckCollectionName(name, lowerCaseName, errCode)) { + GLOGE("Check collection name invalid. %d", errCode); + return errCode; } - int errCode = E_OK; + errCode = E_OK; CollectionOption collOption = CollectionOption::ReadOption(option, errCode); if (errCode != E_OK) { GLOGE("Read collection option str failed. %d", errCode); return errCode; } - if (flags != 0 && flags != IGNORE_EXIST_TABLE) { + if (flags != 0 && flags != CHK_EXIST_COLLECTION) { GLOGE("Check flags invalid."); return -E_INVALID_ARGS; } - bool ignoreExists = (flags == IGNORE_EXIST_TABLE); - errCode = executor_->CreateCollection(name, ignoreExists); + std::lock_guard lock(dbMutex_); + bool ignoreExists = (flags != CHK_EXIST_COLLECTION); + errCode = executor_->CreateCollection(lowerCaseName, ignoreExists); if (errCode != E_OK) { GLOGE("Create collection failed. %d", errCode); return errCode; } std::string oriOptStr; - errCode = executor_->GetCollectionOption(name, oriOptStr); + errCode = executor_->GetCollectionOption(lowerCaseName, oriOptStr); if (errCode == -E_NOT_FOUND) { - executor_->SetCollectionOption(name, collOption.ToString()); + executor_->SetCollectionOption(lowerCaseName, collOption.ToString()); errCode = E_OK; } else { CollectionOption oriOption = CollectionOption::ReadOption(oriOptStr, errCode); @@ -74,24 +80,27 @@ int DocumentStore::CreateCollection(const std::string &name, const std::string & int DocumentStore::DropCollection(const std::string &name, int flags) { - if (!CheckCommon::CheckCollectionName(name)) { - GLOGE("Check collection name invalid."); - return -E_INVALID_ARGS; + std::string lowerCaseName; + int errCode = E_OK; + if (!CheckCommon::CheckCollectionName(name, lowerCaseName, errCode)) { + GLOGE("Check collection name invalid. %d", errCode); + return errCode; } - if (flags != 0 && flags != IGNORE_NON_EXIST_TABLE) { + if (flags != 0 && flags != CHK_NON_EXIST_COLLECTION) { GLOGE("Check flags invalid."); return -E_INVALID_ARGS; } - bool ignoreNonExists = (flags == IGNORE_NON_EXIST_TABLE); - int errCode = executor_->DropCollection(name, ignoreNonExists); + bool ignoreNonExists = (flags == CHK_NON_EXIST_COLLECTION); + errCode = executor_->DropCollection(lowerCaseName, ignoreNonExists); if (errCode != E_OK) { GLOGE("Drop collection failed. %d", errCode); return errCode; } - errCode = executor_->CleanCollectionOption(name); + std::lock_guard lock(dbMutex_); + errCode = executor_->CleanCollectionOption(lowerCaseName); if (errCode != E_OK) { GLOGE("Clean collection option failed. %d", errCode); } @@ -108,9 +117,11 @@ int DocumentStore::UpdateDocument(const std::string &collection, const std::stri int DocumentStore::UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flags) { - if (!CheckCommon::CheckCollectionName(collection)) { - GLOGE("Check collection name invalid."); - return -E_INVALID_ARGS; + std::string lowerCaseCollName; + int errCode = E_OK; + if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { + GLOGE("Check collection name invalid. %d", errCode); + return errCode; } // TODO:: check filter @@ -122,97 +133,123 @@ int DocumentStore::UpsertDocument(const std::string &collection, const std::stri return -E_INVALID_ARGS; } - auto coll = Collection(collection, executor_); + auto coll = Collection(lowerCaseCollName, executor_); std::string docId(filter.begin(), filter.end()); bool isReplace = (flags & GRD_DOC_REPLACE == GRD_DOC_REPLACE); + + std::lock_guard lock(dbMutex_); return coll.UpsertDocument(docId, document, isReplace); } int DocumentStore::InsertDocument(const std::string &collection, const std::string &document, int flag) { - if (!CheckCommon::CheckCollectionName(collection)) { - GLOGE("Check collection name invalid."); - return -E_INVALID_ARGS; + std::string lowerCaseCollName; + int errCode = E_OK; + if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { + GLOGE("Check collection name invalid. %d", errCode); + return errCode; } auto coll = Collection(collection, executor_); if (document.length() + 1 > JSON_LENS_MAX) { - return E_OVER_LIMIT; + GLOGE("document's length is larger than JSON_LENS_MAX"); + return -E_OVER_LIMIT; } int errCode1; JsonObject documentObj = JsonObject::Parse(document, errCode1); if (errCode1 != E_OK) { + GLOGE("Document Parsed faild"); return errCode1; } if (!CheckCommon::CheckDocument(&documentObj) || flag != 0) { - return E_INVALID_ARGS; + GLOGE("Document format unvalid"); + return -E_INVALID_ARGS; } auto documentObjChild = documentObj.GetChild(); auto idValue = JsonCommon::GetValueByFiled(&documentObjChild, KEY_ID); - if (idValue.GetValueType() != ResultValue::ValueType::VALUE_STRING) { - return E_INVALID_ARGS; + if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { + GLOGE("Id value is not string"); + return -E_INVALID_ARGS; } std::string id = idValue.GetStringValue(); Key key(id.begin(), id.end()); Value value(document.begin(), document.end()); + std::lock_guard lock(dbMutex_); return coll.PutDocument(key, value); } int DocumentStore::DeleteDocument(const std::string &collection, const std::string &filter, int flag) { - if (!CheckCommon::CheckCollectionName(collection)) { - GLOGE("Check collection name invalid."); - return -E_INVALID_ARGS; + std::string lowerCaseCollName; + int errCode = E_OK; + if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { + GLOGE("Check collection name invalid. %d", errCode); + return errCode; } auto coll = Collection(collection, executor_); int errCode1; + if (filter == "") { + GLOGE("Filter is empty"); + return -E_INVALID_ARGS; + } JsonObject filterObj = JsonObject::Parse(filter, errCode1); if (errCode1 != E_OK) { + GLOGE("filter Parsed faild"); return errCode1; } if (!CheckCommon::CheckFilter(&filterObj) || flag != 0) { - return E_INVALID_ARGS; + GLOGE("Filter format is illegal"); + return -E_INVALID_ARGS; } auto filterObjChild = filterObj.GetChild(); auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); - if (idValue.GetValueType() != ResultValue::ValueType::VALUE_STRING) { - return E_INVALID_ARGS; + if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { + GLOGE("Id value is not string"); + return -E_INVALID_ARGS; } std::string id = idValue.GetStringValue(); Key key(id.begin(), id.end()); + std::lock_guard lock(dbMutex_); return coll.DeleteDocument(key); } int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet) { - if (!CheckCommon::CheckCollectionName(collection)) { - GLOGE("Check collection name invalid."); - return -E_INVALID_ARGS; + std::string lowerCaseCollName; + int errCode = E_OK; + if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { + GLOGE("Check collection name invalid. %d", errCode); + return errCode; } int errCode1; JsonObject filterObj = JsonObject::Parse(filter, errCode1); if (errCode1 != E_OK) { + GLOGE("filter Parsed faild"); return errCode1; } if (!CheckCommon::CheckFilter(&filterObj)) { - return E_INVALID_ARGS; + GLOGE("Filter format is illegal"); + return -E_INVALID_ARGS; } auto filterObjChild = filterObj.GetChild(); auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); - if (idValue.GetValueType() != ResultValue::ValueType::VALUE_STRING) { - return E_INVALID_ARGS; + if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { + GLOGE("Id value is not string"); + return -E_INVALID_ARGS; } std::string filterId = idValue.GetStringValue(); int errCode2; JsonObject projectionObj = JsonObject::Parse(projection, errCode2); if (errCode2 != E_OK) { + GLOGE("projection Parsed faild"); return errCode2; } bool viewType = false; std::vector> allPath; if (projection != "{}") { if (GetViewType(&projectionObj, viewType) != E_OK) { - return E_INVALID_ARGS; + GLOGE("GetViewType faild"); + return -E_INVALID_ARGS; } allPath = JsonCommon::ParsePath(&projectionObj); } @@ -221,17 +258,16 @@ int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const ifShowId = true; } Collection coll = Collection(collection, executor_); - resultSet->Init(coll, filterId, allPath, ifShowId, viewType); - return E_OK; + return resultSet->Init(coll, filterId, allPath, ifShowId, viewType); } int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { auto leafValue = JsonCommon::GetLeafValue(jsonObj); if (leafValue.size() == 0) { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } switch (leafValue[0].GetValueType()) { - case ResultValue::ValueType::VALUE_BOOL: + case ValueObject::ValueType::VALUE_BOOL: if (leafValue[0].GetBoolValue()) { viewType = true; } @@ -239,15 +275,15 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { viewType = false; } break; - case ResultValue::ValueType::VALUE_STRING: + case ValueObject::ValueType::VALUE_STRING: if (leafValue[0].GetStringValue() == "") { viewType = true; } else { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } break; - case ResultValue::ValueType::VALUE_NUMBER: + case ValueObject::ValueType::VALUE_NUMBER: if (leafValue[0].GetIntValue() == 0) { viewType = false; } @@ -256,14 +292,14 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { } break; default: - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } for (int i = 1; i < leafValue.size(); i++) { switch (leafValue[i].GetValueType()) { - case ResultValue::ValueType::VALUE_BOOL: + case ValueObject::ValueType::VALUE_BOOL: if (leafValue[i].GetBoolValue()) { if (viewType != true) { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } } else { @@ -272,20 +308,20 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { } } break; - case ResultValue::ValueType::VALUE_STRING: + case ValueObject::ValueType::VALUE_STRING: if (leafValue[i].GetStringValue() == "") { if (viewType != false) { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } } else { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } break; - case ResultValue::ValueType::VALUE_NUMBER: + case ValueObject::ValueType::VALUE_NUMBER: if (leafValue[i].GetIntValue() == 0) { if (viewType != false) { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } } else { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp index 7078536b..1c0b306f 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp @@ -34,6 +34,14 @@ bool CheckDBCloseFlag(unsigned int flag) { return (flag == GRD_DB_CLOSE) || (flag == GRD_DB_CLOSE_IGNORE_ERROR); } + +bool CheckDBCreate(unsigned int flags, const std::string &path) +{ + if ((flags & GRD_DB_OPEN_CREATE) == 0 && !OSAPI::CheckPathExistence(path)) { + return false; + } + return true; +} } int DocumentStoreManager::GetDocumentStore(const std::string &path, const std::string &config, unsigned int flags, @@ -58,6 +66,11 @@ int DocumentStoreManager::GetDocumentStore(const std::string &path, const std::s return -E_INVALID_ARGS; } + if (!CheckDBCreate(flags, path)) { + GLOGE("Open db failed, file no exists."); + return -E_INVALID_ARGS; + } + KvStoreExecutor *executor = nullptr; errCode = KvStoreManager::GetKvStore(canonicalPath + "/" + dbName, dbConfig, executor); if (errCode != E_OK) { @@ -109,8 +122,12 @@ bool DocumentStoreManager::CheckDBPath(const std::string &path, std::string &can return false; } - GLOGD("----> path: %s, dirPath: %s, dbName: %s, canonicalPath: %s", path.c_str(), dirPath.c_str(), dbName.c_str(), - canonicalPath.c_str()); + if (!OSAPI::CheckPermission(canonicalPath)) { + GLOGE("Check path permission failed. %d", errCode); + errCode = -E_FILE_OPERATION; + return false; + } + return true; } 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 67412a02..368ae846 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 @@ -14,10 +14,9 @@ */ #include "result_set.h" #include "log_print.h" -#include "grd_format_config.h" namespace DocumentDB { - +#define KEY_ID "_id" ResultSet::~ResultSet() { GLOGE("delte ResultSet"); @@ -30,12 +29,16 @@ int ResultSet::Init(Collection &coll, const std::string &key, std::vectorInit(); if (projectionTree->ParseTree(path) == E_INVALID_ARGS) { - return E_INVALID_ARGS; + GLOGE("Parse ProjectionTree failed"); + delete[] coll_; + delete[] projectionTree; + return -E_INVALID_ARGS; } projectionTree_ = projectionTree; ifShowId_ = ifShowId; viewType_ = viewType; findValue_.reserve(1 + 1); + return E_OK; } int ResultSet::GetNext() @@ -46,12 +49,14 @@ int ResultSet::GetNext() } Value document; if (key_ == "") { - return E_NO_DATA; + GLOGE("key_ is empty"); + return -E_NO_DATA; } Key key(key_.begin(), key_.end()); coll_->GetDocument(key, document); if (document.size() == 0) { - return E_NO_DATA; + GLOGE("Cant get value from db"); + return -E_NO_DATA; } std::string jsonData(document.begin(), document.end()); CutString(jsonData); @@ -62,10 +67,12 @@ int ResultSet::GetNext() int ResultSet::GetValue(char **value) { if (findValue_.size() == 0) { - return E_NO_DATA; + return -E_NO_DATA; } auto jsonData = findValue_.back(); - errno_t err = strcpy_s(value[0], jsonData.size() + 1, jsonData.c_str()); + char *tmp = new char[jsonData.size() + 1]; + errno_t err = strcpy_s(tmp, jsonData.size() + 1, jsonData.c_str()); + *value = tmp; if (err != 0) { GLOGE("strcpy_s failed"); } @@ -77,8 +84,7 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat if (node == nullptr) { return E_OK; } - int ret; - singlePath.emplace_back(node->GetItemFiled(ret)); + singlePath.emplace_back(node->GetItemFiled()); int index = 0; if (projectionTree_ == nullptr) { GLOGE("======>projectionTree_ is null"); @@ -103,6 +109,7 @@ int ResultSet::CutString(std::string &jsonData) int errCode; JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode); if (errCode != E_OK) { + GLOGE("jsonData Parsed faild"); return errCode; } std::vector> allPath; 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 02a7262b..d0d8bbb2 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 @@ -27,7 +27,6 @@ namespace DocumentDB { class ValueObject { public: enum class ValueType { - // VALUE_INVALID = -1, VALUE_NULL = 0, VALUE_BOOL, VALUE_NUMBER, @@ -42,7 +41,7 @@ public: ValueType GetValueType() const; bool GetBoolValue() const; - int GetIntValue() const; + int64_t GetIntValue() const; double GetDoubleValue() const; std::string GetStringValue() const; @@ -54,45 +53,53 @@ private: }; std::string stringValue; }; - -using ResultValue = ValueObject; using JsonFieldPath = std::vector; class JsonObject { public: static JsonObject Parse(const std::string &jsonStr, int &errCode, bool caseSensitive = false); - //JsonObject(const JsonObject &obj); ~JsonObject (); - int Init(const std::string &str); - - std::string Print(); + std::string Print() const; JsonObject GetObjectItem(const std::string &field, int &errCode); JsonObject GetArrayItem(int index, int &errCode); - JsonObject GetNext(); - JsonObject GetChild(); + JsonObject GetNext() const; + JsonObject GetChild() const; int DeleteItemFromObject(const std::string &field); + int AddItemToObject(const JsonObject &item); + int AddItemToObject(const std::string &fieldName, const JsonObject &item); ValueObject GetItemValue() const; + void SetItemValue(const ValueObject &value) const; + + std::string GetItemFiled() const; std::string GetItemFiled(int &errCode) const; bool IsFieldExists(const JsonFieldPath &jsonPath) const; JsonObject FindItem(const JsonFieldPath &jsonPath, int &errCode) const; ValueObject GetObjectByPath(const JsonFieldPath &jsonPath, int &errCode) const; int DeleteItemOnTarget(const JsonFieldPath &path); - bool IsNull(); + bool IsNull() const; + + enum class Type { + JSON_LEAF, + JSON_OBJECT, + JSON_ARRAY + }; + Type GetType() const; private: JsonObject(); + int Init(const std::string &str); int GetDeep(cJSON *cjson); int CheckNumber(cJSON *cjson, int &errCode); - cJSON *cjson_; + cJSON *cjson_ = nullptr; bool isOwner_ = false; bool caseSensitive_ = false; }; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.cpp deleted file mode 100644 index 5841c2dc..00000000 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.cpp +++ /dev/null @@ -1,211 +0,0 @@ -// /* -// * 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 "doc_errno.h" -// #include "cjson_object.h" -// #include "log_print.h" - -// namespace DocumentDB { -// int CjsonObject::Parse(const std::string &str) -// { -// cjson_ = cJSON_Parse(str.c_str()); -// if (cjson_ == nullptr) { -// GLOGE("json parse failed."); -// return -E_INVALID_JSON_FORMAT; -// } -// return E_OK; -// } - -// std::string CjsonObject::Print() -// { -// if (cjson_ == nullptr) { -// GLOGE("======================>NULL"); -// return ""; -// } -// char *ret = cJSON_Print(cjson_); -// std::string str = ret; -// free(ret); -// GLOGE("======================>%s", str.c_str()); -// return str; -// } - -// CjsonObject* CjsonObject::GetObjectItem(const std::string &field) -// { -// if (cjson_ == nullptr) { -// return nullptr; -// } -// CjsonObject *item = new CjsonObject(); -// auto cjson_item = cJSON_GetObjectItem(cjson_, field.c_str()); -// if (cjson_item == nullptr) { -// return item; -// } -// item->cjson_ = cjson_item; -// return item; -// } - -// CjsonObject* CjsonObject::GetArrayItem(const int index) -// { -// if (cjson_ == nullptr) { -// return nullptr; -// } -// CjsonObject *item = new CjsonObject(); -// auto cjson_item = cJSON_GetArrayItem(cjson_, index); -// if (cjson_item == nullptr) { -// return item; -// } -// item->cjson_ = cjson_item; -// return item; -// } - -// CjsonObject* CjsonObject::GetNext() -// { -// if (cjson_ == nullptr) { -// return nullptr; -// } -// CjsonObject *next = new CjsonObject(); -// if (cjson_->next == nullptr) { -// return next; -// } -// next->cjson_ = cjson_->next; -// return next; -// } - -// CjsonObject* CjsonObject::GetChild() -// { -// if (cjson_ == nullptr) { -// return nullptr; -// } -// CjsonObject *child = new CjsonObject(); -// if (cjson_->child == nullptr) { -// return child; -// } -// child->cjson_ = cjson_->child; -// return child; -// } - -// int CjsonObject::DeleteItemFromObject(const std::string &field) -// { -// if (field == "") { -// return E_OK; -// } -// cJSON_DeleteItemFromObject(cjson_, field.c_str()); -// return E_OK; -// } - -// ResultValue* CjsonObject::GetItemValue() -// { -// if (cjson_ == nullptr) { -// return nullptr; -// } -// ResultValue* value = new ResultValue(); -// switch (cjson_->type) -// { -// case cJSON_False: -// { -// value->value_type = ResultValue::ValueType::VALUE_FALSE; -// } -// break; -// case cJSON_True: -// { -// value->value_type = ResultValue::ValueType::VALUE_TRUE; -// } -// break; -// case cJSON_NULL: -// { -// value->value_type = ResultValue::ValueType::VALUE_NULL; -// } -// break; -// case cJSON_Number: -// { -// value->value_type = ResultValue::ValueType::VALUE_NUMBER; -// value->value_number = cjson_->valuedouble; -// } -// break; -// case cJSON_String: -// { -// value->value_type = ResultValue::ValueType::VALUE_STRING; -// value->value_string = cjson_->valuestring; -// } -// break; -// case cJSON_Array: -// { -// value->value_type = ResultValue::ValueType::VALUE_ARRAY; -// value->value_Object = GetChild(); -// } -// break; -// case cJSON_Object: -// { -// value->value_type = ResultValue::ValueType::VALUE_OBJECT; -// value->value_Object = GetChild(); -// } -// break; -// default: -// break; -// } -// return value; -// } - -// std::string CjsonObject::GetItemFiled() -// { -// if (cjson_ == nullptr) { -// GLOGE("cjson is null"); -// return ""; -// } -// if (cjson_->string == nullptr) { -// GLOGE("cjson string is null"); -// return ""; -// } -// return cjson_->string; -// } - -// int CjsonObject::Delete() -// { -// if (cjson_ != nullptr) { -// cJSON_Delete(cjson_); -// } -// return E_OK; -// } - -// bool CjsonObject::IsFieldExists(const JsonFieldPath &path) -// { -// cJSON *item = cjson_; -// for (const auto &field : path) { -// item = cJSON_GetObjectItem(item, field.c_str()); // TODO: parse array -// if (item == nullptr) { -// return false; -// } -// } -// return true; -// } - -// int CjsonObject::GetObjectByPath(const JsonFieldPath &path, ValueObject &obj) -// { -// cJSON *item = cjson_; -// for (const auto &field : path) { -// item = cJSON_GetObjectItem(item, field.c_str()); // TODO: parse array -// if (item == nullptr) { -// GLOGE("Invalid json field path. %s", field.c_str()); -// return -E_JSON_PATH_NOT_EXISTS; -// } -// } - -// if (item->type == cJSON_Number) { -// obj.valueType = ValueObject::ValueType::VALUE_NUMBER; -// obj.intValue = item->valueint; -// } - -// return E_OK; -// } -// } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.h deleted file mode 100644 index 398e45dd..00000000 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/cjson_object.h +++ /dev/null @@ -1,47 +0,0 @@ -// /* -// * 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 CJSON_OBJECT_H -// #define CJSON_OBJECT_H - -// #include -// #include "cJSON.h" -// #include "json_object.h" - -// namespace DocumentDB { -// class CjsonObject : public JsonObject{ -// public: -// CjsonObject () = default; -// virtual ~CjsonObject () = default; - -// int Parse(const std::string &str) override; -// std::string Print() override; -// CjsonObject* GetObjectItem(const std::string &field) override; -// CjsonObject* GetArrayItem(const int index) override; -// CjsonObject* GetNext(); -// CjsonObject* GetChild(); -// int DeleteItemFromObject(const std::string &field) override; -// ResultValue* GetItemValue() override; -// std::string GetItemFiled() override; -// int Delete() override; - -// bool IsFieldExists(const JsonFieldPath &path) override; -// int GetObjectByPath(const JsonFieldPath &path, ValueObject &obj) override; -// private: -// cJSON *cjson_; -// }; -// } // DocumentDB -// #endif // CJSON_OBJECT_H - 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 c72237e0..ea151d93 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 @@ -17,14 +17,20 @@ #include #include "doc_errno.h" #include "log_print.h" -// #include "grd_format_config.h" namespace DocumentDB { namespace { -#define COLLECTION_LENS_MAX (512) -#define JSON_LENS_MAX (512) +#define COLLECTION_LENS_MAX (512 * 1024) +#define JSON_LENS_MAX (512 * 1024) #define JSON_DEEP_MAX (4) + +bool IsNumber(const std::string &str) +{ + return std::all_of(str.begin(), str.end(), [](char c) { + return std::isdigit(c); + }); +} } ValueObject::ValueObject(bool val) @@ -61,9 +67,9 @@ bool ValueObject::GetBoolValue() const return boolValue; } -int ValueObject::GetIntValue() const +int64_t ValueObject::GetIntValue() const { - return static_cast(doubleValue + 0.5); + return static_cast(doubleValue + 0.5); } double ValueObject::GetDoubleValue() const @@ -89,13 +95,6 @@ JsonObject::JsonObject() cjson_ = nullptr; } -// JsonObject::JsonObject(const JsonObject &obj) -// { -// this->cjson_ = cJSON_Duplicate(obj.cjson_, true); -// this->isOwner_ = true; -// this->caseSensitive_ = obj.caseSensitive_; -// } - JsonObject::~JsonObject() { if (isOwner_ == true) { @@ -103,7 +102,7 @@ JsonObject::~JsonObject() } } -bool JsonObject::IsNull() +bool JsonObject::IsNull() const { if (cjson_ == nullptr) { return true; @@ -111,10 +110,20 @@ bool JsonObject::IsNull() return false; } +JsonObject::Type JsonObject::GetType() const +{ + if (cjson_->type == cJSON_Object) { + return JsonObject::Type::JSON_OBJECT; + } else if (cjson_->type == cJSON_Array) { + return JsonObject::Type::JSON_ARRAY; + } + return JsonObject::Type::JSON_LEAF; +} + int JsonObject::GetDeep(cJSON *cjson) { if (cjson->child == nullptr) { - return 1; // leaf node + return 0; // leaf node } int depth = -1; @@ -146,36 +155,45 @@ int JsonObject::CheckNumber(cJSON *item, int &errCode) int JsonObject::Init(const std::string &str) { if (str.length() + 1 > JSON_LENS_MAX) { + GLOGE("lens is ========>%d", str.length()); + GLOGE("str's length is longer than JSON_LENS_MAX"); return -E_INVALID_ARGS; } const char *end = NULL; isOwner_ = true; cjson_ = cJSON_ParseWithOpts(str.c_str(), &end, true); if (cjson_ == nullptr) { - return -E_INVALID_ARGS; + GLOGE("Json's format is wrong"); + return -E_INVALID_JSON_FORMAT; } + if (cjson_->type != cJSON_Object) { + GLOGE("after Parse,cjson_'s type is not cJSON_Object"); return -E_INVALID_ARGS; } + if (GetDeep(cjson_) > JSON_DEEP_MAX) { + GLOGE("Deep is ======>%d", GetDeep(cjson_)); + GLOGE("Deep is longer than JSON_DEEP_MAX"); return -E_INVALID_ARGS; } int ret; CheckNumber(cjson_, ret); if (ret == E_INVALID_ARGS) { - return E_INVALID_ARGS; + GLOGE("Int value is larger than double"); + return -E_INVALID_ARGS; } return E_OK; } -std::string JsonObject::Print() +std::string JsonObject::Print() const { if (cjson_ == nullptr) { return ""; } char *ret = cJSON_PrintUnformatted(cjson_); std::string str = ret; - free(ret); + cJSON_free(ret); return str; } @@ -215,7 +233,7 @@ JsonObject JsonObject::GetArrayItem(int index, int &errCode) return item; } -JsonObject JsonObject::GetNext() +JsonObject JsonObject::GetNext() const { if (cjson_ == nullptr) { return JsonObject(); @@ -229,7 +247,7 @@ JsonObject JsonObject::GetNext() return next; } -JsonObject JsonObject::GetChild() +JsonObject JsonObject::GetChild() const { if (cjson_ == nullptr) { return JsonObject(); @@ -252,6 +270,42 @@ int JsonObject::DeleteItemFromObject(const std::string &field) return E_OK; } +int JsonObject::AddItemToObject(const JsonObject &item) +{ + if (item.IsNull()) { + GLOGD("Add null object."); + return E_OK; + } + + cJSON *cpoyItem = cJSON_Duplicate(item.cjson_, true); + cJSON_AddItemToObject(cjson_, item.GetItemFiled().c_str(), cpoyItem); + return E_OK; +} + +int JsonObject::AddItemToObject(const std::string &fieldName, const JsonObject &item) +{ + if (item.IsNull()) { + GLOGD("Add null object."); + return E_OK; + } + // TODO: check item exist + if (cjson_->type == cJSON_Array) { + int n = 0; + cJSON *child = cjson_->child; + while (child != nullptr) { + child = child->next; + n++; + } + if (IsNumber(fieldName) && n <= std::stoi(fieldName)) { + GLOGE("Add item object to array over size."); + return -E_DATA_CONFLICT; + } + } + cJSON *cpoyItem = cJSON_Duplicate(item.cjson_, true); + cJSON_AddItemToObject(cjson_, fieldName.c_str(), cpoyItem); + return E_OK; +} + ValueObject JsonObject::GetItemValue() const { if (cjson_ == nullptr) { @@ -279,6 +333,47 @@ ValueObject JsonObject::GetItemValue() const return value; } +void JsonObject::SetItemValue(const ValueObject &value) const +{ + if (cjson_ == nullptr) { + return; + } + switch(value.GetValueType()) { + case ValueObject::ValueType::VALUE_NUMBER: + cJSON_SetNumberValue(cjson_, value.GetDoubleValue()); + break; + case ValueObject::ValueType::VALUE_STRING: + cJSON_SetValuestring(cjson_, value.GetStringValue().c_str()); + break; + default: + break; + } +} + +std::string JsonObject::GetItemFiled() const +{ + if (cjson_ == nullptr) { + return ""; + } + + if (cjson_->string == nullptr) { + cJSON *tail = cjson_; + while(tail->next != nullptr) { + tail = tail->next; + } + + int index = 0; + cJSON *head = cjson_; + while (head->prev != tail) { + head = head->prev; + index++; + } + return std::to_string(index); + } else { + return cjson_->string; + } +} + std::string JsonObject::GetItemFiled(int &errCode) const { if (cjson_ == nullptr) { @@ -293,14 +388,6 @@ std::string JsonObject::GetItemFiled(int &errCode) const return cjson_->string; } - -namespace { -bool IsNumber(const std::string &str) { - return std::all_of(str.begin(), str.end(), [](char c) { - return std::isdigit(c); - }); -} - cJSON *GetChild(cJSON *cjson, const std::string &field, bool caseSens) { if (cjson->type == cJSON_Object) { @@ -326,29 +413,33 @@ cJSON *MoveToPath(cJSON *cjson, const JsonFieldPath &jsonPath, bool caseSens) for (const auto &field : jsonPath) { cjson = GetChild(cjson, field, caseSens); if (cjson == nullptr) { - GLOGW("Invalid json field path, no such field."); + break; } } return cjson; } -} - bool JsonObject::IsFieldExists(const JsonFieldPath &jsonPath) const { - return (MoveToPath(cjson_, jsonPath, caseSensitive_) == nullptr); + return (MoveToPath(cjson_, jsonPath, caseSensitive_) != nullptr); } JsonObject JsonObject::FindItem(const JsonFieldPath &jsonPath, int &errCode) const { if (jsonPath.empty()) { - return JsonObject(); + JsonObject curr = JsonObject(); + curr.cjson_ = cjson_; + curr.caseSensitive_ = caseSensitive_; + curr.isOwner_ = false; + GLOGW("Path empty, return current object"); + return curr; } cJSON *findItem = MoveToPath(cjson_, jsonPath, caseSensitive_); if (findItem == nullptr) { GLOGE("Find item failed. json field path not found."); errCode = -E_JSON_PATH_NOT_EXISTS; + return {}; } JsonObject item; @@ -400,4 +491,4 @@ int JsonObject::DeleteItemOnTarget(const JsonFieldPath &path) return E_OK; } -} +} // namespace DocumentDB diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp index d22d47cf..fedc5197 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/kv_store_manager.cpp @@ -39,12 +39,12 @@ int KvStoreManager::GetKvStore(const std::string &path, const DBConfig &config, auto *sqliteExecutor = new (std::nothrow) SqliteStoreExecutor(db); if (sqliteExecutor == nullptr) { + sqlite3_close_v2(db); return -E_OUT_OF_MEMORY; } std::string oriConfigStr; errCode = sqliteExecutor->GetDBConfig(oriConfigStr); - GLOGD("----> Get original db config: [%s] %d", oriConfigStr.c_str(), errCode); if (errCode == -E_NOT_FOUND) { errCode = sqliteExecutor->SetDBConfig(config.ToString()); } else if (errCode != E_OK) { 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 b50872b1..18fdc1e4 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 @@ -95,6 +95,10 @@ int SqliteStoreExecutor::PutData(const std::string &collName, const Key &key, co }, nullptr); if (errCode != SQLITE_OK) { GLOGE("[sqlite executor] Put data failed. err=%d", errCode); + if (errCode == -E_ERROR) { + GLOGE("Cant find the collection"); + return -E_INVALID_ARGS; + } return errCode; } return E_OK; @@ -129,6 +133,7 @@ int SqliteStoreExecutor::DelData(const std::string &collName, const Key &key) GLOGE("Invalid db handle."); return -E_ERROR; } + std::string sql = "DELETE FROM '" + collName + "' WHERE key=?;"; int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key](sqlite3_stmt *stmt) { SQLiteUtils::BindBlobToStatement(stmt, 1, key); @@ -137,6 +142,10 @@ int SqliteStoreExecutor::DelData(const std::string &collName, const Key &key) if (errCode != SQLITE_OK) { GLOGE("[sqlite executor] Delete data failed. err=%d", errCode); + if (errCode == -E_ERROR) { + GLOGE("Cant find the collection"); + return -E_INVALID_ARGS; + } } return errCode; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp index 0c431b1c..30c0d095 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/src/sqlite_utils.cpp @@ -25,6 +25,22 @@ const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION"; const std::string COMMIT_SQL = "COMMIT TRANSACTION"; const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION"; +namespace { +int MapSqliteError(int errCode) +{ + switch (errCode) { + case SQLITE_OK: + return E_OK; + case SQLITE_PERM: + case SQLITE_CANTOPEN: + case SQLITE_READONLY: + return -E_FILE_OPERATION; + default: + return -E_ERROR; + } +} +} + void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) { GLOGD("[SQLite] err=%d sys=%d %s msg=%s", err, errno, sqlite3_errstr(err), msg); @@ -32,7 +48,6 @@ void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg) int SQLiteUtils::CreateDataBase(const std::string &path, int flag, sqlite3 *&db) { - GLOGD("----> open sqlite: %s", path.c_str()); int errCode = sqlite3_open_v2(path.c_str(), &db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, nullptr); if (errCode != SQLITE_OK) { GLOGE("Open database [%s] failed. %d", path.c_str(), errCode); @@ -41,7 +56,7 @@ int SQLiteUtils::CreateDataBase(const std::string &path, int flag, sqlite3 *&db) db = nullptr; } } - return errCode; + return MapSqliteError(errCode); } int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement) @@ -224,7 +239,7 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql) } sqlite3_free(errMsg); - return errCode; + return MapSqliteError(errCode); } int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::function &bindCallback, @@ -233,7 +248,6 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::functio if (db == nullptr || sql.empty()) { return -E_INVALID_ARGS; } - GLOGD("----> execSql: %s", sql.c_str()); bool bindFinish = true; sqlite3_stmt *stmt = nullptr; int errCode = SQLiteUtils::GetStatement(db, sql, stmt); @@ -267,6 +281,6 @@ int SQLiteUtils::ExecSql(sqlite3 *db, const std::string &sql, const std::functio END: (void)SQLiteUtils::ResetStatement(stmt, true); - return errCode; + return MapSqliteError(errCode); } } // namespace DocumentDB 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 c647ca0d..346b4f27 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 @@ -41,8 +41,9 @@ public: }; void DocumentDeleteApiTest::SetUpTestCase(void) { - GRD_DBOpen(path.c_str(), nullptr, 0, &g_db); - EXPECT_NE(g_db, nullptr); + std::string path = "./document.db"; + int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &g_db); + EXPECT_EQ(status, GRD_OK); } void DocumentDeleteApiTest::TearDownTestCase(void) @@ -134,84 +135,84 @@ void DocumentDeleteApiTest::InsertDoc(const char *collectionName, const char *do EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, document, 0), GRD_OK); } -// /** -// * @tc.name: DocumentDelete001 -// * @tc.desc: Delete with NULL filter -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// 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); -// } +/** + * @tc.name: DocumentDelete001 + * @tc.desc: Delete with NULL filter + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +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); +} -// /** -// * @tc.name: DocumentDelete002 -// * @tc.desc: Delete with filter which has no _id -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest002, TestSize.Level1) -// { -// /** -// * @tc.steps:step1. Delete with filter which has no _id -// * @tc.expected: step1. GRD_INVALID_ARGS -// */ -// const char *filter = "{\"age\" : 15}"; -// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); -// } +/** + * @tc.name: DocumentDelete002 + * @tc.desc: Delete with filter which has no _id + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1. Delete with filter which has no _id + * @tc.expected: step1. GRD_INVALID_ARGS + */ + const char *filter = "{\"age\" : 15}"; + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); +} -// /** -// * @tc.name: DocumentDelete003 -// * @tc.desc: Delete with filter which has more than one fileds. -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest003, TestSize.Level1) -// { -// /** -// * @tc.steps:step1. Delete with filter which has more than one fileds. -// * @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); -// } +/** + * @tc.name: DocumentDelete003 + * @tc.desc: Delete with filter which has more than one fileds. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest003, TestSize.Level1) +{ + /** + * @tc.steps:step1. Delete with filter which has more than one fileds. + * @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); +} -// /** -// * @tc.name: DocumentDelete004 -// * @tc.desc: Test delete with invalid input -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest004, TestSize.Level1) -// { -// /** -// * @tc.steps:step1. Test delete with un-zero flags -// * @tc.expected: step1. GRD_INVALID_ARGS -// */ -// const char *filter1 = "{\"_id\" : \"1\"}"; -// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter1, 1), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2. Test delete with NULL collection name -// * @tc.expected: step2. GRD_INVALID_ARGS -// */ -// // const char *filter2 = "{\"_id\" : \"1\"}"; -// // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter2, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step3. Test delete with empty collection name -// * @tc.expected: step3. GRD_INVALID_ARGS -// */ -// // const char *filter1 = "{\"_id\" : \"1\"}"; -// // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter1, 1), GRD_INVALID_ARGS); -// } +/** + * @tc.name: DocumentDelete004 + * @tc.desc: Test delete with invalid input + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1. Test delete with un-zero flags + * @tc.expected: step1. GRD_INVALID_ARGS + */ + const char *filter1 = "{\"_id\" : \"1\"}"; + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter1, 1), GRD_INVALID_ARGS); + /** + * @tc.steps:step2. Test delete with NULL collection name + * @tc.expected: step2. GRD_INVALID_ARGS + */ + // const char *filter2 = "{\"_id\" : \"1\"}"; + // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step3. Test delete with empty collection name + * @tc.expected: step3. GRD_INVALID_ARGS + */ + // const char *filter1 = "{\"_id\" : \"1\"}"; + // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter1, 1), GRD_INVALID_ARGS); +} /** * @tc.name: DocumentDelete005 @@ -237,74 +238,74 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest005, TestSize.Level1) ChkDeleteResWithFilter(filter); } -// /** -// * @tc.name: DocumentDelete006 -// * @tc.desc: Test delete after calling find interface -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, 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\"}"; -// GRD_ResultSet *resultSet; -// resultSet = new GRD_ResultSet; -// Query query = {filter, "{}"}; -// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); -// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); -// /** -// * @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); -// } +/** + * @tc.name: DocumentDelete006 + * @tc.desc: Test delete after calling find interface + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, 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\"}"; + GRD_ResultSet *resultSet; + resultSet = new GRD_ResultSet; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); + /** + * @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); +} -// /** -// * @tc.name: DocumentDelete008 -// * @tc.desc: Test delete with invalid NULL input for all parameters. -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest008, TestSize.Level1) -// { -// /** -// * @tc.steps:step1. Delete with filter which has more than one fileds. -// * @tc.expected: step1. GRD_INVALID_ARGS -// */ -// const char *filter = "{\"_id\" : \"1\"}"; -// EXPECT_EQ(GRD_DeleteDoc(NULL, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); -// // EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter, 0), GRD_INVALID_ARGS); -// // EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter, 0), GRD_INVALID_ARGS); -// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0), GRD_INVALID_ARGS); -// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0), GRD_INVALID_ARGS); -// EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), GRD_INVALID_ARGS); -// } +/** + * @tc.name: DocumentDelete008 + * @tc.desc: Test delete with invalid NULL input for all parameters. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest008, TestSize.Level1) +{ + /** + * @tc.steps:step1. Delete with filter which has more than one fileds. + * @tc.expected: step1. GRD_INVALID_ARGS + */ + const char *filter = "{\"_id\" : \"1\"}"; + EXPECT_EQ(GRD_DeleteDoc(NULL, COLLECTION_NAME, filter, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, NULL, filter, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), GRD_INVALID_ARGS); +} -// /** -// * @tc.name: DocumentDelete010 -// * @tc.desc: Test delete document when filter _id is int and string -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) -// { -// /** -// * @tc.steps:step1. Test delete document when filter _id is int and string. -// * @tc.expected: step1. GRD_INVALID_ARGS -// */ -// std::vector filterVec = {R"({"_id" : 1})", R"("_id":[1, 2]})", -// R"({"_id" : {"t1" : 1}})", R"({"_id":null})", R"({"_id":true})", R"({"_id" : 1.333})", R"({"_id" : -2.0})"}; -// for (const auto &item : filterVec) { -// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, item.c_str(), 0), GRD_INVALID_ARGS); -// } -// const char *filter = "{\"_id\" : \"1\"}"; -// EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); +/** + * @tc.name: DocumentDelete010 + * @tc.desc: Test delete document when filter _id is int and string + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) +{ + /** + * @tc.steps:step1. Test delete document when filter _id is int and string. + * @tc.expected: step1. GRD_INVALID_ARGS + */ + std::vector filterVec = {R"({"_id" : 1})", R"({"_id":[1, 2]})", + R"({"_id" : {"t1" : 1}})", R"({"_id":null})", R"({"_id":true})", R"({"_id" : 1.333})", R"({"_id" : -2.0})"}; + for (const auto &item : filterVec) { + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, item.c_str(), 0), GRD_INVALID_ARGS); + } + const char *filter = "{\"_id\" : \"1\"}"; + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); -// } \ No newline at end of file +} \ No newline at end of file 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 30a03191..4468665c 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 @@ -28,6 +28,7 @@ GRD_DB *g_db = nullptr; static const char *g_document1 = "{\"_id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"personInfo\":\ {\"school\":\"AB\", \"age\" : 51}}"; +static const char *g_document_test = "{\"_id\" : \"weatherUri_1_com.acts.test\"}"; static const char *g_document2 = "{\"_id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"personInfo\":\ [1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; static const char *g_document3 = "{\"_id\" : \"3\", \"name\":\"doc3\",\"item\":\"notebook\",\"personInfo\":\ @@ -54,7 +55,7 @@ static const char *g_document14 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\ // static std::vectorg_data = {g_document1, g_document2, g_document3, g_document4, g_document5, g_document6, g_document7, // g_document8}; -static std::vectorg_data = {g_document1}; +static std::vectorg_data = {g_document1, g_document_test}; static void InsertData(GRD_DB *g_db, const char *collectionName) { for (const auto &item : g_data) { @@ -73,7 +74,9 @@ public: }; void DocumentFindApiTest::SetUpTestCase(void) { - GRD_DBOpen(path.c_str(), nullptr, 0, &g_db); + std::string path = "./document.db"; + int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &g_db); + EXPECT_EQ(status, GRD_OK); EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); EXPECT_NE(g_db, nullptr); } @@ -104,19 +107,17 @@ void DocumentFindApiTest::TearDown(void) HWTEST_F(DocumentFindApiTest, DocumentFindApiTest, TestSize.Level1) { - const char *filter = "{\"_id\":\"1\"}"; - const char *projection = "{\"item\" : 0, \"personInfo.school\" : 0, \"_id\" : 0}"; + const char *filter = "{\"_id\" : \"weatherUri_1_com.acts.test\"}"; + const char *projection = "{}"; Query query; query.filter = filter; query.projection = projection; GRD_ResultSet *resultSet; - resultSet = new GRD_ResultSet; EXPECT_EQ(GRD_FindDoc(g_db, "student", query, GRD_DOC_ID_DISPLAY, &resultSet), GRD_OK); - char **test; - test = new char*[1]; - test[0] = new char[521 + 1]; + char **test = nullptr; GRD_Next(resultSet); - EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); - GRD_FreeValue(test[0]); - //GRD_FreeResultSet(resultSet); + char *result = NULL; + GRD_GetValue(resultSet, &result); + GRD_FreeValue(result); + GRD_FreeResultSet(resultSet); } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp index a0b44f5f..cb7b1c76 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp @@ -68,7 +68,9 @@ public: }; void DocumentInsertApiTest::SetUpTestCase(void) { - GRD_DBOpen(path.c_str(), nullptr, 0, &g_db); + std::string path = "./document.db"; + int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &g_db); + EXPECT_EQ(status, GRD_OK); EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); EXPECT_NE(g_db, nullptr); } @@ -88,72 +90,72 @@ void DocumentInsertApiTest::TearDown(void) } -// /** -// * @tc.name: DocumentInsertApiTest001 -// * @tc.desc: Insert documents into collection which dose not exist -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest001, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Insert document into collection which dose not exist -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"_id\" : \"1\", \"name\" : \"Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, no_exsit_collectionName, document1, 0), GRD_INVALID_ARGS); -// } - -// /** -// * @tc.name: DocumentInsertApiTest002 -// * @tc.desc: Insert documents into collection which _id is not string -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest002, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Insert a document whose _id is integer -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"_id\" : 2, \"name\" : \"Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2.Insert a document whose _id is bool -// * @tc.expected:step2.GRD_INVALID_ARGS -// */ -// const char *document2 = "{\"_id\" : true, \"name\" : \"Chuan\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2.Insert a document whose _id is NULL -// * @tc.expected:step2.GRD_INVALID_ARGS -// */ -// const char *document3 = "{\"_id\" : null, \"name\" : \"Chuan\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2.Insert a document whose _id is ARRAY -// * @tc.expected:step2.GRD_INVALID_ARGS -// */ -// const char *document4 = "{\"_id\" : [\"2\"], \"name\" : \"Chuan\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2.Insert a document whose _id is OBJECT -// * @tc.expected:step2.GRD_INVALID_ARGS -// */ -// const char *document5 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"Chuan\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_INVALID_ARGS); -// } - - -// /** -// * @tc.name: DocumentInsertApiTest003 -// * @tc.desc: Insert a document whose _id has appeared before -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ +/** + * @tc.name: DocumentInsertApiTest001 + * @tc.desc: Insert documents into collection which dose not exist + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest001, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert document into collection which dose not exist + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"1\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, no_exsit_collectionName, document1, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest002 + * @tc.desc: Insert documents into collection which _id is not string + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest002, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a document whose _id is integer + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : 2, \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is bool + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document2 = "{\"_id\" : true, \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is NULL + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document3 = "{\"_id\" : null, \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is ARRAY + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document4 = "{\"_id\" : [\"2\"], \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert a document whose _id is OBJECT + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document5 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_INVALID_ARGS); +} + + +/** + * @tc.name: DocumentInsertApiTest003 + * @tc.desc: Insert a document whose _id has appeared before + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ HWTEST_F(DocumentInsertApiTest, InsertDBTest003, TestSize.Level1) { /** @@ -171,449 +173,449 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest003, TestSize.Level1) // EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_DATA_CONFLICT); } -// /** -// * @tc.name: DocumentInsertApiTest004 -// * @tc.desc: Test Insert with null parameter. parameter db is NULL -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest004, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.step1.parameter db is NULL -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"_id\" : \"4\", \"name\" : \"Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(NULL, right_collectionName, document1, 0), GRD_INVALID_ARGS); -// } - -// /** -// * @tc.name: DocumentInsertApiTest005 -// * @tc.desc: Test insert with null parameter. parameter collectionName is NULL. -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest005, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Parameter collectionName is NULL -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"_id\" : \"5\", \"name\" : \"Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, NULL, document1, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2.Parameter collectionName is empty string -// * @tc.expected:step2.GRD_INVALID_ARGS -// */ -// const char *document2 = "{\"_id\" : \"5\", \"name\" : \"Chuang\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, "", document2, 0), GRD_INVALID_ARGS); -// } - -// /** -// * @tc.name: DocumentInsertApiTest006 -// * @tc.desc: parameter flags is not zero -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest006, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.parameter flags is not zero -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"_id\" : \"6\", \"name\" : \"Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 1), GRD_INVALID_ARGS); -// } - -// /** -// * @tc.name: DocumentInsertApiTest007 -// * @tc.desc: parameter flags is INT_MAX -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest007, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.parameter flags is int_max -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"_id\" : \"7\", \"name\" : \"Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_max), GRD_INVALID_ARGS); -// } - -// /** -// * @tc.name: DocumentInsertApiTest008 -// * @tc.desc: parameter flags is int_min -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest008, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.parameter flags is int_min -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"_id\" : \"8\", \"name\" : \"Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_min), GRD_INVALID_ARGS); -// } - -// /** -// * @tc.name: DocumentInsertApiTest009 -// * @tc.desc: parameter collectionName and document is NULL or invalid -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.parameter collectionName and document is NULL; -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// EXPECT_EQ(GRD_InsertDoc(g_db, NULL, NULL, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2.parameter collectionName is larger than max_collectionName_lens; -// * @tc.expected:step2.GRD_OVER_LIMIT -// */ -// // std::string collectionName2(max_collection_lens + 1, 'a'); -// // EXPECT_EQ(GRD_InsertDoc(g_db, collectionName2.c_str(), JSON_STR_HASID, 0), GRD_OVER_LIMIT); -// } - -// /** -// * @tc.name: DocumentInsertApiTest010 -// * @tc.desc: parameter collectionName contains irregular charactor -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest010, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor -// * @tc.expected:step1.GRD_OK -// */ -// const char *collectionName = "collction@!#"; -// const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; -// TestInsertDocIntoCertainColl(collectionName, document1, GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest011 -// * @tc.desc: parameter collectionName is longer than 256 charactors -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest011, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor -// * @tc.expected:step1.GRD_OK -// */ -// string collectionName(257, 'k'); -// const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; -// TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest014 -// * @tc.desc: Inserted document's JSON depth is larger than 4, which is 5. -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.document's JSON depth is larger than 4, which is 5. -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document1 = "{\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}}, \"level3_2\" : \"level3_2_val\"\ -// }},\"_id\":\"14\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step1.document's JSON depth is larger than 4, which is 5.But with array type. -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// const char *document2 = "{\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"level5_1val\", \"level5_2\":\ -// \"level5_2_val\"}, \"level4_val1\",\"level4_val2\"], \"level3_2\" : \"level3_2_val\"\ -// }},\"_id\":\"14\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step1.document's JSON depth is 4 -// * @tc.expected:step1.GRD_OK -// */ -// const char *document3 = "{\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"level5_1val\"}, \"level3_2\" : \"level3_2_val\"\ -// }},\"_id\":\"14\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest015 -// * @tc.desc: Inserted document with all kinds of size -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.document's JSON is bigger than 512k - 1 -// * @tc.expected:step1.GRD_INVALID_ARGS -// */ -// string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; -// string documentPart2 = "\" }"; -// string jsonVal = string(512 * 1024 - documentPart1.size() - documentPart2.size(), 'k'); -// string document = documentPart1 + jsonVal + documentPart2; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OVER_LIMIT); -// /** -// * @tc.steps:step2.Insert document's JSON is a large data but lower than 512k - 1 -// * @tc.expected:step2.GRD_OK -// */ -// string jsonVal2 = string(512 * 1024 - 1 - documentPart1.size() - documentPart2.size(), 'k'); -// string document2 = documentPart1 + jsonVal2 + documentPart2; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2.c_str(), 0), GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest016 -// * @tc.desc: document JSON string contains irregular char -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest016, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.document JSON string contains irregular char. -// * @tc.expected:step1.GRD_OK -// */ -// const char *document1 = "{\"_id\" : \"16\", \"name\" : \"!@#Ori\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest017 -// * @tc.desc: document JSON string contains invalid value type such as BLOB type -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.document JSON string contains invalid value type such as BLOB type. -// * @tc.expected:step1.GRD_INVALID_FORMAT. -// */ -// const char *document = "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : x'1234'\ -// } } }, \"level1_2\" : \"level1_2Val\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); -// } - -// /** -// * @tc.name: DocumentInsertApiTest018 -// * @tc.desc: The Inserted document is not JSON format -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest018, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.The Inserted document is not JSON format -// * @tc.expected:step1.GRD_INVALID_FORMAT. -// */ -// const char *document = "some random string not JSON format"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); -// } - -// /** -// * @tc.name: DocumentInsertApiTest019 -// * @tc.desc: Insert a normal documents -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest019, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Insert a normal documents which _id is in the end of the string -// * @tc.expected:step1.GRD_OK. -// */ -// const char *document1 = "{\"name\" : \"Jack\", \"age\" : 18, \"friend\" : {\"name\" : \" lucy\"}, \"_id\" : \"19\"}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest022 -// * @tc.desc: parameter collectionName is equal to 256 charactors -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest022, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.parameter collectionName is equal to 256 charactors -// * @tc.expected:step1.GRD_OK. -// */ -// string collectionName = string(256, 'k'); -// const char *document1 = "{\"_id\" : \"22\", \"name\" : \"Ori\"}"; -// TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest023 -// * @tc.desc: parameter collectionName contains upper & lower case charactors, -// * numbers and underline -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.parameter collectionName contains upper & lower case charactors, -// * numbers and underline -// * @tc.expected:step1.GRD_OK. -// */ -// string collectionName = "Aads_sd__23Asb_"; -// const char *document1 = "{\"_id\" : \"23\", \"name\" : \"Ori\"}"; -// TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest025 -// * @tc.desc: Insert document whose depth is 4, which is allowed -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.documents JSON depth is 4, which is allowed. -// * @tc.expected:step1.GRD_OK. -// */ -// const char *document1 = "{\"_id\" : \"25_0\", \"level1\" : { \"level2\" : {\"level3\" :\ -// {\"level4\" : \"level4Val\" } } } , \"level1_2\" : \"level1_2Val\" }"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); -// /** -// * @tc.steps:step2.documents JSON depth is exactly 4. -// * @tc.expected:step2.GRD_OK. -// */ -// const char *document2 = "{\"_id\" : \"25_1\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ -// \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\"] }]}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK); -// /** -// * @tc.steps:step3.documents JSON depth is exactly 4, but the last field in array contains leading number -// * @tc.expected:step3.GRD_INVALID_ARGS. -// */ -// const char *document3 = "{\"_id\" : \"25_2\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ -// \"age\" : 18, \"sex\" : \"男\"}, [\"qw\", \"dr\", 0, \"ab\", {\"0ab\" : null}]]}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step4.documents JSON depth is exactly 5. -// * @tc.expected:step4.GRD_INVALID_ARGS. -// */ -// const char *document4 = "{\"_id\" : \"25_3\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ -// \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\", {\"level5\" : 1}] }]}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); -// } - -// /** -// * @tc.name: DocumentInsertApiTest026 -// * @tc.desc: Insert 100 normal documents continuously -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Insert 100 normal documents continuously -// * @tc.expected:step1.GRD_OK. -// */ -// string document1 = "{\"_id\" : "; -// string document2 = "\""; -// string document4 = "\""; -// string document5 = ", \"name\" : \"Ori\"}"; -// for (int i = 0; i < 5; i++) { -// string document_midlle = {'2','6' + i}; -// string document = document1 + document2 + document_midlle + document4 + document5; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OK); -// } -// } - -// /** -// * @tc.name: DocumentInsertApiTest036 -// * @tc.desc: Insert a document whose value contains -// * string, number, bool, null, array and object type -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Insert a document whose value contains -// * string, number, bool, null, array and object type -// * @tc.expected:step1.GRD_OK. -// */ -// const char *document1 = "{\"_id\" : \"36_0\", \"stringType\" : \"stringVal\", \"numType\" : 1, \"BoolType\" : true,\ -// \"nullType\" : null, \"arrayType\" : [1, 2, 3, 4], \"objectType\" : {\"A\" : 3}}"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); -// } - -// /** -// * @tc.name: DocumentInsertApiTest038 -// * @tc.desc: Insert document whose value is over the range of double -// * string, number, bool, null, array and object type -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentInsertApiTest, InsertDBTest038, TestSize.Level1) -// { -// /** -// * @tc.steps:step1.Insert document whose value is over the range of double -// * @tc.expected:step1.GRD_INVALID_ARGS. -// */ -// const char *document1 = R"({"_id" : "38_0", "field2" : 1.79769313486232e308})"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step2.Insert document whose value is over the range of double -// * @tc.expected:step2.GRD_INVALID_ARGS. -// */ -// const char *document2 = R"({"_id" : "38_1", "t1" : {"field2" : 1.79769313486232e308}})"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step3.Insert document whose value is over the range of double -// * @tc.expected:step3.GRD_INVALID_ARGS. -// */ -// const char *document3 = R"({"_id" : "38_2", "t1" : [1, 2, 1.79769313486232e308]})"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step4.Insert document whose value is over the range of double -// * @tc.expected:step4.GRD_INVALID_ARGS. -// */ -// const char *document4 = R"({"_id" : "38_3", "t1" : [1, 2, -1.7976931348623167E+308]})"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); -// /** -// * @tc.steps:step5.Insert document with minimum double value -// * @tc.expected:step5.GRD_INVALID_ARGS. -// */ -// const char *document5 = R"({"_id" : "38_4", "t1" : [1, 2, -1.79769313486231570E+308]})"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_OK); -// /** -// * @tc.steps:step6.Insert document with maxium double value -// * @tc.expected:step6.GRD_INVALID_ARGS. -// */ -// const char *document6 = R"({"_id" : "38_5", "t1" : [1, 2, 1.79769313486231570E+308]})"; -// EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document6, 0), GRD_OK); -// } \ No newline at end of file +/** + * @tc.name: DocumentInsertApiTest004 + * @tc.desc: Test Insert with null parameter. parameter db is NULL + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest004, TestSize.Level1) +{ + /** + * @tc.steps:step1.step1.parameter db is NULL + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"4\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(NULL, right_collectionName, document1, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest005 + * @tc.desc: Test insert with null parameter. parameter collectionName is NULL. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest005, TestSize.Level1) +{ + /** + * @tc.steps:step1.Parameter collectionName is NULL + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"5\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, NULL, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Parameter collectionName is empty string + * @tc.expected:step2.GRD_INVALID_ARGS + */ + const char *document2 = "{\"_id\" : \"5\", \"name\" : \"Chuang\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, "", document2, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest006 + * @tc.desc: parameter flags is not zero + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest006, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter flags is not zero + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"6\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 1), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest007 + * @tc.desc: parameter flags is INT_MAX + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest007, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter flags is int_max + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"7\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_max), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest008 + * @tc.desc: parameter flags is int_min + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest008, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter flags is int_min + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"_id\" : \"8\", \"name\" : \"Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_min), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest009 + * @tc.desc: parameter collectionName and document is NULL or invalid + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter collectionName and document is NULL; + * @tc.expected:step1.GRD_INVALID_ARGS + */ + EXPECT_EQ(GRD_InsertDoc(g_db, NULL, NULL, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.parameter collectionName is larger than max_collectionName_lens; + * @tc.expected:step2.GRD_OVER_LIMIT + */ + // std::string collectionName2(max_collection_lens + 1, 'a'); + // EXPECT_EQ(GRD_InsertDoc(g_db, collectionName2.c_str(), JSON_STR_HASID, 0), GRD_OVER_LIMIT); +} + +/** + * @tc.name: DocumentInsertApiTest010 + * @tc.desc: parameter collectionName contains irregular charactor + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest010, TestSize.Level1) +{ + /** + * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor + * @tc.expected:step1.GRD_OK + */ + const char *collectionName = "collction@!#"; + const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName, document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest011 + * @tc.desc: parameter collectionName is longer than 256 charactors + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest011, TestSize.Level1) +{ + /** + * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor + * @tc.expected:step1.GRD_OK + */ + string collectionName(257, 'k'); + const char *document1 = "{\"_id\" : \"10\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest014 + * @tc.desc: Inserted document's JSON depth is larger than 4, which is 5. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) +{ + /** + * @tc.steps:step1.document's JSON depth is larger than 4, which is 5. + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document1 = "{\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}}, \"level3_2\" : \"level3_2_val\"\ + }},\"_id\":\"14\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step1.document's JSON depth is larger than 4, which is 5.But with array type. + * @tc.expected:step1.GRD_INVALID_ARGS + */ + const char *document2 = "{\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"level5_1val\", \"level5_2\":\ + \"level5_2_val\"}, \"level4_val1\",\"level4_val2\"], \"level3_2\" : \"level3_2_val\"\ + }},\"_id\":\"14\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step1.document's JSON depth is 4 + * @tc.expected:step1.GRD_OK + */ + const char *document3 = "{\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"level5_1val\"}, \"level3_2\" : \"level3_2_val\"\ + }},\"_id\":\"14\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest015 + * @tc.desc: Inserted document with all kinds of size + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) +{ + /** + * @tc.steps:step1.document's JSON is bigger than 512k - 1 + * @tc.expected:step1.GRD_INVALID_ARGS + */ + string documentPart1 = "{ \"_id\" : \"15\", \"textVal\" : \" "; + string documentPart2 = "\" }"; + string jsonVal = string(512 * 1024 - documentPart1.size() - documentPart2.size(), 'k'); + string document = documentPart1 + jsonVal + documentPart2; + //EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OVER_LIMIT); + /** + * @tc.steps:step2.Insert document's JSON is a large data but lower than 512k - 1 + * @tc.expected:step2.GRD_OK + */ + string jsonVal2 = string(512 * 1024 - 1 - documentPart1.size() - documentPart2.size(), 'k'); + string document2 = documentPart1 + jsonVal2 + documentPart2; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2.c_str(), 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest016 + * @tc.desc: document JSON string contains irregular char + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest016, TestSize.Level1) +{ + /** + * @tc.steps:step1.document JSON string contains irregular char. + * @tc.expected:step1.GRD_OK + */ + const char *document1 = "{\"_id\" : \"16\", \"name\" : \"!@#Ori\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest017 + * @tc.desc: document JSON string contains invalid value type such as BLOB type + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) +{ + /** + * @tc.steps:step1.document JSON string contains invalid value type such as BLOB type. + * @tc.expected:step1.GRD_INVALID_FORMAT. + */ + const char *document = "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : x'1234'\ + } } }, \"level1_2\" : \"level1_2Val\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); +} + +/** + * @tc.name: DocumentInsertApiTest018 + * @tc.desc: The Inserted document is not JSON format + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest018, TestSize.Level1) +{ + /** + * @tc.steps:step1.The Inserted document is not JSON format + * @tc.expected:step1.GRD_INVALID_FORMAT. + */ + const char *document = "some random string not JSON format"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); +} + +/** + * @tc.name: DocumentInsertApiTest019 + * @tc.desc: Insert a normal documents + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest019, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a normal documents which _id is in the end of the string + * @tc.expected:step1.GRD_OK. + */ + const char *document1 = "{\"name\" : \"Jack\", \"age\" : 18, \"friend\" : {\"name\" : \" lucy\"}, \"_id\" : \"19\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest022 + * @tc.desc: parameter collectionName is equal to 256 charactors + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest022, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter collectionName is equal to 256 charactors + * @tc.expected:step1.GRD_OK. + */ + string collectionName = string(256, 'k'); + const char *document1 = "{\"_id\" : \"22\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest023 + * @tc.desc: parameter collectionName contains upper & lower case charactors, + * numbers and underline + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter collectionName contains upper & lower case charactors, + * numbers and underline + * @tc.expected:step1.GRD_OK. + */ + string collectionName = "Aads_sd__23Asb_"; + const char *document1 = "{\"_id\" : \"23\", \"name\" : \"Ori\"}"; + TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest025 + * @tc.desc: Insert document whose depth is 4, which is allowed + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) +{ + /** + * @tc.steps:step1.documents JSON depth is 4, which is allowed. + * @tc.expected:step1.GRD_OK. + */ + const char *document1 = "{\"_id\" : \"25_0\", \"level1\" : { \"level2\" : {\"level3\" :\ + {\"level4\" : \"level4Val\" } } } , \"level1_2\" : \"level1_2Val\" }"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + /** + * @tc.steps:step2.documents JSON depth is exactly 4. + * @tc.expected:step2.GRD_OK. + */ + const char *document2 = "{\"_id\" : \"25_1\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ + \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\"] }]}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK); + /** + * @tc.steps:step3.documents JSON depth is exactly 4, but the last field in array contains leading number + * @tc.expected:step3.GRD_INVALID_ARGS. + */ + const char *document3 = "{\"_id\" : \"25_2\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ + \"age\" : 18, \"sex\" : \"男\"}, [\"qw\", \"dr\", 0, \"ab\", {\"0ab\" : null}]]}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step4.documents JSON depth is exactly 5. + * @tc.expected:step4.GRD_INVALID_ARGS. + */ + const char *document4 = "{\"_id\" : \"25_3\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ + \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\", {\"level5\" : 1}] }]}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentInsertApiTest026 + * @tc.desc: Insert 100 normal documents continuously + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert 100 normal documents continuously + * @tc.expected:step1.GRD_OK. + */ + string document1 = "{\"_id\" : "; + string document2 = "\""; + string document4 = "\""; + string document5 = ", \"name\" : \"Ori\"}"; + for (int i = 0; i < 5; i++) { + string document_midlle = {'2','6' + i}; + string document = document1 + document2 + document_midlle + document4 + document5; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OK); + } +} + +/** + * @tc.name: DocumentInsertApiTest036 + * @tc.desc: Insert a document whose value contains + * string, number, bool, null, array and object type + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a document whose value contains + * string, number, bool, null, array and object type + * @tc.expected:step1.GRD_OK. + */ + const char *document1 = "{\"_id\" : \"36_0\", \"stringType\" : \"stringVal\", \"numType\" : 1, \"BoolType\" : true,\ + \"nullType\" : null, \"arrayType\" : [1, 2, 3, 4], \"objectType\" : {\"A\" : 3}}"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest038 + * @tc.desc: Insert document whose value is over the range of double + * string, number, bool, null, array and object type + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, InsertDBTest038, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert document whose value is over the range of double + * @tc.expected:step1.GRD_INVALID_ARGS. + */ + const char *document1 = R"({"_id" : "38_0", "field2" : 1.79769313486232e308})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step2.Insert document whose value is over the range of double + * @tc.expected:step2.GRD_INVALID_ARGS. + */ + const char *document2 = R"({"_id" : "38_1", "t1" : {"field2" : 1.79769313486232e308}})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step3.Insert document whose value is over the range of double + * @tc.expected:step3.GRD_INVALID_ARGS. + */ + const char *document3 = R"({"_id" : "38_2", "t1" : [1, 2, 1.79769313486232e308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step4.Insert document whose value is over the range of double + * @tc.expected:step4.GRD_INVALID_ARGS. + */ + const char *document4 = R"({"_id" : "38_3", "t1" : [1, 2, -1.7976931348623167E+308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + /** + * @tc.steps:step5.Insert document with minimum double value + * @tc.expected:step5.GRD_INVALID_ARGS. + */ + const char *document5 = R"({"_id" : "38_4", "t1" : [1, 2, -1.79769313486231570E+308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_OK); + /** + * @tc.steps:step6.Insert document with maxium double value + * @tc.expected:step6.GRD_INVALID_ARGS. + */ + const char *document6 = R"({"_id" : "38_5", "t1" : [1, 2, 1.79769313486231570E+308]})"; + EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document6, 0), GRD_OK); +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp index 1d9ba8a8..f21cb278 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp @@ -70,8 +70,8 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest001, TestSize.Level0) EXPECT_EQ(GRD_CreateCollection(db, "student", "", 0), GRD_OK); - EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", "{name:\"Tom\",age:23}", 0), GRD_OK); - EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", "{name:\"Tom\",age:24}", 0), GRD_OK); + EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", R""({"name":"Tom","age":23})"", 0), GRD_OK); + EXPECT_EQ(GRD_UpSertDoc(db, "student", "10001", R""({"name":"Tom","age":23})"", 0), GRD_OK); EXPECT_EQ(GRD_DropCollection(db, "student", 0), GRD_OK); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp index 22af9ecb..5614bb41 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_collection_test.cpp @@ -75,6 +75,10 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest001, TestSize.Level0) EXPECT_EQ(GRD_CreateCollection(nullptr, "student", "", 0), GRD_INVALID_ARGS); } +namespace { +const int MAX_COLLECTION_LEN = 512; +} + /** * @tc.name: CollectionTest002 * @tc.desc: Test create/drop collection with invalid collection name @@ -84,6 +88,7 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest001, TestSize.Level0) */ HWTEST_F(DocumentDBCollectionTest, CollectionTest002, TestSize.Level0) { + string overLenName(MAX_COLLECTION_LEN, 'a'); std::vector invalidName = { nullptr, "", @@ -91,12 +96,13 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest002, TestSize.Level0) "grd_123", "GM_SYS_123", "gm_sys_123", + overLenName.c_str() }; for (auto *it : invalidName) { GLOGD("CollectionTest002: create collection with name: %s", it); - EXPECT_EQ(GRD_CreateCollection(g_db, it, "", 0), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_DropCollection(g_db, it, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_CreateCollection(g_db, it, "", 0), GRD_INVALID_FORMAT); + EXPECT_EQ(GRD_DropCollection(g_db, it, 0), GRD_INVALID_FORMAT); } } @@ -109,13 +115,15 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest002, TestSize.Level0) */ HWTEST_F(DocumentDBCollectionTest, CollectionTest003, TestSize.Level0) { + string overLenName(MAX_COLLECTION_LEN - 1, 'a'); std::vector validName = { "123", "&^%@", "中文字符", "sqlite_master", "NULL", - "SELECT" + "SELECT", + overLenName.c_str() }; for (auto *it : validName) { @@ -135,8 +143,8 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest003, TestSize.Level0) HWTEST_F(DocumentDBCollectionTest, CollectionTest004, TestSize.Level0) { EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); - EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_COLLECTION_CONFLICT); - EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", IGNORE_EXIST_TABLE), GRD_OK); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); + EXPECT_EQ(GRD_CreateCollection(g_db, "Student", "", CHK_EXIST_COLLECTION), GRD_DATA_CONFLICT); } /** @@ -148,19 +156,19 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest004, TestSize.Level0) */ HWTEST_F(DocumentDBCollectionTest, CollectionTest005, TestSize.Level0) { - EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({aa})"", 0), GRD_INVALID_JSON_FORMAT); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({aa})"", 0), GRD_INVALID_FORMAT); std::vector invalidOption = { - // R""({"invalidOption":2})"", R""({"maxDoc":0})"", R""({"maxDoc":"123"})"", R""({"maxDoc":{"value":1024}})"", R""({"maxDoc":[1,2,4,8]})"", + R""({"minDoc":1024})"", }; for (auto opt : invalidOption) { GLOGD("CollectionTest005: create collection with option: %s", opt); - EXPECT_EQ(GRD_CreateCollection(g_db, "student", opt, 0), GRD_INVALID_CONFIG_VALUE); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", opt, 0), GRD_INVALID_ARGS); } } @@ -175,12 +183,11 @@ HWTEST_F(DocumentDBCollectionTest, CollectionTest006, TestSize.Level0) { EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({"maxDoc":1024})"", 0), GRD_OK); - EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({"maxDoc":2048})"", IGNORE_EXIST_TABLE), - GRD_INVALID_CONFIG_VALUE); + EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({"maxDoc":2048})"", 0), GRD_INVALID_ARGS); EXPECT_EQ(GRD_DropCollection(g_db, "student", 0), GRD_OK); EXPECT_EQ(GRD_DropCollection(g_db, "student", 0), GRD_NO_DATA); - EXPECT_EQ(GRD_DropCollection(g_db, "student", IGNORE_NON_EXIST_TABLE), GRD_OK); + EXPECT_EQ(GRD_DropCollection(g_db, "student", CHK_NON_EXIST_COLLECTION), GRD_OK); // Create collection with different option returnh OK after drop collection EXPECT_EQ(GRD_CreateCollection(g_db, "student", R""({"maxDoc":2048})"", 0), GRD_OK); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp index 6832993f..6f61aac7 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_data_test.cpp @@ -51,7 +51,6 @@ void DocumentDBDataTest::TearDownTestCase(void) void DocumentDBDataTest::SetUp(void) { - DocumentDBTestUtils::RemoveTestDbFiles(g_path); EXPECT_EQ(GRD_DBOpen(g_path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &g_db), GRD_OK); EXPECT_NE(g_db, nullptr); @@ -64,6 +63,7 @@ void DocumentDBDataTest::TearDown(void) EXPECT_EQ(GRD_DBClose(g_db, GRD_DB_CLOSE), GRD_OK); g_db = nullptr; } + DocumentDBTestUtils::RemoveTestDbFiles(g_path); } /** @@ -143,7 +143,7 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest005, TestSize.Level0) "gm_sys_123", }; for (auto document : invalidDocument) { - EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document, GRD_DOC_REPLACE), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_UpSertDoc(g_db, g_coll, filter.c_str(), document, GRD_DOC_REPLACE), GRD_INVALID_FORMAT); } } @@ -179,7 +179,7 @@ HWTEST_F(DocumentDBDataTest, UpsertDataTest007, TestSize.Level0) /** * @tc.name: UpsertDataTest008 - * @tc.desc: Test upsert data with different document + * @tc.desc: Test upsert data with different document in append * @tc.type: FUNC * @tc.require: * @tc.author: lianhuix -- Gitee From fb40ed8a47e97b566282552150c5c7e39f90c945 Mon Sep 17 00:00:00 2001 From: mazhao Date: Wed, 12 Apr 2023 02:41:00 +0000 Subject: [PATCH 08/18] Feature merging complete Signed-off-by: mazhao --- .../gaussdb_rd_Simple/src/common/include/doc_common.h | 6 ------ .../src/interface/include/document_store.h | 5 ----- 2 files changed, 11 deletions(-) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h index 01937de9..5ef1dd38 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h @@ -29,15 +29,9 @@ public: ~CheckCommon() = default; static bool CheckCollectionName(const std::string &collectionName, std::string &lowerCaseName, int &errCode); -<<<<<<< HEAD static bool CheckFilter(JsonObject *document); static bool CheckIdFormat(JsonObject *data); static bool CheckDocument(JsonObject *document); -======= - static bool CheckFilter(const std::string &filter); - static bool CheckIdFormat(const std::string &data); - static bool CheckDocument(const std::string &document); ->>>>>>> ddb/master }; using Key = std::vector; using Value = std::vector; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h index 7678eb67..f51a77a1 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h @@ -35,16 +35,11 @@ public: int UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update, int flag); int UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flags); -<<<<<<< HEAD int InsertDocument(const std::string &collection, const std::string &document, int flag); int DeleteDocument(const std::string &collection, const std::string &filter, int flag); int FindDocument(GRD_DB* db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet); private: int GetViewType(JsonObject *jsonObj, bool &viewType); -======= - -private: ->>>>>>> ddb/master std::mutex dbMutex_; KvStoreExecutor *executor_ = nullptr; -- Gitee From 12c870b07c0b34510eaa0492a49e2960a652e1f1 Mon Sep 17 00:00:00 2001 From: mazhao Date: Wed, 12 Apr 2023 02:50:12 +0000 Subject: [PATCH 09/18] Sencond Merge2 Signed-off-by: mazhao --- .../test/unittest/api/documentdb_api_test.cpp | 44 ------------ .../api/documentdb_jsonobject_test.cpp | 68 ------------------- 2 files changed, 112 deletions(-) delete mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp index 6fb52b54..382fe5ef 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp @@ -83,8 +83,6 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest001, TestSize.Level0) } /** -<<<<<<< HEAD -======= * @tc.name: OpenDBTest002 * @tc.desc: Test open document db with invalid db * @tc.type: FUNC @@ -110,7 +108,6 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest002, TestSize.Level0) } /** ->>>>>>> ddb/master * @tc.name: OpenDBPathTest001 * @tc.desc: Test open document db with NULL path * @tc.type: FUNC @@ -159,11 +156,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigTest001, TestSize.Level0) GRD_DB *db = nullptr; std::string path= "./document.db"; const int MAX_JSON_LEN = 512 * 1024; -<<<<<<< HEAD - std::string configStr = std::string(MAX_JSON_LEN + 1, 'a'); -======= std::string configStr = std::string(MAX_JSON_LEN, 'a'); ->>>>>>> ddb/master int status = GRD_DBOpen(path.c_str(), configStr.c_str(), GRD_DB_OPEN_CREATE, &db); EXPECT_EQ(status, GRD_OVER_LIMIT); } @@ -180,11 +173,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigTest002, TestSize.Level0) GRD_DB *db = nullptr; std::string path= "./document.db"; int status = GRD_DBOpen(path.c_str(), "{aa}", GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_JSON_FORMAT); -======= EXPECT_EQ(status, GRD_INVALID_FORMAT); ->>>>>>> ddb/master } /** @@ -199,11 +188,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigTest003, TestSize.Level0) GRD_DB *db = nullptr; std::string path= "./document.db"; int status = GRD_DBOpen(path.c_str(), R""({"notSupport":123})"", GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_NOT_SUPPORT); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } /** @@ -230,11 +215,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest001, TestSize.Level0) for (const auto &config : configList) { GLOGD("OpenDBConfigMaxConnNumTest001: test with config:%s", config.c_str()); int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - ASSERT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= ASSERT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } } @@ -286,11 +267,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest003, TestSize.Level1) config = R""({"maxConnNum":17})""; status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master DocumentDBTestUtils::RemoveTestDbFiles(path); } @@ -319,13 +296,8 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest004, TestSize.Level1) GRD_DB *db = nullptr; int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_OVER_LIMIT); - EXPECT_EQ(db, nullptr); -======= EXPECT_EQ(status, GRD_OK); EXPECT_NE(db, nullptr); ->>>>>>> ddb/master for (auto *it : dbList) { status = GRD_DBClose(it, GRD_DB_CLOSE); @@ -359,11 +331,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigPageSizeTest001, TestSize.Level0) for (const auto &config : configList) { GLOGD("OpenDBConfigPageSizeTest001: test with config:%s", config.c_str()); int status = GRD_DBOpen(path.c_str(), config.c_str(), 0, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } } @@ -436,11 +404,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigPageSizeTest003, TestSize.Level1) config = R""({"pageSize":8})""; status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master DocumentDBTestUtils::RemoveTestDbFiles(path); } @@ -484,11 +448,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigRedoFlushTest002, TestSize.Level0) std::string config = R""({"redoFlushByTrx":3})""; int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } /** @@ -527,14 +487,10 @@ HWTEST_F(DocumentDBApiTest, OpenDBFlagTest002, TestSize.Level0) { GRD_DB *db = nullptr; std::string path= "./document.db"; -<<<<<<< HEAD - int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); -======= int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &db); EXPECT_EQ(status, GRD_INVALID_ARGS); status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); ->>>>>>> ddb/master EXPECT_EQ(status, GRD_OK); status = GRD_DBClose(db, GRD_DB_CLOSE); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp deleted file mode 100644 index fa16a27a..00000000 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -* 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 "documentdb_test_utils.h" -#include "doc_errno.h" -#include "json_object.h" - -using namespace DocumentDB; -using namespace testing::ext; -using namespace DocumentDBUnitTest; - -class DocumentDBJsonObjectTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DocumentDBJsonObjectTest::SetUpTestCase(void) -{ -} - -void DocumentDBJsonObjectTest::TearDownTestCase(void) -{ -} - -void DocumentDBJsonObjectTest::SetUp(void) -{ -} - -void DocumentDBJsonObjectTest::TearDown(void) -{ -} - -/** - * @tc.name: OpenDBTest001 - * @tc.desc: Test open document db - * @tc.type: FUNC - * @tc.require: - * @tc.author: lianhuix - */ -HWTEST_F(DocumentDBJsonObjectTest, JsonObjectTest001, TestSize.Level0) -{ - const std::string config = R""({"a":123,"b":{"c":234,"d":"12345"}})""; - - int ret = E_OK; - JsonObject conf = JsonObject::Parse(config, ret); - EXPECT_EQ(ret, E_OK); - - ValueObject obj = conf.GetObjectByPath({"b", "c"}, ret); - - EXPECT_EQ(obj.GetValueType(), ValueObject::ValueType::VALUE_NUMBER); - EXPECT_EQ(obj.GetIntValue(), 234); -} \ No newline at end of file -- Gitee From c60db46b8d9da25be56d0f34c3829caf8929340c Mon Sep 17 00:00:00 2001 From: mazhao Date: Sat, 15 Apr 2023 03:23:45 +0000 Subject: [PATCH 10/18] Complete the query to remove the inserted UT use case and modify the issues found in it Signed-off-by: mazhao --- .../src/common/include/doc_common.h | 1 + .../src/common/include/json_common.h | 2 + .../src/common/src/doc_common.cpp | 32 +- .../src/common/src/json_common.cpp | 65 +- .../src/executor/base/grd_resultset_api.cpp | 12 +- .../executor/document/grd_document_api.cpp | 6 +- .../src/interface/include/projection_tree.h | 2 +- .../src/interface/include/result_set.h | 1 + .../src/interface/src/document_store.cpp | 27 +- .../src/interface/src/projection_tree.cpp | 10 +- .../src/interface/src/result_set.cpp | 17 +- .../src/oh_adapter/include/json_object.h | 1 + .../src/oh_adapter/src/json_object.cpp | 48 +- .../unittest/api/ documentdb_delete_test.cpp | 29 +- .../unittest/api/ documentdb_find_test.cpp | 1358 ++++++++++++++++- .../unittest/api/ documentdb_insert_test.cpp | 234 ++- .../test/unittest/api/documentdb_api_test.cpp | 44 - .../api/documentdb_jsonobject_test.cpp | 68 - 18 files changed, 1710 insertions(+), 247 deletions(-) delete mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h index 5ef1dd38..551101cb 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h @@ -32,6 +32,7 @@ public: static bool CheckFilter(JsonObject *document); static bool CheckIdFormat(JsonObject *data); static bool CheckDocument(JsonObject *document); + static bool CheckProjection(JsonObject *projectionObj, std::vector> &path); }; using Key = std::vector; using Value = std::vector; 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 96813bed..eacd07e3 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 @@ -31,6 +31,7 @@ public: static ValueObject GetValueByFiled(JsonObject *node, const std::string& filed); 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* const node); static std::vector GetLeafValue(JsonObject *node); @@ -39,6 +40,7 @@ public: 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); }; } // DocumentDB diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp index d3e4bb6e..75a02013 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp @@ -25,7 +25,8 @@ namespace { #define KEY_ID "_id" constexpr const char *COLLECTION_PREFIX_GRD = "GRD_"; constexpr const char *COLLECTION_PREFIX_GM_SYS = "GM_SYS_"; -const int MAX_COLLECTION_NAME = 512; +const int MAX_COLLECTION_NAME = 511; +const int MAX_ID_LENS = 899; bool CheckCollectionNamePrefix(const std::string &name, const std::string &prefix) { @@ -52,7 +53,7 @@ bool CheckCommon::CheckCollectionName(const std::string &collectionName, std::st errCode = -E_INVALID_ARGS; return false; } - if (collectionName.length() + 1 > MAX_COLLECTION_NAME) { + if (collectionName.length() > MAX_COLLECTION_NAME) { errCode = -E_OVER_LIMIT; return false; } @@ -86,6 +87,9 @@ bool CheckCommon::CheckIdFormat(JsonObject *filterJson) if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { return false; } + if (idValue.GetStringValue().length() > MAX_ID_LENS) { + return false; + } return true; } @@ -104,4 +108,28 @@ bool CheckCommon::CheckDocument(JsonObject *documentObj) } return true; } + +bool CheckCommon::CheckProjection(JsonObject *projectionObj, std::vector> &path) +{ + if (projectionObj->GetChild().IsNull() != true) { + auto projectionObjChild = projectionObj->GetChild(); + if (JsonCommon::CheckProjectionField(&projectionObjChild) == false) { + GLOGE("projection json field format is illegal"); + return false; + } + } + for (int i = 0; i < path.size(); i++) { + for (auto fieldName : path[i]) { + for (int i = 0; i < fieldName.size(); i++) { + if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || ('_' == fieldName[i]))) { + return false; + } + if (i == 0 && (isdigit(fieldName[i]))) { + return false; + } + } + } + } + return true; +} } // namespace DocumentDB \ 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 2b91eebf..925b601d 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 @@ -64,13 +64,14 @@ std::vector JsonCommon::GetLeafValue(JsonObject *node) return leafValue; } -bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, bool &errFlag) { +bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, bool &errFlag) +{ if (errFlag == false) { return false; } std::string fieldName; if (node->IsNull() != true) { - int ret; + int ret = 0; fieldName = node->GetItemFiled(ret); if (filedSet.find(fieldName) == filedSet.end()) { if (ret == E_OK) { @@ -86,11 +87,11 @@ bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, boo return false; } for (int i = 0; i < fieldName.size(); i++) { - if (!(('a'<=fieldName[i] && fieldName[i]<='z')|| ('A'<=fieldName[i] && fieldName[i]<='Z') || ('0'<=fieldName[i] && fieldName[i]<='9') || '_' == fieldName[i])) { + if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || '_' == fieldName[i])) { errFlag = false; return false; } - if (i == 0 && ('0'<=fieldName[i] && fieldName[i]<='9')) { + if (i == 0 && (isdigit(fieldName[i]))) { errFlag = false; return false; } @@ -108,12 +109,66 @@ bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, boo return errFlag; } -bool JsonCommon::CheckJsonField(JsonObject *jsonObj) { +bool JsonCommon::CheckJsonField(JsonObject *jsonObj) +{ std::set filedSet; bool errFlag = true; return CheckNode(jsonObj, filedSet, errFlag); } +bool JsonCommon::CheckProjectionNode(JsonObject *node, std::set filedSet, bool &errFlag, bool isFirstFloor) +{ + if (errFlag == false) { + return false; + } + std::string fieldName; + if (node->IsNull() != true) { + int ret = 0; + fieldName = node->GetItemFiled(ret); + if (filedSet.find(fieldName) == filedSet.end()) { + if (ret == E_OK) { + filedSet.insert(fieldName); + } + if (ret == E_OK && fieldName == "") { + errFlag = false; + return false; + } + } + else { + errFlag = false; + return false; + } + for (int i = 0; i < fieldName.size(); i++) { + if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || ('_' == fieldName[i]) || (isFirstFloor == true && '.' == fieldName[i]))) { + errFlag = false; + return false; + } + if (i == 0 && (isdigit(fieldName[i]))) { + errFlag = false; + return false; + } + } + } + if (node->GetChild().IsNull() != true) { + auto nodeNew = node->GetChild(); + std::set newFiledSet; + CheckProjectionNode(&nodeNew, newFiledSet, errFlag, false); + } + if (node->GetNext().IsNull() != true) { + auto nodeNew = node->GetNext(); + CheckProjectionNode(&nodeNew, filedSet, errFlag, isFirstFloor); + } + return errFlag; +} + +bool JsonCommon::CheckProjectionField(JsonObject *jsonObj) +{ + std::set filedSet; + bool errFlag = true; + bool isFirstFloor = true; + return CheckProjectionNode(jsonObj, filedSet, errFlag, isFirstFloor); +} + int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor) { std::vector fatherPath; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp index bd23a4f5..d5c11a5d 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp @@ -25,6 +25,10 @@ using namespace DocumentDB; int GRD_Next(GRD_ResultSet *resultSet) { + if (resultSet == nullptr) { + GLOGE("resultSet is nullptr"); + return GRD_INVALID_ARGS; + }; std::mutex dbMutex; std::lock_guard lock(dbMutex); int ret = resultSet->resultSet_->GetNext(); @@ -33,10 +37,14 @@ int GRD_Next(GRD_ResultSet *resultSet) int GRD_GetValue(GRD_ResultSet *resultSet, char **value) { + if (resultSet == nullptr) { + GLOGE("resultSet is nullptr,cant get value from it"); + return GRD_INVALID_ARGS; + }; char *val = nullptr; int ret = resultSet->resultSet_->GetValue(&val); if (val == nullptr) { - return GRD_NO_DATA; + return GRD_NOT_AVAILABLE; } *value = val; return TrasnferDocErr(ret); @@ -54,7 +62,7 @@ int GRD_FreeValue(char *value) int GRD_FreeResultSet(GRD_ResultSet *resultSet) { if (resultSet == nullptr) { - return GRD_OK; + return GRD_INVALID_ARGS; } delete[] resultSet; return GRD_OK; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index f5deac52..0b805ef5 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -70,7 +70,7 @@ int GRD_UpSertDoc(GRD_DB *db, const char *collectionName, const char *filter, co int GRD_InsertDoc(GRD_DB *db, const char *collectionName, const char *document, unsigned int flags) { - if (db == nullptr || db->store_ == nullptr || collectionName == nullptr) { + if (db == nullptr || db->store_ == nullptr || collectionName == nullptr || document == nullptr) { return GRD_INVALID_ARGS; } int ret = db->store_->InsertDocument(collectionName, document, flags); @@ -88,13 +88,15 @@ int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, un int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned int flags, GRD_ResultSet **resultSet) { - if (db == nullptr || db->store_ == nullptr || collectionName == nullptr || resultSet == nullptr) { + if (db == nullptr || db->store_ == nullptr || collectionName == nullptr || resultSet == nullptr || query.filter == nullptr + || query.projection == nullptr) { return GRD_INVALID_ARGS; } GRD_ResultSet *tmp = new GRD_ResultSet(); int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, tmp->resultSet_); if (ret != E_OK) { delete[] tmp; + *resultSet = nullptr; return TrasnferDocErr(ret); } *resultSet = tmp; 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 625066b0..fe7adbaf 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 @@ -15,7 +15,7 @@ struct ProjectionNode { int Deep; int ViewType; ProjectionNode() { - Deep = 1; + Deep = 0; isDeepest = true; } }; 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 63d7d3fd..1ae2f79e 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 @@ -25,6 +25,7 @@ #include "securec.h" #include "collection.h" #include "doc_common.h" +#include "json_common.h" namespace DocumentDB { 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 b3b9edd5..6904063e 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 @@ -187,11 +187,15 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri return errCode; } auto coll = Collection(collection, executor_); - int errCode1; if (filter == "") { GLOGE("Filter is empty"); return -E_INVALID_ARGS; } + if (filter.length() + 1 > JSON_LENS_MAX) { + GLOGE("filter's length is larger than JSON_LENS_MAX"); + return -E_OVER_LIMIT; + } + int errCode1; JsonObject filterObj = JsonObject::Parse(filter, errCode1); if (errCode1 != E_OK) { GLOGE("filter Parsed faild"); @@ -215,19 +219,26 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet) { + if (flags != 0 && flags != GRD_DOC_ID_DISPLAY) { + return -E_INVALID_ARGS;; + } std::string lowerCaseCollName; int errCode = E_OK; if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { GLOGE("Check collection name invalid. %d", errCode); return errCode; } + if (filter.length() + 1 > JSON_LENS_MAX) { + GLOGE("filter's length is larger than JSON_LENS_MAX"); + return -E_OVER_LIMIT; + } int errCode1; JsonObject filterObj = JsonObject::Parse(filter, errCode1); if (errCode1 != E_OK) { GLOGE("filter Parsed faild"); return errCode1; } - if (!CheckCommon::CheckFilter(&filterObj)) { + if (!CheckCommon::CheckFilter(&filterObj)) { GLOGE("Filter format is illegal"); return -E_INVALID_ARGS; } @@ -238,6 +249,10 @@ int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const return -E_INVALID_ARGS; } std::string filterId = idValue.GetStringValue(); + if (projection.length() + 1 > JSON_LENS_MAX) { + GLOGE("projection's length is larger than JSON_LENS_MAX"); + return -E_OVER_LIMIT; + } int errCode2; JsonObject projectionObj = JsonObject::Parse(projection, errCode2); if (errCode2 != E_OK) { @@ -247,11 +262,15 @@ int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const bool viewType = false; std::vector> allPath; if (projection != "{}") { + allPath = JsonCommon::ParsePath(&projectionObj); + if (!CheckCommon::CheckProjection(&projectionObj, allPath)) { + GLOGE("projection format unvalid"); + return -E_INVALID_ARGS; + } if (GetViewType(&projectionObj, viewType) != E_OK) { GLOGE("GetViewType faild"); return -E_INVALID_ARGS; } - allPath = JsonCommon::ParsePath(&projectionObj); } bool ifShowId = false; if (flags == GRD_DOC_ID_DISPLAY) { @@ -310,7 +329,7 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { break; case ValueObject::ValueType::VALUE_STRING: if (leafValue[i].GetStringValue() == "") { - if (viewType != false) { + if (viewType != true) { return -E_INVALID_ARGS; } } 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 3e076914..1f681efb 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 @@ -3,12 +3,11 @@ namespace DocumentDB { - +#define JSON_DEEP_MAX (4) ProjectionTree::ProjectionTree() { } ProjectionTree::~ProjectionTree() { - GLOGE("ProjectionTree free2222"); } int ProjectionTree::ParseTree(std::vector> &path) { @@ -22,15 +21,18 @@ int ProjectionTree::ParseTree(std::vector> &path) { if (node->SonNode[path[i][j]] != nullptr) { node = node->SonNode[path[i][j]]; if (j < path[i].size() - 1 && node->isDeepest == true) { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } if (j == path[i].size() - 1 && node->isDeepest == false) { - return E_INVALID_ARGS; + return -E_INVALID_ARGS; } } else { auto tempNode = new ProjectionNode; tempNode->Deep = node->Deep + 1; + if (tempNode->Deep > JSON_DEEP_MAX) { + return -E_INVALID_ARGS; + } node->isDeepest = false; node->SonNode[path[i][j]] = tempNode; node = node->SonNode[path[i][j]]; 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 368ae846..6f4fc330 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 @@ -28,10 +28,8 @@ int ResultSet::Init(Collection &coll, const std::string &key, std::vectorInit(); - if (projectionTree->ParseTree(path) == E_INVALID_ARGS) { + if (projectionTree->ParseTree(path) == -E_INVALID_ARGS) { GLOGE("Parse ProjectionTree failed"); - delete[] coll_; - delete[] projectionTree; return -E_INVALID_ARGS; } projectionTree_ = projectionTree; @@ -45,7 +43,10 @@ int ResultSet::GetNext() { index_++; if (index_ != 1) { - return E_OK; + if (findValue_.size() != 0) { + findValue_.pop_back(); + } + return -E_NO_DATA; } Value document; if (key_ == "") { @@ -107,7 +108,7 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat int ResultSet::CutString(std::string &jsonData) { int errCode; - JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode); + JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode, true); if (errCode != E_OK) { GLOGE("jsonData Parsed faild"); return errCode; @@ -120,18 +121,18 @@ int ResultSet::CutString(std::string &jsonData) CheckCutNode(&cjsonObjChild, singlePath, allPath); for (int i = 0; i < allPath.size(); i++) { if (ifShowId_ == false || allPath[i][0] != KEY_ID) { - cjsonObj.DeleteItemOnTarget(allPath[i]); + cjsonObj.DeleteItemDeeplyOnTarget(allPath[i]); } } } if (viewType_ == false) { for (int i = 0; i < path_.size(); i++) { - cjsonObj.DeleteItemOnTarget(path_[i]); + cjsonObj.DeleteItemDeeplyOnTarget(path_[i]); } if (ifShowId_ == false) { std::vector idPath; idPath.emplace_back(KEY_ID); - cjsonObj.DeleteItemOnTarget(idPath); + cjsonObj.DeleteItemDeeplyOnTarget(idPath); } } jsonData = cjsonObj.Print(); 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 ec22220d..54f4ea57 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 @@ -86,6 +86,7 @@ public: JsonObject FindItem(const JsonFieldPath &jsonPath, int &errCode) const; ValueObject GetObjectByPath(const JsonFieldPath &jsonPath, int &errCode) const; int DeleteItemOnTarget(const JsonFieldPath &path); + int DeleteItemDeeplyOnTarget(const JsonFieldPath &path); bool IsNull() const; enum class Type { 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 ea151d93..ab30fbd2 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 @@ -177,7 +177,7 @@ int JsonObject::Init(const std::string &str) GLOGE("Deep is longer than JSON_DEEP_MAX"); return -E_INVALID_ARGS; } - int ret; + int ret = 0; CheckNumber(cjson_, ret); if (ret == E_INVALID_ARGS) { GLOGE("Int value is larger than double"); @@ -491,4 +491,50 @@ int JsonObject::DeleteItemOnTarget(const JsonFieldPath &path) return E_OK; } + +int JsonObject::DeleteItemDeeplyOnTarget(const JsonFieldPath &path) +{ + if (path.empty()) { + return -E_INVALID_ARGS; + } + + std::string fieldName = path.back(); + JsonFieldPath patherPath = path; + patherPath.pop_back(); + + int errCode = E_OK; + cJSON *nodeFather = MoveToPath(cjson_, patherPath, caseSensitive_); + if (nodeFather == nullptr) { + GLOGE("Delete item failed, json field path not found."); + return -E_JSON_PATH_NOT_EXISTS; + } + + if (nodeFather->type == cJSON_Object) { + if (caseSensitive_) { + cJSON_DeleteItemFromObjectCaseSensitive(nodeFather, fieldName.c_str()); + if (nodeFather->child == nullptr && path.size() > 1) { + JsonFieldPath fatherPath(path.begin(), path.end() - 1); + DeleteItemDeeplyOnTarget(fatherPath); + } + } else { + cJSON_DeleteItemFromObject(nodeFather, fieldName.c_str()); + if (nodeFather->child == nullptr && path.size() > 1) { + JsonFieldPath fatherPath(path.begin(), path.end() - 1); + DeleteItemDeeplyOnTarget(fatherPath); + } + } + } else if (nodeFather->type == cJSON_Array) { + if (!IsNumber(fieldName)) { + GLOGW("Invalid json field path, expect array index."); + return -E_JSON_PATH_NOT_EXISTS; + } + cJSON_DeleteItemFromArray(nodeFather, std::stoi(fieldName)); + if (nodeFather->child == nullptr && path.size() > 1) { + JsonFieldPath fatherPath(path.begin(), path.end() - 1); + DeleteItemDeeplyOnTarget(fatherPath); + } + } + + return E_OK; +} } // namespace DocumentDB 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 346b4f27..8cff9d6f 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 @@ -24,6 +24,7 @@ #define COLLECTION_NAME "student" #define NULL_JSON_STR "{}" +const int MAX_COLLECTION_LENS = 511; using namespace testing::ext; namespace { @@ -114,19 +115,13 @@ static void ChkDeleteResWithFilter(const char *filter) query.filter = filter; const char *projection = "{}"; query.projection = projection; - GRD_ResultSet *resultSet; - resultSet = new GRD_ResultSet; + GRD_ResultSet *resultSet = nullptr; EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); /** * @tc.steps:step2. The resultset should be NULL * @tc.expected: step2. GRD_OK */ EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); - char **test; - test = new char*[1]; - test[0] = new char[521 + 1]; - EXPECT_EQ(GRD_GetValue(resultSet, test), GRD_NO_DATA); - EXPECT_EQ(GRD_FreeValue(test[0]), GRD_OK); EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } @@ -265,6 +260,26 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, TestSize.Level1) EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } +/** + * @tc.name: DocumentDelete007 + * @tc.desc: Test delete with too long collectionName. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentDeleteApiTest, DeleteDBTest007, TestSize.Level1) +{ + const char *filter = "{\"_id\" : \"1\"}"; + string collectionName1(MAX_COLLECTION_LENS, 'a'); + EXPECT_EQ(GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName1.c_str(), filter, 0), GRD_OK); + EXPECT_EQ(GRD_DropCollection(g_db, collectionName1.c_str(), 0), GRD_OK); + + string collectionName2(MAX_COLLECTION_LENS + 1, 'a'); + EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName2.c_str(), filter, 0), GRD_OVER_LIMIT); +} + + /** * @tc.name: DocumentDelete008 * @tc.desc: Test delete with invalid NULL input for all parameters. 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 4468665c..6bb054d7 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 @@ -21,47 +21,76 @@ #include "grd_base/grd_type_export.h" #include "grd_type_inner.h" #include "grd_base/grd_resultset_api.h" +#include "doc_errno.h" +#include "log_print.h" +#include "documentdb_test_utils.h" + using namespace testing::ext; namespace { std::string path = "./document.db"; GRD_DB *g_db = nullptr; +#define E_OK (0) +#define COLLECTION_NAME "student" +const int MAX_COLLECTION_NAME = 511; +const int INT_MAX = 2147483647; +const int INT_MIN = -2147483648; static const char *g_document1 = "{\"_id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"personInfo\":\ -{\"school\":\"AB\", \"age\" : 51}}"; -static const char *g_document_test = "{\"_id\" : \"weatherUri_1_com.acts.test\"}"; + {\"school\":\"AB\", \"age\" : 51}}"; static const char *g_document2 = "{\"_id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"personInfo\":\ -[1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; + [1, \"my string\", {\"school\":\"AB\", \"age\" : 51}, true, {\"school\":\"CD\", \"age\" : 15}, false]}"; static const char *g_document3 = "{\"_id\" : \"3\", \"name\":\"doc3\",\"item\":\"notebook\",\"personInfo\":\ -[{\"school\":\"C\", \"age\" : 5}]}"; + [{\"school\":\"C\", \"age\" : 5}]}"; static const char *g_document4 = "{\"_id\" : \"4\", \"name\":\"doc4\",\"item\":\"paper\",\"personInfo\":\ -{\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; + {\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; static const char *g_document5 = "{\"_id\" : \"5\", \"name\":\"doc5\",\"item\":\"journal\",\"personInfo\":\ -[{\"sex\" : \"woma\", \"school\" : \"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; + [{\"sex\" : \"woma\", \"school\" : \"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; static const char *g_document6 = "{\"_id\" : \"6\", \"name\":\"doc6\",\"item\":false,\"personInfo\":\ -[{\"school\":\"B\", \"teacher\" : \"mike\",\"age\" : 15}, {\"school\":\"C\", \"teacher\" : \"moon\",\"age\" : 20}]}"; + [{\"school\":\"B\", \"teacher\" : \"mike\",\"age\" : 15}, {\"school\":\"C\", \"teacher\" : \"moon\",\"age\" : 20}]}"; static const char *g_document7 = "{\"_id\" : \"7\", \"name\":\"doc7\",\"item\":\"fruit\",\"other_Info\":\ -[{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; + [{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; static const char *g_document8 = "{\"_id\" : \"8\", \"name\":\"doc8\",\"item\":true,\"personInfo\":\ -[{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; + [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}"; static const char *g_document9 = "{\"_id\" : \"9\", \"name\":\"doc9\",\"item\": true}"; static const char *g_document10 = "{\"_id\" : \"10\", \"name\":\"doc10\", \"parent\" : \"kate\"}"; static const char *g_document11 = "{\"_id\" : \"11\", \"name\":\"doc11\", \"other\" : \"null\"}"; static const char *g_document12 = "{\"_id\" : \"12\", \"name\":\"doc12\",\"other\" : null}"; static const char *g_document13 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"personInfo\":\ -{\"school\":\"AB\", \"age\" : 15}}"; -static const char *g_document14 = "{\"_id\" : \"13\", \"name\":\"doc13\",\"item\" : \"shoes\",\"personInfo\":\ -{\"school\":\"AB\", \"age\" : 15}}"; + {\"school\":\"AB\", \"age\" : 15}}"; +static const char *g_document14 = "{\"_id\" : \"14\", \"name\":\"doc14\",\"item\" : true,\"personInfo\":\ + [{\"school\":\"B\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 85}]}"; +static const char *g_document15 = "{\"_id\" : \"15\", \"name\":\"doc15\",\"personInfo\":[{\"school\":\"C\", \"age\" : 5}]}"; +static const char *g_document16 = "{\"_id\" : \"16\", \"name\":\"doc16\", \"nested1\":{\"nested2\":{\"nested3\":\ + {\"nested4\":\"ABC\", \"field2\":\"CCC\"}}}}"; +static const char *g_document17 = "{\"_id\" : \"17\", \"name\":\"doc17\",\"personInfo\":\"oh,ok\"}"; +static const char *g_document18 = "{\"_id\" : \"18\", \"name\":\"doc18\",\"item\" : \"mobile phone\",\"personInfo\":\ + {\"school\":\"DD\", \"age\":66}, \"color\":\"blue\"}"; +static const char *g_document19 = "{\"_id\" : \"19\", \"name\":\"doc19\",\"ITEM\" : true,\"PERSONINFO\":\ + {\"school\":\"AB\", \"age\":15}}"; +static const char *g_document20 = "{\"_id\" : \"20\", \"name\":\"doc20\",\"ITEM\" : true,\"personInfo\":\ + [{\"SCHOOL\":\"B\", \"AGE\":15}, {\"SCHOOL\":\"C\", \"AGE\":35}]}"; -// static std::vectorg_data = {g_document1, g_document2, g_document3, g_document4, g_document5, g_document6, g_document7, -// g_document8}; -static std::vectorg_data = {g_document1, g_document_test}; +static std::vectorg_data = {g_document1, g_document2, g_document3, g_document4, g_document5, g_document6, g_document7, + g_document8, g_document9, g_document10, g_document11, g_document12, g_document13, g_document14, g_document15, g_document16, g_document17, g_document18, g_document19, g_document20}; -static void InsertData(GRD_DB *g_db, const char *collectionName) { +static void InsertData(GRD_DB *g_db, const char *collectionName) +{ for (const auto &item : g_data) { EXPECT_EQ(GRD_InsertDoc(g_db, collectionName, item, 0), GRD_OK); } } + +static void CompareValue(const char *value, const char *targetValue) +{ + int errCode1; + DocumentDB::JsonObject valueObj = DocumentDB::JsonObject::Parse(value, errCode1); + EXPECT_EQ(errCode1, E_OK); + int errCode2; + DocumentDB::JsonObject targetValueObj = DocumentDB::JsonObject::Parse(targetValue, errCode2); + EXPECT_EQ(errCode2, E_OK); + EXPECT_EQ(valueObj.Print(), targetValueObj.Print()); +} } class DocumentFindApiTest : public testing::Test { @@ -77,7 +106,7 @@ void DocumentFindApiTest::SetUpTestCase(void) std::string path = "./document.db"; int status = GRD_DBOpen(path.c_str(), nullptr, GRD_DB_OPEN_CREATE, &g_db); EXPECT_EQ(status, GRD_OK); - EXPECT_EQ(GRD_CreateCollection(g_db, "student", "", 0), GRD_OK); + EXPECT_EQ(GRD_CreateCollection(g_db, COLLECTION_NAME, "", 0), GRD_OK); EXPECT_NE(g_db, nullptr); } @@ -98,26 +127,1289 @@ void DocumentFindApiTest::TearDown(void) /** - * @tc.name: DocumentDelete001 + * @tc.name: DocumentFindApiTest001 * @tc.desc: Test Insert document db * @tc.type: FUNC * @tc.require: * @tc.author: mazhao */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest001, 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\" : \"6\"}"; + 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); +} + +/** + * @tc.name: DocumentFindApiTest002 + * @tc.desc: Test filter with multiple fields and _id. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest002, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter with multiple and _id. and get the record according to filter condition. + * @tc.expected: step1. Faild to get the record, the result is GRD_INVALID_ARGS, GRD_GetValue return GRD_NOT_AVAILABLE and GRD_Next return GRD_NO_DATA. + */ + 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); + /** + * @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); + char *value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest004 + * @tc.desc: test filter with string filter without _id. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest004, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter without _id and get the record according to filter condition. + * @tc.expected: step1. Faild to get the record, the result is GRD_INVALID_ARGS, + */ + 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); + + /** + * @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_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), 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_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: DocumentFindApiTest006 + * @tc.desc: test filter field with id which has different type of value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest006, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter with _id which value is string + * @tc.expected: step1. Faild to get the record, the result is GRD_INVALID_ARGS, + */ + GRD_ResultSet *resultSet1 = nullptr; + const char *filter1 = "{\"_id\" : \"valstring\"}"; + Query query1 = {filter1, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query1, 1, &resultSet1), GRD_OK); + + /** + * @tc.steps: step2. Create filter with _id which value is number + * @tc.expected: step2. Faild to get the record, the result is GRD_INVALID_ARGS, + */ + GRD_ResultSet *resultSet2 = nullptr; + const char *filter2 = "{\"_id\" : 1}"; + Query query2 = {filter2, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query2, 1, &resultSet2), GRD_INVALID_ARGS); + + /** + * @tc.steps: step3. Create filter with _id which value is array + * @tc.expected: step3. Faild to get the record, the result is GRD_INVALID_ARGS, + */ + GRD_ResultSet *resultSet3 = nullptr; + const char *filter3 = "{\"_id\" : [\"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 _id which value is object + * @tc.expected: step4. Faild to get the record, the result is GRD_INVALID_ARGS, + */ + GRD_ResultSet *resultSet4 = nullptr; + const char *filter4 = "{\"_id\" : {\"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 _id which value is bool + * @tc.expected: step5. Faild to get the record, the result is GRD_INVALID_ARGS, + */ + GRD_ResultSet *resultSet5 = nullptr; + const char *filter5 = "{\"_id\" : true}"; + Query query5 = {filter5, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query5, 1, &resultSet5), GRD_INVALID_ARGS); + + /** + * @tc.steps: step6. Create filter with _id which value is null + * @tc.expected: step6. Faild to get the record, the result is GRD_INVALID_ARGS, + */ + GRD_ResultSet *resultSet6 = nullptr; + const char *filter6 = "{\"_id\" : null}"; + Query query6 = {filter6, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query6, 1, &resultSet6), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest016 + * @tc.desc: Test filter with collection Name is invalid. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest016, TestSize.Level1) +{ + const char *colName1 = "grd_type"; + const char *colName2 = "GM_SYS_sysfff"; + GRD_ResultSet *resultSet = NULL; + const char *filter = "{\"_id\" : \"1\"}"; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, colName1, query, 1, &resultSet), GRD_INVALID_FORMAT); + EXPECT_EQ(GRD_FindDoc(g_db, colName2, query, 1, &resultSet), GRD_INVALID_FORMAT); +} + +// /** +// * @tc.name: DocumentFindApiTest017 +// * @tc.desc: Test filter field with large filter +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentFindApiTest, DocumentFindApiTest017, TestSize.Level1) +// { +// GRD_ResultSet *resultSet = nullptr; +// string documentPart1 = "{\"_id\" : \"18\", \"item\" :\" "; +// string documentPart2 = "\" }"; +// string jsonVal = string(512 * 1024 - documentPart1.size() - documentPart2.size() - 1, 'k'); +// string document = documentPart1 + jsonVal + documentPart2; +// string jsonVal1 = string(512 * 1024 - documentPart1.size() - documentPart2.size(), 'k'); +// string document1 = documentPart1 + jsonVal1 + documentPart2; + +// Query query = {document.c_str(), "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); +// EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); +// char *value = NULL; +// EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_NOT_AVAILABLE); +// EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + +// query = {document1.c_str(), "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OVER_LIMIT); +// } + +/** + * @tc.name: DocumentFindApiTest019 + * @tc.desc: Test filter field with no result + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest019, TestSize.Level1) +{ + const char *filter = "{\"_id\" : \"100\"}"; + 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_NO_DATA); + char *value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_NOT_AVAILABLE); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +// /** +// * @tc.name: DocumentFindApiTest023 +// * @tc.desc: Test filter field with double find. +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentFindApiTest, DocumentFindApiTest023, 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 *collectionName = "CollEctionNname"; +// const char *filter = "{\"_id\" : \"6\"}"; +// GRD_ResultSet *resultSet = nullptr; +// GRD_ResultSet *resultSet2 = nullptr; +// Query query = {filter, "{}"}; +// EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 1, &resultSet), GRD_OK); +// EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 1, &resultSet2), GRD_RESOURCE_BUSY); + +// 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); +// EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 1, &resultSet), GRD_OK); +// EXPECT_EQ(GRD_Next(resultSet), GRD_OK); +// value = nullptr; +// EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); +// CompareValue(value, g_document6); +// EXPECT_EQ(GRD_FreeValue(value), GRD_OK); +// EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +// } + +/** + * @tc.name: DocumentFindApiTest024 + * @tc.desc: Test filter field with multi collections + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest024, TestSize.Level1) +{ + const char *filter = "{\"_id\" : \"6\"}"; + GRD_ResultSet *resultSet = nullptr; + GRD_ResultSet *resultSet2 = nullptr; + Query query = {filter, "{}"}; + const char* collectionName = "DocumentFindApiTest024"; + EXPECT_EQ(GRD_CreateCollection(g_db, collectionName, "", 0), GRD_OK); + InsertData(g_db, collectionName); + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 1, &resultSet2), 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); + + EXPECT_EQ(GRD_Next(resultSet2), GRD_OK); + char *value2 = NULL; + EXPECT_EQ(GRD_GetValue(resultSet2, &value2), GRD_OK); + CompareValue(value2, g_document6); + EXPECT_EQ(GRD_FreeValue(value2), GRD_OK); + + EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); + EXPECT_EQ(GRD_Next(resultSet2), GRD_NO_DATA); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_NOT_AVAILABLE); + EXPECT_EQ(GRD_GetValue(resultSet2, &value), GRD_NOT_AVAILABLE); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet2), GRD_OK); + + EXPECT_EQ(GRD_DropCollection(g_db, collectionName, 0), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest025 + * @tc.desc: Test nested projection, with viewType equals to 1. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest025, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document16, _id flag is 0. + * Create projection to display name,nested4. + * @tc.expected: step1. resultSet init successfuly, the result is GRD_OK, + */ + const char *filter = "{\"_id\" : \"16\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\": true, \"nested1.nested2.nested3.nested4\":true}"; + const char *targetDocument = "{\"name\":\"doc16\", \"nested1\":{\"nested2\":{\"nested3\":\ + {\"nested4\":\"ABC\"}}}}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + /** + * @tc.steps: step2. After loop, cannot get more record. + * @tc.expected: step2. 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); + /** + * @tc.steps: step3. Create filter to match g_document16, _id flag is 0; + * Create projection to display name、nested4 with different projection format. + * @tc.expected: step3. succeed to get the record. + */ + projectionInfo = "{\"name\": true, \"nested1\":{\"nested2\":{\"nested3\":{\"nested4\":true}}}}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + /** + * @tc.steps: step4. After loop, cannot get more record. + * @tc.expected: step4. 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); + /** + * @tc.steps: step5. Create filter to match g_document16, _id flag is 0. + * Create projection to conceal name,nested4 with different projection format. + * @tc.expected: step5. succeed to get the record. + */ + projectionInfo = "{\"name\": 0, \"nested1.nested2.nested3.nested4\":0}"; + targetDocument = "{\"nested1\":{\"nested2\":{\"nested3\":{\"field2\":\"CCC\"}}}}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest026 + * @tc.desc: Test nested projection, with _id flag equals to 1. Projection is 5 level. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest026, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document16, _id flag is 0. + * Create projection to display name,nested5 + * @tc.expected: step1. Error GRD_INVALID_ARGS. + */ + const char *filter = "{\"_id\" : \"16\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\": true, \"nested1.nested2.nested3.nested4.nested5\":true}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_INVALID_ARGS); + /** + * @tc.steps: step2. After loop, cannot get more record. + * @tc.expected: step2. Return GRD_NO_DATA. + */ + EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest027 + * @tc.desc: Test projection with invalid field, _id field equals to 1. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest027, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document7, _id flag is 0. + * Create projection to display name, other _info and non existing field. + * @tc.expected: step1. Match the g_document7 and display name, other_info + */ + const char *filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\": true, \"other_Info\":true, \"non_exist_field\":true}"; + const char *targetDocument = "{\"name\": \"doc7\", \"other_Info\":[{\"school\":\"BX\", \"age\":15},\ + {\"school\":\"C\", \"age\":35}]}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step2. Create filter to match g_document7, _id flag is 0. + * Create projection to display name, other _info and existing field with space. + * @tc.expected: step2. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\": true, \"other_Info\":true, \" item \":true}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step3. Create filter to match g_document7, _id flag is 0. + * Create projection to display name, other _info and existing field with different case. + * @tc.expected: step3. Match the g_document7 and display name, other_Info. + */ + projectionInfo = "{\"name\": true, \"other_Info\":true, \"ITEM\": true}"; + query = {filter, projectionInfo}; + resultSet = nullptr; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest028 + * @tc.desc: Test projection with invalid field in Array,_id field equals to 1. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest028, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document7, _id flag is 0. + * Create projection to display name, non existing field in array. + * @tc.expected: step1. Match the g_document7 and display name, other_info. + */ + const char *filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\": true, \"other_Info.non_exist_field\":true}"; + const char *targetDocument = "{\"name\": \"doc7\"}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step2. Create filter to match g_document7, _id flag is 0. + * Create projection to display name, other _info and existing field with space. + * @tc.expected: step2. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\": true, \"other_Info\":{\"non_exist_field\":true}}"; + query = {filter, projectionInfo}; + resultSet = nullptr; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step3. Create filter to match g_document7, _id flag is 0. + * Create projection to display name, non existing field in array with index format. + * @tc.expected: step3. Match the g_document7 and display name, other_Info. + */ + projectionInfo = "{\"name\": true, \"other_Info.0\": true}"; + query = {filter, projectionInfo}; + resultSet = nullptr; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest029 + * @tc.desc: Test projection with path conflict._id field equals to 0. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest029, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document4, _id flag is 0. + * Create projection to display conflict path. + * @tc.expected: step1. Return GRD_INVALID_ARGS. + */ + const char *filter = "{\"_id\" : \"4\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"personInfo\": true, \"personInfo.grade\": true}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest030 + * @tc.desc: Test _id flag and field.None exist field. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest030, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document7, _id flag is 0. + * @tc.expected: step1. Match the g_document7 and return empty json. + */ + const char *filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"non_exist_field\":true}"; + int flag = 0; + const char *targetDocument = "{}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step2. Create filter to match g_document7, _id flag is 1. + * @tc.expected: step2. Match g_document7, and return a json with _id. + */ + resultSet = nullptr; + flag = 1; + targetDocument = "{\"_id\": \"7\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest031 + * @tc.desc: Test _id flag and field.Exist field with 1 value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest031, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document7, _id flag is 0. + * @tc.expected: step1. Match the g_document7 and return json with name, item. + */ + const char *filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\":true, \"item\":true}"; + int flag = 0; + const char *targetDocument = "{\"name\":\"doc7\", \"item\":\"fruit\"}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step2. Create filter to match g_document7, _id flag is 1. + * @tc.expected: step2. Match g_document7, and return a json with _id. + */ + resultSet = nullptr; + flag = 1; + projectionInfo = "{\"name\": 1, \"item\": 1}"; + targetDocument = "{\"_id\":\"7\", \"name\":\"doc7\", \"item\":\"fruit\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest032 + * @tc.desc: Test _id flag and field.Exist field with 1 value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest032, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document7, _id flag is 0. + * @tc.expected: step1. Match the g_document7 and return json with name, item. + */ + const char *filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\":true, \"item\":true}"; + int flag = 0; + const char *targetDocument = "{\"name\":\"doc7\", \"item\":\"fruit\"}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + /** + * @tc.steps: step2. Create filter to match g_document7, _id flag is 1. + * @tc.expected: step2. Match g_document7, and return a json with _id. + */ + resultSet = nullptr; + flag = 1; + projectionInfo = "{\"name\": 1, \"item\": 1}"; + targetDocument = "{\"_id\":\"7\", \"name\":\"doc7\", \"item\":\"fruit\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + /** + * @tc.steps: step3. Create filter to match g_document7, _id flag is 1.Projection value is not 0. + * @tc.expected: step3. Match g_document7, and return a json with name, item and _id. + */ + resultSet = nullptr; + flag = 1; + projectionInfo = "{\"name\": 10, \"item\": 10}"; + targetDocument = "{\"_id\":\"7\", \"name\":\"doc7\", \"item\":\"fruit\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest033 + * @tc.desc: Test _id flag and field.Exist field with 0 value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest033, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document7, _id flag is 0. + * @tc.expected: step1. Match the g_document7 and return json with name, item and _id + */ + const char *filter = "{\"_id\" : \"7\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\":false, \"item\":false}"; + int flag = 0; + const char *targetDocument = "{\"other_Info\":[{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}";; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + /** + * @tc.steps: step2. Create filter to match g_document7, _id flag is 1. + * @tc.expected: step2. Match g_document7, and return a json without name and item. + */ + resultSet = nullptr; + flag = 1; + projectionInfo = "{\"name\": 0, \"item\": 0}"; + targetDocument = "{\"_id\": \"7\", \"other_Info\":[{\"school\":\"BX\", \"age\" : 15}, {\"school\":\"C\", \"age\" : 35}]}";; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + value = NULL; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest034 + * @tc.desc: Test projection with nonexist field in nested structure. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest034, TestSize.Level1) +{ + /** + * @tc.steps: step1. Create filter to match g_document4, _id flag is 0. + * @tc.expected: step1. Match the g_document4 and return json without name + */ + const char *filter = "{\"_id\" : \"4\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\": 1, \"personInfo.grade1\": 1, \ + \"personInfo.shool1\": 1, \"personInfo.age1\": 1}"; + int flag = 0; + const char *targetDocument = "{\"name\":\"doc4\"}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step2. Create filter to match g_document4, _id flag is 0, display part of fields in nested structure. + * @tc.expected: step2. Match the g_document4 and return json without name + */ + projectionInfo = "{\"name\": false, \"personInfo.grade1\": false, \ + \"personInfo.shool1\": false, \"personInfo.age1\": false}"; + const char *targetDocument2 = "{\"item\":\"paper\",\"personInfo\":{\"grade\" : 1, \"school\":\"A\", \"age\" : 18}}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument2); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step3. Create filter to match g_document4, _id flag is 0, display part of fields in nested structure. + * @tc.expected: step3. Match the g_document4 and return json with name, personInfo.school and personInfo.age. + */ + projectionInfo = "{\"name\": 1, \"personInfo.school\": 1, \"personInfo.age\": 1}"; + const char *targetDocument3 = "{\"name\":\"doc4\", \"personInfo\": {\"school\":\"A\", \"age\" : 18}}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument3); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step4. Create filter to match g_document4, _id flag is 0, display part of fields in nested structure. + * @tc.expected: step4. Match the g_document4 and return json with name, personInfo.school + */ + projectionInfo = "{\"name\": 1, \"personInfo.school\": 1, \"personInfo.age1\": 1}"; + const char *targetDocument4 = "{\"name\":\"doc4\", \"personInfo\": {\"school\":\"A\"}}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument4); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest035 + * @tc.desc: test filter with id string filter + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest035, 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_document17 + */ + const char *filter = "{\"_id\" : \"17\"}"; + GRD_ResultSet *resultSet = nullptr; + int flag = 0; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, GRD_DOC_ID_DISPLAY, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, g_document17); + 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); +} + +/** + * @tc.name: DocumentFindApiTest036 + * @tc.desc: Test with invalid collectionName. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest036, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test with invalid collectionName. + * @tc.expected: step1. Return GRD_INVALID_ARGS. + */ + const char *filter = "{\"_id\" : \"17\"}"; + GRD_ResultSet *resultSet = nullptr; + int flag = 0; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, "", query, 0, &resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FindDoc(g_db, NULL, query, 0, &resultSet), GRD_INVALID_ARGS); +} -HWTEST_F(DocumentFindApiTest, DocumentFindApiTest, TestSize.Level1) +/** + * @tc.name: DocumentFindApiTest037 + * @tc.desc: Test filed with different value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest037, TestSize.Level1) { - const char *filter = "{\"_id\" : \"weatherUri_1_com.acts.test\"}"; - const char *projection = "{}"; - Query query; - query.filter = filter; - query.projection = projection; - GRD_ResultSet *resultSet; - EXPECT_EQ(GRD_FindDoc(g_db, "student", query, GRD_DOC_ID_DISPLAY, &resultSet), GRD_OK); - char **test = nullptr; - GRD_Next(resultSet); - char *result = NULL; - GRD_GetValue(resultSet, &result); - GRD_FreeValue(result); - GRD_FreeResultSet(resultSet); -} \ No newline at end of file + /** + * @tc.steps: step1. Test filed with different value.some are 1, other are 0. + * @tc.expected: step1. Return GRD_INVALID_ARGS. + */ + const char *filter = "{\"_id\" : \"4\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\":1, \"personInfo\":0, \"item\":1}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step2. Test filed with different value.some are 2, other are 0. + * @tc.expected: step2. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\":2, \"personInfo\":0, \"item\":2}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step3. Test filed with different value.some are 0, other are true. + * @tc.expected: step3. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\":true, \"personInfo\":0, \"item\":true}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step4. Test filed with different value.some are 0, other are "". + * @tc.expected: step4. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\":\"\", \"personInfo\":0, \"item\":\"\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step5. Test filed with different value.some are 1, other are false. + * @tc.expected: step5. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\":false, \"personInfo\":1, \"item\":false"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_FORMAT); + + /** + * @tc.steps: step6. Test filed with different value.some are -1.123, other are false. + * @tc.expected: step6. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\":false, \"personInfo\":-1.123, \"item\":false"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_FORMAT); + + /** + * @tc.steps: step7. Test filed with different value.some are true, other are false. + * @tc.expected: step7. Return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"name\":false, \"personInfo\":true, \"item\":false"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_FORMAT); +} + +/** + * @tc.name: DocumentFindApiTest038 + * @tc.desc: Test field with false value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest038, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test field with different false value. Some are false, other are 0. flag is 0. + * @tc.expected: step1. Match the g_document6 and return empty json. + */ + const char *filter = "{\"_id\" : \"6\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\":false, \"personInfo\": 0, \"item\":0}"; + int flag = 0; + const char *targetDocument = "{}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step2. Test field with different false value.Some are false, others are 0. flag is 1. + * @tc.expected: step2. Match g_document6, Return json with _id. + */ + targetDocument = "{\"_id\": \"6\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest039 + * @tc.desc: Test field with true value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest039, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test field with different true value. Some are true, other are 1. flag is 0. + * @tc.expected: step1. Match the g_document18 and return json with name, item, personInfo.age and color. + */ + const char *filter = "{\"_id\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"name\":true, \"personInfo.age\": \"\", \"item\":1, \"color\":10, \"nonExist\" : -100}"; + const char *targetDocument = "{\"name\":\"doc18\", \"item\":\"mobile phone\", \"personInfo\":\ + {\"age\":66}, \"color\":\"blue\"}"; + int flag = 0; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + char *value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + + /** + * @tc.steps: step2. Test field with different true value.Some are false, others are 0. flag is 1. + * @tc.expected: step2. Match g_document18, Return json with name, item, personInfo.age, color and _id. + */ + targetDocument = "{\"_id\" : \"18\", \"name\":\"doc18\",\"item\" : \"mobile phone\",\"personInfo\":\ + {\"age\":66}, \"color\":\"blue\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest040 + * @tc.desc: Test field with invalid value. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest040, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test field with invalid value.Value is array. + * @tc.expected: step1. Match the g_document18 and return GRD_INVALID_ARGS. + */ + const char *filter = "{\"_id\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"personInfo\":[true, 1]}"; + int flag = 1; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step2. Test field with invalid value.Value is null. + * @tc.expected: step2. Match the g_document18 and return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"personInfo\":null}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step3. Test field with invalid value.Value is invalid string. + * @tc.expected: step3. Match the g_document18 and return GRD_INVALID_ARGS. + */ + projectionInfo = "{\"personInfo\":\"invalid string.\"}"; + query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest042 + * @tc.desc: Test field with no existed uppercase filter + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest042, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test field with no existed uppercase filter. + * @tc.expected: step1. not match any item. + */ + const char *filter = "{\"_iD\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"Name\":true, \"personInfo.age\": \"\", \"item\":1, \"COLOR\":10, \"nonExist\" : -100}"; + int flag = 0; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, flag, &resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step2. Test field with upper projection. + * @tc.expected: step2. Match g_document18, Return json with item, personInfo.age, color and _id. + */ + const char *filter1 = "{\"_id\" : \"18\"}"; + const char* targetDocument = "{\"_id\" : \"18\", \"item\" : \"mobile phone\",\"personInfo\":\ + {\"age\":66}}"; + query = {filter1, projectionInfo}; + char *value = nullptr; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest044 + * @tc.desc: Test field with uppercase projection + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest044, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test with false uppercase projection + * @tc.expected: step1. Match g_document18, Return json with item, personInfo.age and _id. + */ + const char *filter = "{\"_id\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{\"Name\":0, \"personInfo.age\": false, \"personInfo.SCHOOL\": false, \"item\":\ + false, \"COLOR\":false, \"nonExist\" : false}"; + const char *targetDocument = "{\"_id\" : \"18\", \"name\":\"doc18\", \"personInfo\":\ + {\"school\":\"DD\"}, \"color\":\"blue\"}"; + int flag = 0; + Query query = {filter, projectionInfo}; + char *value = nullptr; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, targetDocument); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} + +/** + * @tc.name: DocumentFindApiTest045 + * @tc.desc: Test field with too long collectionName + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest045, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test with false uppercase projection + * @tc.expected: step1. Match g_document18, Return json with item, personInfo.age and _id. + */ + const char *filter = "{\"_id\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + int flag = 0; + Query query = {filter, "{}"}; + string collectionName1(MAX_COLLECTION_NAME, 'a'); + ASSERT_EQ(GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0), GRD_OK); + EXPECT_EQ(GRD_FindDoc(g_db, collectionName1.c_str(), query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + ASSERT_EQ(GRD_DropCollection(g_db, collectionName1.c_str(), 0), GRD_OK); + + string collectionName2(MAX_COLLECTION_NAME + 1, 'a'); + EXPECT_EQ(GRD_FindDoc(g_db, collectionName2.c_str(), query, 1, &resultSet), GRD_OVER_LIMIT); + EXPECT_EQ(GRD_FindDoc(g_db, "", query, 1, &resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest052 + * @tc.desc: Test field when id string len is large than max + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest052, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test with false uppercase projection + * @tc.expected: step1. Match g_document18, Return json with item, personInfo.age and _id. + */ + const char *filter = "{\"_id\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + int flag = 0; + Query query = {filter, "{}"}; + string collectionName1(MAX_COLLECTION_NAME, 'a'); + ASSERT_EQ(GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0), GRD_OK); + EXPECT_EQ(GRD_FindDoc(g_db, collectionName1.c_str(), query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); + ASSERT_EQ(GRD_DropCollection(g_db, collectionName1.c_str(), 0), GRD_OK); + + string collectionName2(MAX_COLLECTION_NAME + 1, 'a'); + EXPECT_EQ(GRD_FindDoc(g_db, collectionName2.c_str(), query, 1, &resultSet), GRD_OVER_LIMIT); + EXPECT_EQ(GRD_FindDoc(g_db, "", query, 1, &resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest053 + * @tc.desc: Test with invalid flags + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest053, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test with invalid flags which is 3. + * @tc.expected: step1. Return GRD_INVALID_ARGS. + */ + const char *filter = "{\"_id\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 3, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps:step1.parameter flags is int_max + * @tc.expected:step1.GRD_INVALID_ARGS + */ + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, INT_MAX, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps:step1.parameter flags is INT_MIN + * @tc.expected:step1.GRD_INVALID_ARGS + */ + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, INT_MIN, &resultSet), GRD_INVALID_ARGS); +} + +/** + * @tc.name: DocumentFindApiTest054 + * @tc.desc: Test with null g_db and resultSet, filter. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest054, TestSize.Level1) +{ + /** + * @tc.steps: step1. Test with null g_db. + * @tc.expected: step1. Return GRD_INVALID_ARGS. + */ + const char *filter = "{\"_id\" : \"18\"}"; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{}"; + Query query = {filter, projectionInfo}; + EXPECT_EQ(GRD_FindDoc(nullptr, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); + + /** + * @tc.steps: step2. Test with null resultSet. + * @tc.expected: step2. Return GRD_INVALID_ARGS. + */ + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, nullptr), GRD_INVALID_ARGS); + + /** + * @tc.steps: step1. Test with query that has two nullptr data. + * @tc.expected: step1. Return GRD_INVALID_ARGS. + */ + query = {nullptr, nullptr}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); +} diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp index cb7b1c76..f5d045c3 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp @@ -22,16 +22,15 @@ using namespace testing::ext; namespace { std::string path = "./document.db"; GRD_DB *g_db = nullptr; -const char *right_collectionName = "student"; -const char *no_exsit_collectionName = "no_exisit"; -const int int_max = 2147483647; -const int int_min = -2147483648; -const int max_collection_lens = 511; +const char *RIGHT_COLLECTION_NAME = "student"; +const char *NO_EXIST_COLLECTION_NAME = "no_exisit"; +const int INT_MAX = 2147483647; +const int INT_MIN = -2147483648; +const int MAX_COLLECTION_LENS = 511; -static void TestInsertDocIntoCertainColl(const char *collectionName, const char *projection, int expectedResult) +static void TestInsertDocIntoCertainColl(const char *collectionName, const char *projection, int expectedResult) { - /** - * @tc.steps: step1. Create Collection + /** * @tc.steps: step1. Create Collection * @tc.expected: step1. GRD_OK */ EXPECT_EQ(GRD_CreateCollection(g_db, collectionName, "", 0), expectedResult); @@ -97,14 +96,14 @@ void DocumentInsertApiTest::TearDown(void) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest001, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest001, TestSize.Level1) { /** * @tc.steps:step1.Insert document into collection which dose not exist * @tc.expected:step1.GRD_INVALID_ARGS */ const char *document1 = "{\"_id\" : \"1\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, no_exsit_collectionName, document1, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, NO_EXIST_COLLECTION_NAME, document1, 0), GRD_INVALID_ARGS); } /** @@ -114,38 +113,38 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest001, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest002, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest002, TestSize.Level1) { /** * @tc.steps:step1.Insert a document whose _id is integer * @tc.expected:step1.GRD_INVALID_ARGS */ const char *document1 = "{\"_id\" : 2, \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_INVALID_ARGS); /** * @tc.steps:step2.Insert a document whose _id is bool * @tc.expected:step2.GRD_INVALID_ARGS */ const char *document2 = "{\"_id\" : true, \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2, 0), GRD_INVALID_ARGS); /** * @tc.steps:step2.Insert a document whose _id is NULL * @tc.expected:step2.GRD_INVALID_ARGS */ const char *document3 = "{\"_id\" : null, \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document3, 0), GRD_INVALID_ARGS); /** * @tc.steps:step2.Insert a document whose _id is ARRAY * @tc.expected:step2.GRD_INVALID_ARGS */ const char *document4 = "{\"_id\" : [\"2\"], \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document4, 0), GRD_INVALID_ARGS); /** * @tc.steps:step2.Insert a document whose _id is OBJECT * @tc.expected:step2.GRD_INVALID_ARGS */ const char *document5 = "{\"_id\" : {\"val\" : \"2\"}, \"name\" : \"Chuan\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document5, 0), GRD_INVALID_ARGS); } @@ -156,21 +155,21 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest002, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest003, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest003, TestSize.Level1) { /** * @tc.steps:step1.Insert a document whose _id is string * @tc.expected:step1.GRD_OK */ const char *document1 = "{\"_id\" : \"3\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); /** * @tc.steps:step2.Insert a document whose _id has appeared before * @tc.expected:step2.GRD_DATA_CONFLICT */ // const char *document2 = "{\"_id\" : \"3\", \"name\" : \"Chuan\"}"; - // EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_DATA_CONFLICT); + // EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2, 0), GRD_DATA_CONFLICT); } /** @@ -180,14 +179,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest003, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest004, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest004, TestSize.Level1) { /** * @tc.steps:step1.step1.parameter db is NULL * @tc.expected:step1.GRD_INVALID_ARGS */ const char *document1 = "{\"_id\" : \"4\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(NULL, right_collectionName, document1, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(NULL, RIGHT_COLLECTION_NAME, document1, 0), GRD_INVALID_ARGS); } /** @@ -197,7 +196,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest004, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest005, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest005, TestSize.Level1) { /** * @tc.steps:step1.Parameter collectionName is NULL @@ -220,14 +219,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest005, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest006, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest006, TestSize.Level1) { /** * @tc.steps:step1.parameter flags is not zero * @tc.expected:step1.GRD_INVALID_ARGS */ const char *document1 = "{\"_id\" : \"6\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 1), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 1), GRD_INVALID_ARGS); } /** @@ -237,14 +236,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest006, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest007, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest007, TestSize.Level1) { /** * @tc.steps:step1.parameter flags is int_max * @tc.expected:step1.GRD_INVALID_ARGS */ const char *document1 = "{\"_id\" : \"7\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_max), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, INT_MAX), GRD_INVALID_ARGS); } /** @@ -254,14 +253,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest007, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest008, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest008, TestSize.Level1) { /** * @tc.steps:step1.parameter flags is int_min * @tc.expected:step1.GRD_INVALID_ARGS */ const char *document1 = "{\"_id\" : \"8\", \"name\" : \"Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, int_min), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, INT_MIN), GRD_INVALID_ARGS); } /** @@ -271,7 +270,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest008, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest009, TestSize.Level1) { /** * @tc.steps:step1.parameter collectionName and document is NULL; @@ -282,8 +281,9 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) * @tc.steps:step2.parameter collectionName is larger than max_collectionName_lens; * @tc.expected:step2.GRD_OVER_LIMIT */ - // std::string collectionName2(max_collection_lens + 1, 'a'); - // EXPECT_EQ(GRD_InsertDoc(g_db, collectionName2.c_str(), JSON_STR_HASID, 0), GRD_OVER_LIMIT); + const char *document1 = "{\"_id\" : \"9\", \"name\" : \"Ori\"}"; + std::string collectionName2(MAX_COLLECTION_LENS + 1, 'a'); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName2.c_str(), document1, 0), GRD_OVER_LIMIT); } /** @@ -293,7 +293,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest009, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest010, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest010, TestSize.Level1) { /** * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor @@ -311,7 +311,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest010, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest011, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest011, TestSize.Level1) { /** * @tc.steps:step1.Create Collection whose parameter collectionName contains irregular charactor @@ -329,7 +329,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest011, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest014, TestSize.Level1) { /** * @tc.steps:step1.document's JSON depth is larger than 4, which is 5. @@ -337,7 +337,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) */ const char *document1 = "{\"level1\" : {\"level2\" : {\"level3\" : {\"level4\": {\"level5\" : 1}}, \"level3_2\" : \"level3_2_val\"\ }},\"_id\":\"14\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_INVALID_ARGS); /** * @tc.steps:step1.document's JSON depth is larger than 4, which is 5.But with array type. * @tc.expected:step1.GRD_INVALID_ARGS @@ -345,14 +345,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) const char *document2 = "{\"level1\" : {\"level2\" : {\"level3\" : [{ \"level5\" : \"level5_1val\", \"level5_2\":\ \"level5_2_val\"}, \"level4_val1\",\"level4_val2\"], \"level3_2\" : \"level3_2_val\"\ }},\"_id\":\"14\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2, 0), GRD_INVALID_ARGS); /** * @tc.steps:step1.document's JSON depth is 4 * @tc.expected:step1.GRD_OK */ const char *document3 = "{\"level1\" : {\"level2\" : {\"level3\" : { \"level4\" : \"level5_1val\"}, \"level3_2\" : \"level3_2_val\"\ }},\"_id\":\"14\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document3, 0), GRD_OK); } /** @@ -362,7 +362,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest014, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest015, TestSize.Level1) { /** * @tc.steps:step1.document's JSON is bigger than 512k - 1 @@ -372,14 +372,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) string documentPart2 = "\" }"; string jsonVal = string(512 * 1024 - documentPart1.size() - documentPart2.size(), 'k'); string document = documentPart1 + jsonVal + documentPart2; - //EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OVER_LIMIT); + //EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document.c_str(), 0), GRD_OVER_LIMIT); /** * @tc.steps:step2.Insert document's JSON is a large data but lower than 512k - 1 * @tc.expected:step2.GRD_OK */ string jsonVal2 = string(512 * 1024 - 1 - documentPart1.size() - documentPart2.size(), 'k'); string document2 = documentPart1 + jsonVal2 + documentPart2; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2.c_str(), 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2.c_str(), 0), GRD_OK); } /** @@ -389,14 +389,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest015, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest016, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest016, TestSize.Level1) { /** * @tc.steps:step1.document JSON string contains irregular char. * @tc.expected:step1.GRD_OK */ const char *document1 = "{\"_id\" : \"16\", \"name\" : \"!@#Ori\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); } /** @@ -406,7 +406,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest016, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest017, TestSize.Level1) { /** * @tc.steps:step1.document JSON string contains invalid value type such as BLOB type. @@ -414,7 +414,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) */ const char *document = "{\"_id\" : \"17\", \"level1\" : {\"level2\" : {\"level3\" : {\"level4\" : x'1234'\ } } }, \"level1_2\" : \"level1_2Val\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document, 0), GRD_INVALID_FORMAT); } /** @@ -424,14 +424,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest017, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest018, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest018, TestSize.Level1) { /** * @tc.steps:step1.The Inserted document is not JSON format * @tc.expected:step1.GRD_INVALID_FORMAT. */ const char *document = "some random string not JSON format"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document, 0), GRD_INVALID_FORMAT); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document, 0), GRD_INVALID_FORMAT); } /** @@ -441,14 +441,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest018, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest019, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest019, TestSize.Level1) { /** * @tc.steps:step1.Insert a normal documents which _id is in the end of the string * @tc.expected:step1.GRD_OK. */ const char *document1 = "{\"name\" : \"Jack\", \"age\" : 18, \"friend\" : {\"name\" : \" lucy\"}, \"_id\" : \"19\"}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); } /** @@ -458,13 +458,14 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest019, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest022, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest022, TestSize.Level1) { /** * @tc.steps:step1.parameter collectionName is equal to 256 charactors * @tc.expected:step1.GRD_OK. */ string collectionName = string(256, 'k'); + string collectionName1(MAX_COLLECTION_LENS, 'a'); const char *document1 = "{\"_id\" : \"22\", \"name\" : \"Ori\"}"; TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); } @@ -477,7 +478,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest022, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest023, TestSize.Level1) { /** * @tc.steps:step1.parameter collectionName contains upper & lower case charactors, @@ -489,6 +490,80 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) TestInsertDocIntoCertainColl(collectionName.c_str(), document1, GRD_OK); } +/** + * @tc.name: DocumentInsertApiTest024 + * @tc.desc: parameter collectionName's head is GRD_ or GM_SYS_ + * numbers and underline + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest024, TestSize.Level1) +{ + /** + * @tc.steps:step1.parameter collectionName's head is GRD_ + * @tc.expected:step1.GRD_INVALID_FORMAT. + */ + string collectionName = "GRD_collectionName"; + const char *document1 = "{\"_id\" : \"24\", \"name\" : \"Ori\"}"; + GRD_CreateCollection(g_db, collectionName.c_str(), "", 0); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName.c_str(), document1, 0), GRD_INVALID_FORMAT); + + /** + * @tc.steps:step2.parameter collectionName's head is GM_SYS_ + * @tc.expected:step2.GRD_INVALID_FORMAT. + */ + collectionName = "GM_SYS__collectionName"; + const char *document2 = "{\"_id\" : \"24_2\", \"name\" : \"Ori\"}"; + GRD_CreateCollection(g_db, collectionName.c_str(), "", 0); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName.c_str(), document2, 0), GRD_INVALID_FORMAT); + + /** + * @tc.steps:step3.parameter collectionName's head is grd_ + * @tc.expected:step3.GRD_INVALID_FORMAT. + */ + collectionName = "grd_collectionName"; + const char *document3 = "{\"_id\" : \"24_3\", \"name\" : \"Ori\"}"; + GRD_CreateCollection(g_db, collectionName.c_str(), "", 0); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName.c_str(), document3, 0), GRD_INVALID_FORMAT); + + /** + * @tc.steps:step4.parameter collectionName's head is gm_sys_ + * @tc.expected:step4.GRD_INVALID_FORMAT. + */ + collectionName = "gm_sys_collectionName"; + const char *document4 = "{\"_id\" : \"24_4\", \"name\" : \"Ori\"}"; + GRD_CreateCollection(g_db, collectionName.c_str(), "", 0); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName.c_str(), document4, 0), GRD_INVALID_FORMAT); + + /** + * @tc.steps:step5.parameter collectionName's head is gM_sYs_ that has Uppercase and lowercase at the same time. + * @tc.expected:step5.GRD_INVALID_FORMAT. + */ + collectionName = "gM_sYs_collectionName"; + const char *document5 = "{\"_id\" : \"24_5\", \"name\" : \"Ori\"}"; + GRD_CreateCollection(g_db, collectionName.c_str(), "", 0); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName.c_str(), document5, 0), GRD_INVALID_FORMAT); + + /** + * @tc.steps:step6.parameter collectionName's head is gRd_ that has Uppercase and lowercase at the same time. + * @tc.expected:step6.GRD_INVALID_FORMAT. + */ + collectionName = "gRd_collectionName"; + const char *document6 = "{\"_id\" : \"24_6\", \"name\" : \"Ori\"}"; + GRD_CreateCollection(g_db, collectionName.c_str(), "", 0); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName.c_str(), document6, 0), GRD_INVALID_FORMAT); + + /** + * @tc.steps:step7.parameter collectionName's head is grd@ that has no '_' + * @tc.expected:step7.GRD_INVALID_FORMAT. + */ + collectionName = "gRd@collectionName"; + const char *document7 = "{\"_id\" : \"24_7\", \"name\" : \"Ori\"}"; + GRD_CreateCollection(g_db, collectionName.c_str(), "", 0); + EXPECT_EQ(GRD_InsertDoc(g_db, collectionName.c_str(), document7, 0), GRD_OK); +} + /** * @tc.name: DocumentInsertApiTest025 * @tc.desc: Insert document whose depth is 4, which is allowed @@ -496,7 +571,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest023, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest025, TestSize.Level1) { /** * @tc.steps:step1.documents JSON depth is 4, which is allowed. @@ -504,28 +579,28 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) */ const char *document1 = "{\"_id\" : \"25_0\", \"level1\" : { \"level2\" : {\"level3\" :\ {\"level4\" : \"level4Val\" } } } , \"level1_2\" : \"level1_2Val\" }"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); /** * @tc.steps:step2.documents JSON depth is exactly 4. * @tc.expected:step2.GRD_OK. */ const char *document2 = "{\"_id\" : \"25_1\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\"] }]}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2, 0), GRD_OK); /** * @tc.steps:step3.documents JSON depth is exactly 4, but the last field in array contains leading number * @tc.expected:step3.GRD_INVALID_ARGS. */ const char *document3 = "{\"_id\" : \"25_2\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ \"age\" : 18, \"sex\" : \"男\"}, [\"qw\", \"dr\", 0, \"ab\", {\"0ab\" : null}]]}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document3, 0), GRD_INVALID_ARGS); /** * @tc.steps:step4.documents JSON depth is exactly 5. * @tc.expected:step4.GRD_INVALID_ARGS. */ const char *document4 = "{\"_id\" : \"25_3\", \"class_name\" : \"计算机科学一班\", \"signed_info\" : true, \"student_info\" : [{\"name\":\"张三\", \ \"age\" : 18, \"sex\" : \"男\"}, { \"newName1\" : [\"qw\", \"dr\", 0, \"ab\", {\"level5\" : 1}] }]}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document4, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document4, 0), GRD_INVALID_ARGS); } /** @@ -535,7 +610,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest025, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest, TestSize.Level1) { /** * @tc.steps:step1.Insert 100 normal documents continuously @@ -548,10 +623,37 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) for (int i = 0; i < 5; i++) { string document_midlle = {'2','6' + i}; string document = document1 + document2 + document_midlle + document4 + document5; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document.c_str(), 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document.c_str(), 0), GRD_OK); } } +/** + * @tc.name: DocumentInsertApiTest035 + * @tc.desc: Insert a document whose value contains + * upper &lower case charactors, numbers and underline. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest035, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a document whose value contains + * upper &lower case charactors, numbers and underline. + * @tc.expected:step1.GRD_OK. + */ + const char *document1 = "{\"_id\" : \"35\", \"A_aBdk_324_\" : \"value\", \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); + /** + * @tc.steps:step1.Insert a document whose value contains + * upper &lower case charactors, numbers and underline. + * But the field started with number, which is not allowed. + * @tc.expected:step1.GRD_OK. + */ + const char *document2 = "{\"_id\" : \"35_2\", \"1A_aBdk_324_\" : \"value\", \"name\" : \"Chuan\"}"; + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2, 0), GRD_INVALID_ARGS); +} + /** * @tc.name: DocumentInsertApiTest036 * @tc.desc: Insert a document whose value contains @@ -560,7 +662,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest026, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest036, TestSize.Level1) { /** * @tc.steps:step1.Insert a document whose value contains @@ -569,7 +671,7 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) */ const char *document1 = "{\"_id\" : \"36_0\", \"stringType\" : \"stringVal\", \"numType\" : 1, \"BoolType\" : true,\ \"nullType\" : null, \"arrayType\" : [1, 2, 3, 4], \"objectType\" : {\"A\" : 3}}"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); } /** @@ -580,42 +682,42 @@ HWTEST_F(DocumentInsertApiTest, InsertDBTest036, TestSize.Level1) * @tc.require: * @tc.author: mazhao */ -HWTEST_F(DocumentInsertApiTest, InsertDBTest038, TestSize.Level1) +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest038, TestSize.Level1) { /** * @tc.steps:step1.Insert document whose value is over the range of double * @tc.expected:step1.GRD_INVALID_ARGS. */ const char *document1 = R"({"_id" : "38_0", "field2" : 1.79769313486232e308})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document1, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_INVALID_ARGS); /** * @tc.steps:step2.Insert document whose value is over the range of double * @tc.expected:step2.GRD_INVALID_ARGS. */ const char *document2 = R"({"_id" : "38_1", "t1" : {"field2" : 1.79769313486232e308}})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2, 0), GRD_INVALID_ARGS); /** * @tc.steps:step3.Insert document whose value is over the range of double * @tc.expected:step3.GRD_INVALID_ARGS. */ const char *document3 = R"({"_id" : "38_2", "t1" : [1, 2, 1.79769313486232e308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document3, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document3, 0), GRD_INVALID_ARGS); /** * @tc.steps:step4.Insert document whose value is over the range of double * @tc.expected:step4.GRD_INVALID_ARGS. */ const char *document4 = R"({"_id" : "38_3", "t1" : [1, 2, -1.7976931348623167E+308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document2, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document2, 0), GRD_INVALID_ARGS); /** * @tc.steps:step5.Insert document with minimum double value * @tc.expected:step5.GRD_INVALID_ARGS. */ const char *document5 = R"({"_id" : "38_4", "t1" : [1, 2, -1.79769313486231570E+308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document5, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document5, 0), GRD_OK); /** * @tc.steps:step6.Insert document with maxium double value * @tc.expected:step6.GRD_INVALID_ARGS. */ const char *document6 = R"({"_id" : "38_5", "t1" : [1, 2, 1.79769313486231570E+308]})"; - EXPECT_EQ(GRD_InsertDoc(g_db, right_collectionName, document6, 0), GRD_OK); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document6, 0), GRD_OK); } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp index 6fb52b54..382fe5ef 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_api_test.cpp @@ -83,8 +83,6 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest001, TestSize.Level0) } /** -<<<<<<< HEAD -======= * @tc.name: OpenDBTest002 * @tc.desc: Test open document db with invalid db * @tc.type: FUNC @@ -110,7 +108,6 @@ HWTEST_F(DocumentDBApiTest, OpenDBTest002, TestSize.Level0) } /** ->>>>>>> ddb/master * @tc.name: OpenDBPathTest001 * @tc.desc: Test open document db with NULL path * @tc.type: FUNC @@ -159,11 +156,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigTest001, TestSize.Level0) GRD_DB *db = nullptr; std::string path= "./document.db"; const int MAX_JSON_LEN = 512 * 1024; -<<<<<<< HEAD - std::string configStr = std::string(MAX_JSON_LEN + 1, 'a'); -======= std::string configStr = std::string(MAX_JSON_LEN, 'a'); ->>>>>>> ddb/master int status = GRD_DBOpen(path.c_str(), configStr.c_str(), GRD_DB_OPEN_CREATE, &db); EXPECT_EQ(status, GRD_OVER_LIMIT); } @@ -180,11 +173,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigTest002, TestSize.Level0) GRD_DB *db = nullptr; std::string path= "./document.db"; int status = GRD_DBOpen(path.c_str(), "{aa}", GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_JSON_FORMAT); -======= EXPECT_EQ(status, GRD_INVALID_FORMAT); ->>>>>>> ddb/master } /** @@ -199,11 +188,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigTest003, TestSize.Level0) GRD_DB *db = nullptr; std::string path= "./document.db"; int status = GRD_DBOpen(path.c_str(), R""({"notSupport":123})"", GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_NOT_SUPPORT); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } /** @@ -230,11 +215,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest001, TestSize.Level0) for (const auto &config : configList) { GLOGD("OpenDBConfigMaxConnNumTest001: test with config:%s", config.c_str()); int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - ASSERT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= ASSERT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } } @@ -286,11 +267,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest003, TestSize.Level1) config = R""({"maxConnNum":17})""; status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master DocumentDBTestUtils::RemoveTestDbFiles(path); } @@ -319,13 +296,8 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigMaxConnNumTest004, TestSize.Level1) GRD_DB *db = nullptr; int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_OVER_LIMIT); - EXPECT_EQ(db, nullptr); -======= EXPECT_EQ(status, GRD_OK); EXPECT_NE(db, nullptr); ->>>>>>> ddb/master for (auto *it : dbList) { status = GRD_DBClose(it, GRD_DB_CLOSE); @@ -359,11 +331,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigPageSizeTest001, TestSize.Level0) for (const auto &config : configList) { GLOGD("OpenDBConfigPageSizeTest001: test with config:%s", config.c_str()); int status = GRD_DBOpen(path.c_str(), config.c_str(), 0, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } } @@ -436,11 +404,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigPageSizeTest003, TestSize.Level1) config = R""({"pageSize":8})""; status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master DocumentDBTestUtils::RemoveTestDbFiles(path); } @@ -484,11 +448,7 @@ HWTEST_F(DocumentDBApiTest, OpenDBConfigRedoFlushTest002, TestSize.Level0) std::string config = R""({"redoFlushByTrx":3})""; int status = GRD_DBOpen(path.c_str(), config.c_str(), GRD_DB_OPEN_CREATE, &db); -<<<<<<< HEAD - EXPECT_EQ(status, GRD_INVALID_CONFIG_VALUE); -======= EXPECT_EQ(status, GRD_INVALID_ARGS); ->>>>>>> ddb/master } /** @@ -527,14 +487,10 @@ HWTEST_F(DocumentDBApiTest, OpenDBFlagTest002, TestSize.Level0) { GRD_DB *db = nullptr; std::string path= "./document.db"; -<<<<<<< HEAD - int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); -======= int status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_ONLY, &db); EXPECT_EQ(status, GRD_INVALID_ARGS); status = GRD_DBOpen(path.c_str(), "", GRD_DB_OPEN_CREATE, &db); ->>>>>>> ddb/master EXPECT_EQ(status, GRD_OK); status = GRD_DBClose(db, GRD_DB_CLOSE); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp deleted file mode 100644 index fa16a27a..00000000 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/documentdb_jsonobject_test.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* -* 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 "documentdb_test_utils.h" -#include "doc_errno.h" -#include "json_object.h" - -using namespace DocumentDB; -using namespace testing::ext; -using namespace DocumentDBUnitTest; - -class DocumentDBJsonObjectTest : public testing::Test { -public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); -}; - -void DocumentDBJsonObjectTest::SetUpTestCase(void) -{ -} - -void DocumentDBJsonObjectTest::TearDownTestCase(void) -{ -} - -void DocumentDBJsonObjectTest::SetUp(void) -{ -} - -void DocumentDBJsonObjectTest::TearDown(void) -{ -} - -/** - * @tc.name: OpenDBTest001 - * @tc.desc: Test open document db - * @tc.type: FUNC - * @tc.require: - * @tc.author: lianhuix - */ -HWTEST_F(DocumentDBJsonObjectTest, JsonObjectTest001, TestSize.Level0) -{ - const std::string config = R""({"a":123,"b":{"c":234,"d":"12345"}})""; - - int ret = E_OK; - JsonObject conf = JsonObject::Parse(config, ret); - EXPECT_EQ(ret, E_OK); - - ValueObject obj = conf.GetObjectByPath({"b", "c"}, ret); - - EXPECT_EQ(obj.GetValueType(), ValueObject::ValueType::VALUE_NUMBER); - EXPECT_EQ(obj.GetIntValue(), 234); -} \ No newline at end of file -- Gitee From 4b1fc76163b9be03c2261f29bd7a1a29dc023ad8 Mon Sep 17 00:00:00 2001 From: mazhao Date: Sat, 15 Apr 2023 03:32:03 +0000 Subject: [PATCH 11/18] finish all TestCase and fix some bug that TestCase found Signed-off-by: mazhao --- .../src/interface/include/result_set.h | 2 +- .../src/interface/src/result_set.cpp | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) 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 1ae2f79e..8e494169 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 @@ -45,7 +45,7 @@ private: std::string key_; bool ifShowId_ = false; bool viewType_ = false; - ProjectionTree* projectionTree_ = nullptr; + ProjectionTree projectionTree_; std::vector> path_; int index_ = 0; std::vector findValue_; 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 6f4fc330..c50a6cbd 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 @@ -26,13 +26,11 @@ int ResultSet::Init(Collection &coll, const std::string &key, std::vectorInit(); - if (projectionTree->ParseTree(path) == -E_INVALID_ARGS) { + projectionTree_.Init(); + if (projectionTree_.ParseTree(path) == -E_INVALID_ARGS) { GLOGE("Parse ProjectionTree failed"); return -E_INVALID_ARGS; } - projectionTree_ = projectionTree; ifShowId_ = ifShowId; viewType_ = viewType; findValue_.reserve(1 + 1); @@ -87,11 +85,7 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat } singlePath.emplace_back(node->GetItemFiled()); int index = 0; - if (projectionTree_ == nullptr) { - GLOGE("======>projectionTree_ is null"); - return E_OK; - } - if (projectionTree_->SerchTree(singlePath, index) == false && index == 0) { + if (projectionTree_.SerchTree(singlePath, index) == false && index == 0) { allPath.emplace_back(singlePath); } if (node->GetChild().IsNull() != true) { -- Gitee From 72d99d0a55097fe1a34155c36f7131364ddcd5cf Mon Sep 17 00:00:00 2001 From: mazhao Date: Sat, 15 Apr 2023 11:46:34 +0000 Subject: [PATCH 12/18] Review comments to modify the first version Signed-off-by: mazhao --- .../src/common/include/json_common.h | 18 +-- .../src/common/src/json_common.cpp | 107 ++++++------- .../document/document_check.cpp} | 71 +++++---- .../document/document_check.h} | 14 +- .../executor/document/grd_document_api.cpp | 11 +- .../{base => document}/grd_resultset_api.cpp | 7 +- .../src/executor/include/grd_type_inner.h | 2 +- .../src/interface/include/collection.h | 2 +- .../src/interface/include/document_store.h | 4 +- .../src/interface/include/projection_tree.h | 7 +- .../src/interface/include/result_set.h | 14 +- .../src/interface/src/collection.cpp | 2 +- .../src/interface/src/document_store.cpp | 149 +++++++----------- .../interface/src/document_store_manager.cpp | 3 + .../src/interface/src/projection_tree.cpp | 20 ++- .../src/interface/src/result_set.cpp | 84 ++++++---- .../src/oh_adapter/include/json_object.h | 3 +- .../oh_adapter/include/kv_store_executor.h | 2 +- .../src/oh_adapter/include/kv_store_manager.h | 2 +- .../src/oh_adapter/src/json_object.cpp | 40 ++--- .../src/sqlite_store_executor_impl.cpp | 2 +- .../unittest/api/ documentdb_delete_test.cpp | 7 +- .../unittest/api/ documentdb_find_test.cpp | 54 +++++-- .../unittest/api/ documentdb_insert_test.cpp | 31 ++++ 24 files changed, 367 insertions(+), 289 deletions(-) rename services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/{common/src/doc_common.cpp => executor/document/document_check.cpp} (63%) rename services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/{common/include/doc_common.h => executor/document/document_check.h} (78%) rename services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/{base => document}/grd_resultset_api.cpp (92%) 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 eacd07e3..4494f01e 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 @@ -29,19 +29,19 @@ public: JsonCommon() = default; ~JsonCommon(); - static ValueObject GetValueByFiled(JsonObject *node, const std::string& filed); - 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* const node); - static std::vector GetLeafValue(JsonObject *node); + static ValueObject GetValueByFiled(JsonObject &node, const std::string& filed); + 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 int Append(const JsonObject &src, const JsonObject &add); 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 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); }; } // 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 925b601d..e9cb2e4e 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 @@ -21,63 +21,60 @@ #include "securec.h" namespace DocumentDB { -ValueObject JsonCommon::GetValueByFiled(JsonObject *node, const std::string& filed) +ValueObject JsonCommon::GetValueByFiled(JsonObject &node, const std::string& filed) { - if (node == nullptr) { - return ValueObject(); - } - while (node != nullptr) { - if (node->GetItemFiled() == filed) { - auto itemValue = node->GetItemValue(); + while (!node.IsNull()) { + if (node.GetItemFiled() == filed) { + auto itemValue = node.GetItemValue(); return itemValue; } - if (node->GetNext().IsNull() == true) { + if (node.GetNext().IsNull()) { return ValueObject(); } - auto nodeNew = node->GetNext(); - node = &nodeNew; + auto nodeNew = node.GetNext(); + node = nodeNew; } return ValueObject(); } -int JsonCommon::CheckLeafNode(JsonObject *node, std::vector &leafValue) +int JsonCommon::CheckLeafNode(JsonObject &node, std::vector &leafValue) { - if (node->GetChild().IsNull() == true) { - auto itemValue = node->GetItemValue(); + if (node.GetChild().IsNull()) { + auto itemValue = node.GetItemValue(); leafValue.emplace_back(itemValue); } - if (node->GetChild().IsNull() != true) { - auto nodeNew = node->GetChild(); - CheckLeafNode(&nodeNew, leafValue); + if (!node.GetChild().IsNull()) { + auto nodeNew = node.GetChild(); + CheckLeafNode(nodeNew, leafValue); } - if (node->GetNext().IsNull() != true) { - auto nodeNew = node->GetNext(); - CheckLeafNode(&nodeNew, leafValue); + if (!node.GetNext().IsNull()) { + auto nodeNew = node.GetNext(); + CheckLeafNode(nodeNew, leafValue); } return E_OK; } -std::vector JsonCommon::GetLeafValue(JsonObject *node) +std::vector JsonCommon::GetLeafValue(JsonObject &node) { std::vector leafValue; CheckLeafNode(node, leafValue); return leafValue; } -bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, bool &errFlag) +bool JsonCommon::CheckNode(JsonObject &node, std::set filedSet, bool &errFlag) { if (errFlag == false) { return false; } std::string fieldName; - if (node->IsNull() != true) { + if (!node.IsNull()) { int ret = 0; - fieldName = node->GetItemFiled(ret); + fieldName = node.GetItemFiled(ret); if (filedSet.find(fieldName) == filedSet.end()) { if (ret == E_OK) { filedSet.insert(fieldName); } - if (ret == E_OK && fieldName == "") { + if (ret == E_OK && fieldName.empty()) { errFlag = false; return false; } @@ -97,39 +94,39 @@ bool JsonCommon::CheckNode(JsonObject *node, std::set filedSet, boo } } } - if (node->GetChild().IsNull() != true) { - auto nodeNew = node->GetChild(); + if (!node.GetChild().IsNull()) { + auto nodeNew = node.GetChild(); std::set newFiledSet; - CheckNode(&nodeNew, newFiledSet, errFlag); + CheckNode(nodeNew, newFiledSet, errFlag); } - if (node->GetNext().IsNull() != true) { - auto nodeNew = node->GetNext(); - CheckNode(&nodeNew, filedSet, errFlag); + if (!node.GetNext().IsNull()) { + auto nodeNew = node.GetNext(); + CheckNode(nodeNew, filedSet, errFlag); } return errFlag; } -bool JsonCommon::CheckJsonField(JsonObject *jsonObj) +bool JsonCommon::CheckJsonField(JsonObject &jsonObj) { std::set filedSet; bool errFlag = true; return CheckNode(jsonObj, filedSet, errFlag); } -bool JsonCommon::CheckProjectionNode(JsonObject *node, std::set filedSet, bool &errFlag, bool isFirstFloor) +bool JsonCommon::CheckProjectionNode(JsonObject &node, std::set filedSet, bool &errFlag, bool isFirstFloor) { if (errFlag == false) { return false; } std::string fieldName; - if (node->IsNull() != true) { + if (!node.IsNull()) { int ret = 0; - fieldName = node->GetItemFiled(ret); + fieldName = node.GetItemFiled(ret); if (filedSet.find(fieldName) == filedSet.end()) { if (ret == E_OK) { filedSet.insert(fieldName); } - if (ret == E_OK && fieldName == "") { + if (ret == E_OK && fieldName.empty()) { errFlag = false; return false; } @@ -149,19 +146,19 @@ bool JsonCommon::CheckProjectionNode(JsonObject *node, std::set fil } } } - if (node->GetChild().IsNull() != true) { - auto nodeNew = node->GetChild(); + if (!node.GetChild().IsNull()) { + auto nodeNew = node.GetChild(); std::set newFiledSet; - CheckProjectionNode(&nodeNew, newFiledSet, errFlag, false); + CheckProjectionNode(nodeNew, newFiledSet, errFlag, false); } - if (node->GetNext().IsNull() != true) { - auto nodeNew = node->GetNext(); - CheckProjectionNode(&nodeNew, filedSet, errFlag, isFirstFloor); + if (!node.GetNext().IsNull()) { + auto nodeNew = node.GetNext(); + CheckProjectionNode(nodeNew, filedSet, errFlag, isFirstFloor); } return errFlag; } -bool JsonCommon::CheckProjectionField(JsonObject *jsonObj) +bool JsonCommon::CheckProjectionField(JsonObject &jsonObj) { std::set filedSet; bool errFlag = true; @@ -169,13 +166,13 @@ bool JsonCommon::CheckProjectionField(JsonObject *jsonObj) return CheckProjectionNode(jsonObj, filedSet, errFlag, isFirstFloor); } -int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor) +int JsonCommon::ParseNode(JsonObject &node, std::vector singlePath, std::vector> &resultPath, bool isFirstFloor) { std::vector fatherPath; if (isFirstFloor) { std::string tempParseName; std::vector allFiledsName; - std::string priFieldName = node->GetItemFiled(); + std::string priFieldName = node.GetItemFiled(); for (int j = 0; j < priFieldName.size(); j++) { if (priFieldName[j] != '.') { tempParseName = tempParseName + priFieldName[j]; @@ -189,33 +186,33 @@ int JsonCommon::ParseNode(JsonObject* node, std::vector singlePath, singlePath.insert(singlePath.end(), allFiledsName.begin(), allFiledsName.end()); } else { std::vector allFiledsName; - allFiledsName.emplace_back(node->GetItemFiled()); + allFiledsName.emplace_back(node.GetItemFiled()); fatherPath = singlePath; singlePath.insert(singlePath.end(), allFiledsName.begin(), allFiledsName.end()); } - if (node->GetChild().IsNull() != true && node->GetChild().GetItemFiled() != "") { - auto nodeNew = node->GetChild(); - ParseNode(&nodeNew, singlePath, resultPath, false); + if (!node.GetChild().IsNull() && node.GetChild().GetItemFiled() != "") { + auto nodeNew = node.GetChild(); + ParseNode(nodeNew, singlePath, resultPath, false); } else { resultPath.emplace_back(singlePath); } - if (node->GetNext().IsNull() != true) { - auto nodeNew = node->GetNext(); - ParseNode(&nodeNew, fatherPath, resultPath, isFirstFloor); + if (!node.GetNext().IsNull()) { + auto nodeNew = node.GetNext(); + ParseNode(nodeNew, fatherPath, resultPath, isFirstFloor); } return 0; } -std::vector> JsonCommon::ParsePath(const JsonObject* const root) +std::vector> JsonCommon::ParsePath(const JsonObject &root) { std::vector> resultPath; - auto projectionJson = root->GetChild(); - if (projectionJson.IsNull() == true) { + auto projectionJson = root.GetChild(); + if (projectionJson.IsNull()) { GLOGE("projectionJson is null"); } std::vector singlePath; - ParseNode(&projectionJson, singlePath, resultPath, true); + ParseNode(projectionJson, singlePath, resultPath, true); return resultPath; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.cpp similarity index 63% rename from services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp rename to services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.cpp index 75a02013..4e3cff78 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/src/doc_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.cpp @@ -15,18 +15,19 @@ #include #include -#include "doc_common.h" +#include "document_check.h" #include "doc_errno.h" #include "log_print.h" #include "securec.h" namespace DocumentDB { namespace { -#define KEY_ID "_id" +constexpr const char *KEY_ID = "_id"; constexpr const char *COLLECTION_PREFIX_GRD = "GRD_"; constexpr const char *COLLECTION_PREFIX_GM_SYS = "GM_SYS_"; const int MAX_COLLECTION_NAME = 511; const int MAX_ID_LENS = 899; +const int JSON_DEEP_MAX = 4; bool CheckCollectionNamePrefix(const std::string &name, const std::string &prefix) { @@ -59,6 +60,7 @@ bool CheckCommon::CheckCollectionName(const std::string &collectionName, std::st } if (CheckCollectionNamePrefix(collectionName, COLLECTION_PREFIX_GRD) || CheckCollectionNamePrefix(collectionName, COLLECTION_PREFIX_GM_SYS)) { + GLOGE("Collection name is illegal"); errCode = -E_INVALID_COLL_NAME_FORMAT; return false; } @@ -69,51 +71,66 @@ bool CheckCommon::CheckCollectionName(const std::string &collectionName, std::st return true; } -bool CheckCommon::CheckFilter(JsonObject *filterObj) -{ - if (CheckIdFormat(filterObj) == false) { - return false; +int CheckCommon::CheckFilter(JsonObject &filterObj) +{ + 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() != true) { - return false; + int ret = CheckIdFormat(filterObj); + if (ret != E_OK) { + GLOGE("Filter Id format is illegal"); + return ret; } - return true; + if (!filterObj.GetChild().GetNext().IsNull()) { + return -E_INVALID_ARGS; + } + return E_OK; } -bool CheckCommon::CheckIdFormat(JsonObject *filterJson) +int CheckCommon::CheckIdFormat(JsonObject &filterJson) { - auto filterObjChild = filterJson->GetChild(); - auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); + auto filterObjChild = filterJson.GetChild(); + auto idValue = JsonCommon::GetValueByFiled(filterObjChild, KEY_ID); if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { - return false; + return -E_INVALID_ARGS; } if (idValue.GetStringValue().length() > MAX_ID_LENS) { - return false; + return -E_OVER_LIMIT; } - return true; + return E_OK; } -bool CheckCommon::CheckDocument(JsonObject *documentObj) +int CheckCommon::CheckDocument(JsonObject &documentObj) { - if (CheckIdFormat(documentObj) == false) { + if (documentObj.GetDeep() > JSON_DEEP_MAX) { + GLOGE("documentObj's json deep is deeper than JSON_DEEP_MAX"); + return -E_INVALID_ARGS; + } + int ret = CheckIdFormat(documentObj); + if (ret != E_OK) { GLOGE("Document Id format is illegal"); - return false; + return ret; } - if (documentObj->GetChild().IsNull() != true) { - auto documentObjChild = documentObj->GetChild(); - if (JsonCommon::CheckJsonField(&documentObjChild) == false) { + if (!documentObj.GetChild().IsNull()) { + auto documentObjChild = documentObj.GetChild(); + if (JsonCommon::CheckJsonField(documentObjChild) == false) { GLOGE("Document json field format is illegal"); - return false; + return -E_INVALID_ARGS; } } - return true; + return E_OK; } -bool CheckCommon::CheckProjection(JsonObject *projectionObj, std::vector> &path) +bool CheckCommon::CheckProjection(JsonObject &projectionObj, std::vector> &path) { - if (projectionObj->GetChild().IsNull() != true) { - auto projectionObjChild = projectionObj->GetChild(); - if (JsonCommon::CheckProjectionField(&projectionObjChild) == false) { + if (projectionObj.GetDeep() > JSON_DEEP_MAX) { + GLOGE("projectionObj's json deep is deeper than JSON_DEEP_MAX"); + return -E_INVALID_ARGS; + } + if (!projectionObj.GetChild().IsNull()) { + auto projectionObjChild = projectionObj.GetChild(); + if (JsonCommon::CheckProjectionField(projectionObjChild) == false) { GLOGE("projection json field format is illegal"); return false; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.h similarity index 78% rename from services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h rename to services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.h index 551101cb..57769260 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/common/include/doc_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/document_check.h @@ -13,8 +13,8 @@ * limitations under the License. */ -#ifndef DOC_COMMON_H -#define DOC_COMMON_H +#ifndef DOCUMENT_CHECK_H +#define DOCUMENT_CHECK_H #include #include @@ -29,14 +29,14 @@ public: ~CheckCommon() = default; static bool CheckCollectionName(const std::string &collectionName, std::string &lowerCaseName, int &errCode); - static bool CheckFilter(JsonObject *document); - static bool CheckIdFormat(JsonObject *data); - static bool CheckDocument(JsonObject *document); - static bool CheckProjection(JsonObject *projectionObj, std::vector> &path); + static int CheckFilter(JsonObject &document); + static int CheckIdFormat(JsonObject &data); + static int CheckDocument(JsonObject &document); + static bool CheckProjection(JsonObject &projectionObj, std::vector> &path); }; using Key = std::vector; using Value = std::vector; constexpr const char *COLL_PREFIX = "GRD_COLL_"; } // DocumentDB -#endif // DOC_COMMON_H \ No newline at end of file +#endif // DOCUMENT_CHECK_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 0b805ef5..a11a3bd6 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -92,14 +92,17 @@ int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned in || query.projection == nullptr) { return GRD_INVALID_ARGS; } - GRD_ResultSet *tmp = new GRD_ResultSet(); - int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, tmp->resultSet_); + GRD_ResultSet *grdResultSet = new (std::nothrow)GRD_ResultSet(); + if (grdResultSet == nullptr) { + GLOGE("Memory allocation failed!" ); + } + int ret = db->store_->FindDocument(db, collectionName, query.filter, query.projection, flags, grdResultSet->resultSet_); if (ret != E_OK) { - delete[] tmp; + delete grdResultSet; *resultSet = nullptr; return TrasnferDocErr(ret); } - *resultSet = tmp; + *resultSet = grdResultSet; return TrasnferDocErr(ret); } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp similarity index 92% rename from services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp rename to services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp index d5c11a5d..07d9ba20 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_resultset_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp @@ -31,7 +31,7 @@ int GRD_Next(GRD_ResultSet *resultSet) }; std::mutex dbMutex; std::lock_guard lock(dbMutex); - int ret = resultSet->resultSet_->GetNext(); + int ret = resultSet->resultSet_.GetNext(); return TrasnferDocErr(ret); } @@ -42,7 +42,7 @@ int GRD_GetValue(GRD_ResultSet *resultSet, char **value) return GRD_INVALID_ARGS; }; char *val = nullptr; - int ret = resultSet->resultSet_->GetValue(&val); + int ret = resultSet->resultSet_.GetValue(&val); if (val == nullptr) { return GRD_NOT_AVAILABLE; } @@ -55,7 +55,7 @@ int GRD_FreeValue(char *value) if (value == nullptr) { return GRD_OK; } - delete[] value; + delete value; return GRD_OK; } @@ -64,6 +64,5 @@ int GRD_FreeResultSet(GRD_ResultSet *resultSet) if (resultSet == nullptr) { return GRD_INVALID_ARGS; } - delete[] resultSet; return GRD_OK; } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h index e5cafb2e..37114ed6 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h @@ -25,6 +25,6 @@ typedef struct GRD_DB { } GRD_DB; typedef struct GRD_ResultSet { - DocumentDB::ResultSet *resultSet_ = new DocumentDB::ResultSet(); + DocumentDB::ResultSet resultSet_; } GRD_ResultSet; #endif // GRD_TYPE_INNER_H \ No newline at end of file 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 b71feaae..e1561430 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 @@ -17,7 +17,7 @@ #define COLLECTION_H #include -#include "doc_common.h" +#include "document_check.h" #include "kv_store_executor.h" namespace DocumentDB { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h index f51a77a1..5cbade13 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h @@ -37,9 +37,9 @@ public: int UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flags); int InsertDocument(const std::string &collection, const std::string &document, int flag); int DeleteDocument(const std::string &collection, const std::string &filter, int flag); - int FindDocument(GRD_DB* db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet); + int FindDocument(GRD_DB* db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet &resultSet); private: - int GetViewType(JsonObject *jsonObj, bool &viewType); + int GetViewType(JsonObject &jsonObj, bool &viewType); std::mutex dbMutex_; KvStoreExecutor *executor_ = nullptr; 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 fe7adbaf..5abd62a0 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 @@ -24,13 +24,10 @@ public: ProjectionTree(); ~ProjectionTree(); - void Init() { - root_ = new ProjectionNode(); - } int ParseTree(std::vector> &path); - bool SerchTree(std::vector &singlePath, int &index); + bool SearchTree(std::vector &singlePath, int &index); private: - ProjectionNode *root_; + ProjectionNode node_; }; } // DocumentDB #endif // PROJECTION_TREE_H \ No newline at end of file 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 8e494169..e9f1f995 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 @@ -24,7 +24,7 @@ #include "json_object.h" #include "securec.h" #include "collection.h" -#include "doc_common.h" +#include "document_check.h" #include "json_common.h" @@ -32,21 +32,21 @@ namespace DocumentDB { class ResultSet { public: - ResultSet() = default; + ResultSet(); ~ResultSet(); - int Init(Collection &coll, const std::string &key, std::vector> &path, bool ifShowId, bool viewType); + int Init(Collection &coll, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType); int GetNext(); int GetValue(char **value); private: - int CutString(std::string &jsonData); - int CheckCutNode(JsonObject *node, std::vector singlePath, std::vector> &allPath); + int CutJsonBranch(std::string &jsonData); + int CheckCutNode(JsonObject *node, std::vector singleCutPath, std::vector> &allCutPath); Collection* coll_ = nullptr; - std::string key_; + ValueObject key_; bool ifShowId_ = false; bool viewType_ = false; ProjectionTree projectionTree_; - std::vector> path_; + std::vector> projectionPath_; int index_ = 0; std::vector findValue_; }; 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 f0f86cf7..445b06cc 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 @@ -17,7 +17,7 @@ #include -#include "doc_common.h" +#include "document_check.h" #include "doc_errno.h" #include "log_print.h" 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 6904063e..100ea69c 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 @@ -15,16 +15,18 @@ #include "document_store.h" #include "collection_option.h" -#include "doc_common.h" +#include "document_check.h" #include "doc_errno.h" #include "grd_base/grd_type_export.h" #include "log_print.h" namespace DocumentDB { -#define COLLECTION_LENS_MAX (512 * 1024) -#define JSON_LENS_MAX (512 * 1024) -#define JSON_DEEP_MAX (4) -#define KEY_ID "_id" +const int COLLECTION_LENS_MAX = 512 * 1024; +const int JSON_LENS_MAX = 512 * 1024; +const int JSON_DEEP_MAX = 4; +constexpr const char *KEY_ID = "_id"; +const bool caseIsSensitive = true; + DocumentStore::DocumentStore(KvStoreExecutor *executor) : executor_(executor) { } @@ -144,6 +146,10 @@ int DocumentStore::UpsertDocument(const std::string &collection, const std::stri int DocumentStore::InsertDocument(const std::string &collection, const std::string &document, int flag) { + if (flag != 0) { + GLOGE("InsertDocument flag is not zero"); + return -E_INVALID_ARGS; + } std::string lowerCaseCollName; int errCode = E_OK; if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { @@ -155,22 +161,17 @@ int DocumentStore::InsertDocument(const std::string &collection, const std::stri GLOGE("document's length is larger than JSON_LENS_MAX"); return -E_OVER_LIMIT; } - int errCode1; - JsonObject documentObj = JsonObject::Parse(document, errCode1); - if (errCode1 != E_OK) { + JsonObject documentObj = JsonObject::Parse(document, errCode, caseIsSensitive); + if (errCode != E_OK) { GLOGE("Document Parsed faild"); - return errCode1; + return errCode; } - if (!CheckCommon::CheckDocument(&documentObj) || flag != 0) { - GLOGE("Document format unvalid"); - return -E_INVALID_ARGS; + errCode = CheckCommon::CheckDocument(documentObj); + if (errCode != E_OK) { + return errCode; } auto documentObjChild = documentObj.GetChild(); - auto idValue = JsonCommon::GetValueByFiled(&documentObjChild, KEY_ID); - if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { - GLOGE("Id value is not string"); - return -E_INVALID_ARGS; - } + auto idValue = JsonCommon::GetValueByFiled(documentObjChild, KEY_ID); std::string id = idValue.GetStringValue(); Key key(id.begin(), id.end()); Value value(document.begin(), document.end()); @@ -180,6 +181,10 @@ int DocumentStore::InsertDocument(const std::string &collection, const std::stri int DocumentStore::DeleteDocument(const std::string &collection, const std::string &filter, int flag) { + if (flag != 0) { + GLOGE("DeleteDocument flag is not zero"); + return -E_INVALID_ARGS; + } std::string lowerCaseCollName; int errCode = E_OK; if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) { @@ -187,7 +192,7 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri return errCode; } auto coll = Collection(collection, executor_); - if (filter == "") { + if (filter.empty()) { GLOGE("Filter is empty"); return -E_INVALID_ARGS; } @@ -195,31 +200,28 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri GLOGE("filter's length is larger than JSON_LENS_MAX"); return -E_OVER_LIMIT; } - int errCode1; - JsonObject filterObj = JsonObject::Parse(filter, errCode1); - if (errCode1 != E_OK) { + JsonObject filterObj = JsonObject::Parse(filter, errCode, caseIsSensitive); + if (errCode != E_OK) { GLOGE("filter Parsed faild"); - return errCode1; + return errCode; } - if (!CheckCommon::CheckFilter(&filterObj) || flag != 0) { - GLOGE("Filter format is illegal"); - return -E_INVALID_ARGS; + errCode = CheckCommon::CheckFilter(filterObj); + if (errCode != E_OK) { + return errCode; } auto filterObjChild = filterObj.GetChild(); - auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); - if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { - GLOGE("Id value is not string"); - return -E_INVALID_ARGS; - } + 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); } -int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet *resultSet) +int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const std::string &filter, const std::string &projection, + int flags, ResultSet &resultSet) { if (flags != 0 && flags != GRD_DOC_ID_DISPLAY) { + GLOGE("FindDocument flag is illegal"); return -E_INVALID_ARGS;; } std::string lowerCaseCollName; @@ -232,42 +234,35 @@ int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const GLOGE("filter's length is larger than JSON_LENS_MAX"); return -E_OVER_LIMIT; } - int errCode1; - JsonObject filterObj = JsonObject::Parse(filter, errCode1); - if (errCode1 != E_OK) { + JsonObject filterObj = JsonObject::Parse(filter, errCode, caseIsSensitive); + if (errCode != E_OK) { GLOGE("filter Parsed faild"); - return errCode1; + return errCode; } - if (!CheckCommon::CheckFilter(&filterObj)) { - GLOGE("Filter format is illegal"); - return -E_INVALID_ARGS; + errCode = CheckCommon::CheckFilter(filterObj); + if (errCode != E_OK) { + return errCode; } auto filterObjChild = filterObj.GetChild(); - auto idValue = JsonCommon::GetValueByFiled(&filterObjChild, KEY_ID); - if (idValue.GetValueType() != ValueObject::ValueType::VALUE_STRING) { - GLOGE("Id value is not string"); - return -E_INVALID_ARGS; - } - std::string filterId = idValue.GetStringValue(); + auto idValue = JsonCommon::GetValueByFiled(filterObjChild, KEY_ID); if (projection.length() + 1 > JSON_LENS_MAX) { GLOGE("projection's length is larger than JSON_LENS_MAX"); return -E_OVER_LIMIT; } - int errCode2; - JsonObject projectionObj = JsonObject::Parse(projection, errCode2); - if (errCode2 != E_OK) { + JsonObject projectionObj = JsonObject::Parse(projection, errCode, caseIsSensitive); + if (errCode != E_OK) { GLOGE("projection Parsed faild"); - return errCode2; + return errCode; } bool viewType = false; std::vector> allPath; if (projection != "{}") { - allPath = JsonCommon::ParsePath(&projectionObj); - if (!CheckCommon::CheckProjection(&projectionObj, allPath)) { + allPath = JsonCommon::ParsePath(projectionObj); + if (!CheckCommon::CheckProjection(projectionObj, allPath)) { GLOGE("projection format unvalid"); return -E_INVALID_ARGS; } - if (GetViewType(&projectionObj, viewType) != E_OK) { + if (GetViewType(projectionObj, viewType) != E_OK) { GLOGE("GetViewType faild"); return -E_INVALID_ARGS; } @@ -277,61 +272,37 @@ int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const ifShowId = true; } Collection coll = Collection(collection, executor_); - return resultSet->Init(coll, filterId, allPath, ifShowId, viewType); + return resultSet.Init(coll, idValue, allPath, ifShowId, viewType); } -int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { +int DocumentStore::GetViewType(JsonObject &jsonObj, bool &viewType) { auto leafValue = JsonCommon::GetLeafValue(jsonObj); if (leafValue.size() == 0) { - return -E_INVALID_ARGS; + return E_INVALID_ARGS; } - switch (leafValue[0].GetValueType()) { - case ValueObject::ValueType::VALUE_BOOL: - if (leafValue[0].GetBoolValue()) { - viewType = true; - } - else { - viewType = false; - } - break; - case ValueObject::ValueType::VALUE_STRING: - if (leafValue[0].GetStringValue() == "") { - viewType = true; - } - else { - return -E_INVALID_ARGS; - } - break; - case ValueObject::ValueType::VALUE_NUMBER: - if (leafValue[0].GetIntValue() == 0) { - viewType = false; - } - else { - viewType = true; - } - break; - default: - return -E_INVALID_ARGS; - } - for (int i = 1; i < leafValue.size(); i++) { + bool viewFlag = false; + for (int i = 0; i < leafValue.size(); i++) { switch (leafValue[i].GetValueType()) { case ValueObject::ValueType::VALUE_BOOL: if (leafValue[i].GetBoolValue()) { - if (viewType != true) { + if (i != 0 && !viewType) { return -E_INVALID_ARGS; } + viewType = true; } else { - if (viewType != false) { + if (i != 0 && viewType) { return E_INVALID_ARGS; } + viewType == false; } break; case ValueObject::ValueType::VALUE_STRING: if (leafValue[i].GetStringValue() == "") { - if (viewType != true) { + if (i != 0 && !viewType) { return -E_INVALID_ARGS; } + viewType = true; } else { return -E_INVALID_ARGS; @@ -339,14 +310,16 @@ int DocumentStore::GetViewType(JsonObject *jsonObj, bool &viewType) { break; case ValueObject::ValueType::VALUE_NUMBER: if (leafValue[i].GetIntValue() == 0) { - if (viewType != false) { + if (i != 0 && viewType) { return -E_INVALID_ARGS; } + viewType = false; } else { - if (viewType != true) { + if (i != 0 && !viewType) { return E_INVALID_ARGS; } + viewType = true; } break; default: diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp index 85a73caf..5b93c90e 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp @@ -79,6 +79,9 @@ int DocumentStoreManager::GetDocumentStore(const std::string &path, const std::s } store = new (std::nothrow) DocumentStore(executor); + if (store == nullptr) { + GLOGE("Memory allocation failed!" ); + } if (store == nullptr) { return -E_OUT_OF_MEMORY; } 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 1f681efb..0d5b25c4 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 @@ -3,7 +3,8 @@ namespace DocumentDB { -#define JSON_DEEP_MAX (4) +const int JSON_DEEP_MAX = 4; + ProjectionTree::ProjectionTree() { } @@ -11,24 +12,27 @@ ProjectionTree::~ProjectionTree() { } int ProjectionTree::ParseTree(std::vector> &path) { - ProjectionNode *node = root_; + ProjectionNode *node = &node_; if (node == NULL) { return E_OK; } for (int i = 0; i < path.size(); i++) { - node = root_; + node = &node_; for (int j = 0; j < path[i].size(); j++) { if (node->SonNode[path[i][j]] != nullptr) { node = node->SonNode[path[i][j]]; - if (j < path[i].size() - 1 && node->isDeepest == true) { + if (j < path[i].size() - 1 && node->isDeepest) { return -E_INVALID_ARGS; } - if (j == path[i].size() - 1 && node->isDeepest == false) { + if (j == path[i].size() - 1 && !node->isDeepest) { return -E_INVALID_ARGS; } } else { - auto tempNode = new ProjectionNode; + auto tempNode = new (std::nothrow) ProjectionNode; + if (tempNode == nullptr) { + GLOGE("Memory allocation failed!" ); + } tempNode->Deep = node->Deep + 1; if (tempNode->Deep > JSON_DEEP_MAX) { return -E_INVALID_ARGS; @@ -42,8 +46,8 @@ int ProjectionTree::ParseTree(std::vector> &path) { return E_OK; } -bool ProjectionTree::SerchTree(std::vector &singlePath, int &index) { - ProjectionNode *node = root_; +bool ProjectionTree::SearchTree(std::vector &singlePath, int &index) { + ProjectionNode *node = &node_; for (int i = 0; i < singlePath.size(); i++) { if (node->isDeepest) { index = i; 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 c50a6cbd..3eca605a 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 @@ -16,19 +16,28 @@ #include "log_print.h" namespace DocumentDB { -#define KEY_ID "_id" +constexpr const char *KEY_ID = "_id"; + +ResultSet::ResultSet() +{ + +} ResultSet::~ResultSet() { - GLOGE("delte ResultSet"); + GLOGE("delete ResultSet"); } -int ResultSet::Init(Collection &coll, const std::string &key, std::vector> &path, bool ifShowId, bool viewType) +int ResultSet::Init(Collection &coll, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType) { - coll_ = new Collection(coll); + coll_ = new (std::nothrow) Collection(coll); + if (coll_ == nullptr) { + GLOGE("Memory allocation failed!" ); + } key_ = key; - path_ = path; - projectionTree_.Init(); + projectionPath_ = path; if (projectionTree_.ParseTree(path) == -E_INVALID_ARGS) { GLOGE("Parse ProjectionTree failed"); + delete coll_; + coll_ == nullptr; return -E_INVALID_ARGS; } ifShowId_ = ifShowId; @@ -46,19 +55,20 @@ int ResultSet::GetNext() } return -E_NO_DATA; } - Value document; - if (key_ == "") { - GLOGE("key_ is empty"); + std::string idValue = key_.GetStringValue(); + if (idValue.empty()) { + GLOGE("id is empty"); return -E_NO_DATA; } - Key key(key_.begin(), key_.end()); - coll_->GetDocument(key, document); - if (document.size() == 0) { + Key key(idValue.begin(), idValue.end()); + Value document; + int 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()); - CutString(jsonData); + CutJsonBranch(jsonData); findValue_.emplace_back(jsonData); return E_OK; } @@ -69,37 +79,42 @@ int ResultSet::GetValue(char **value) return -E_NO_DATA; } auto jsonData = findValue_.back(); - char *tmp = new char[jsonData.size() + 1]; - errno_t err = strcpy_s(tmp, jsonData.size() + 1, jsonData.c_str()); - *value = tmp; + char *jsonstr = new char[jsonData.size() + 1]; + if (jsonstr == nullptr) { + GLOGE("Memory allocation failed!" ); + } + errno_t err = strcpy_s(jsonstr, jsonData.size() + 1, jsonData.c_str()); if (err != 0) { GLOGE("strcpy_s failed"); + return -E_NO_DATA;; } + *value = jsonstr; return E_OK; } -int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePath, std::vector> &allPath) +int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePath, std::vector> &allCutPath) { if (node == nullptr) { - return E_OK; + GLOGE("No node to cut"); + return -E_NO_DATA; } singlePath.emplace_back(node->GetItemFiled()); int index = 0; - if (projectionTree_.SerchTree(singlePath, index) == false && index == 0) { - allPath.emplace_back(singlePath); + if (projectionTree_.SearchTree(singlePath, index) == false && index == 0) { + allCutPath.emplace_back(singlePath); } - if (node->GetChild().IsNull() != true) { + if (!node->GetChild().IsNull()) { auto nodeNew = node->GetChild(); - CheckCutNode(&nodeNew, singlePath, allPath); + CheckCutNode(&nodeNew, singlePath, allCutPath); } - if (node->GetNext().IsNull() != true) { + if (!node->GetNext().IsNull()) { singlePath.pop_back(); auto nodeNew = node->GetNext(); - CheckCutNode(&nodeNew, singlePath, allPath); + CheckCutNode(&nodeNew, singlePath, allCutPath); } return E_OK; } -int ResultSet::CutString(std::string &jsonData) +int ResultSet::CutJsonBranch(std::string &jsonData) { int errCode; JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode, true); @@ -107,21 +122,24 @@ int ResultSet::CutString(std::string &jsonData) GLOGE("jsonData Parsed faild"); return errCode; } - std::vector> allPath; + std::vector> allCutPath; bool idFlag = false; - if (viewType_ == true) { + if (viewType_) { std::vector singlePath; auto cjsonObjChild = cjsonObj.GetChild(); - CheckCutNode(&cjsonObjChild, singlePath, allPath); - for (int i = 0; i < allPath.size(); i++) { - if (ifShowId_ == false || allPath[i][0] != KEY_ID) { - cjsonObj.DeleteItemDeeplyOnTarget(allPath[i]); + errCode = CheckCutNode(&cjsonObjChild, singlePath, allCutPath); + if (errCode != E_OK) { + return errCode; + } + for (int i = 0; i < allCutPath.size(); i++) { + if (ifShowId_ == false || allCutPath[i][0] != KEY_ID) { + cjsonObj.DeleteItemDeeplyOnTarget(allCutPath[i]); } } } if (viewType_ == false) { - for (int i = 0; i < path_.size(); i++) { - cjsonObj.DeleteItemDeeplyOnTarget(path_[i]); + for (int i = 0; i < projectionPath_.size(); i++) { + cjsonObj.DeleteItemDeeplyOnTarget(projectionPath_[i]); } if (ifShowId_ == false) { std::vector idPath; 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 54f4ea57..12510f1d 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 @@ -88,7 +88,7 @@ public: int DeleteItemOnTarget(const JsonFieldPath &path); int DeleteItemDeeplyOnTarget(const JsonFieldPath &path); bool IsNull() const; - + int GetDeep(); enum class Type { JSON_LEAF, JSON_OBJECT, @@ -104,6 +104,7 @@ private: int CheckNumber(cJSON *cjson, int &errCode); cJSON *cjson_ = nullptr; + int jsonDeep_ = 0; bool isOwner_ = false; bool caseSensitive_ = false; }; 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 8037fc6b..0f81f5b1 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 @@ -17,7 +17,7 @@ #define KV_STORE_EXECUTOR_H #include -#include "doc_common.h" +#include "document_check.h" namespace DocumentDB { class KvStoreExecutor { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h index 97b79f64..c1df1072 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/oh_adapter/include/kv_store_manager.h @@ -18,7 +18,7 @@ #include #include "db_config.h" -#include "doc_common.h" +#include "document_check.h" #include "kv_store_executor.h" namespace DocumentDB { 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 ab30fbd2..2d3ed07e 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 @@ -21,9 +21,8 @@ namespace DocumentDB { namespace { -#define COLLECTION_LENS_MAX (512 * 1024) -#define JSON_LENS_MAX (512 * 1024) -#define JSON_DEEP_MAX (4) +const int COLLECTION_LENS_MAX = 512 * 1024; +const int JSON_LENS_MAX = 512 * 1024; bool IsNumber(const std::string &str) { @@ -97,7 +96,7 @@ JsonObject::JsonObject() JsonObject::~JsonObject() { - if (isOwner_ == true) { + if (isOwner_) { cJSON_Delete(cjson_); } } @@ -119,10 +118,23 @@ JsonObject::Type JsonObject::GetType() const } return JsonObject::Type::JSON_LEAF; } - +int JsonObject::GetDeep() +{ + if (cjson_ == nullptr) { + GLOGE("cJson is nullptr,deep is 0"); + return 0; + } + if (jsonDeep_ != 0) { + return jsonDeep_; + } + jsonDeep_ = GetDeep(cjson_); + return jsonDeep_; + +} int JsonObject::GetDeep(cJSON *cjson) { if (cjson->child == nullptr) { + jsonDeep_ = 0; return 0; // leaf node } @@ -132,9 +144,11 @@ int JsonObject::GetDeep(cJSON *cjson) depth = std::max(depth, GetDeep(child) + 1); child = child->next; } + jsonDeep_ = depth; return depth; } + int JsonObject::CheckNumber(cJSON *item, int &errCode) { if (item != NULL && cJSON_IsNumber(item)) { @@ -144,21 +158,16 @@ int JsonObject::CheckNumber(cJSON *item, int &errCode) } } if (item->child != nullptr) { - CheckNumber(item->child, errCode); + return CheckNumber(item->child, errCode); } if (item->next != nullptr) { - CheckNumber(item->next, errCode); + return CheckNumber(item->next, errCode); } return E_OK; } int JsonObject::Init(const std::string &str) { - if (str.length() + 1 > JSON_LENS_MAX) { - GLOGE("lens is ========>%d", str.length()); - GLOGE("str's length is longer than JSON_LENS_MAX"); - return -E_INVALID_ARGS; - } const char *end = NULL; isOwner_ = true; cjson_ = cJSON_ParseWithOpts(str.c_str(), &end, true); @@ -172,11 +181,6 @@ int JsonObject::Init(const std::string &str) return -E_INVALID_ARGS; } - if (GetDeep(cjson_) > JSON_DEEP_MAX) { - GLOGE("Deep is ======>%d", GetDeep(cjson_)); - GLOGE("Deep is longer than JSON_DEEP_MAX"); - return -E_INVALID_ARGS; - } int ret = 0; CheckNumber(cjson_, ret); if (ret == E_INVALID_ARGS) { @@ -263,7 +267,7 @@ JsonObject JsonObject::GetChild() const int JsonObject::DeleteItemFromObject(const std::string &field) { - if (field == "") { + if (field.empty()) { return E_OK; } cJSON_DeleteItemFromObjectCaseSensitive(cjson_, field.c_str()); 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 18fdc1e4..a7647f34 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 @@ -13,7 +13,7 @@ * limitations under the License. */ -#include "doc_common.h" +#include "document_check.h" #include "doc_errno.h" #include "log_print.h" #include "sqlite_utils.h" 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 8cff9d6f..d9cd4c66 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 @@ -22,12 +22,11 @@ #include "grd_type_inner.h" #include "grd_base/grd_resultset_api.h" -#define COLLECTION_NAME "student" -#define NULL_JSON_STR "{}" -const int MAX_COLLECTION_LENS = 511; using namespace testing::ext; namespace { - +constexpr const char *COLLECTION_NAME = "student"; +constexpr const char *NULL_JSON_STR = "{}"; +const int MAX_COLLECTION_LENS = 511; std::string path = "./document.db"; GRD_DB *g_db = nullptr; } 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 6bb054d7..0f750b76 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 @@ -29,12 +29,13 @@ using namespace testing::ext; namespace { std::string path = "./document.db"; GRD_DB *g_db = nullptr; -#define E_OK (0) -#define COLLECTION_NAME "student" +constexpr const char *COLLECTION_NAME = "student"; +constexpr const char *NULL_JSON_STR = "{}"; +const int E_OK = 0; const int MAX_COLLECTION_NAME = 511; const int INT_MAX = 2147483647; const int INT_MIN = -2147483648; - +const int MAX_ID_LENS = 899; static const char *g_document1 = "{\"_id\" : \"1\", \"name\":\"doc1\",\"item\":\"journal\",\"personInfo\":\ {\"school\":\"AB\", \"age\" : 51}}"; static const char *g_document2 = "{\"_id\" : \"2\", \"name\":\"doc2\",\"item\": 1, \"personInfo\":\ @@ -69,8 +70,6 @@ static const char *g_document19 = "{\"_id\" : \"19\", \"name\":\"doc19\",\"ITEM\ {\"school\":\"AB\", \"age\":15}}"; static const char *g_document20 = "{\"_id\" : \"20\", \"name\":\"doc20\",\"ITEM\" : true,\"personInfo\":\ [{\"SCHOOL\":\"B\", \"AGE\":15}, {\"SCHOOL\":\"C\", \"AGE\":35}]}"; - - static std::vectorg_data = {g_document1, g_document2, g_document3, g_document4, g_document5, g_document6, g_document7, g_document8, g_document9, g_document10, g_document11, g_document12, g_document13, g_document14, g_document15, g_document16, g_document17, g_document18, g_document19, g_document20}; @@ -83,12 +82,11 @@ static void InsertData(GRD_DB *g_db, const char *collectionName) static void CompareValue(const char *value, const char *targetValue) { - int errCode1; - DocumentDB::JsonObject valueObj = DocumentDB::JsonObject::Parse(value, errCode1); - EXPECT_EQ(errCode1, E_OK); - int errCode2; - DocumentDB::JsonObject targetValueObj = DocumentDB::JsonObject::Parse(targetValue, errCode2); - EXPECT_EQ(errCode2, E_OK); + int errCode; + DocumentDB::JsonObject valueObj = DocumentDB::JsonObject::Parse(value, errCode); + EXPECT_EQ(errCode, E_OK); + DocumentDB::JsonObject targetValueObj = DocumentDB::JsonObject::Parse(targetValue, errCode); + EXPECT_EQ(errCode, E_OK); EXPECT_EQ(valueObj.Print(), targetValueObj.Print()); } } @@ -1413,3 +1411,37 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest054, TestSize.Level1) query = {nullptr, nullptr}; EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); } + +/** + * @tc.name: DocumentFindApiTest055 + * @tc.desc: Find doc, but filter' _id value lens is larger than MAX_ID_LENS + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest055, TestSize.Level1) +{ + /** + * @tc.steps:step1.Find doc, but filter' _id value lens is larger than MAX_ID_LENS + * @tc.expected:step1.GRD_OVER_LIMIT. + */ + string document1 = "{\"_id\" : "; + string document2 = "\""; + string document4 = "\""; + string document5 = "}"; + string document_midlle(MAX_ID_LENS + 1, 'k'); + string filter = document1 + document2 + document_midlle + document4 + document5; + GRD_ResultSet *resultSet = nullptr; + const char *projectionInfo = "{}"; + Query query = {filter.c_str(), projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OVER_LIMIT); + + /** + * @tc.steps:step1.Find doc, filter' _id value lens is equal as MAX_ID_LENS + * @tc.expected:step1.GRD_OK. + */ + string document_midlle2(MAX_ID_LENS, 'k'); + filter = document1 + document2 + document_midlle2 + document4 + document5; + query = {filter.c_str(), projectionInfo}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_OK); +} \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp index f5d045c3..393c4bbc 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_insert_test.cpp @@ -27,6 +27,7 @@ const char *NO_EXIST_COLLECTION_NAME = "no_exisit"; const int INT_MAX = 2147483647; const int INT_MIN = -2147483648; const int MAX_COLLECTION_LENS = 511; +const int MAX_ID_LENS = 899; static void TestInsertDocIntoCertainColl(const char *collectionName, const char *projection, int expectedResult) { @@ -720,4 +721,34 @@ HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest038, TestSize.Level1) */ const char *document6 = R"({"_id" : "38_5", "t1" : [1, 2, 1.79769313486231570E+308]})"; EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document6, 0), GRD_OK); +} + +/** + * @tc.name: DocumentInsertApiTest039 + * @tc.desc: Insert a filter which _id value's lens is larger than MAX_ID_LENS + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentInsertApiTest, DocumentInsertApiTest039, TestSize.Level1) +{ + /** + * @tc.steps:step1.Insert a filter which _id value's lens is larger than MAX_ID_LENS. + * @tc.expected:step1.GRD_OVER_LIMIT. + */ + string document1 = "{\"_id\" : "; + string document2 = "\""; + string document4 = "\""; + string document5 = ", \"name\" : \"Ori\"}"; + string document_midlle(MAX_ID_LENS + 1, 'k'); + string document = document1 + document2 + document_midlle + document4 + document5; + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document.c_str(), 0), GRD_OVER_LIMIT); + + /** + * @tc.steps:step1.Insert a filter which _id value's lens is equal as MAX_ID_LENS. + * @tc.expected:step1.GRD_OK. + */ + string document_midlle2(MAX_ID_LENS, 'k'); + document = document1 + document2 + document_midlle2 + document4 + document5; + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document.c_str(), 0), GRD_OK); } \ No newline at end of file -- Gitee From 540bab5f82bad42cea43c955bc41a8c267d2df62 Mon Sep 17 00:00:00 2001 From: mazhao Date: Tue, 18 Apr 2023 01:13:57 +0000 Subject: [PATCH 13/18] fix some problem Signed-off-by: mazhao --- .../src/common/src/json_common.cpp | 8 +- .../src/executor/base/grd_db_api.cpp | 3 +- .../src/executor/document/document_check.cpp | 4 +- .../executor/document/grd_document_api.cpp | 7 +- .../executor/document/grd_resultset_api.cpp | 7 +- .../executor/include/grd_resultset_inner.h | 26 ++++++ .../src/executor/include/grd_type_inner.h | 3 - .../src/interface/include/collection.h | 4 +- .../src/interface/include/doc_errno.h | 2 + .../src/interface/include/document_store.h | 11 +-- .../src/interface/include/result_set.h | 11 ++- .../src/interface/include/result_set_common.h | 31 +++++++ .../src/interface/src/doc_errno.cpp | 6 ++ .../src/interface/src/document_store.cpp | 33 ++++++-- .../interface/src/document_store_manager.cpp | 1 + .../src/interface/src/projection_tree.cpp | 1 + .../src/interface/src/result_set.cpp | 33 +++++--- .../src/interface/src/result_set_common.cpp | 30 +++++++ .../unittest/api/ documentdb_delete_test.cpp | 4 +- .../unittest/api/ documentdb_find_test.cpp | 81 ++++++++++--------- 20 files changed, 218 insertions(+), 88 deletions(-) create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_resultset_inner.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set_common.h create mode 100644 services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set_common.cpp 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 e9cb2e4e..47a75e9c 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 @@ -63,7 +63,7 @@ std::vector JsonCommon::GetLeafValue(JsonObject &node) bool JsonCommon::CheckNode(JsonObject &node, std::set filedSet, bool &errFlag) { - if (errFlag == false) { + if (!errFlag) { return false; } std::string fieldName; @@ -115,7 +115,7 @@ bool JsonCommon::CheckJsonField(JsonObject &jsonObj) bool JsonCommon::CheckProjectionNode(JsonObject &node, std::set filedSet, bool &errFlag, bool isFirstFloor) { - if (errFlag == false) { + if (!errFlag) { return false; } std::string fieldName; @@ -136,7 +136,7 @@ bool JsonCommon::CheckProjectionNode(JsonObject &node, std::set fil return false; } for (int i = 0; i < fieldName.size(); i++) { - if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || ('_' == fieldName[i]) || (isFirstFloor == true && '.' == fieldName[i]))) { + if (!((isalpha(fieldName[i])) || (isdigit(fieldName[i])) || ('_' == fieldName[i]) || (isFirstFloor && '.' == fieldName[i]))) { errFlag = false; return false; } @@ -286,7 +286,7 @@ int JsonCommon::Append(const JsonObject &src, const JsonObject &add) } return true; // Both array or object } else { - if (isCollapse == true) { + if (isCollapse) { GLOGE("Add collapse item to object failed, path not exist."); externErrCode = -E_DATA_CONFLICT; return false; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp index e6c954e3..a60e53f4 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/base/grd_db_api.cpp @@ -17,10 +17,9 @@ #include "doc_errno.h" #include "document_store_manager.h" -#include "document_store.h" #include "grd_base/grd_error.h" -#include "grd_type_inner.h" #include "log_print.h" +#include "grd_type_inner.h" using namespace DocumentDB; 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 4e3cff78..e8370c8d 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 @@ -114,7 +114,7 @@ int CheckCommon::CheckDocument(JsonObject &documentObj) } if (!documentObj.GetChild().IsNull()) { auto documentObjChild = documentObj.GetChild(); - if (JsonCommon::CheckJsonField(documentObjChild) == false) { + if (!JsonCommon::CheckJsonField(documentObjChild)) { GLOGE("Document json field format is illegal"); return -E_INVALID_ARGS; } @@ -130,7 +130,7 @@ bool CheckCommon::CheckProjection(JsonObject &projectionObj, std::vectorstore_->FindDocument(db, collectionName, query.filter, query.projection, flags, grdResultSet->resultSet_); + int ret = db->store_->FindDocument(collectionName, query.filter, query.projection, flags, grdResultSet); if (ret != E_OK) { - delete grdResultSet; + delete[] grdResultSet; *resultSet = nullptr; return TrasnferDocErr(ret); } *resultSet = grdResultSet; return TrasnferDocErr(ret); - } int GRD_Flush(GRD_DB *db, unsigned int flags) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp index 07d9ba20..17b57241 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp @@ -17,7 +17,7 @@ #include "grd_base/grd_error.h" #include "doc_errno.h" #include "grd_base/grd_error.h" -#include "grd_type_inner.h" +#include "grd_resultset_inner.h" #include "grd_base/grd_resultset_api.h" #include "log_print.h" @@ -44,6 +44,7 @@ int GRD_GetValue(GRD_ResultSet *resultSet, char **value) char *val = nullptr; int ret = resultSet->resultSet_.GetValue(&val); if (val == nullptr) { + GLOGE("Value that get from resultSet is nullptr"); return GRD_NOT_AVAILABLE; } *value = val; @@ -55,7 +56,7 @@ int GRD_FreeValue(char *value) if (value == nullptr) { return GRD_OK; } - delete value; + delete[] value; return GRD_OK; } @@ -64,5 +65,7 @@ int GRD_FreeResultSet(GRD_ResultSet *resultSet) if (resultSet == nullptr) { return GRD_INVALID_ARGS; } + resultSet->resultSet_.EraseCollection(); + delete[] resultSet; return GRD_OK; } \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_resultset_inner.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_resultset_inner.h new file mode 100644 index 00000000..d840ad79 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_resultset_inner.h @@ -0,0 +1,26 @@ +/* +* 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 GRD_RESULTSET_INNER_H +#define GRD_RESULTSET_INNER_H + +#include "doc_errno.h" +#include "grd_base/grd_error.h" +#include "result_set.h" + +typedef struct GRD_ResultSet { + DocumentDB::ResultSet resultSet_; +} GRD_ResultSet; +#endif // GRD_RESULTSET_INNER_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h index 37114ed6..63663701 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/include/grd_type_inner.h @@ -24,7 +24,4 @@ typedef struct GRD_DB { DocumentDB::DocumentStore *store_ = nullptr; } GRD_DB; -typedef struct GRD_ResultSet { - DocumentDB::ResultSet resultSet_; -} GRD_ResultSet; #endif // GRD_TYPE_INNER_H \ No newline at end of file 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 e1561430..de149af2 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 @@ -24,14 +24,16 @@ namespace DocumentDB { class Collection { public: Collection(const std::string &name, KvStoreExecutor *executor); + Collection(const Collection &a) {}; + Collection() {}; ~Collection(); int PutDocument(const Key &key, const Value &document); int GetDocument(const Key &key, Value &document) const; int DeleteDocument(const Key &key); - int UpsertDocument(const std::string &id, const std::string &document, bool isReplace = true); int UpdateDocument(const Key &key, Value &update); + private: std::string name_; KvStoreExecutor *executor_ = nullptr; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h index 6c80c693..6f159683 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/doc_errno.h @@ -36,6 +36,8 @@ constexpr int E_DATA_CONFLICT = E_BASE + 18; constexpr int E_INVALID_COLL_NAME_FORMAT = E_BASE + 18; constexpr int E_INVALID_JSON_FORMAT = E_BASE + 40; constexpr int E_JSON_PATH_NOT_EXISTS = E_BASE + 41; +constexpr int E_RESOURCE_BUSY = E_BASE + 50; +constexpr int E_FAILED_MEMORY_ALLOCATE = E_BASE + 51; int TrasnferDocErr(int err); } // DocumentDB diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h index 5cbade13..0e06db1f 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/document_store.h @@ -20,10 +20,10 @@ #include #include -#include "collection.h" #include "kv_store_executor.h" -#include "result_set.h" +#include "collection.h" +class GRD_ResultSet; namespace DocumentDB { class DocumentStore { public: @@ -37,13 +37,14 @@ public: int UpsertDocument(const std::string &collection, const std::string &filter, const std::string &document, int flags); int InsertDocument(const std::string &collection, const std::string &document, int flag); int DeleteDocument(const std::string &collection, const std::string &filter, int flag); - int FindDocument(GRD_DB* db, const std::string &collection, const std::string &filter, const std::string &projection, int flags, ResultSet &resultSet); + int FindDocument(const std::string &collection, const std::string &filter, const std::string &projection, int flags, GRD_ResultSet *grdResultSet); + KvStoreExecutor *GetExecutor(int errCode); + int EraseCollection(const std::string collectionName); private: int GetViewType(JsonObject &jsonObj, bool &viewType); std::mutex dbMutex_; - KvStoreExecutor *executor_ = nullptr; - std::map collections_; + std::map collections_; }; } // DocumentDB #endif // DOCUMENT_STORE_H \ No newline at end of file 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 e9f1f995..dc87115e 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 @@ -23,25 +23,24 @@ #include "doc_errno.h" #include "json_object.h" #include "securec.h" -#include "collection.h" #include "document_check.h" -#include "json_common.h" - +#include "document_store.h" namespace DocumentDB { - class ResultSet { public: ResultSet(); ~ResultSet(); - int Init(Collection &coll, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType); + int Init(DocumentStore *store, const std::string collectionName, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType); int GetNext(); int GetValue(char **value); + int EraseCollection(); private: int CutJsonBranch(std::string &jsonData); int CheckCutNode(JsonObject *node, std::vector singleCutPath, std::vector> &allCutPath); - Collection* coll_ = nullptr; + DocumentStore *store_ = nullptr; + std::string collectionName_; ValueObject key_; bool ifShowId_ = false; bool viewType_ = false; 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 new file mode 100644 index 00000000..dfef9c26 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/include/result_set_common.h @@ -0,0 +1,31 @@ +/* +* 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 RESULTSET_COMMON_H +#define RESULTSET_COMMON_H + +#include +#include "grd_base/grd_type_export.h" +#include "vector" +#include "doc_errno.h" +#include "result_set.h" + +namespace DocumentDB { +class ValueObject; +int InitResultSet(DocumentStore *store, const std::string collectionName, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType, + ResultSet &resultSet); +} // DocumentDB +#endif //RESULTSET_COMMON_H + diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp index 9cedce6a..24eaca76 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/doc_errno.cpp @@ -58,6 +58,12 @@ int TrasnferDocErr(int err) case -E_INVALID_COLL_NAME_FORMAT: outErr = GRD_INVALID_COLLECTION_NAME; break; + case -E_RESOURCE_BUSY: + outErr = GRD_RESOURCE_BUSY; + break; + case -E_FAILED_MEMORY_ALLOCATE: + outErr = GRD_FAILED_MEMORY_ALLOCATE; + break; default: outErr = GRD_INNER_ERR; break; 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 100ea69c..0f89d603 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 @@ -19,6 +19,8 @@ #include "doc_errno.h" #include "grd_base/grd_type_export.h" #include "log_print.h" +#include "result_set_common.h" +#include "grd_resultset_inner.h" namespace DocumentDB { const int COLLECTION_LENS_MAX = 512 * 1024; @@ -216,9 +218,12 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri std::lock_guard lock(dbMutex_); return coll.DeleteDocument(key); } - -int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const std::string &filter, const std::string &projection, - int flags, ResultSet &resultSet) +KvStoreExecutor *DocumentStore::GetExecutor(int errCode) +{ + return executor_; +} +int DocumentStore::FindDocument(const std::string &collection, const std::string &filter, const std::string &projection, + int flags, GRD_ResultSet *grdResultSet) { if (flags != 0 && flags != GRD_DOC_ID_DISPLAY) { GLOGE("FindDocument flag is illegal"); @@ -271,10 +276,26 @@ int DocumentStore::FindDocument(GRD_DB *db, const std::string &collection, const if (flags == GRD_DOC_ID_DISPLAY) { ifShowId = true; } - Collection coll = Collection(collection, executor_); - return resultSet.Init(coll, idValue, allPath, ifShowId, viewType); + if (collections_.find(collection) != collections_.end()) { + GLOGE("DB is resource busy"); + return -E_RESOURCE_BUSY; + } + int ret = InitResultSet(this, collection, idValue, allPath, ifShowId, viewType, grdResultSet->resultSet_); + if (ret == E_OK) { + collections_[collection] = nullptr; + } + if (ret != E_OK) { + collections_.erase(collection); + } + return ret; +} +int DocumentStore::EraseCollection(const std::string collectionName) { + if (collections_.find(collectionName) != collections_.end()) { + collections_.erase(collectionName); + return E_OK; + } + GLOGE("erase collection failed"); } - int DocumentStore::GetViewType(JsonObject &jsonObj, bool &viewType) { auto leafValue = JsonCommon::GetLeafValue(jsonObj); if (leafValue.size() == 0) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp index 5b93c90e..f4f2faac 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/document_store_manager.cpp @@ -81,6 +81,7 @@ int DocumentStoreManager::GetDocumentStore(const std::string &path, const std::s store = new (std::nothrow) DocumentStore(executor); if (store == nullptr) { GLOGE("Memory allocation failed!" ); + return -E_FAILED_MEMORY_ALLOCATE; } if (store == nullptr) { return -E_OUT_OF_MEMORY; 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 0d5b25c4..f2ab5cb8 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 @@ -32,6 +32,7 @@ int ProjectionTree::ParseTree(std::vector> &path) { auto tempNode = new (std::nothrow) ProjectionNode; if (tempNode == nullptr) { GLOGE("Memory allocation failed!" ); + return -E_FAILED_MEMORY_ALLOCATE; } tempNode->Deep = node->Deep + 1; if (tempNode->Deep > JSON_DEEP_MAX) { 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 3eca605a..038ada1d 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 @@ -24,20 +24,23 @@ ResultSet::ResultSet() } ResultSet::~ResultSet() { - GLOGE("delete ResultSet"); + } -int ResultSet::Init(Collection &coll, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType) +int ResultSet::EraseCollection() { - coll_ = new (std::nothrow) Collection(coll); - if (coll_ == nullptr) { - GLOGE("Memory allocation failed!" ); + if (store_ != nullptr) { + store_->EraseCollection(collectionName_); } + return E_OK; +} +int ResultSet::Init(DocumentStore *store, const std::string collectionName, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType) +{ + store_ = store; + collectionName_ = collectionName; key_ = key; projectionPath_ = path; if (projectionTree_.ParseTree(path) == -E_INVALID_ARGS) { GLOGE("Parse ProjectionTree failed"); - delete coll_; - coll_ == nullptr; return -E_INVALID_ARGS; } ifShowId_ = ifShowId; @@ -62,7 +65,9 @@ int ResultSet::GetNext() } Key key(idValue.begin(), idValue.end()); Value document; - int errCode = coll_->GetDocument(key, 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; @@ -76,16 +81,19 @@ int ResultSet::GetNext() int ResultSet::GetValue(char **value) { if (findValue_.size() == 0) { + GLOGE("The value vector in resultSet is empty"); return -E_NO_DATA; } auto jsonData = findValue_.back(); char *jsonstr = new char[jsonData.size() + 1]; if (jsonstr == nullptr) { GLOGE("Memory allocation failed!" ); + return -E_FAILED_MEMORY_ALLOCATE; } errno_t err = strcpy_s(jsonstr, jsonData.size() + 1, jsonData.c_str()); if (err != 0) { GLOGE("strcpy_s failed"); + delete[] jsonstr; return -E_NO_DATA;; } *value = jsonstr; @@ -100,7 +108,7 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat } singlePath.emplace_back(node->GetItemFiled()); int index = 0; - if (projectionTree_.SearchTree(singlePath, index) == false && index == 0) { + if (!projectionTree_.SearchTree(singlePath, index) && index == 0) { allCutPath.emplace_back(singlePath); } if (!node->GetChild().IsNull()) { @@ -129,19 +137,20 @@ int ResultSet::CutJsonBranch(std::string &jsonData) auto cjsonObjChild = cjsonObj.GetChild(); errCode = CheckCutNode(&cjsonObjChild, singlePath, allCutPath); if (errCode != E_OK) { + GLOGE("The node in CheckCutNode is nullptr"); return errCode; } for (int i = 0; i < allCutPath.size(); i++) { - if (ifShowId_ == false || allCutPath[i][0] != KEY_ID) { + if (!ifShowId_ || allCutPath[i][0] != KEY_ID) { cjsonObj.DeleteItemDeeplyOnTarget(allCutPath[i]); } } } - if (viewType_ == false) { + if (!viewType_) { for (int i = 0; i < projectionPath_.size(); i++) { cjsonObj.DeleteItemDeeplyOnTarget(projectionPath_[i]); } - if (ifShowId_ == false) { + if (!ifShowId_) { std::vector idPath; idPath.emplace_back(KEY_ID); cjsonObj.DeleteItemDeeplyOnTarget(idPath); 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 new file mode 100644 index 00000000..ad195a6b --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/interface/src/result_set_common.cpp @@ -0,0 +1,30 @@ +/* +* 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 "doc_errno.h" +#include "grd_base/grd_error.h" +#include "result_set_common.h" +#include +#include + +namespace DocumentDB { +class ValueObject; +int InitResultSet(DocumentStore *store, const std::string collectionName, ValueObject &key, std::vector> &path, bool ifShowId, bool viewType, + ResultSet &resultSet) +{ + return resultSet.Init(store, collectionName, key, path, ifShowId, viewType); +} +} + 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 d9cd4c66..d4c58d3d 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 @@ -20,6 +20,7 @@ #include "grd_base/grd_error.h" #include "grd_base/grd_type_export.h" #include "grd_type_inner.h" +#include "grd_resultset_inner.h" #include "grd_base/grd_resultset_api.h" using namespace testing::ext; @@ -246,8 +247,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, TestSize.Level1) * @tc.expected: step1. GRD_OK */ const char *filter = "{\"_id\" : \"1\"}"; - GRD_ResultSet *resultSet; - resultSet = new GRD_ResultSet; + 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, filter, 0), 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 0f750b76..4a0901c7 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 @@ -24,6 +24,7 @@ #include "doc_errno.h" #include "log_print.h" #include "documentdb_test_utils.h" +#include "grd_resultset_inner.h" using namespace testing::ext; namespace { @@ -293,6 +294,7 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest006, TestSize.Level1) const char *filter1 = "{\"_id\" : \"valstring\"}"; 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 _id which value is number @@ -405,47 +407,46 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest019, TestSize.Level1) EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } -// /** -// * @tc.name: DocumentFindApiTest023 -// * @tc.desc: Test filter field with double find. -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentFindApiTest, DocumentFindApiTest023, 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 *collectionName = "CollEctionNname"; -// const char *filter = "{\"_id\" : \"6\"}"; -// GRD_ResultSet *resultSet = nullptr; -// GRD_ResultSet *resultSet2 = nullptr; -// Query query = {filter, "{}"}; -// EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 1, &resultSet), GRD_OK); -// EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 1, &resultSet2), GRD_RESOURCE_BUSY); +/** + * @tc.name: DocumentFindApiTest023 + * @tc.desc: Test filter field with double find. + * @tc.type: FUNC + * @tc.require: + * @tc.author: mazhao + */ +HWTEST_F(DocumentFindApiTest, DocumentFindApiTest023, 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\" : \"6\"}"; + GRD_ResultSet *resultSet = nullptr; + GRD_ResultSet *resultSet2 = nullptr; + Query query = {filter, "{}"}; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet2), GRD_RESOURCE_BUSY); -// 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); -// EXPECT_EQ(GRD_FindDoc(g_db, collectionName, query, 1, &resultSet), GRD_OK); -// EXPECT_EQ(GRD_Next(resultSet), GRD_OK); -// value = nullptr; -// EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); -// CompareValue(value, g_document6); -// EXPECT_EQ(GRD_FreeValue(value), GRD_OK); -// EXPECT_EQ(GRD_FreeResultSet(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); + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + value = nullptr; + EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_OK); + CompareValue(value, g_document6); + EXPECT_EQ(GRD_FreeValue(value), GRD_OK); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} /** * @tc.name: DocumentFindApiTest024 -- Gitee From 5d55e330c2d50de580d75f871a8094e85bacdc04 Mon Sep 17 00:00:00 2001 From: mazhao Date: Tue, 18 Apr 2023 02:44:42 +0000 Subject: [PATCH 14/18] fix problem of memory Signed-off-by: mazhao --- .../src/executor/document/grd_document_api.cpp | 2 +- .../src/executor/document/grd_resultset_api.cpp | 2 +- .../src/interface/include/projection_tree.h | 4 ++++ .../src/interface/src/projection_tree.cpp | 11 +++++++++++ .../test/unittest/api/ documentdb_find_test.cpp | 13 +++++++------ 5 files changed, 24 insertions(+), 8 deletions(-) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 27987544..c752f132 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -100,7 +100,7 @@ int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned in } int ret = db->store_->FindDocument(collectionName, query.filter, query.projection, flags, grdResultSet); if (ret != E_OK) { - delete[] grdResultSet; + delete grdResultSet; *resultSet = nullptr; return TrasnferDocErr(ret); } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp index 17b57241..6db93e85 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_resultset_api.cpp @@ -66,6 +66,6 @@ int GRD_FreeResultSet(GRD_ResultSet *resultSet) return GRD_INVALID_ARGS; } resultSet->resultSet_.EraseCollection(); - delete[] resultSet; + delete resultSet; return GRD_OK; } \ No newline at end of file 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 5abd62a0..15920bd4 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 @@ -18,6 +18,10 @@ struct ProjectionNode { Deep = 0; isDeepest = true; } + int DeleteProjectionNode(); + ~ProjectionNode () { + DeleteProjectionNode(); + } }; class ProjectionTree { public: 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 f2ab5cb8..edf6f356 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 @@ -36,6 +36,7 @@ int ProjectionTree::ParseTree(std::vector> &path) { } tempNode->Deep = node->Deep + 1; if (tempNode->Deep > JSON_DEEP_MAX) { + delete tempNode; return -E_INVALID_ARGS; } node->isDeepest = false; @@ -62,4 +63,14 @@ bool ProjectionTree::SearchTree(std::vector &singlePath, int &index } return true; } + +int ProjectionNode::DeleteProjectionNode() { + for (auto item : SonNode) { + if (item.second != nullptr) { + delete item.second; + item.second = nullptr; + } + } + return E_OK; +} } // namespace DocumentDB \ No newline at end of file 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 4a0901c7..0051493b 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 @@ -555,7 +555,7 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest025, TestSize.Level1) EXPECT_EQ(GRD_FreeValue(value), GRD_OK); EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); } - +#include /** * @tc.name: DocumentFindApiTest026 * @tc.desc: Test nested projection, with _id flag equals to 1. Projection is 5 level. @@ -575,15 +575,15 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest026, TestSize.Level1) const char *projectionInfo = "{\"name\": true, \"nested1.nested2.nested3.nested4.nested5\":true}"; Query query = {filter, projectionInfo}; EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 0, &resultSet), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); - char *value = nullptr; - EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_INVALID_ARGS); + // EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); + // char *value = nullptr; + // EXPECT_EQ(GRD_GetValue(resultSet, &value), GRD_INVALID_ARGS); /** * @tc.steps: step2. After loop, cannot get more record. * @tc.expected: step2. Return GRD_NO_DATA. */ - EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); + // EXPECT_EQ(GRD_Next(resultSet), GRD_INVALID_ARGS); + // EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_INVALID_ARGS); } /** @@ -1445,4 +1445,5 @@ HWTEST_F(DocumentFindApiTest, DocumentFindApiTest055, TestSize.Level1) filter = document1 + document2 + document_midlle2 + document4 + document5; 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); } \ No newline at end of file -- Gitee From d4c65ac4fa73d42339ac8b257e76faac0b9cdf7d Mon Sep 17 00:00:00 2001 From: mazhao Date: Tue, 18 Apr 2023 06:10:55 +0000 Subject: [PATCH 15/18] add lock of find Signed-off-by: mazhao --- .../gaussdb_rd_Simple/src/interface/src/document_store.cpp | 1 + 1 file changed, 1 insertion(+) 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 0f89d603..14dc4fb1 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 @@ -280,6 +280,7 @@ int DocumentStore::FindDocument(const std::string &collection, const std::string GLOGE("DB is resource busy"); return -E_RESOURCE_BUSY; } + std::lock_guard lock(dbMutex_); int ret = InitResultSet(this, collection, idValue, allPath, ifShowId, viewType, grdResultSet->resultSet_); if (ret == E_OK) { collections_[collection] = nullptr; -- Gitee From 3e2fdd7e557829f585404b843d3e0a410f587fa2 Mon Sep 17 00:00:00 2001 From: mazhao Date: Tue, 18 Apr 2023 07:55:29 +0000 Subject: [PATCH 16/18] change return code of DeleteDoc Signed-off-by: mazhao --- .../executor/document/grd_document_api.cpp | 7 ++++- .../unittest/api/ documentdb_delete_test.cpp | 29 +++++++++++++++---- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index c752f132..87b1d899 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -84,7 +84,12 @@ int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, un return GRD_INVALID_ARGS; } int ret = db->store_->DeleteDocument(collectionName, filter, flags); - return TrasnferDocErr(ret); + int errCode = TrasnferDocErr(ret); + int deleteCount = 1; + if (errCode == GRD_OK) { + return deleteCount; + } + return errCode; } int GRD_FindDoc(GRD_DB *db, const char *collectionName, Query query, unsigned int flags, GRD_ResultSet **resultSet) 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 d4c58d3d..770b711d 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 @@ -225,7 +225,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest005, TestSize.Level1) * @tc.expected: step1. GRD_INVALID_ARGS */ const char *filter = "{\"_id\" : \"1\"}"; - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), 1); /** * @tc.step2: Check whether doc has been deleted compeletely * @tc.expected: step2. GRD_OK @@ -250,7 +250,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest006, TestSize.Level1) 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, filter, 0), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 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. @@ -271,7 +271,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest007, TestSize.Level1) const char *filter = "{\"_id\" : \"1\"}"; string collectionName1(MAX_COLLECTION_LENS, 'a'); EXPECT_EQ(GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0), GRD_OK); - EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName1.c_str(), filter, 0), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName1.c_str(), filter, 0), 1); EXPECT_EQ(GRD_DropCollection(g_db, collectionName1.c_str(), 0), GRD_OK); string collectionName2(MAX_COLLECTION_LENS + 1, 'a'); @@ -320,6 +320,25 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, item.c_str(), 0), GRD_INVALID_ARGS); } const char *filter = "{\"_id\" : \"1\"}"; - EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), GRD_OK); + EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, filter, 0), 1); -} \ No newline at end of file +} + +// /** +// * @tc.name: DocumentDelete011 +// * @tc.desc: Test delete with too long collectionName. +// * @tc.type: FUNC +// * @tc.require: +// * @tc.author: mazhao +// */ +// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest011, TestSize.Level1) +// { +// const char *filter = "{\"_id\" : \"1\"}"; +// string collectionName1(MAX_COLLECTION_LENS, 'a'); +// EXPECT_EQ(GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0), GRD_OK); +// EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName1.c_str(), filter, 0), GRD_OK); +// EXPECT_EQ(GRD_DropCollection(g_db, collectionName1.c_str(), 0), GRD_OK); + +// string collectionName2(MAX_COLLECTION_LENS + 1, 'a'); +// EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName2.c_str(), filter, 0), GRD_OVER_LIMIT); +// } \ No newline at end of file -- Gitee From 7f230e700742499157701ea1f2e6b8c6a0122b25 Mon Sep 17 00:00:00 2001 From: mazhao Date: Tue, 18 Apr 2023 09:03:38 +0000 Subject: [PATCH 17/18] change deleteDoc return Code Signed-off-by: mazhao --- .../src/executor/document/grd_document_api.cpp | 11 +++++++++-- .../src/oh_adapter/src/sqlite_store_executor_impl.cpp | 2 +- .../test/unittest/api/ documentdb_delete_test.cpp | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 87b1d899..70990df3 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -86,8 +86,15 @@ int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, un int ret = db->store_->DeleteDocument(collectionName, filter, flags); int errCode = TrasnferDocErr(ret); int deleteCount = 1; - if (errCode == GRD_OK) { - return deleteCount; + switch (errCode) { + case GRD_OK: + deleteCount = 1; + return deleteCount; + break; + case GRD_NO_DATA: + deleteCount = 0; + return deleteCount; + break; } return 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 a7647f34..db4e66fd 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 @@ -144,7 +144,7 @@ int SqliteStoreExecutor::DelData(const std::string &collName, const Key &key) GLOGE("[sqlite executor] Delete data failed. err=%d", errCode); if (errCode == -E_ERROR) { GLOGE("Cant find the collection"); - return -E_INVALID_ARGS; + return -E_NO_DATA; } } return errCode; 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 770b711d..2db4e964 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 @@ -298,7 +298,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest008, TestSize.Level1) EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter, 0), GRD_INVALID_ARGS); EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0), GRD_INVALID_ARGS); EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), 0); } /** -- Gitee From f6dae7fd73de742ebf504a4ceb8417946599a4a5 Mon Sep 17 00:00:00 2001 From: mazhao Date: Tue, 18 Apr 2023 10:11:17 +0000 Subject: [PATCH 18/18] add check collectionName exist abillity Signed-off-by: mazhao --- .../executor/document/grd_document_api.cpp | 2 +- .../src/interface/include/collection.h | 1 + .../src/interface/src/collection.cpp | 9 ++++++++ .../src/interface/src/document_store.cpp | 5 +++++ .../src/sqlite_store_executor_impl.cpp | 12 ++++++++-- .../unittest/api/ documentdb_delete_test.cpp | 22 ++----------------- 6 files changed, 28 insertions(+), 23 deletions(-) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp index 70990df3..58ac1f5a 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/src/executor/document/grd_document_api.cpp @@ -85,7 +85,7 @@ int GRD_DeleteDoc(GRD_DB *db, const char *collectionName, const char *filter, un } int ret = db->store_->DeleteDocument(collectionName, filter, flags); int errCode = TrasnferDocErr(ret); - int deleteCount = 1; + int deleteCount = 0; switch (errCode) { case GRD_OK: deleteCount = 1; 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 de149af2..602ca359 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 @@ -33,6 +33,7 @@ public: int DeleteDocument(const Key &key); int UpsertDocument(const std::string &id, const std::string &document, bool isReplace = true); int UpdateDocument(const Key &key, Value &update); + bool FindDocument(); private: std::string name_; 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 445b06cc..e76a2239 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 @@ -44,6 +44,15 @@ int Collection::PutDocument(const Key &key, const Value &document) return executor_->PutData(name_, key, document); } +bool Collection::FindDocument() +{ + if (executor_ == nullptr) { + return -E_INVALID_ARGS; + } + int errCode = 0; + return executor_->IsCollectionExists(name_, errCode); +} + int Collection::GetDocument(const Key &key, Value &document) const { 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 14dc4fb1..67b2c2d4 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 @@ -280,7 +280,12 @@ int DocumentStore::FindDocument(const std::string &collection, const std::string GLOGE("DB is resource busy"); return -E_RESOURCE_BUSY; } + auto coll = Collection(collection, executor_); std::lock_guard lock(dbMutex_); + if (!coll.FindDocument()) { + GLOGE("no corresponding table name"); + return -E_INVALID_ARGS; + } int ret = InitResultSet(this, collection, idValue, allPath, ifShowId, viewType, grdResultSet->resultSet_); if (ret == E_OK) { collections_[collection] = nullptr; 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 db4e66fd..937a2793 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 @@ -133,9 +133,16 @@ int SqliteStoreExecutor::DelData(const std::string &collName, const Key &key) GLOGE("Invalid db handle."); 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; + } std::string sql = "DELETE FROM '" + collName + "' WHERE key=?;"; - int errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key](sqlite3_stmt *stmt) { + errCode = SQLiteUtils::ExecSql(dbHandle_, sql, [key](sqlite3_stmt *stmt) { SQLiteUtils::BindBlobToStatement(stmt, 1, key); return E_OK; }, nullptr); @@ -249,4 +256,5 @@ 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/test/unittest/api/ documentdb_delete_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd_Simple/test/unittest/api/ documentdb_delete_test.cpp index 2db4e964..42d4d2d7 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 @@ -271,7 +271,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest007, TestSize.Level1) const char *filter = "{\"_id\" : \"1\"}"; string collectionName1(MAX_COLLECTION_LENS, 'a'); EXPECT_EQ(GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0), GRD_OK); - EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName1.c_str(), filter, 0), 1); + EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName1.c_str(), filter, 0), 0); EXPECT_EQ(GRD_DropCollection(g_db, collectionName1.c_str(), 0), GRD_OK); string collectionName2(MAX_COLLECTION_LENS + 1, 'a'); @@ -298,7 +298,7 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest008, TestSize.Level1) EXPECT_EQ(GRD_DeleteDoc(g_db, "", filter, 0), GRD_INVALID_ARGS); EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, NULL, 0), GRD_INVALID_ARGS); EXPECT_EQ(GRD_DeleteDoc(g_db, COLLECTION_NAME, "", 0), GRD_INVALID_ARGS); - EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), 0); + EXPECT_EQ(GRD_DeleteDoc(g_db, "notExisted", filter, 0), GRD_INVALID_ARGS); } /** @@ -324,21 +324,3 @@ HWTEST_F(DocumentDeleteApiTest, DeleteDBTest010, TestSize.Level1) } -// /** -// * @tc.name: DocumentDelete011 -// * @tc.desc: Test delete with too long collectionName. -// * @tc.type: FUNC -// * @tc.require: -// * @tc.author: mazhao -// */ -// HWTEST_F(DocumentDeleteApiTest, DeleteDBTest011, TestSize.Level1) -// { -// const char *filter = "{\"_id\" : \"1\"}"; -// string collectionName1(MAX_COLLECTION_LENS, 'a'); -// EXPECT_EQ(GRD_CreateCollection(g_db, collectionName1.c_str(), "", 0), GRD_OK); -// EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName1.c_str(), filter, 0), GRD_OK); -// EXPECT_EQ(GRD_DropCollection(g_db, collectionName1.c_str(), 0), GRD_OK); - -// string collectionName2(MAX_COLLECTION_LENS + 1, 'a'); -// EXPECT_EQ(GRD_DeleteDoc(g_db, collectionName2.c_str(), filter, 0), GRD_OVER_LIMIT); -// } \ No newline at end of file -- Gitee