• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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