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 "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
JudgeViewType(const size_t & index,ValueObject & leafItem,bool & viewType)623 int JudgeViewType(const size_t &index, ValueObject &leafItem, bool &viewType)
624 {
625 switch (leafItem.GetValueType()) {
626 case ValueObject::ValueType::VALUE_BOOL:
627 if (leafItem.GetBoolValue()) {
628 if (index != 0 && !viewType) {
629 return -E_INVALID_ARGS;
630 }
631 viewType = true;
632 } else {
633 if (index != 0 && viewType) {
634 return E_INVALID_ARGS;
635 }
636 viewType = false;
637 }
638 break;
639 case ValueObject::ValueType::VALUE_STRING:
640 if (leafItem.GetStringValue() == "") {
641 if (index != 0 && !viewType) {
642 return -E_INVALID_ARGS;
643 }
644 viewType = true;
645 } else {
646 return -E_INVALID_ARGS;
647 }
648 break;
649 case ValueObject::ValueType::VALUE_NUMBER:
650 if (leafItem.GetIntValue() == 0) {
651 if (index != 0 && viewType) {
652 return -E_INVALID_ARGS;
653 }
654 viewType = false;
655 } else {
656 if (index != 0 && !viewType) {
657 return E_INVALID_ARGS;
658 }
659 viewType = true;
660 }
661 break;
662 default:
663 return E_INVALID_ARGS;
664 }
665 return E_OK;
666 }
667
GetViewType(JsonObject & jsonObj,bool & viewType)668 int GetViewType(JsonObject &jsonObj, bool &viewType)
669 {
670 std::vector<ValueObject> leafValue = JsonCommon::GetLeafValue(jsonObj);
671 if (leafValue.size() == 0) {
672 return E_INVALID_ARGS;
673 }
674 int ret = E_OK;
675 for (size_t i = 0; i < leafValue.size(); i++) {
676 ret = JudgeViewType(i, leafValue[i], viewType);
677 if (ret != E_OK) {
678 return ret;
679 }
680 }
681 return ret;
682 }
683
FindArgsCheck(const std::string & collection,const std::string & filter,const std::string & projection,uint32_t flags)684 int FindArgsCheck(const std::string &collection, const std::string &filter, const std::string &projection,
685 uint32_t flags)
686 {
687 if (flags != 0u && flags != GRD_DOC_ID_DISPLAY) {
688 GLOGE("FindDocument flags is illegal");
689 return -E_INVALID_ARGS;
690 }
691 std::string lowerCaseCollName;
692 int errCode = E_OK;
693 if (!CheckCommon::CheckCollectionName(collection, lowerCaseCollName, errCode)) {
694 GLOGE("Check collection name invalid. %d", errCode);
695 return errCode;
696 }
697 if (filter.length() >= JSON_LENS_MAX || projection.length() >= JSON_LENS_MAX) {
698 GLOGE("args length is too long");
699 return -E_OVER_LIMIT;
700 }
701 if (projection.length() >= JSON_LENS_MAX) {
702 GLOGE("projection's length is too long");
703 return -E_OVER_LIMIT;
704 }
705 return errCode;
706 }
707
FindProjectionInit(const std::string & projection,const std::shared_ptr<QueryContext> & context)708 int FindProjectionInit(const std::string &projection, const std::shared_ptr<QueryContext> &context)
709 {
710 int errCode = E_OK;
711 std::vector<std::vector<std::string>> allPath;
712 JsonObject projectionObj = JsonObject::Parse(projection, errCode, true);
713 if (errCode != E_OK) {
714 GLOGE("projection Parsed failed");
715 return errCode;
716 }
717 bool viewType = false;
718 if (projection != "{}") {
719 allPath = JsonCommon::ParsePath(projectionObj, errCode);
720 if (errCode != E_OK) {
721 return errCode;
722 }
723 if (GetViewType(projectionObj, viewType) != E_OK) {
724 GLOGE("GetViewType failed");
725 return -E_INVALID_ARGS;
726 }
727 errCode = CheckCommon::CheckProjection(projectionObj, allPath);
728 if (errCode != E_OK) {
729 GLOGE("projection format unvalid");
730 return errCode;
731 }
732 }
733 context->projectionPath = std::move(allPath);
734 context->viewType = viewType;
735 return errCode;
736 }
737
InitFindResultSet(GRD_ResultSet * grdResultSet,std::shared_ptr<QueryContext> & context)738 int DocumentStore::InitFindResultSet(GRD_ResultSet *grdResultSet, std::shared_ptr<QueryContext> &context)
739 {
740 std::lock_guard<std::mutex> lock(dbMutex_);
741 int errCode = E_OK;
742 Collection coll = Collection(context->collectionName, executor_);
743 if (IsExistResultSet(context->collectionName)) {
744 return -E_RESOURCE_BUSY;
745 }
746 if (executor_ == nullptr) {
747 return -E_INNER_ERROR;
748 }
749 errCode = executor_->StartTransaction();
750 if (errCode != E_OK) {
751 return errCode;
752 }
753 bool isCollectionExist = coll.IsCollectionExists(errCode);
754 if (!isCollectionExist) {
755 errCode = -E_INVALID_ARGS;
756 }
757 if (errCode != E_OK) {
758 goto END;
759 }
760 errCode = InitResultSet(context, this, grdResultSet->resultSet_, true);
761 if (errCode == E_OK) {
762 collections_[context->collectionName] = nullptr;
763 }
764 END:
765 if (errCode == E_OK) {
766 executor_->Commit();
767 } else {
768 executor_->Rollback();
769 }
770 return errCode;
771 }
772
FindDocument(const std::string & collection,const std::string & filter,const std::string & projection,uint32_t flags,GRD_ResultSet * grdResultSet)773 int DocumentStore::FindDocument(const std::string &collection, const std::string &filter,
774 const std::string &projection, uint32_t flags, GRD_ResultSet *grdResultSet)
775 {
776 int errCode = FindArgsCheck(collection, filter, projection, flags);
777 if (errCode != E_OK) {
778 GLOGE("delete arg is illegal");
779 return errCode;
780 }
781 JsonObject filterObj = JsonObject::Parse(filter, errCode, true, true);
782 if (errCode != E_OK) {
783 GLOGE("filter Parsed failed");
784 return errCode;
785 }
786 std::shared_ptr<QueryContext> context = std::make_shared<QueryContext>();
787 errCode = FindProjectionInit(projection, context);
788 if (errCode != E_OK) {
789 return errCode;
790 }
791 bool isIdExist = false;
792 std::vector<std::vector<std::string>> filterAllPath;
793 errCode = TranFilter(filterObj, filterAllPath, isIdExist);
794 if (errCode != E_OK) {
795 GLOGE("filter is invalid");
796 return errCode;
797 }
798 if (flags == GRD_DOC_ID_DISPLAY) {
799 context->ifShowId = true;
800 } else {
801 context->ifShowId = false;
802 }
803 context->collectionName = collection;
804 context->filter = filter;
805 context->isIdExist = isIdExist;
806 return InitFindResultSet(grdResultSet, context);
807 }
808
IsExistResultSet(const std::string & collection)809 bool DocumentStore::IsExistResultSet(const std::string &collection)
810 {
811 if (collections_.find(collection) != collections_.end()) {
812 GLOGE("DB is resource busy");
813 return true;
814 }
815 return false;
816 }
817
EraseCollection(const std::string & collectionName)818 int DocumentStore::EraseCollection(const std::string &collectionName)
819 {
820 std::lock_guard<std::mutex> lock(dbMutex_);
821 if (collections_.find(collectionName) != collections_.end()) {
822 collections_.erase(collectionName);
823 return E_OK;
824 }
825 GLOGE("erase collection failed");
826 return E_INVALID_ARGS;
827 }
828
OnClose(const std::function<void (void)> & notifier)829 void DocumentStore::OnClose(const std::function<void(void)> ¬ifier)
830 {
831 closeNotifier_ = notifier;
832 }
833
Close(uint32_t flags)834 int DocumentStore::Close(uint32_t flags)
835 {
836 std::lock_guard<std::mutex> lock(dbMutex_);
837 if (flags == GRD_DB_CLOSE && !collections_.empty()) {
838 GLOGE("Close store failed with result set not closed.");
839 return -E_RESOURCE_BUSY;
840 }
841
842 if (closeNotifier_) {
843 closeNotifier_();
844 }
845 return E_OK;
846 }
847
StartTransaction()848 int DocumentStore::StartTransaction()
849 {
850 if (executor_ == nullptr) {
851 return -E_INNER_ERROR;
852 }
853 return executor_->StartTransaction();
854 }
Commit()855 int DocumentStore::Commit()
856 {
857 if (executor_ == nullptr) {
858 return -E_INNER_ERROR;
859 }
860 return executor_->Commit();
861 }
Rollback()862 int DocumentStore::Rollback()
863 {
864 if (executor_ == nullptr) {
865 return -E_INNER_ERROR;
866 }
867 return executor_->Rollback();
868 }
869
IsCollectionExists(const std::string & collectionName,int & errCode)870 bool DocumentStore::IsCollectionExists(const std::string &collectionName, int &errCode)
871 {
872 if (executor_ == nullptr) {
873 errCode = -E_INNER_ERROR;
874 return false;
875 }
876 return executor_->IsCollectionExists(collectionName, errCode);
877 }
878 } // namespace DocumentDB