diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/common/src/json_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/common/src/json_common.cpp index 61f29c65ee047542ba2292ae4814f50faa230ce6..cf103af148ee649709b22ccd0d6a692151662caa 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/common/src/json_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/common/src/json_common.cpp @@ -719,7 +719,6 @@ bool JsonCommon::IsJsonNodeMatch(const JsonObject &src, const JsonObject &target if (isAlreadyMatched == 0) { // Not match anything isMatchFlag = false; } - // Source path not exist, if leaf value is null, isMatchFlag become true, else it will become false. return false; } }); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp index 1e5fc7588306b3f9635e035f24b03f12bcc775cc..1bd7e4c3a02b8f02d15a0d55b6dbb5b9f21edeac 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.cpp @@ -125,18 +125,13 @@ int CheckCommon::CheckIdFormat(JsonObject &filterJson, bool &isIdExisit) return E_OK; } -int CheckCommon::CheckDocument(JsonObject &documentObj) +int CheckCommon::CheckDocument(JsonObject &documentObj, bool &isIdExist) { if (documentObj.GetDeep() > JSON_DEEP_MAX) { GLOGE("documentObj's json deep is deeper than JSON_DEEP_MAX"); return -E_INVALID_ARGS; } - bool isIdExist = true; int ret = CheckIdFormat(documentObj, isIdExist); - if (!isIdExist) { - GLOGE("Document Id format is illegal"); - return -E_INVALID_ARGS; - } if (ret != E_OK) { return ret; } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h b/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h index 18a01c64519d3c836799dbb4e441825e0b859001..92860bc5c214a5606afd00643ea81ecedebeea3a 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/executor/document/check_common.h @@ -31,7 +31,7 @@ public: static bool CheckCollectionName(const std::string &collectionName, std::string &formattedName, int &errCode); static int CheckFilter(JsonObject &document, std::vector> &filterPath, bool &isIdExist); static int CheckIdFormat(JsonObject &data, bool &isIdExisit); - static int CheckDocument(JsonObject &document); + static int CheckDocument(JsonObject &document, bool &isIdExist); static int CheckUpdata(JsonObject &updata, std::vector> &path); static int CheckProjection(JsonObject &projectionObj, std::vector> &path); }; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/collection.h b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/collection.h index 33158c5e7f2c7a092e143d1d2349768872431177..7c7cfcb5aeea9c8dfaaf204d01ab72a1c7d59cdb 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/collection.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/collection.h @@ -29,14 +29,13 @@ public: Collection(){}; ~Collection(); - int PutDocument(const Key &key, const Value &document); - int InsertDocument(const Key &key, const Value &document); - int GetDocumentByKey(const Key &key, Value &document) const; - int GetMatchedDocument(const JsonObject &filterObj, const Key &key, std::pair &values, + int InsertDocument(const std::string &id, const std::string &document, bool &isIdExist); + int GetDocumentByKey(Key &key, Value &document) const; + int GetMatchedDocument(const JsonObject &filterObj, Key &key, std::pair &values, int isIdExist) const; - int DeleteDocument(const Key &key); + int DeleteDocument(Key &key); int IsCollectionExists(int &errCode); - int UpsertDocument(const std::string &id, const std::string &newStr, bool isReplace = true); + int UpsertDocument(const std::string &id, const std::string &newStr, bool &isIdExist, bool isReplace = true); bool FindDocument(); int UpdateDocument(const std::string &id, const std::string &document, bool isReplace = false); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/document_key.h b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/document_key.h new file mode 100644 index 0000000000000000000000000000000000000000..8aa157c0545a354606612d2393c89c0dd46c70ed --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/document_key.h @@ -0,0 +1,54 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#ifndef DOCUMENT_KEY_H +#define DOCUMENT_KEY_H + +#include +#include + +#include "json_object.h" + +#define GRD_DOC_OID_TIME_SIZE 4 +#define GRD_DOC_OID_INCREMENTAL_VALUE_SIZE 2 +#define GRD_DOC_OID_SIZE (GRD_DOC_OID_TIME_SIZE + GRD_DOC_OID_INCREMENTAL_VALUE_SIZE) +#define GRD_DOC_OID_HEX_SIZE (GRD_DOC_OID_SIZE * 2) +#define GRD_DOC_ID_TYPE_SIZE 1 + +namespace DocumentDB { + +typedef enum DocIdType { + INT = 1, + STRING, +} DocIdType; + +class DocKey { +public: + ~DocKey(){}; + int32_t keySize; + std::string id; + std::string key; + uint8_t type; +}; + +class DocumentKey { +public: + static int GetOidDocKey(DocKey &key); + static int GetStringDocKey(const std::string &id, DocKey &key); + static std::string GetIdFromKey(std::string &keyStr); +}; + +} // namespace DocumentDB +#endif // DOCUMENT_KEY_H \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/document_store.h b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/document_store.h index 3437d8ca0d4da139d698fafebf18a7f6e639af29..3f1deacb9279377a9e1f689672beeed5a83dd38e 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/document_store.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/document_store.h @@ -71,7 +71,8 @@ private: bool &isReplace); int UpsertDataIntoDB(std::shared_ptr &context, JsonObject &filterObj, const std::string &document, JsonObject &documentObj, bool &isReplace); - int InsertDataIntoDB(const std::string &collection, const std::string &document, JsonObject &documentObj); + int InsertDataIntoDB(const std::string &collection, const std::string &document, JsonObject &documentObj, + bool &isIdExist); int DeleteDataFromDB(std::shared_ptr &context, JsonObject &filterObj); int InitFindResultSet(GRD_ResultSet *grdResultSet, std::shared_ptr &context); KvStoreExecutor *executor_ = nullptr; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/result_set.h b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/result_set.h index 1191c54579b1cc4be8a24bbd70811d5370bfb483..8c015533f20b3b957b4ef4a3cf78dce9cea3e1ca 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/result_set.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/include/result_set.h @@ -39,7 +39,8 @@ public: private: int GetNextInner(bool isNeedCheckTable); - int CutJsonBranch(std::string &jsonData); + int GetValueFromDB(Key &key, JsonObject &filterObj, std::string &jsonKey, std::string &jsonData); + int CutJsonBranch(std::string &jsonKey, std::string &jsonData); int CheckCutNode(JsonObject *node, std::vector singleCutPath, std::vector> &allCutPath); int GetNextWithField(); diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/collection.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/collection.cpp index 88887ff683250a0aed846fa155260cbbefc08187..2879a04c9bda8201975290b64cf4af1b0ad7cf40 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/collection.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/collection.cpp @@ -18,6 +18,7 @@ #include "check_common.h" #include "db_constant.h" #include "doc_errno.h" +#include "document_key.h" #include "log_print.h" namespace DocumentDB { @@ -43,15 +44,7 @@ Collection::~Collection() executor_ = nullptr; } -int Collection::PutDocument(const Key &key, const Value &document) -{ - if (executor_ == nullptr) { - return -E_INNER_ERROR; - } - return executor_->PutData(name_, key, document); -} - -int Collection::InsertDocument(const Key &key, const Value &document) +int Collection::InsertDocument(const std::string &id, const std::string &document, bool &isIdExist) { if (executor_ == nullptr) { return -E_INNER_ERROR; @@ -64,7 +57,24 @@ int Collection::InsertDocument(const Key &key, const Value &document) if (!isCollectionExist) { return -E_INVALID_ARGS; } - return executor_->InsertData(name_, key, document); + Key key; + Value valSet(document.begin(), document.end()); + DocKey docKey; + if (!isIdExist) { + key.assign(id.begin(), id.end()); + errCode = executor_->InsertData(name_, key, valSet); + while (errCode != E_OK) { + DocumentKey::GetOidDocKey(docKey); + key.assign(docKey.key.begin(), docKey.key.end()); + errCode = executor_->InsertData(name_, key, valSet); + } + return errCode; + } else { + DocKey docKey; + DocumentKey::GetStringDocKey(id, docKey); + key.assign(docKey.key.begin(), docKey.key.end()); + } + return executor_->InsertData(name_, key, valSet); } bool Collection::FindDocument() @@ -76,7 +86,7 @@ bool Collection::FindDocument() return executor_->IsCollectionExists(name_, errCode); } -int Collection::GetDocumentByKey(const Key &key, Value &document) const +int Collection::GetDocumentByKey(Key &key, Value &document) const { if (executor_ == nullptr) { return -E_INNER_ERROR; @@ -84,8 +94,8 @@ int Collection::GetDocumentByKey(const Key &key, Value &document) const return executor_->GetDataByKey(name_, key, document); } -int Collection::GetMatchedDocument(const JsonObject &filterObj, const Key &key, - std::pair &values, int isIdExist) const +int Collection::GetMatchedDocument(const JsonObject &filterObj, Key &key, std::pair &values, + int isIdExist) const { if (executor_ == nullptr) { return -E_INNER_ERROR; @@ -93,7 +103,7 @@ int Collection::GetMatchedDocument(const JsonObject &filterObj, const Key &key, return executor_->GetDataByFilter(name_, key, filterObj, values, isIdExist); } -int Collection::DeleteDocument(const Key &key) +int Collection::DeleteDocument(Key &key) { if (executor_ == nullptr) { return -E_INNER_ERROR; @@ -114,7 +124,7 @@ int Collection::IsCollectionExists(int &errCode) return executor_->IsCollectionExists(name_, errCode); } -int Collection::UpsertDocument(const std::string &id, const std::string &newStr, bool isReplace) +int Collection::UpsertDocument(const std::string &id, const std::string &newStr, bool &isIdExist, bool isReplace) { if (executor_ == nullptr) { return -E_INNER_ERROR; @@ -129,9 +139,24 @@ int Collection::UpsertDocument(const std::string &id, const std::string &newStr, GLOGE("Collection not created."); return -E_INVALID_ARGS; } - Key keyId(id.begin(), id.end()); + Key key; Value valSet(newStr.begin(), newStr.end()); - return executor_->PutData(name_, keyId, valSet); + DocKey docKey; + if (!isIdExist) { + key.assign(id.begin(), id.end()); + errCode = executor_->PutData(name_, key, valSet); + while (errCode != E_OK) { + DocumentKey::GetOidDocKey(docKey); + key.assign(docKey.key.begin(), docKey.key.end()); + errCode = executor_->PutData(name_, key, valSet); + } + return errCode; + } else { + DocKey docKey; + DocumentKey::GetStringDocKey(id, docKey); + key.assign(docKey.key.begin(), docKey.key.end()); + } + return executor_->PutData(name_, key, valSet); } int Collection::UpdateDocument(const std::string &id, const std::string &newStr, bool isReplace) diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_key.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_key.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e99582f1d6c6da7b326163fcf3eadb862b852c28 --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_key.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 "document_key.h" + +#include "doc_errno.h" +#include "log_print.h" +#include "securec.h" +namespace DocumentDB { + +static uint16_t g_oIdIncNum = 0; + +static int InitDocIdFromOid(DocKey &docKey) +{ + time_t nowTime = time(nullptr); + if (nowTime < 0) { + return -E_INNER_ERROR; + } + uint32_t now = (uint32_t)nowTime; + uint16_t iv = g_oIdIncNum++; + // The maximum number of autoincrements is 65535, and if it is exceeded, it becomes 0. + if (g_oIdIncNum > (uint16_t)65535) { + g_oIdIncNum = (uint16_t)0; + } + char *idTemp = new char[GRD_DOC_OID_HEX_SIZE + 1]; + if (sprintf_s(idTemp, GRD_DOC_OID_HEX_SIZE + 1, "%08x%04x", now, iv) < 0) { + GLOGE("get oid error"); + return -E_INNER_ERROR; + } + docKey.id = idTemp; + delete[] idTemp; + docKey.type = (uint8_t)STRING; + return E_OK; +} + +static int SerializeDocKey(DocKey &key, const std::string &id) +{ + std::string idStr = id; + key.key = idStr; + key.key = key.key + std::to_string(key.type); // Question here + return E_OK; +} + +int DocumentKey::GetStringDocKey(const std::string &id, DocKey &key) +{ + if (id.empty()) { + return GetOidDocKey(key); // It won't go to this branch at the moment. + } + key.id = id; + key.type = (uint8_t)STRING; + int ret = SerializeDocKey(key, key.id); + return ret; +} + +int DocumentKey::GetOidDocKey(DocKey &key) +{ + int ret = InitDocIdFromOid(key); + { + if (ret != E_OK) { + return ret; + } + } + ret = SerializeDocKey(key, key.id); + return ret; +} + +std::string DocumentKey::GetIdFromKey(std::string &keyStr) +{ + if (!keyStr.empty()) { + keyStr.pop_back(); + } + return keyStr; +} +} // namespace DocumentDB \ No newline at end of file diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp index c8d99221ae0e0514b6c8c4dd265825d48c23e016..42e6a9e0a1053a02f2cdca52829ddaf094110476 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/document_store.cpp @@ -18,6 +18,7 @@ #include "check_common.h" #include "collection_option.h" #include "doc_errno.h" +#include "document_key.h" #include "grd_base/grd_type_export.h" #include "grd_resultset_inner.h" #include "log_print.h" @@ -279,6 +280,7 @@ int DocumentStore::UpdateDocument(const std::string &collection, const std::stri } bool isReplace = ((flags & GRD_DOC_REPLACE) == GRD_DOC_REPLACE); std::shared_ptr context = std::make_shared(); + context->isIdExist = isIdExist; context->collectionName = collection; context->filter = filter; context->ifShowId = true; @@ -307,13 +309,17 @@ int UpsertArgsCheck(const std::string &collection, const std::string &filter, co int CheckUpsertConflict(ResultSet &resultSet, JsonObject &filterObj, std::string &docId, Collection &coll) { - int errCode = resultSet.GetNext(false, true); + std::string val; // use to know whether there is data in the resultSet or not. + int errCode = resultSet.GetValue(val); bool isfilterMatch = false; if (errCode == E_OK) { isfilterMatch = true; } Value ValueDocument; - Key key(docId.begin(), docId.end()); + DocKey docKey; + std::string keyStr = docId; + DocumentKey::GetStringDocKey(keyStr, docKey); + Key key(docKey.key.begin(), docKey.key.end()); errCode = coll.GetDocumentByKey(key, ValueDocument); if (errCode == E_OK && !(isfilterMatch)) { GLOGE("id exist but filter does not match, data conflict"); @@ -322,13 +328,11 @@ int CheckUpsertConflict(ResultSet &resultSet, JsonObject &filterObj, std::string return errCode; } -int GetUpsertRePlaceData(ResultSet &resultSet, std::string &targetDocument, JsonObject &documentObj, bool isReplace, - std::string &valStr) +int GetUpsertRePlaceData(ResultSet &resultSet, JsonObject &documentObj, bool isReplace, std::string &valStr) { - resultSet.GetNext(); int errCode = resultSet.GetValue(valStr); if (errCode != E_OK || isReplace) { - valStr = targetDocument; // If cant not find data, insert it. + valStr = documentObj.Print(); // If cant not find data, insert it. return E_OK; } if (errCode != E_OK && errCode != -E_NOT_FOUND) { @@ -354,18 +358,25 @@ int GetUpsertRePlaceData(ResultSet &resultSet, std::string &targetDocument, Json return errCode; } -int InsertIdToDocument(JsonObject &filterObj, JsonObject &documentObj, bool &isIdExist, std::string &targetDocument, - std::string &docId) +int InsertIdToDocument(ResultSet &resultSet, JsonObject &filterObj, JsonObject &documentObj, std::string &docId) { auto filterObjChild = filterObj.GetChild(); + bool isIdExist; ValueObject idValue = JsonCommon::GetValueInSameLevel(filterObjChild, KEY_ID, isIdExist); - docId = idValue.GetStringValue(); int errCode = E_OK; - JsonObject idObj = filterObj.GetObjectItem(KEY_ID, errCode); - documentObj.InsertItemObject(0, idObj); - targetDocument = documentObj.Print(); - if (!isIdExist) { - errCode = -E_INVALID_ARGS; + int ret = resultSet.GetNext(false, true); // All anomalies will be judged later + if (isIdExist) { + docId = idValue.GetStringValue(); + JsonObject idObj = filterObj.GetObjectItem(KEY_ID, errCode); + documentObj.InsertItemObject(0, idObj); + } else { + if (ret == E_OK) { // E_OK means find data. + (void)resultSet.GetKey(docId); // This errCode will always be E_OK. + } else { + DocKey docKey; + DocumentKey::GetOidDocKey(docKey); + docId = docKey.key; + } } return errCode; } @@ -384,30 +395,27 @@ int DocumentStore::UpsertDataIntoDB(std::shared_ptr &context, Json Collection coll = Collection(context->collectionName, executor_); int count = 0; std::string docId; - bool isIdExist; ResultSet resultSet; - std::string targetDocument; std::string newStr; - errCode = InsertIdToDocument(filterObj, documentObj, isIdExist, targetDocument, docId); - if (errCode != E_OK) { - return errCode; - } - context->isIdExist = isIdExist; errCode = InitResultSet(context, this, resultSet, false); if (errCode != E_OK) { goto END; } + errCode = InsertIdToDocument(resultSet, filterObj, documentObj, docId); + if (errCode != E_OK) { + return errCode; + } errCode = CheckUpsertConflict(resultSet, filterObj, docId, coll); // There are only three return values, the two other situation can continue to move forward. if (errCode == -E_DATA_CONFLICT) { GLOGE("upsert data conflict"); goto END; } - errCode = GetUpsertRePlaceData(resultSet, targetDocument, documentObj, isReplace, newStr); + errCode = GetUpsertRePlaceData(resultSet, documentObj, isReplace, newStr); if (errCode != E_OK) { goto END; } - errCode = coll.UpsertDocument(docId, newStr, isReplace); + errCode = coll.UpsertDocument(docId, newStr, context->isIdExist, isReplace); if (errCode == E_OK) { count++; } else if (errCode == -E_NOT_FOUND) { @@ -473,6 +481,7 @@ int DocumentStore::UpsertDocument(const std::string &collection, const std::stri context->filter = filter; context->collectionName = collection; context->ifShowId = true; + context->isIdExist = isIdExist; bool isReplace = ((flags & GRD_DOC_REPLACE) == GRD_DOC_REPLACE); return UpsertDataIntoDB(context, filterObj, document, documentObj, isReplace); } @@ -496,16 +505,23 @@ int InsertArgsCheck(const std::string &collection, const std::string &document, return errCode; } -int DocumentStore::InsertDataIntoDB(const std::string &collection, const std::string &document, JsonObject &documentObj) +int DocumentStore::InsertDataIntoDB(const std::string &collection, const std::string &document, + JsonObject &documentObj, bool &isIdExist) { std::lock_guard lock(dbMutex_); - JsonObject documentObjChild = documentObj.GetChild(); - ValueObject idValue = JsonCommon::GetValueInSameLevel(documentObjChild, KEY_ID); - std::string id = idValue.GetStringValue(); - Key key(id.begin(), id.end()); - Value value(document.begin(), document.end()); + std::string id; + if (isIdExist) { + JsonObject documentObjChild = documentObj.GetChild(); + ValueObject idValue = JsonCommon::GetValueInSameLevel(documentObjChild, KEY_ID); + id = idValue.GetStringValue(); + + } else { + DocKey docKey; + DocumentKey::GetOidDocKey(docKey); + id = docKey.key; + } Collection coll = Collection(collection, executor_); - return coll.InsertDocument(key, value); + return coll.InsertDocument(id, document, isIdExist); } int DocumentStore::InsertDocument(const std::string &collection, const std::string &document, uint32_t flags) @@ -519,11 +535,12 @@ int DocumentStore::InsertDocument(const std::string &collection, const std::stri GLOGE("Document Parsed failed"); return errCode; } - errCode = CheckCommon::CheckDocument(documentObj); + bool isIdExist = true; + errCode = CheckCommon::CheckDocument(documentObj, isIdExist); if (errCode != E_OK) { return errCode; } - return InsertDataIntoDB(collection, document, documentObj); + return InsertDataIntoDB(collection, document, documentObj, isIdExist); } int DeleteArgsCheck(const std::string &collection, const std::string &filter, uint32_t flags) @@ -600,6 +617,7 @@ int DocumentStore::DeleteDocument(const std::string &collection, const std::stri return errCode; } std::shared_ptr context = std::make_shared(); + context->isIdExist = isIdExist; context->filter = filter; context->collectionName = collection; return DeleteDataFromDB(context, filterObj); @@ -762,20 +780,18 @@ END: int DocumentStore::FindDocument(const std::string &collection, const std::string &filter, const std::string &projection, uint32_t flags, GRD_ResultSet *grdResultSet) { - std::shared_ptr context = std::make_shared(); int errCode = E_OK; errCode = FindArgsCheck(collection, filter, projection, flags); if (errCode != E_OK) { GLOGE("delete arg is illegal"); return errCode; } - context->collectionName = collection; - context->filter = filter; JsonObject filterObj = JsonObject::Parse(filter, errCode, true, true); if (errCode != E_OK) { GLOGE("filter Parsed failed"); return errCode; } + std::shared_ptr context = std::make_shared(); errCode = FindProjectionInit(projection, context); if (errCode != E_OK) { return errCode; @@ -792,6 +808,9 @@ int DocumentStore::FindDocument(const std::string &collection, const std::string } else { context->ifShowId = false; } + context->collectionName = collection; + context->filter = filter; + context->isIdExist = isIdExist; return InitFindResultSet(grdResultSet, context); } diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp index 65751f2e2dd7385fe65eb1305fd4c736bac53b18..c35ff9a2c50b6151c4362e90a5106b9b8038896f 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set.cpp @@ -14,7 +14,10 @@ */ #include "result_set.h" +#include + #include "db_constant.h" +#include "document_key.h" #include "log_print.h" #include "securec.h" @@ -41,6 +44,28 @@ int ResultSet::Init(std::shared_ptr &context, DocumentStore *store return E_OK; } +int ResultSet::GetValueFromDB(Key &key, JsonObject &filterObj, std::string &jsonKey, std::string &jsonData) +{ + std::pair value; + Collection coll = store_->GetCollection(context_->collectionName); + filterObj.DeleteItemFromObject("_id"); + int errCode = coll.GetMatchedDocument(filterObj, key, value, context_->isIdExist); + if (errCode == -E_NOT_FOUND) { + return -E_NO_DATA; + } + jsonData.assign(value.second.begin(), value.second.end()); + jsonKey.assign(value.first.begin(), value.first.end()); + GLOGE("jsonKey is =========>%s", jsonKey.c_str()); + lastKeyIndex_ = jsonKey; + if (isCutBranch_) { + errCode = CutJsonBranch(jsonKey, jsonData); + if (errCode != E_OK) { + GLOGE("cut branch faild"); + } + } + return errCode; +} + int ResultSet::GetNextWithField() { int errCode = E_OK; @@ -50,34 +75,29 @@ int ResultSet::GetNextWithField() return errCode; } Key key; - if (context_->isIdExist) { // get id from filter or from previous data. - JsonObject filterObjChild = filterObj.GetChild(); - ValueObject idValue = JsonCommon::GetValueInSameLevel(filterObjChild, KEY_ID); - std::string idKey = idValue.GetStringValue(); - key.assign(idKey.begin(), idKey.end()); + if (context_->isIdExist) { + if (index_ == 0) { // get id from filter, if alreay has got id once, get from lastKeyIndex. + JsonObject filterObjChild = filterObj.GetChild(); + ValueObject idValue = JsonCommon::GetValueInSameLevel(filterObjChild, KEY_ID); + std::string idKey = idValue.GetStringValue(); + DocKey docKey; + DocumentKey::GetStringDocKey(idKey, docKey); + key.assign(docKey.key.begin(), docKey.key.end()); + } else { // Use id to find data that can only get one data. + matchData_.first.clear(); // Delete previous data. + matchData_.second.clear(); + return -E_NO_DATA; + } } else { key.assign(lastKeyIndex_.begin(), lastKeyIndex_.end()); } - matchData_.first.clear(); // Delete previous data. + matchData_.first.clear(); matchData_.second.clear(); - std::pair value; - Collection coll = store_->GetCollection(context_->collectionName); - errCode = coll.GetMatchedDocument(filterObj, key, value, context_->isIdExist); - if (errCode == -E_NOT_FOUND) { - return -E_NO_DATA; - } - std::string jsonData(value.second.begin(), value.second.end()); - std::string jsonkey(value.first.begin(), value.first.end()); - lastKeyIndex_ = jsonkey; - if (isCutBranch_) { - errCode = CutJsonBranch(jsonData); - if (errCode != E_OK) { - GLOGE("cut branch faild"); - return errCode; - } - } - matchData_ = std::make_pair(jsonkey, jsonData); - return E_OK; + std::string jsonKey; + std::string jsonData; + errCode = GetValueFromDB(key, filterObj, jsonKey, jsonData); + matchData_ = std::make_pair(jsonKey, jsonData); + return errCode; } int ResultSet::GetNextInner(bool isNeedCheckTable) @@ -97,6 +117,7 @@ int ResultSet::GetNextInner(bool isNeedCheckTable) } } errCode = GetNextWithField(); + index_++; if (errCode != E_OK) { return errCode; } @@ -193,7 +214,35 @@ int ResultSet::CheckCutNode(JsonObject *node, std::vector singlePat } return E_OK; } -int ResultSet::CutJsonBranch(std::string &jsonData) + +JsonObject CreatIdObj(const std::string &idStr, int errCode) +{ + std::stringstream sstream; + sstream << "{\"_id\":" + << "\"" << idStr << "\"}"; + JsonObject idObj = JsonObject::Parse(sstream.str(), errCode, true); // cant be faild. + idObj = idObj.GetChild(); + return idObj; +} + +int InsertRandomId(JsonObject &cjsonObj, std::string &jsonKey) +{ + std::string idStr = DocumentKey::GetIdFromKey(jsonKey); + if (idStr.empty()) { + GLOGE("Genalral Id faild"); + return -E_INNER_ERROR; + } + int errCode = E_OK; + JsonObject idObj = CreatIdObj(idStr, errCode); + if (errCode != E_OK) { + GLOGE("CreatIdObj faild"); + return errCode; + } + cjsonObj.InsertItemObject(0, idObj); + return E_OK; +} + +int ResultSet::CutJsonBranch(std::string &jsonKey, std::string &jsonData) { int errCode; JsonObject cjsonObj = JsonObject::Parse(jsonData, errCode, true); @@ -201,8 +250,14 @@ int ResultSet::CutJsonBranch(std::string &jsonData) GLOGE("jsonData Parsed failed"); return errCode; } - std::vector> allCutPath; + bool isIdExistInValue = true; // if id exsit in the value string that get from db. + bool isInsertIdflag = false; + isIdExistInValue = cjsonObj.GetObjectItem("_id", errCode).IsNull() ? false : true; + if (context_->ifShowId && !isIdExistInValue) { + isInsertIdflag = true; // ifShowId is true,and then the data taken out does not have IDs, insert id. + } if (context_->viewType) { + std::vector> allCutPath; std::vector singlePath; JsonObject cjsonObjChild = cjsonObj.GetChild(); errCode = CheckCutNode(&cjsonObjChild, singlePath, allCutPath); @@ -214,6 +269,15 @@ int ResultSet::CutJsonBranch(std::string &jsonData) if (!context_->ifShowId || singleCutPaht[0] != KEY_ID) { cjsonObj.DeleteItemDeeplyOnTarget(singleCutPaht); } + if (singleCutPaht[0] == KEY_ID && !isIdExistInValue) { // projection has Id, and its showType is true. + isInsertIdflag = true; + } + } + } + if (isInsertIdflag) { + errCode = InsertRandomId(cjsonObj, jsonKey); + if (errCode != E_OK) { + return errCode; } } if (!context_->viewType) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set_common.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set_common.cpp index d4e73e5660f02e184ee19f6caa4a4f8e3a49a885..8a142704cf0eb621dfd9b1f7d68a162ab15718ae 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set_common.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/interface/src/result_set_common.cpp @@ -23,6 +23,12 @@ class ValueObject; int InitResultSet(std::shared_ptr &context, DocumentStore *store, ResultSet &resultSet, bool isCutBranch) { if (isCutBranch) { + for (const auto &singlePath : context->projectionPath) { + if (singlePath[0] == "_id" && context->viewType == true) { // projection has Id and viewType is true + context->ifShowId = true; + break; + } + } if (context->projectionTree.ParseTree(context->projectionPath) == -E_INVALID_ARGS) { GLOGE("Parse ProjectionTree failed"); return -E_INVALID_ARGS; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/kv_store_executor.h b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/kv_store_executor.h index a701cddf060a7a0d69aece2f1a8e263f9d6b5b35..cee70c17666b369cc368430b5d4ea14edc253508 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/kv_store_executor.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/include/kv_store_executor.h @@ -29,12 +29,12 @@ public: virtual int Commit() = 0; virtual int Rollback() = 0; - virtual int PutData(const std::string &collName, const Key &key, const Value &value) = 0; - virtual int InsertData(const std::string &collName, const Key &key, const Value &value) = 0; - virtual int GetDataByKey(const std::string &collName, const Key &key, Value &value) const = 0; - virtual int GetDataByFilter(const std::string &collName, const Key &key, const JsonObject &filterObj, + virtual int PutData(const std::string &collName, Key &key, const Value &value) = 0; + virtual int InsertData(const std::string &collName, Key &key, const Value &value) = 0; + virtual int GetDataByKey(const std::string &collName, Key &key, Value &value) const = 0; + virtual int GetDataByFilter(const std::string &collName, Key &key, const JsonObject &filterObj, std::pair &values, int isIdExist) const = 0; - virtual int DelData(const std::string &collName, const Key &key) = 0; + virtual int DelData(const std::string &collName, Key &key) = 0; virtual int CreateCollection(const std::string &name, const std::string &option, bool ignoreExists) = 0; virtual int DropCollection(const std::string &name, bool ignoreNonExists) = 0; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp index d038491f3a02e918753f055f507fcf611fad2ad0..8deb1babad421de4a2c91016ade8a864288c38b2 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/kv_store_manager.cpp @@ -63,7 +63,7 @@ int KvStoreManager::GetKvStore(const std::string &path, const DBConfig &config, goto END; } } - + executor = sqliteExecutor; return E_OK; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp index c8d21319033e8e1c78ca0e85ba321d423176e025..8140e1d237219c07434089ccff29a6d01bf4e764 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.cpp @@ -102,11 +102,12 @@ int SqliteStoreExecutorImpl::Rollback() return SQLiteUtils::RollbackTransaction(dbHandle_); } -int SqliteStoreExecutorImpl::PutData(const std::string &collName, const Key &key, const Value &value) +int SqliteStoreExecutorImpl::PutData(const std::string &collName, Key &key, const Value &value) { if (dbHandle_ == nullptr) { return -E_ERROR; } + key.push_back(uint8_t(2)); std::string sql = "INSERT OR REPLACE INTO '" + collName + "' VALUES (?,?);"; int errCode = SQLiteUtils::ExecSql( dbHandle_, sql, @@ -127,11 +128,12 @@ int SqliteStoreExecutorImpl::PutData(const std::string &collName, const Key &key return E_OK; } -int SqliteStoreExecutorImpl::InsertData(const std::string &collName, const Key &key, const Value &value) +int SqliteStoreExecutorImpl::InsertData(const std::string &collName, Key &key, const Value &value) { if (dbHandle_ == nullptr) { return -E_ERROR; } + key.push_back(uint8_t(2)); std::string sql = "INSERT INTO '" + collName + "' VALUES (?,?);"; int errCode = SQLiteUtils::ExecSql( dbHandle_, sql, @@ -152,12 +154,13 @@ int SqliteStoreExecutorImpl::InsertData(const std::string &collName, const Key & return E_OK; } -int SqliteStoreExecutorImpl::GetDataByKey(const std::string &collName, const Key &key, Value &value) const +int SqliteStoreExecutorImpl::GetDataByKey(const std::string &collName, Key &key, Value &value) const { if (dbHandle_ == nullptr) { GLOGE("Invalid db handle."); return -E_ERROR; } + key.push_back(uint8_t(2)); int innerErrorCode = -E_NOT_FOUND; std::string sql = "SELECT value FROM '" + collName + "' WHERE key=?;"; int errCode = SQLiteUtils::ExecSql( @@ -178,7 +181,7 @@ int SqliteStoreExecutorImpl::GetDataByKey(const std::string &collName, const Key return innerErrorCode; } -std::string GeneralInsertSql(const std::string &collName, const Key &key, int isIdExist) +std::string GeneralInsertSql(const std::string &collName, Key &key, int isIdExist) { std::string sqlEqual = "SELECT key, value FROM '" + collName + "' WHERE key=?;"; std::string sqlOrder = "SELECT key, value FROM '" + collName + "'ORDER BY KEY;"; @@ -190,18 +193,18 @@ std::string GeneralInsertSql(const std::string &collName, const Key &key, int is } } -int SqliteStoreExecutorImpl::GetDataByFilter(const std::string &collName, const Key &key, const JsonObject &filterObj, +int SqliteStoreExecutorImpl::GetDataByFilter(const std::string &collName, Key &key, const JsonObject &filterObj, std::pair &values, int isIdExist) const { if (dbHandle_ == nullptr) { GLOGE("Invalid db handle."); return -E_ERROR; } + key.push_back(uint8_t(2)); Value keyResult; Value valueResult; bool isFindMatch = false; int innerErrorCode = -E_NOT_FOUND; - std::string test(key.begin(), key.end()); std::string sql = GeneralInsertSql(collName, key, isIdExist); std::string keyStr(key.begin(), key.end()); int errCode = SQLiteUtils::ExecSql( @@ -243,12 +246,13 @@ int SqliteStoreExecutorImpl::GetDataByFilter(const std::string &collName, const return innerErrorCode; } -int SqliteStoreExecutorImpl::DelData(const std::string &collName, const Key &key) +int SqliteStoreExecutorImpl::DelData(const std::string &collName, Key &key) { if (dbHandle_ == nullptr) { GLOGE("Invalid db handle."); return -E_ERROR; } + key.push_back(uint8_t(2)); int errCode = 0; Value valueRet; if (GetDataByKey(collName, key, valueRet) != E_OK) { diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.h b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.h index aa392294adafdaa33f1b8f425f4428a74aff4a58..ad93fdfdc3d32e4fbda8ef9adad08a3e5704b87c 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.h +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/src/oh_adapter/src/sqlite_store_executor_impl.h @@ -37,12 +37,12 @@ public: int Commit() override; int Rollback() override; - int PutData(const std::string &collName, const Key &key, const Value &value) override; - int InsertData(const std::string &collName, const Key &key, const Value &value) override; - int GetDataByKey(const std::string &collName, const Key &key, Value &value) const override; - int GetDataByFilter(const std::string &collName, const Key &key, const JsonObject &filterObj, + int PutData(const std::string &collName, Key &key, const Value &value) override; + int InsertData(const std::string &collName, Key &key, const Value &value) override; + int GetDataByKey(const std::string &collName, Key &key, Value &value) const override; + int GetDataByFilter(const std::string &collName, Key &key, const JsonObject &filterObj, std::pair &values, int isIdExist) const override; - int DelData(const std::string &collName, const Key &key) override; + int DelData(const std::string &collName, Key &key) override; int CreateCollection(const std::string &name, const std::string &option, bool ignoreExists) override; int DropCollection(const std::string &name, bool ignoreNonExists) override; diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp index 01320cbcc21d53d6c947204ae398604597e37a37..38da55bd95e170e81bfbbfe4017bf4dfd926ab2f 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_find_test.cpp @@ -1465,4 +1465,33 @@ HWTEST_F(DocumentDBFindTest, DocumentDBFindTest062, TestSize.Level1) Query query = { filter, projection }; EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_INVALID_ARGS); } + +HWTEST_F(DocumentDBFindTest, DocumentDBFindTest063, TestSize.Level1) +{ + const char *document = "{\"a\":1, \"doc64\" : 2}"; + const char *filter1 = "{\"b\":1}"; + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + EXPECT_EQ(GRD_UpsertDoc(g_db, COLLECTION_NAME, filter1, document, 0), 1); + const char *filter = "{\"a\":1}"; + GRD_ResultSet *resultSet = nullptr; + const char *projection = R"({})"; + Query query = { filter, projection }; + EXPECT_EQ(GRD_FindDoc(g_db, COLLECTION_NAME, query, 1, &resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_OK); + EXPECT_EQ(GRD_Next(resultSet), GRD_NO_DATA); + EXPECT_EQ(GRD_FreeResultSet(resultSet), GRD_OK); +} } // namespace diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp index 54be32da739f55f4338a71f2c3d56ef418f664a8..d2739db211f7acc30b7fcd9d8986539ec4ed8eff 100644 --- a/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/api/documentdb_insert_test.cpp @@ -824,6 +824,6 @@ HWTEST_F(DocumentDBInsertTest, DocumentDBInsertTest045, TestSize.Level1) HWTEST_F(DocumentDBInsertTest, DocumentDBInsertTest046, TestSize.Level1) { const char *document1 = R""({})""; - EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_INVALID_ARGS); + EXPECT_EQ(GRD_InsertDoc(g_db, RIGHT_COLLECTION_NAME, document1, 0), GRD_OK); } } // namespace diff --git a/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/oh_adapter/documentdb_key_document_test.cpp b/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/oh_adapter/documentdb_key_document_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9e53f90a0f40ca61ee87f2b7f07b730cb7785cab --- /dev/null +++ b/services/distributeddataservice/service/data_share/gaussdb_rd/test/unittest/oh_adapter/documentdb_key_document_test.cpp @@ -0,0 +1,56 @@ +/* +* Copyright (c) 2023 Huawei Device Co., Ltd. +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include + +#include "doc_errno.h" +#include "document_key.h" +#include "documentdb_test_utils.h" +#include "log_print.h" + +using namespace DocumentDB; +using namespace testing::ext; +using namespace DocumentDBUnitTest; + +namespace { +class DocumentDBKeyCommonTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +void DocumentDBKeyCommonTest::SetUpTestCase(void) {} + +void DocumentDBKeyCommonTest::TearDownTestCase(void) {} + +void DocumentDBKeyCommonTest::SetUp(void) {} + +void DocumentDBKeyCommonTest::TearDown(void) {} + +HWTEST_F(DocumentDBKeyCommonTest, KeyCommonTest001, TestSize.Level0) +{ + DocKey docKey; + for (int i = 0; i < 65537; i++) { + DocumentKey::GetOidDocKey(docKey); + if (i > 65530) { + GLOGE("docKey key is=============>%s", docKey.key.c_str()); + } + } +} + +} // namespace \ No newline at end of file