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)> ¬ifier)
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