1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 
16 #include "document_store.h"
17 
18 #include "check_common.h"
19 #include "collection_option.h"
20 #include "doc_errno.h"
21 #include "document_key.h"
22 #include "grd_base/grd_type_export.h"
23 #include "grd_resultset_inner.h"
24 #include "rd_log_print.h"
25 #include "result_set.h"
26 #include "result_set_common.h"
27 
28 namespace DocumentDB {
29 constexpr int JSON_LENS_MAX = 1024 * 1024;
30 constexpr const char *KEY_ID = "_id";
31 
DocumentStore(KvStoreExecutor * executor)32 DocumentStore::DocumentStore(KvStoreExecutor *executor) : executor_(executor) {}
33 
~DocumentStore()34 DocumentStore::~DocumentStore()
35 {
36     delete executor_;
37 }
38 
CreateCollection(const std::string & name,const std::string & option,uint32_t flags)39 int DocumentStore::CreateCollection(const std::string &name, const std::string &option, uint32_t flags)
40 {
41     std::string lowerCaseName;
42     int errCode = E_OK;
43     if (!CheckCommon::CheckCollectionName(name, lowerCaseName, errCode)) {
44         GLOGE("Check collection name invalid. %d", errCode);
45         return errCode;
46     }
47     errCode = E_OK;
48     CollectionOption collOption = CollectionOption::ReadOption(option, errCode);
49     if (errCode != E_OK) {
50         GLOGE("Read collection option str failed. %d", errCode);
51         return errCode;
52     }
53 
54     if (flags != 0u && flags != CHK_EXIST_COLLECTION) {
55         GLOGE("Check flags invalid.");
56         return -E_INVALID_ARGS;
57     }
58 
59     std::lock_guard<std::mutex> lock(dbMutex_);
60     if (executor_ == nullptr) {
61         return -E_INNER_ERROR;
62     }
63     errCode = executor_->StartTransaction();
64     if (errCode != E_OK) {
65         return errCode;
66     }
67 
68     std::string oriOptStr;
69     bool ignoreExists = (flags != CHK_EXIST_COLLECTION);
70     errCode = executor_->CreateCollection(lowerCaseName, oriOptStr, ignoreExists);
71     if (errCode != E_OK) {
72         GLOGE("Create collection failed. %d", errCode);
73         goto END;
74     }
75 
76 END:
77     if (errCode == E_OK) {
78         executor_->Commit();
79     } else {
80         executor_->Rollback();
81     }
82     return errCode;
83 }
84 
DropCollection(const std::string & name,uint32_t flags)85 int DocumentStore::DropCollection(const std::string &name, uint32_t flags)
86 {
87     std::string lowerCaseName;
88     int errCode = E_OK;
89     if (!CheckCommon::CheckCollectionName(name, lowerCaseName, errCode)) {
90         GLOGE("Check collection name invalid. %d", errCode);
91         return errCode;
92     }
93 
94     if (flags != 0u && flags != CHK_NON_EXIST_COLLECTION) {
95         GLOGE("Check flags invalid.");
96         return -E_INVALID_ARGS;
97     }
98 
99     bool ignoreNonExists = (flags != CHK_NON_EXIST_COLLECTION);
100     std::lock_guard<std::mutex> lock(dbMutex_);
101     if (executor_ == nullptr) {
102         return -E_INNER_ERROR;
103     }
104     errCode = executor_->StartTransaction();
105     if (errCode != E_OK) {
106         return errCode;
107     }
108 
109     errCode = executor_->DropCollection(lowerCaseName, ignoreNonExists);
110     if (errCode != E_OK) {
111         GLOGE("Drop collection failed. %d", errCode);
112         goto END;
113     }
114 
115     errCode = executor_->CleanCollectionOption(lowerCaseName);
116     if (errCode != E_OK && errCode != -E_NO_DATA) {
117         GLOGE("Clean collection option failed. %d", errCode);
118     } else {
119         errCode = E_OK;
120     }
121 
122 END:
123     if (errCode == E_OK) {
124         executor_->Commit();
125     } else {
126         executor_->Rollback();
127     }
128     return errCode;
129 }
130 
TranFilter(JsonObject & filterObj,std::vector<std::vector<std::string>> & filterAllPath,bool & isIdExist)131 int TranFilter(JsonObject &filterObj, std::vector<std::vector<std::string>> &filterAllPath, bool &isIdExist)
132 {
133     int errCode = E_OK;
134     filterAllPath = JsonCommon::ParsePath(filterObj, errCode);
135     if (errCode != E_OK) {
136         GLOGE("filter ParsePath failed");
137         return errCode;
138     }
139     return CheckCommon::CheckFilter(filterObj, filterAllPath, isIdExist);
140 }
141 
UpdateArgsCheck(const std::string & collection,const std::string & filter,const std::string & update,uint32_t flags)142 int UpdateArgsCheck(const std::string &collection, const std::string &filter, const std::string &update, uint32_t flags)
143 {
144     std::string lowerCaseCollName;
145     int errCode = E_OK;
146     if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) {
147         GLOGE("Check collection name invalid. %d", errCode);
148         return errCode;
149     }
150     if (update.length() >= JSON_LENS_MAX || filter.length() >= JSON_LENS_MAX) {
151         GLOGE("args document's length is too long");
152         return -E_OVER_LIMIT;
153     }
154     JsonObject updateObj = JsonObject::Parse(update, errCode, true);
155     if (errCode != E_OK) {
156         GLOGE("update Parsed failed");
157         return errCode;
158     }
159     if (update != "{}") {
160         errCode = CheckCommon::CheckUpdata(updateObj);
161         if (errCode != E_OK) {
162             GLOGE("Updata format is illegal");
163             return errCode;
164         }
165     }
166     if (flags != GRD_DOC_APPEND && flags != GRD_DOC_REPLACE) {
167         GLOGE("Check flags invalid.");
168         return -E_INVALID_ARGS;
169     }
170     return errCode;
171 }
172 
GetUpDataRePlaceData(ResultSet & resultSet,const std::string & id,const std::string & update,std::string & valStr,bool isReplace)173 int GetUpDataRePlaceData(ResultSet &resultSet, const std::string &id, const std::string &update, std::string &valStr,
174     bool isReplace)
175 {
176     std::string valueGotStr;
177     int errCode = resultSet.GetValue(valueGotStr);
178     if (errCode == -E_NO_DATA) {
179         GLOGW("Get original document not found.");
180         return -E_NOT_FOUND;
181     } else if (errCode != E_OK) {
182         GLOGE("Get original document failed. %d", errCode);
183         return errCode;
184     }
185     JsonObject updateValue = JsonObject::Parse(update, errCode, true);
186     if (errCode != E_OK) {
187         GLOGD("Parse upsert value failed. %d", errCode);
188         return errCode;
189     }
190     JsonObject originValue = JsonObject::Parse(valueGotStr, errCode, true);
191     if (errCode != E_OK) {
192         GLOGD("Parse original value failed. %d %s", errCode, valueGotStr.c_str());
193         return errCode;
194     }
195     errCode = JsonCommon::Append(originValue, updateValue, isReplace);
196     if (errCode != E_OK) {
197         GLOGD("Append value failed. %d", errCode);
198         return errCode;
199     }
200     valStr = originValue.Print();
201     if (valStr.length() >= JSON_LENS_MAX) {
202         GLOGE("document's length is too long");
203         return -E_OVER_LIMIT;
204     }
205     return errCode;
206 }
207 
UpdateDataIntoDB(std::shared_ptr<QueryContext> & context,JsonObject & filterObj,const std::string & update,bool & isReplace)208 int DocumentStore::UpdateDataIntoDB(std::shared_ptr<QueryContext> &context, JsonObject &filterObj,
209     const std::string &update, bool &isReplace)
210 {
211     std::lock_guard<std::mutex> lock(dbMutex_);
212     if (executor_ == nullptr) {
213         return -E_INNER_ERROR;
214     }
215     int errCode = executor_->StartTransaction();
216     if (errCode != E_OK) {
217         return errCode;
218     }
219     std::string docId;
220     int count = 0;
221     std::string valStr;
222     auto coll = Collection(context->collectionName, executor_);
223     ResultSet resultSet;
224     errCode = InitResultSet(context, this, resultSet, false);
225     if (errCode != E_OK) {
226         goto END;
227     }
228     // no start transaction inner
229     errCode = resultSet.GetNext(false, true);
230     if (errCode == -E_NO_DATA) {
231         // no need to set count
232         errCode = E_OK;
233         goto END;
234     } else if (errCode != E_OK) {
235         goto END;
236     }
237     resultSet.GetKey(docId);
238     errCode = GetUpDataRePlaceData(resultSet, docId, update, valStr, isReplace);
239     if (errCode != E_OK) {
240         goto END;
241     }
242     errCode = coll.UpdateDocument(docId, valStr);
243     if (errCode == E_OK) {
244         count++;
245     } else if (errCode == -E_NOT_FOUND) {
246         errCode = E_OK;
247     }
248 END:
249     if (errCode == E_OK) {
250         executor_->Commit();
251     } else {
252         executor_->Rollback();
253     }
254     return (errCode == E_OK) ? count : errCode;
255 }
256 
UpdateDocument(const std::string & collection,const std::string & filter,const std::string & update,uint32_t flags)257 int DocumentStore::UpdateDocument(const std::string &collection, const std::string &filter, const std::string &update,
258     uint32_t flags)
259 {
260     int errCode = UpdateArgsCheck(collection, filter, update, flags);
261     if (errCode != E_OK) {
262         return errCode;
263     }
264     JsonObject filterObj = JsonObject::Parse(filter, errCode, true, true);
265     if (errCode != E_OK) {
266         GLOGE("filter Parsed failed");
267         return errCode;
268     }
269     bool isIdExist = false;
270     std::vector<std::vector<std::string>> filterAllPath;
271     errCode = TranFilter(filterObj, filterAllPath, isIdExist);
272     if (errCode != E_OK) {
273         return errCode;
274     }
275     bool isReplace = ((flags & GRD_DOC_REPLACE) == GRD_DOC_REPLACE);
276     std::shared_ptr<QueryContext> context = std::make_shared<QueryContext>();
277     context->isIdExist = isIdExist;
278     context->collectionName = collection;
279     context->filter = filter;
280     context->ifShowId = true;
281     return UpdateDataIntoDB(context, filterObj, update, isReplace);
282 }
283 
UpsertArgsCheck(const std::string & collection,const std::string & filter,const std::string & document,uint32_t flags)284 int UpsertArgsCheck(const std::string &collection, const std::string &filter, const std::string &document,
285     uint32_t flags)
286 {
287     std::string lowerCaseCollName;
288     int errCode = E_OK;
289     if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) {
290         GLOGE("Check collection name invalid. %d", errCode);
291         return errCode;
292     }
293     if (document.length() >= JSON_LENS_MAX || filter.length() >= JSON_LENS_MAX) {
294         GLOGE("args length is too long");
295         return -E_OVER_LIMIT;
296     }
297     if (flags != GRD_DOC_APPEND && flags != GRD_DOC_REPLACE) {
298         GLOGE("Check flags invalid.");
299         return -E_INVALID_ARGS;
300     }
301     return errCode;
302 }
303 
CheckUpsertConflict(ResultSet & resultSet,JsonObject & filterObj,std::string & docId,Collection & coll,bool & isDataExist)304 int CheckUpsertConflict(ResultSet &resultSet, JsonObject &filterObj, std::string &docId, Collection &coll,
305     bool &isDataExist)
306 {
307     std::string val; // use to know whether there is data in the resultSet or not.
308     int errCode = resultSet.GetValue(val);
309     if (errCode == E_OK) {
310         isDataExist = true;
311     }
312     Value ValueDocument;
313     Key id(docId.begin(), docId.end());
314     errCode = coll.GetDocumentById(id, ValueDocument);
315     if (errCode == E_OK && !(isDataExist)) {
316         GLOGE("id exist but filter does not match, data conflict");
317         errCode = -E_DATA_CONFLICT;
318     }
319     return errCode;
320 }
321 
GetUpsertRePlaceData(ResultSet & resultSet,JsonObject & documentObj,bool isReplace,std::string & valStr)322 int GetUpsertRePlaceData(ResultSet &resultSet, JsonObject &documentObj, bool isReplace, std::string &valStr)
323 {
324     int errCode = resultSet.GetValue(valStr);
325     if (errCode != E_OK || isReplace) {
326         valStr = documentObj.Print(); // If cant not find data, insert it.
327         if (valStr.length() >= JSON_LENS_MAX) {
328             GLOGE("document's length is too long");
329             return -E_OVER_LIMIT;
330         }
331         return E_OK;
332     }
333     if (errCode != E_OK && errCode != -E_NOT_FOUND) {
334         GLOGW("Get original document failed. %d", errCode);
335         return errCode;
336     } else if (errCode == E_OK) { // document has been inserted
337         JsonObject originValue = JsonObject::Parse(valStr, errCode, true);
338         if (errCode != E_OK) {
339             GLOGD("Parse original value failed. %d %s", errCode, valStr.c_str());
340             return errCode;
341         }
342         errCode = JsonCommon::Append(originValue, documentObj, isReplace);
343         if (errCode != E_OK) {
344             GLOGD("Append value failed. %d", errCode);
345             return errCode;
346         }
347         valStr = originValue.Print();
348         if (valStr.length() >= JSON_LENS_MAX) {
349             GLOGE("document's length is too long");
350             return -E_OVER_LIMIT;
351         }
352     }
353     return errCode;
354 }
355 
InsertIdToDocument(ResultSet & resultSet,JsonObject & filterObj,JsonObject & documentObj,std::string & docId)356 int InsertIdToDocument(ResultSet &resultSet, JsonObject &filterObj, JsonObject &documentObj, std::string &docId)
357 {
358     auto filterObjChild = filterObj.GetChild();
359     bool isIdExist;
360     ValueObject idValue = JsonCommon::GetValueInSameLevel(filterObjChild, KEY_ID, isIdExist);
361     int errCode = E_OK;
362     int ret = resultSet.GetNext(false, true); // All anomalies will be judged later
363     if (ret != E_OK && ret != -E_NO_DATA) {
364         return ret;
365     }
366     if (isIdExist) {
367         docId = idValue.GetStringValue();
368         JsonObject idObj = filterObj.GetObjectItem(KEY_ID, errCode); // this errCode will always be E_OK.
369         documentObj.InsertItemObject(0, idObj);
370     } else {
371         if (ret == E_OK) { // E_OK means find data.
372             (void)resultSet.GetKey(docId); // This errCode will always be E_OK.
373         } else {
374             DocKey docKey;
375             DocumentKey::GetOidDocKey(docKey);
376             docId = docKey.key;
377         }
378     }
379     return errCode;
380 }
381 
UpsertDataIntoDB(std::shared_ptr<QueryContext> & context,JsonObject & filterObj,const std::string & document,JsonObject & documentObj,bool & isReplace)382 int DocumentStore::UpsertDataIntoDB(std::shared_ptr<QueryContext> &context, JsonObject &filterObj,
383     const std::string &document, JsonObject &documentObj, bool &isReplace)
384 {
385     std::lock_guard<std::mutex> lock(dbMutex_);
386     if (executor_ == nullptr) {
387         return -E_INNER_ERROR;
388     }
389     int errCode = executor_->StartTransaction();
390     if (errCode != E_OK) {
391         return errCode;
392     }
393     Collection coll = Collection(context->collectionName, executor_);
394     int count = 0;
395     std::string docId;
396     ResultSet resultSet;
397     std::string newDocument;
398     bool isDataExist = false;
399     errCode = InitResultSet(context, this, resultSet, false);
400     if (errCode != E_OK) {
401         goto END;
402     }
403     errCode = InsertIdToDocument(resultSet, filterObj, documentObj, docId);
404     if (errCode != E_OK) {
405         goto END;
406     }
407     errCode = CheckUpsertConflict(resultSet, filterObj, docId, coll, isDataExist);
408     // There are only three return values, the two other situation can continue to move forward.
409     if (errCode == -E_DATA_CONFLICT) {
410         GLOGE("upsert data conflict");
411         goto END;
412     }
413     errCode = GetUpsertRePlaceData(resultSet, documentObj, isReplace, newDocument);
414     if (errCode != E_OK) {
415         goto END;
416     }
417     errCode = coll.UpsertDocument(docId, newDocument, isDataExist);
418     if (errCode == E_OK) {
419         count++;
420     } else if (errCode == -E_NOT_FOUND) {
421         errCode = E_OK;
422     }
423 END:
424     if (errCode == E_OK) {
425         executor_->Commit();
426     } else {
427         executor_->Rollback();
428     }
429     return (errCode == E_OK) ? count : errCode;
430 }
431 
UpsertDocumentFormatCheck(const std::string & document,JsonObject & documentObj)432 int UpsertDocumentFormatCheck(const std::string &document, JsonObject &documentObj)
433 {
434     int errCode = E_OK;
435     if (document != "{}") {
436         errCode = CheckCommon::CheckUpdata(documentObj);
437         if (errCode != E_OK) {
438             GLOGE("UpsertDocument document format is illegal");
439             return errCode;
440         }
441     }
442     return errCode;
443 }
444 
UpsertDocument(const std::string & collection,const std::string & filter,const std::string & document,uint32_t flags)445 int DocumentStore::UpsertDocument(const std::string &collection, const std::string &filter,
446     const std::string &document, uint32_t flags)
447 {
448     int errCode = UpsertArgsCheck(collection, filter, document, flags);
449     if (errCode != E_OK) {
450         return errCode;
451     }
452     JsonObject filterObj = JsonObject::Parse(filter, errCode, true, true);
453     if (errCode != E_OK) {
454         GLOGE("filter Parsed failed");
455         return errCode;
456     }
457     JsonObject documentObj = JsonObject::Parse(document, errCode, true);
458     if (errCode != E_OK) {
459         GLOGE("document Parsed failed");
460         return errCode;
461     }
462     errCode = UpsertDocumentFormatCheck(document, documentObj);
463     if (errCode != E_OK) {
464         GLOGE("document format is illegal");
465         return errCode;
466     }
467     bool isIdExist = false;
468     std::vector<std::vector<std::string>> filterAllPath;
469     errCode = TranFilter(filterObj, filterAllPath, isIdExist);
470     if (errCode != E_OK) {
471         GLOGE("filter is invalid");
472         return errCode;
473     }
474     std::shared_ptr<QueryContext> context = std::make_shared<QueryContext>();
475     context->filter = filter;
476     context->collectionName = collection;
477     context->ifShowId = true;
478     context->isIdExist = isIdExist;
479     bool isReplace = ((flags & GRD_DOC_REPLACE) == GRD_DOC_REPLACE);
480     return UpsertDataIntoDB(context, filterObj, document, documentObj, isReplace);
481 }
482 
InsertArgsCheck(const std::string & collection,const std::string & document,uint32_t flags)483 int InsertArgsCheck(const std::string &collection, const std::string &document, uint32_t flags)
484 {
485     if (flags != 0u) {
486         GLOGE("InsertDocument flags is not zero");
487         return -E_INVALID_ARGS;
488     }
489     std::string lowerCaseCollName;
490     int errCode = E_OK;
491     if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) {
492         GLOGE("Check collection name invalid. %d", errCode);
493         return errCode;
494     }
495     if (document.length() >= JSON_LENS_MAX) {
496         GLOGE("document's length is too long");
497         return -E_OVER_LIMIT;
498     }
499     return errCode;
500 }
501 
InsertDataIntoDB(const std::string & collection,const std::string & document,JsonObject & documentObj,bool & isIdExist)502 int DocumentStore::InsertDataIntoDB(const std::string &collection, const std::string &document,
503     JsonObject &documentObj, bool &isIdExist)
504 {
505     std::lock_guard<std::mutex> lock(dbMutex_);
506     std::string id;
507     if (isIdExist) {
508         JsonObject documentObjChild = documentObj.GetChild();
509         ValueObject idValue = JsonCommon::GetValueInSameLevel(documentObjChild, KEY_ID);
510         id = idValue.GetStringValue();
511     } else {
512         DocKey docKey;
513         DocumentKey::GetOidDocKey(docKey);
514         id = docKey.key;
515     }
516     Collection coll = Collection(collection, executor_);
517     return coll.InsertDocument(id, document, isIdExist);
518 }
519 
InsertDocument(const std::string & collection,const std::string & document,uint32_t flags)520 int DocumentStore::InsertDocument(const std::string &collection, const std::string &document, uint32_t flags)
521 {
522     int errCode = InsertArgsCheck(collection, document, flags);
523     if (errCode != E_OK) {
524         return errCode;
525     }
526     JsonObject documentObj = JsonObject::Parse(document, errCode, true);
527     if (errCode != E_OK) {
528         GLOGE("Document Parsed failed");
529         return errCode;
530     }
531     bool isIdExist = true;
532     errCode = CheckCommon::CheckDocument(documentObj, isIdExist);
533     if (errCode != E_OK) {
534         return errCode;
535     }
536     return InsertDataIntoDB(collection, document, documentObj, isIdExist);
537 }
538 
DeleteArgsCheck(const std::string & collection,const std::string & filter,uint32_t flags)539 int DeleteArgsCheck(const std::string &collection, const std::string &filter, uint32_t flags)
540 {
541     if (flags != 0u) {
542         GLOGE("DeleteDocument flags is not zero");
543         return -E_INVALID_ARGS;
544     }
545     std::string lowerCaseCollName;
546     int errCode = E_OK;
547     if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) {
548         GLOGE("Check collection name invalid. %d", errCode);
549         return errCode;
550     }
551     if (filter.empty()) {
552         GLOGE("Filter is empty");
553         return -E_INVALID_ARGS;
554     }
555     if (filter.length() >= JSON_LENS_MAX) {
556         GLOGE("filter's length is too long");
557         return -E_OVER_LIMIT;
558     }
559     return errCode;
560 }
561 
DeleteDataFromDB(std::shared_ptr<QueryContext> & context,JsonObject & filterObj)562 int DocumentStore::DeleteDataFromDB(std::shared_ptr<QueryContext> &context, JsonObject &filterObj)
563 {
564     std::lock_guard<std::mutex> lock(dbMutex_);
565     if (executor_ == nullptr) {
566         return -E_INNER_ERROR;
567     }
568     Collection coll = Collection(context->collectionName, executor_);
569     int errCode = executor_->StartTransaction();
570     if (errCode != E_OK) {
571         return errCode;
572     }
573     std::string id;
574     ResultSet resultSet;
575     errCode = InitResultSet(context, this, resultSet, false);
576     if (errCode != E_OK) {
577         goto END;
578     }
579     errCode = resultSet.GetNext(false, true);
580     if (errCode != E_OK) {
581         goto END;
582     }
583     resultSet.GetKey(id);
584 END:
585     if (errCode == E_OK) {
586         Key key(id.begin(), id.end());
587         errCode = coll.DeleteDocument(key);
588     }
589     if (errCode == E_OK || errCode == E_NOT_FOUND) {
590         executor_->Commit();
591     } else {
592         executor_->Rollback();
593     }
594     return errCode;
595 }
DeleteDocument(const std::string & collection,const std::string & filter,uint32_t flags)596 int DocumentStore::DeleteDocument(const std::string &collection, const std::string &filter, uint32_t flags)
597 {
598     int errCode = DeleteArgsCheck(collection, filter, flags);
599     if (errCode != E_OK) {
600         return errCode;
601     }
602     JsonObject filterObj = JsonObject::Parse(filter, errCode, true, true);
603     if (errCode != E_OK) {
604         return errCode;
605     }
606     bool isIdExist = false;
607     std::vector<std::vector<std::string>> filterAllPath;
608     errCode = TranFilter(filterObj, filterAllPath, isIdExist);
609     if (errCode != E_OK) {
610         return errCode;
611     }
612     std::shared_ptr<QueryContext> context = std::make_shared<QueryContext>();
613     context->isIdExist = isIdExist;
614     context->filter = filter;
615     context->collectionName = collection;
616     return DeleteDataFromDB(context, filterObj);
617 }
GetCollection(std::string & collectionName)618 Collection DocumentStore::GetCollection(std::string &collectionName)
619 {
620     return Collection(collectionName, executor_);
621 }
622 
JudgeBoolViewType(const size_t index,ValueObject & leafItem,bool & viewType)623 int JudgeBoolViewType(const size_t index, ValueObject &leafItem, bool &viewType)
624 {
625     if (leafItem.GetBoolValue()) {
626         if (index != 0 && !viewType) {
627             return -E_INVALID_ARGS;
628         }
629         viewType = true;
630     } else {
631         if (index != 0 && viewType) {
632             return E_INVALID_ARGS;
633         }
634         viewType = false;
635     }
636     return E_OK;
637 }
638 
JudgeStringViewType(const size_t index,ValueObject & leafItem,bool & viewType)639 int JudgeStringViewType(const size_t index, ValueObject &leafItem, bool &viewType)
640 {
641     if (leafItem.GetStringValue() == "") {
642         if (index != 0 && !viewType) {
643             return -E_INVALID_ARGS;
644         }
645         viewType = true;
646     } else {
647         return -E_INVALID_ARGS;
648     }
649     return E_OK;
650 }
651 
JudgeIntViewType(const size_t index,ValueObject & leafItem,bool & viewType)652 int JudgeIntViewType(const size_t index, ValueObject &leafItem, bool &viewType)
653 {
654     if (leafItem.GetIntValue() == 0) {
655         if (index != 0 && viewType) {
656             return -E_INVALID_ARGS;
657         }
658         viewType = false;
659     } else {
660         if (index != 0 && !viewType) {
661             return E_INVALID_ARGS;
662         }
663         viewType = true;
664     }
665     return E_OK;
666 }
667 
JudgeViewType(const size_t index,ValueObject & leafItem,bool & viewType)668 int JudgeViewType(const size_t index, ValueObject &leafItem, bool &viewType)
669 {
670     int errCode = E_OK;
671     switch (leafItem.GetValueType()) {
672         case ValueObject::ValueType::VALUE_BOOL:
673             errCode = JudgeBoolViewType(index, leafItem, viewType);
674             if (errCode != E_OK) {
675                 return errCode;
676             }
677             break;
678         case ValueObject::ValueType::VALUE_STRING:
679             errCode = JudgeStringViewType(index, leafItem, viewType);
680             if (errCode != E_OK) {
681                 return errCode;
682             }
683             break;
684         case ValueObject::ValueType::VALUE_NUMBER:
685             errCode = JudgeIntViewType(index, leafItem, viewType);
686             if (errCode != E_OK) {
687                 return errCode;
688             }
689             break;
690         default:
691             return E_INVALID_ARGS;
692     }
693     return E_OK;
694 }
695 
GetViewType(JsonObject & jsonObj,bool & viewType)696 int GetViewType(JsonObject &jsonObj, bool &viewType)
697 {
698     std::vector<ValueObject> leafValue = JsonCommon::GetLeafValue(jsonObj);
699     if (leafValue.size() == 0) {
700         return E_INVALID_ARGS;
701     }
702     int ret = E_OK;
703     for (size_t i = 0; i < leafValue.size(); i++) {
704         ret = JudgeViewType(i, leafValue[i], viewType);
705         if (ret != E_OK) {
706             return ret;
707         }
708     }
709     return ret;
710 }
711 
FindArgsCheck(const std::string & collection,const std::string & filter,const std::string & projection,uint32_t flags)712 int FindArgsCheck(const std::string &collection, const std::string &filter, const std::string &projection,
713     uint32_t flags)
714 {
715     if (flags != 0u && flags != GRD_DOC_ID_DISPLAY) {
716         GLOGE("FindDocument flags is illegal");
717         return -E_INVALID_ARGS;
718     }
719     std::string lowerCaseCollName;
720     int errCode = E_OK;
721     if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) {
722         GLOGE("Check collection name invalid. %d", errCode);
723         return errCode;
724     }
725     if (filter.length() >= JSON_LENS_MAX || projection.length() >= JSON_LENS_MAX) {
726         GLOGE("args length is too long");
727         return -E_OVER_LIMIT;
728     }
729     if (projection.length() >= JSON_LENS_MAX) {
730         GLOGE("projection's length is too long");
731         return -E_OVER_LIMIT;
732     }
733     return errCode;
734 }
735 
FindProjectionInit(const std::string & projection,const std::shared_ptr<QueryContext> & context)736 int FindProjectionInit(const std::string &projection, const std::shared_ptr<QueryContext> &context)
737 {
738     int errCode = E_OK;
739     std::vector<std::vector<std::string>> allPath;
740     JsonObject projectionObj = JsonObject::Parse(projection, errCode, true);
741     if (errCode != E_OK) {
742         GLOGE("projection Parsed failed");
743         return errCode;
744     }
745     bool viewType = false;
746     if (projection != "{}") {
747         allPath = JsonCommon::ParsePath(projectionObj, errCode);
748         if (errCode != E_OK) {
749             return errCode;
750         }
751         if (GetViewType(projectionObj, viewType) != E_OK) {
752             GLOGE("GetViewType failed");
753             return -E_INVALID_ARGS;
754         }
755         errCode = CheckCommon::CheckProjection(projectionObj, allPath);
756         if (errCode != E_OK) {
757             GLOGE("projection format unvalid");
758             return errCode;
759         }
760     }
761     context->projectionPath = std::move(allPath);
762     context->viewType = viewType;
763     return errCode;
764 }
765 
InitFindResultSet(GRD_ResultSet * grdResultSet,std::shared_ptr<QueryContext> & context)766 int DocumentStore::InitFindResultSet(GRD_ResultSet *grdResultSet, std::shared_ptr<QueryContext> &context)
767 {
768     std::lock_guard<std::mutex> lock(dbMutex_);
769     int errCode = E_OK;
770     Collection coll = Collection(context->collectionName, executor_);
771     if (IsExistResultSet(context->collectionName)) {
772         return -E_RESOURCE_BUSY;
773     }
774     if (executor_ == nullptr) {
775         return -E_INNER_ERROR;
776     }
777     errCode = executor_->StartTransaction();
778     if (errCode != E_OK) {
779         return errCode;
780     }
781     bool isCollectionExist = coll.IsCollectionExists(errCode);
782     if (!isCollectionExist) {
783         errCode = -E_INVALID_ARGS;
784     }
785     if (errCode != E_OK) {
786         goto END;
787     }
788     errCode = InitResultSet(context, this, grdResultSet->resultSet_, true);
789     if (errCode == E_OK) {
790         collections_[context->collectionName] = nullptr;
791     }
792 END:
793     if (errCode == E_OK) {
794         executor_->Commit();
795     } else {
796         executor_->Rollback();
797     }
798     return errCode;
799 }
800 
FindDocument(const std::string & collection,const std::string & filter,const std::string & projection,uint32_t flags,GRD_ResultSet * grdResultSet)801 int DocumentStore::FindDocument(const std::string &collection, const std::string &filter,
802     const std::string &projection, uint32_t flags, GRD_ResultSet *grdResultSet)
803 {
804     int errCode = FindArgsCheck(collection, filter, projection, flags);
805     if (errCode != E_OK) {
806         GLOGE("delete arg is illegal");
807         return errCode;
808     }
809     JsonObject filterObj = JsonObject::Parse(filter, errCode, true, true);
810     if (errCode != E_OK) {
811         GLOGE("filter Parsed failed");
812         return errCode;
813     }
814     std::shared_ptr<QueryContext> context = std::make_shared<QueryContext>();
815     errCode = FindProjectionInit(projection, context);
816     if (errCode != E_OK) {
817         return errCode;
818     }
819     bool isIdExist = false;
820     std::vector<std::vector<std::string>> filterAllPath;
821     errCode = TranFilter(filterObj, filterAllPath, isIdExist);
822     if (errCode != E_OK) {
823         GLOGE("filter is invalid");
824         return errCode;
825     }
826     if (flags == GRD_DOC_ID_DISPLAY) {
827         context->ifShowId = true;
828     } else {
829         context->ifShowId = false;
830     }
831     context->collectionName = collection;
832     context->filter = filter;
833     context->isIdExist = isIdExist;
834     return InitFindResultSet(grdResultSet, context);
835 }
836 
IsExistResultSet(const std::string & collection)837 bool DocumentStore::IsExistResultSet(const std::string &collection)
838 {
839     if (collections_.find(collection) != collections_.end()) {
840         GLOGE("DB is resource busy");
841         return true;
842     }
843     return false;
844 }
845 
EraseCollection(const std::string & collectionName)846 int DocumentStore::EraseCollection(const std::string &collectionName)
847 {
848     std::lock_guard<std::mutex> lock(dbMutex_);
849     if (collections_.find(collectionName) != collections_.end()) {
850         collections_.erase(collectionName);
851         return E_OK;
852     }
853     GLOGE("erase collection failed");
854     return E_INVALID_ARGS;
855 }
856 
OnClose(const std::function<void (void)> & notifier)857 void DocumentStore::OnClose(const std::function<void(void)> &notifier)
858 {
859     closeNotifier_ = notifier;
860 }
861 
Close(uint32_t flags)862 int DocumentStore::Close(uint32_t flags)
863 {
864     std::lock_guard<std::mutex> lock(dbMutex_);
865     if (flags == GRD_DB_CLOSE && !collections_.empty()) {
866         GLOGE("Close store failed with result set not closed.");
867         return -E_RESOURCE_BUSY;
868     }
869 
870     if (closeNotifier_) {
871         closeNotifier_();
872     }
873     return E_OK;
874 }
875 
StartTransaction()876 int DocumentStore::StartTransaction()
877 {
878     if (executor_ == nullptr) {
879         return -E_INNER_ERROR;
880     }
881     return executor_->StartTransaction();
882 }
Commit()883 int DocumentStore::Commit()
884 {
885     if (executor_ == nullptr) {
886         return -E_INNER_ERROR;
887     }
888     return executor_->Commit();
889 }
Rollback()890 int DocumentStore::Rollback()
891 {
892     if (executor_ == nullptr) {
893         return -E_INNER_ERROR;
894     }
895     return executor_->Rollback();
896 }
897 
IsCollectionExists(const std::string & collectionName,int & errCode)898 bool DocumentStore::IsCollectionExists(const std::string &collectionName, int &errCode)
899 {
900     if (executor_ == nullptr) {
901         errCode = -E_INNER_ERROR;
902         return false;
903     }
904     return executor_->IsCollectionExists(collectionName, errCode);
905 }
906 } // namespace DocumentDB