1 /*
2 * Copyright (c) 2021 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 "schema_utils.h"
17
18 #include <cctype>
19 #include <cfloat>
20 #include <cmath>
21 #include <map>
22
23 #include "db_common.h"
24 #include "db_errno.h"
25 #include "log_print.h"
26 #include "schema_constant.h"
27
28 namespace DistributedDB {
29 namespace {
IsLegalFieldCharacter(char character)30 bool IsLegalFieldCharacter(char character)
31 {
32 return (std::isalnum(character) || character == '_');
33 }
TrimFiled(std::string & inString)34 void TrimFiled(std::string &inString)
35 {
36 inString.erase(0, inString.find_first_not_of("\r\t "));
37 size_t temp = inString.find_last_not_of("\r\t ");
38 if (temp < inString.size()) {
39 inString.erase(temp + 1);
40 }
41 }
42
43 // TYPE, [NOT NULL,] [DEFAULT X]
44 // DEFAULT at last
45 // State transition matrix
46 const int STATE_TRANSFER[8][6] = { // 5 type input and 7 type state
47 // blank, NOT NULL, DEFAULT, OTHER AlNUM, COMMA
48 {0, -1, -1, 1, -1}, // state 0: empty
49 {1, -1, -1, 1, 2}, // state 1: only type
50 {2, 3, 5, -1, -1}, // state 2: alnum ,
51 {3, -1, -1, -1, 4}, // state 3: alnum , notnull
52 {4, -1, 5, -1, -1}, // state 4: alnum , notnull ,
53 {6, -1, -1, -1, -1}, // state 5: finish with DEFAULT
54 {6, -1, -1, 7, -1}, // state 6: finish with DEFAULT and blank
55 {7, 7, 7, 7, 7}, // state 7: finish with DEFAULT and blank and no matter what value
56 };
57 enum StateTransferColNum {
58 COLUMN_ILLEGAL = -1,
59 COLUMN_BLANK,
60 COLUMN_NOT_NULL,
61 COLUMN_DEFAULT,
62 COLUMN_OTHER_ALNUM,
63 COLUMN_COMMA,
64 };
65 } // namespace
66
67 // compare function can make sure not to cross the border, pos < oriContent.size() - 1
68 // Get symbol type and Converts to the corresponding column of the state transition matrix
MakeTrans(const std::string & oriContent,size_t & pos)69 int SchemaUtils::MakeTrans(const std::string &oriContent, size_t &pos)
70 {
71 if (isspace(oriContent[pos])) {
72 return COLUMN_BLANK;
73 } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_NOT_NULL.size(),
74 SchemaConstant::KEYWORD_ATTR_NOT_NULL) == 0) {
75 pos = pos + SchemaConstant::KEYWORD_ATTR_NOT_NULL.size() - 1;
76 return COLUMN_NOT_NULL;
77 } else if (oriContent.compare(pos, SchemaConstant::KEYWORD_ATTR_DEFAULT.size(),
78 SchemaConstant::KEYWORD_ATTR_DEFAULT) == 0) {
79 pos = pos + SchemaConstant::KEYWORD_ATTR_DEFAULT.size() - 1;
80 return COLUMN_DEFAULT;
81 } else if (std::isalnum(oriContent[pos]) || oriContent[pos] == '\'' ||
82 oriContent[pos] == '+' || oriContent[pos] == '-') {
83 return COLUMN_OTHER_ALNUM;
84 } else if (oriContent[pos] == ',') {
85 return COLUMN_COMMA;
86 } else {
87 return COLUMN_ILLEGAL;
88 }
89 }
90
91 // Use DFA to check and Parsing
92 // You can get the corresponding state meaning in the state transition matrix STATE_TRANSFER
SplitSchemaAttribute(const std::string & inAttrString,std::vector<std::string> & outAttrString)93 int SchemaUtils::SplitSchemaAttribute(const std::string &inAttrString, std::vector<std::string> &outAttrString)
94 {
95 int state = 0;
96 outAttrString.resize(3); // attribute have 3 type keywords
97 for (size_t i = 0; i < inAttrString.size(); i++) {
98 int id = MakeTrans(inAttrString, i);
99 if (id < 0) {
100 LOGD("Split Schema Attribute err, Contains unrecognized content [%c]", inAttrString[i]);
101 return -E_SCHEMA_PARSE_FAIL;
102 }
103 state = STATE_TRANSFER[state][id];
104 if (state < 0) {
105 LOGD("Split Schema Attribute err, err state [%d]", state);
106 return -E_SCHEMA_PARSE_FAIL;
107 }
108 switch (state) {
109 case 1: // state 1 :Indicates that only type information is currently available
110 outAttrString[0].push_back(inAttrString[i]);
111 break;
112 case 3: // state 3 :Gets the NOT_NULL keyword
113 outAttrString[1] = SchemaConstant::KEYWORD_ATTR_NOT_NULL;
114 break;
115 case 7: // state 7 :Contains complete information
116 // Get default string. Now transfer matrix can ensure > 1, but you should pay attention when fix it
117 if (i <= 1) {
118 LOGE("default string size must be over 1.");
119 return -E_SCHEMA_PARSE_FAIL;
120 }
121 outAttrString[2] = inAttrString.substr(i - 1); // 2 is index
122 return E_OK;
123 default:
124 break;
125 }
126 }
127 // Only these states are legal, The meaning of the state can be seen in the matrix STATE_TRANSFER explanation
128 if (!(state == 1 || state == 3 || state == 7)) { // 1 is state; 3 is state; 7 is state;
129 LOGD("Split Schema Attribute err, err state [%d]", state);
130 return -E_SCHEMA_PARSE_FAIL;
131 }
132 return E_OK;
133 }
134
TransToBool(const std::string & defaultContent,SchemaAttribute & outAttr)135 int SchemaUtils::TransToBool(const std::string &defaultContent, SchemaAttribute &outAttr)
136 {
137 // Have been trim
138 if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_TRUE) == 0) {
139 outAttr.defaultValue.boolValue = true;
140 return E_OK;
141 } else if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_FALSE) == 0) {
142 outAttr.defaultValue.boolValue = false;
143 return E_OK;
144 }
145 LOGE("Default value can not transform to bool!!");
146 return -E_SCHEMA_PARSE_FAIL;
147 }
148
TransToString(const std::string & defaultContent,SchemaAttribute & outAttr)149 int SchemaUtils::TransToString(const std::string &defaultContent, SchemaAttribute &outAttr)
150 {
151 // Have been trim, Strip leading and trailing '
152 if (defaultContent.size() > 1 && defaultContent.front() == '\'' && defaultContent.back() == '\'') {
153 outAttr.defaultValue.stringValue = defaultContent.substr(1, defaultContent.size() - 2); // 2: trim trailing
154 if (outAttr.defaultValue.stringValue.size() > SchemaConstant::SCHEMA_DEFAULT_STRING_SIZE_LIMIT) {
155 return -E_SCHEMA_PARSE_FAIL;
156 }
157 return E_OK;
158 }
159 LOGE("Substandard format! Default value can not transform to string!!");
160 return -E_SCHEMA_PARSE_FAIL;
161 }
162
TransToInteger(const std::string & defaultContent,SchemaAttribute & outAttr)163 int SchemaUtils::TransToInteger(const std::string &defaultContent, SchemaAttribute &outAttr)
164 {
165 // defaultContent can not be null
166 if (defaultContent.empty()) {
167 return -E_SCHEMA_PARSE_FAIL;
168 }
169 int transRes = strtol(defaultContent.c_str(), nullptr, 10); // 10: decimal
170 std::string resReview = std::to_string(transRes);
171 if (defaultContent.compare(defaultContent.find_first_not_of("+- "), defaultContent.size(),
172 resReview, resReview.find_first_not_of("+- "), resReview.size()) == 0) {
173 // Check the sign of the number
174 if ((defaultContent[0] == '-' && resReview[0] == '-') ||
175 (defaultContent[0] != '-' && resReview[0] != '-') ||
176 transRes == 0) {
177 outAttr.defaultValue.integerValue = transRes;
178 return E_OK;
179 }
180 }
181 LOGE("Default value can not transform to Integer!!");
182 return -E_SCHEMA_PARSE_FAIL;
183 }
184
TransToLong(const std::string & defaultContent,SchemaAttribute & outAttr)185 int SchemaUtils::TransToLong(const std::string &defaultContent, SchemaAttribute &outAttr)
186 {
187 // defaultContent can not be null
188 if (defaultContent.empty()) {
189 return -E_SCHEMA_PARSE_FAIL;
190 }
191 int64_t transRes = strtoll(defaultContent.c_str(), nullptr, 10); // 10: decimal
192 std::string resReview = std::to_string(transRes);
193 if (defaultContent.compare(defaultContent.find_first_not_of("+- "), defaultContent.size(),
194 resReview, resReview.find_first_not_of("+- "), resReview.size()) == 0) {
195 // Check the sign of the number
196 if ((defaultContent[0] == '-' && resReview[0] == '-') ||
197 (defaultContent[0] != '-' && resReview[0] != '-') ||
198 transRes == 0) {
199 outAttr.defaultValue.longValue = transRes;
200 return E_OK;
201 }
202 }
203
204 LOGE("Default value[%s] can not transform to LONG!!", resReview.c_str());
205 return -E_SCHEMA_PARSE_FAIL;
206 }
207
TransToDouble(const std::string & defaultContent,SchemaAttribute & outAttr)208 int SchemaUtils::TransToDouble(const std::string &defaultContent, SchemaAttribute &outAttr)
209 {
210 // defaultContent can not be null
211 if (defaultContent.empty()) {
212 return -E_SCHEMA_PARSE_FAIL;
213 }
214
215 // Disable scientific notation
216 int dotCount = 0;
217 for (const auto &iter : defaultContent) {
218 if (!(std::isdigit(iter) || iter == '.' || iter == '-' || iter == '+')) {
219 LOGE("Default value to double, exist invalid symbol[%c]", iter);
220 return -E_SCHEMA_PARSE_FAIL;
221 }
222 if (iter == '.') {
223 dotCount++;
224 }
225 if (dotCount > 1) {
226 LOGE("Default value to double, exist invalid extra dot");
227 return -E_SCHEMA_PARSE_FAIL;
228 }
229 }
230
231 char *end = nullptr;
232 double transRes = std::strtod(defaultContent.c_str(), &end);
233 // Double exist problems with accuracy, overflow is subject to the legality of the c++ conversion.
234 if (transRes > -HUGE_VAL && transRes < HUGE_VAL && std::isfinite(transRes)) {
235 // Cleared blank
236 if (end != &defaultContent.back() + 1) {
237 LOGD("Termination of parsing due to exception symbol");
238 return -E_SCHEMA_PARSE_FAIL;
239 }
240 outAttr.defaultValue.doubleValue = transRes;
241 return E_OK;
242 }
243 LOGE("Default value can not transform to double, overflow double max!");
244 return -E_SCHEMA_PARSE_FAIL;
245 }
246
TransformDefaultValue(std::string & defaultContent,SchemaAttribute & outAttr)247 int SchemaUtils::TransformDefaultValue(std::string &defaultContent, SchemaAttribute &outAttr)
248 {
249 TrimFiled(defaultContent);
250 if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_NULL) == 0 && outAttr.hasNotNullConstraint) {
251 LOGE("NOT NULL and DEFAULT null Simultaneously");
252 return -E_SCHEMA_PARSE_FAIL;
253 } else if (defaultContent.compare(SchemaConstant::KEYWORD_ATTR_VALUE_NULL) == 0) {
254 outAttr.hasDefaultValue = false;
255 return E_OK;
256 }
257
258 int errCode = E_OK;
259 switch (outAttr.type) {
260 case FieldType::LEAF_FIELD_BOOL:
261 errCode = TransToBool(defaultContent, outAttr);
262 break;
263 case FieldType::LEAF_FIELD_INTEGER:
264 errCode = TransToInteger(defaultContent, outAttr);
265 break;
266 case FieldType::LEAF_FIELD_LONG:
267 errCode = TransToLong(defaultContent, outAttr);
268 break;
269 case FieldType::LEAF_FIELD_DOUBLE:
270 errCode = TransToDouble(defaultContent, outAttr);
271 break;
272 case FieldType::LEAF_FIELD_STRING:
273 errCode = TransToString(defaultContent, outAttr);
274 break;
275 default:
276 LOGE("Unrecognized or unsupported type, please check!!");
277 errCode = -E_SCHEMA_PARSE_FAIL;
278 break;
279 }
280
281 LOGD("SchemaAttribute type is [%d], transfer result is [%d]", static_cast<int>(outAttr.type), errCode);
282 return errCode;
283 }
284
ParseAndCheckSchemaAttribute(const std::string & inAttrString,SchemaAttribute & outAttr,bool useAffinity)285 int SchemaUtils::ParseAndCheckSchemaAttribute(const std::string &inAttrString, SchemaAttribute &outAttr,
286 bool useAffinity)
287 {
288 if (inAttrString.empty()) {
289 return -E_SCHEMA_PARSE_FAIL;
290 }
291 std::string tempinAttrString = inAttrString;
292 TrimFiled(tempinAttrString);
293
294 std::vector<std::string> attrContext;
295 int errCode = SplitSchemaAttribute(inAttrString, attrContext);
296 if (errCode != E_OK) {
297 LOGD("Syntax error, please check!");
298 return errCode;
299 }
300 errCode = ParseSchemaAttribute(attrContext, outAttr, useAffinity);
301 if (errCode != E_OK) {
302 LOGD("Grammatical error, please check!");
303 return errCode;
304 }
305
306 return E_OK;
307 }
308
ParseSchemaAttribute(std::vector<std::string> & attrContext,SchemaAttribute & outAttr,bool useAffinity)309 int SchemaUtils::ParseSchemaAttribute(std::vector<std::string> &attrContext, SchemaAttribute &outAttr, bool useAffinity)
310 {
311 // Currently supported types
312 static const std::map<std::string, FieldType> FIELD_TYPE_DIC = {
313 {SchemaConstant::KEYWORD_TYPE_BOOL, FieldType::LEAF_FIELD_BOOL},
314 {SchemaConstant::KEYWORD_TYPE_INTEGER, FieldType::LEAF_FIELD_INTEGER},
315 {SchemaConstant::KEYWORD_TYPE_LONG, FieldType::LEAF_FIELD_LONG},
316 {SchemaConstant::KEYWORD_TYPE_DOUBLE, FieldType::LEAF_FIELD_DOUBLE},
317 {SchemaConstant::KEYWORD_TYPE_STRING, FieldType::LEAF_FIELD_STRING},
318 };
319
320 // After split attribute? attrContext include 3 type field
321 if (attrContext.size() < 3) {
322 LOGE("No parsing preprocessing!!");
323 return -E_SCHEMA_PARSE_FAIL;
324 }
325 TrimFiled(attrContext[0]);
326 if (!useAffinity) {
327 if (FIELD_TYPE_DIC.find(attrContext[0]) == FIELD_TYPE_DIC.end()) {
328 LOGE("Errno schema field type [%s]!!", attrContext[0].c_str());
329 return -E_SCHEMA_PARSE_FAIL;
330 } else {
331 outAttr.type = FIELD_TYPE_DIC.at(attrContext[0]);
332 }
333 } else {
334 outAttr.type = FieldType::LEAF_FIELD_NULL;
335 outAttr.customFieldType = attrContext[0];
336 }
337
338 outAttr.hasNotNullConstraint = !attrContext[1].empty();
339
340 // if DEFAULT value context exist, fix hasDefaultValue flag, 2nd represents the default value
341 if (attrContext[2].empty()) {
342 outAttr.hasDefaultValue = false;
343 } else {
344 outAttr.hasDefaultValue = true;
345 int errCode = TransformDefaultValue(attrContext[2], outAttr); // 2nd element is DEFAULT value
346 if (errCode != E_OK) {
347 LOGE("Default value is malformed!!");
348 return -E_SCHEMA_PARSE_FAIL;
349 }
350 }
351 return E_OK;
352 }
353
354 namespace {
355 // Check prefix and attempt to find any illegal, returns E_OK if nothing illegal and an hasPrefix indicator.
CheckDollarDotPrefix(const std::string & inPathStr,bool & hasPrefix)356 int CheckDollarDotPrefix(const std::string &inPathStr, bool &hasPrefix)
357 {
358 if (inPathStr.empty()) {
359 return -E_SCHEMA_PARSE_FAIL;
360 }
361 if (inPathStr.size() >= std::string("$.").size()) {
362 // In this case, $. prefix may exist, but also may not exist.
363 if (inPathStr[0] == '$' && inPathStr[1] == '.') { // 1 for second char
364 // $. prefix may exist
365 hasPrefix = true;
366 return E_OK;
367 }
368 if (inPathStr[0] == '$' && inPathStr[1] != '.') { // 1 for second char
369 return -E_SCHEMA_PARSE_FAIL;
370 }
371 if (inPathStr[1] == '$') { // 1 for second char
372 return -E_SCHEMA_PARSE_FAIL;
373 }
374 }
375 // here, inPathStr not empty, has at least one char, should not begin with '.'
376 if (inPathStr[0] == '.') {
377 return -E_SCHEMA_PARSE_FAIL;
378 }
379 hasPrefix = false;
380 return E_OK;
381 }
382 }
383
ParseAndCheckFieldPath(const std::string & inPathString,FieldPath & outPath,bool permitPrefix)384 int SchemaUtils::ParseAndCheckFieldPath(const std::string &inPathString, FieldPath &outPath, bool permitPrefix)
385 {
386 std::string tempInPathString = inPathString;
387 TrimFiled(tempInPathString);
388 bool hasPrefix = false;
389 int errCode = CheckDollarDotPrefix(tempInPathString, hasPrefix);
390 if (errCode != E_OK) {
391 LOGE("CheckDollarDotPrefix Fail.");
392 return errCode;
393 }
394
395 if (!permitPrefix && hasPrefix) {
396 LOGE("Not permit $. prefix.");
397 return -E_SCHEMA_PARSE_FAIL;
398 }
399
400 if (!hasPrefix) {
401 tempInPathString = std::string("$.") + tempInPathString;
402 }
403
404 for (size_t curPos = 1; curPos < tempInPathString.size();) {
405 if (curPos + 1 == tempInPathString.size()) {
406 LOGE("Dot at end will generate empty illegal path!");
407 return -E_SCHEMA_PARSE_FAIL;
408 }
409 size_t nextPointPos = tempInPathString.find_first_of(".", curPos + 1);
410 outPath.push_back(tempInPathString.substr(curPos + 1, nextPointPos - curPos - 1));
411 curPos = nextPointPos;
412 }
413
414 if (outPath.size() > SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) {
415 LOGE("Parse Schema Index depth illegality!");
416 return -E_SCHEMA_PARSE_FAIL;
417 }
418
419 for (const auto &iter : outPath) {
420 if (CheckFieldName(iter) != E_OK) {
421 LOGE("Parse Schema Index field illegality!");
422 return -E_SCHEMA_PARSE_FAIL;
423 }
424 }
425 return E_OK;
426 }
427
CheckFieldName(const FieldName & inName)428 int SchemaUtils::CheckFieldName(const FieldName &inName)
429 {
430 if (inName.empty() || inName.size() > SchemaConstant::SCHEMA_FEILD_NAME_LENGTH_MAX) {
431 LOGE("Schema FieldName have invalid size!");
432 return -E_SCHEMA_PARSE_FAIL;
433 }
434
435 // The first letter must be a number or an underscore
436 if (!(std::isalpha(inName[0]) || inName[0] == '_')) {
437 LOGE("Schema FieldName begin with un support symbol!");
438 return -E_SCHEMA_PARSE_FAIL;
439 }
440
441 // Must consist of numeric underscore letters
442 for (const auto &iter : inName) {
443 if (!(IsLegalFieldCharacter(iter))) {
444 LOGE("Schema FieldName exist un support symbol!");
445 return -E_SCHEMA_PARSE_FAIL;
446 }
447 }
448
449 return E_OK;
450 }
451
Strip(const std::string & inString)452 std::string SchemaUtils::Strip(const std::string &inString)
453 {
454 std::string stripRes = inString;
455 TrimFiled(stripRes);
456 return stripRes;
457 }
458
StripNameSpace(const std::string & inFullName)459 std::string SchemaUtils::StripNameSpace(const std::string &inFullName)
460 {
461 auto pos = inFullName.find_last_of('.');
462 if (pos == std::string::npos) { // No '.', so no namespace
463 return inFullName;
464 }
465 return inFullName.substr(pos + 1);
466 }
467
FieldTypeString(FieldType inType)468 std::string SchemaUtils::FieldTypeString(FieldType inType)
469 {
470 static std::map<FieldType, std::string> fieldTypeMapString = {
471 {FieldType::LEAF_FIELD_NULL, "NULL"},
472 {FieldType::LEAF_FIELD_BOOL, "BOOL"},
473 {FieldType::LEAF_FIELD_INTEGER, "INTEGER"},
474 {FieldType::LEAF_FIELD_LONG, "LONG"},
475 {FieldType::LEAF_FIELD_DOUBLE, "DOUBLE"},
476 {FieldType::LEAF_FIELD_STRING, "STRING"},
477 {FieldType::LEAF_FIELD_ARRAY, "ARRAY"},
478 {FieldType::LEAF_FIELD_OBJECT, "LEAF_OBJECT"},
479 {FieldType::INTERNAL_FIELD_OBJECT, "INTERNAL_OBJECT"},
480 };
481 return fieldTypeMapString[inType];
482 }
483
SchemaTypeString(SchemaType inType)484 std::string SchemaUtils::SchemaTypeString(SchemaType inType)
485 {
486 static std::map<SchemaType, std::string> schemaTypeMapString {
487 {SchemaType::NONE, "NONE"},
488 {SchemaType::JSON, "JSON-SCHEMA"},
489 {SchemaType::FLATBUFFER, "FLATBUFFER-SCHEMA"},
490 {SchemaType::RELATIVE, "RELATIVE"},
491 {SchemaType::UNRECOGNIZED, "UNRECOGNIZED"},
492 };
493 return schemaTypeMapString[inType];
494 }
495
FieldPathString(const FieldPath & inPath)496 std::string SchemaUtils::FieldPathString(const FieldPath &inPath)
497 {
498 std::string outString = "$";
499 for (const auto &entry : inPath) {
500 outString += ".";
501 outString += entry;
502 }
503 return outString;
504 }
505
TransTrackerSchemaToLower(const TrackerSchema & srcSchema,TrackerSchema & destSchema)506 void SchemaUtils::TransTrackerSchemaToLower(const TrackerSchema &srcSchema, TrackerSchema &destSchema)
507 {
508 std::string tableName(srcSchema.tableName.length(), ' ');
509 std::transform(srcSchema.tableName.begin(), srcSchema.tableName.end(), tableName.begin(), ::tolower);
510 destSchema.tableName = tableName;
511 for (const auto &extendColName : srcSchema.extendColNames) {
512 destSchema.extendColNames.insert(DBCommon::ToLowerCase(extendColName));
513 }
514 for (const auto &srcName : srcSchema.trackerColNames) {
515 destSchema.trackerColNames.insert(DBCommon::ToLowerCase(srcName));
516 }
517 }
518
ExtractJsonObj(const JsonObject & inJsonObject,const std::string & field,JsonObject & out)519 int SchemaUtils::ExtractJsonObj(const JsonObject &inJsonObject, const std::string &field,
520 JsonObject &out)
521 {
522 FieldType fieldType;
523 auto fieldPath = FieldPath {field};
524 int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType);
525 if (errCode != E_OK) {
526 LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s fieldType failed: %d.", field.c_str(), errCode);
527 return -E_SCHEMA_PARSE_FAIL;
528 }
529 if (FieldType::INTERNAL_FIELD_OBJECT != fieldType) {
530 LOGE("[SchemaUtils][ExtractJsonObj] Expect %s Object but %s.", field.c_str(),
531 SchemaUtils::FieldTypeString(fieldType).c_str());
532 return -E_SCHEMA_PARSE_FAIL;
533 }
534 errCode = inJsonObject.GetObjectByFieldPath(fieldPath, out);
535 if (errCode != E_OK) {
536 LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s value failed: %d.", field.c_str(), errCode);
537 return -E_SCHEMA_PARSE_FAIL;
538 }
539 return E_OK;
540 }
541
ExtractJsonObjArray(const JsonObject & inJsonObject,const std::string & field,std::vector<JsonObject> & out)542 int SchemaUtils::ExtractJsonObjArray(const JsonObject &inJsonObject, const std::string &field,
543 std::vector<JsonObject> &out)
544 {
545 FieldType fieldType;
546 auto fieldPath = FieldPath {field};
547 int errCode = inJsonObject.GetFieldTypeByFieldPath(fieldPath, fieldType);
548 if (errCode != E_OK) {
549 LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s fieldType failed: %d.", field.c_str(), errCode);
550 return -E_SCHEMA_PARSE_FAIL;
551 }
552 if (FieldType::LEAF_FIELD_ARRAY != fieldType) {
553 LOGE("[SchemaUtils][ExtractJsonObj] Expect %s Object but %s.", field.c_str(),
554 SchemaUtils::FieldTypeString(fieldType).c_str());
555 return -E_SCHEMA_PARSE_FAIL;
556 }
557 errCode = inJsonObject.GetObjectArrayByFieldPath(fieldPath, out);
558 if (errCode != E_OK) {
559 LOGE("[SchemaUtils][ExtractJsonObj] Get schema %s value failed: %d.", field.c_str(), errCode);
560 return -E_SCHEMA_PARSE_FAIL;
561 }
562 return E_OK;
563 }
564 } // namespace DistributedDB
565