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_object.h"
17
18 #include <algorithm>
19 #include <cmath>
20
21 #include "db_errno.h"
22 #include "log_print.h"
23 #include "schema_constant.h"
24 #include "schema_utils.h"
25
26 namespace DistributedDB {
27 namespace {
28 #ifndef OMIT_FLATBUFFER
29 constexpr double EPSILON = 0.000001; // 0.000001 for tolerance
IsDoubleNearlyEqual(double left,double right)30 inline bool IsDoubleNearlyEqual(double left, double right)
31 {
32 if (std::fabs(left - right) < EPSILON) {
33 return true;
34 }
35 double absBigger = std::max(std::fabs(left), std::fabs(right));
36 double relativeDiff = ((absBigger == 0.0) ? 0.0 : (std::fabs(left - right) / absBigger)); // 0.0 for double 0
37 return relativeDiff < EPSILON;
38 }
39 #endif // OMIT_FLATBUFFER
40 }
41
CopyFrom(const FlatBufferSchema & other)42 void SchemaObject::FlatBufferSchema::CopyFrom(const FlatBufferSchema &other)
43 {
44 // The SchemaObject guarantee not CopyFrom "Self"; owner_ can only be set at construction.
45 description_ = other.description_;
46 }
47
GetDescription() const48 std::string SchemaObject::FlatBufferSchema::GetDescription() const
49 {
50 return description_;
51 }
52
53 #ifndef OMIT_FLATBUFFER
IsFlatBufferSchema(const std::string & inOriginal,std::string & outDecoded)54 bool SchemaObject::FlatBufferSchema::IsFlatBufferSchema(const std::string &inOriginal, std::string &outDecoded)
55 {
56 if (inOriginal.empty()) {
57 LOGE("[FBSchema][Is] OriSchema empty.");
58 return false;
59 }
60 if (inOriginal.size() >= SchemaConstant::SCHEMA_STRING_SIZE_LIMIT * 2) { // 2 :Maximum base64 encode size multiple
61 // Base64 encode will not exceed 2 times original binary
62 LOGE("[FBSchema][Is] OriSchemaSize=%zu too large even after base64 encode.", inOriginal.size());
63 return false;
64 }
65 auto oriSchemaBuf = reinterpret_cast<const uint8_t *>(inOriginal.c_str());
66 flatbuffers::Verifier oriVerifier(oriSchemaBuf, inOriginal.size());
67 if (reflection::VerifySizePrefixedSchemaBuffer(oriVerifier)) {
68 outDecoded = inOriginal; // The original one is the decoded one
69 return true;
70 }
71 outDecoded.clear();
72 return false;
73 }
74
75 // A macro check pointer get from flatbuffer that won't be nullptr(required field) in fact after verified by flatbuffer
76 #define CHECK_NULL_UNLIKELY_RETURN_ERROR(pointer) \
77 if ((pointer) == nullptr) { \
78 return -E_INTERNAL_ERROR; \
79 }
80
81 namespace {
82 constexpr uint32_t ROOT_DEFINE_DEPTH = 0;
83 constexpr uint32_t SIZE_PREFIX_SIZE = sizeof(flatbuffers::uoffset_t);
84 constexpr int32_t INDEX_OF_NOT_ENUM = -1;
85
AttributeExistAndHasValue(const reflection::KeyValue * inAttr)86 inline bool AttributeExistAndHasValue(const reflection::KeyValue *inAttr)
87 {
88 return (inAttr != nullptr) && (inAttr->value() != nullptr) && (inAttr->value()->size() > 0);
89 }
90
IsIntegerType(reflection::BaseType inType)91 inline bool IsIntegerType(reflection::BaseType inType)
92 {
93 return (inType >= reflection::BaseType::Bool) && (inType <= reflection::BaseType::ULong);
94 }
95
IsRealType(reflection::BaseType inType)96 inline bool IsRealType(reflection::BaseType inType)
97 {
98 return (inType >= reflection::BaseType::Float) && (inType <= reflection::BaseType::Double);
99 }
100
IsScalarType(reflection::BaseType inType)101 inline bool IsScalarType(reflection::BaseType inType)
102 {
103 return IsIntegerType(inType) || IsRealType(inType);
104 }
105
IsStringType(reflection::BaseType inType)106 inline bool IsStringType(reflection::BaseType inType)
107 {
108 return inType == reflection::BaseType::String;
109 }
110
IsIndexableType(reflection::BaseType inType)111 inline bool IsIndexableType(reflection::BaseType inType)
112 {
113 return IsScalarType(inType) || IsStringType(inType);
114 }
115
IsVectorType(reflection::BaseType inType)116 inline bool IsVectorType(reflection::BaseType inType)
117 {
118 return inType == reflection::BaseType::Vector;
119 }
120
IsStringOrVectorType(reflection::BaseType inType)121 inline bool IsStringOrVectorType(reflection::BaseType inType)
122 {
123 return IsStringType(inType) || IsVectorType(inType);
124 }
125
IsObjectType(reflection::BaseType inType)126 inline bool IsObjectType(reflection::BaseType inType)
127 {
128 return inType == reflection::BaseType::Obj;
129 }
130
IsSupportTypeAtRoot(reflection::BaseType inType)131 inline bool IsSupportTypeAtRoot(reflection::BaseType inType)
132 {
133 return IsIndexableType(inType) || IsVectorType(inType) || IsObjectType(inType);
134 }
135
IsRequiredSupportType(reflection::BaseType inType)136 inline bool IsRequiredSupportType(reflection::BaseType inType)
137 {
138 return IsStringOrVectorType(inType) || IsObjectType(inType);
139 }
140
IsConflict(bool deprecated,bool required)141 inline bool IsConflict(bool deprecated, bool required)
142 {
143 return deprecated && required;
144 }
145 }
146
ParseFlatBufferSchema(const std::string & inDecoded)147 int SchemaObject::FlatBufferSchema::ParseFlatBufferSchema(const std::string &inDecoded)
148 {
149 description_.clear(); // For recovering from a fail parse
150 // The upper logic had guaranteed that the inDecoded be verified OK
151 auto schema = reflection::GetSizePrefixedSchema(inDecoded.c_str());
152 CHECK_NULL_UNLIKELY_RETURN_ERROR(schema);
153 auto rootTable = schema->root_table();
154 if (rootTable == nullptr || rootTable->is_struct()) {
155 LOGE("[FBSchema][Parse] Root table nullptr or is struct.");
156 return -E_SCHEMA_PARSE_FAIL;
157 }
158
159 auto rootTableName = rootTable->name();
160 CHECK_NULL_UNLIKELY_RETURN_ERROR(rootTableName);
161 description_ += ("RootTableName=" + SchemaUtils::StripNameSpace(rootTableName->str()) + ";");
162
163 int errCode = ParseCheckRootTableAttribute(*rootTable);
164 if (errCode != E_OK) {
165 return errCode;
166 }
167
168 RawIndexInfos indexCollect;
169 errCode = ParseCheckRootTableDefine(*schema, *rootTable, indexCollect);
170 if (errCode != E_OK) {
171 return errCode;
172 }
173
174 return ParseCheckIndexes(indexCollect);
175 }
176
CompareFlatBufferDefine(const FlatBufferSchema & other) const177 int SchemaObject::FlatBufferSchema::CompareFlatBufferDefine(const FlatBufferSchema &other) const
178 {
179 // Schema had been parsed and constraint checked before this function is called, so as we assumed.
180 // Here in the compare procedure, we only check null-point, do not check or suspect of constraint any more.
181 auto selfSchema = GetSchema();
182 auto otherSchema = other.GetSchema();
183 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfSchema);
184 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherSchema);
185 auto selfRootTable = selfSchema->root_table();
186 auto otherRootTable = otherSchema->root_table();
187 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfRootTable);
188 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherRootTable);
189 auto selfRootTableName = selfRootTable->name();
190 auto otherRootTableName = otherRootTable->name();
191 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfRootTableName);
192 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherRootTableName);
193
194 std::string selfRootName = SchemaUtils::StripNameSpace(selfRootTableName->str());
195 std::string otherRootName = SchemaUtils::StripNameSpace(otherRootTableName->str());
196 if (selfRootName != otherRootName) {
197 LOGE("[FBSchema][Compare] RootName dif.");
198 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
199 }
200 // We don't have to compare rootTableAttribute or index here, they are done by SchemaObject
201 std::set<std::string> comparedTypeNameSet;
202 return CompareTableOrStructDefine({selfSchema, otherSchema}, {selfRootTable, otherRootTable}, true,
203 comparedTypeNameSet);
204 }
205
206 namespace {
CheckSizePrefixRawValue(const RawValue & inValue)207 int CheckSizePrefixRawValue(const RawValue &inValue)
208 {
209 if (inValue.first == nullptr) { // Unlikely
210 return -E_INVALID_ARGS;
211 }
212 if (inValue.second <= SIZE_PREFIX_SIZE) {
213 LOGW("[FBSchema][CheckSizePreValue] ValueSize too short:%" PRIu32, inValue.second);
214 return -E_INVALID_ARGS;
215 }
216 auto realSize = flatbuffers::ReadScalar<flatbuffers::uoffset_t>(inValue.first);
217 if (realSize != inValue.second - SIZE_PREFIX_SIZE) {
218 LOGE("[FBSchema][CheckSizePreValue] RealSize=%" PRIu32 " mismatch %" PRIu32, realSize, inValue.second);
219 return -E_INVALID_ARGS;
220 }
221 return E_OK;
222 }
223 }
224
VerifyFlatBufferValue(const RawValue & inValue,bool tryNoSizePrefix) const225 int SchemaObject::FlatBufferSchema::VerifyFlatBufferValue(const RawValue &inValue, bool tryNoSizePrefix) const
226 {
227 (void)tryNoSizePrefix; // Use it in the future, currently we demand value is sizePrefixed
228 int errCode = CheckSizePrefixRawValue(inValue);
229 if (errCode != E_OK) {
230 return errCode;
231 }
232 auto schema = GetSchema();
233 CHECK_NULL_UNLIKELY_RETURN_ERROR(schema);
234 auto rootTable = schema->root_table();
235 CHECK_NULL_UNLIKELY_RETURN_ERROR(rootTable);
236 if (!flatbuffers::Verify(*schema, *rootTable, inValue.first + SIZE_PREFIX_SIZE,
237 inValue.second - SIZE_PREFIX_SIZE)) {
238 return -E_FLATBUFFER_VERIFY_FAIL;
239 }
240 return E_OK;
241 }
242
243 namespace {
MapFieldType(reflection::BaseType inType)244 FieldType MapFieldType(reflection::BaseType inType)
245 {
246 static std::map<reflection::BaseType, FieldType> fieldTypeMap{
247 {reflection::BaseType::Bool, FieldType::LEAF_FIELD_BOOL},
248 {reflection::BaseType::Byte, FieldType::LEAF_FIELD_INTEGER},
249 {reflection::BaseType::UByte, FieldType::LEAF_FIELD_INTEGER},
250 {reflection::BaseType::Short, FieldType::LEAF_FIELD_INTEGER},
251 {reflection::BaseType::UShort, FieldType::LEAF_FIELD_INTEGER},
252 {reflection::BaseType::Int, FieldType::LEAF_FIELD_INTEGER},
253 {reflection::BaseType::UInt, FieldType::LEAF_FIELD_LONG},
254 {reflection::BaseType::Long, FieldType::LEAF_FIELD_LONG},
255 {reflection::BaseType::ULong, FieldType::LEAF_FIELD_DOUBLE},
256 {reflection::BaseType::Float, FieldType::LEAF_FIELD_DOUBLE},
257 {reflection::BaseType::Double, FieldType::LEAF_FIELD_DOUBLE},
258 {reflection::BaseType::String, FieldType::LEAF_FIELD_STRING},
259 {reflection::BaseType::Vector, FieldType::LEAF_FIELD_ARRAY},
260 {reflection::BaseType::Obj, FieldType::INTERNAL_FIELD_OBJECT},
261 };
262 if (fieldTypeMap.count(inType) == 0) {
263 return FieldType::LEAF_FIELD_NULL;
264 }
265 return fieldTypeMap[inType];
266 }
267
CheckDollarDotAndSkipIt(RawString inPath)268 RawString CheckDollarDotAndSkipIt(RawString inPath)
269 {
270 if (inPath == nullptr) {
271 return nullptr;
272 }
273 auto pathStr = inPath;
274 if (*pathStr++ != '$') {
275 return nullptr;
276 }
277 if (*pathStr++ != '.') {
278 return nullptr;
279 }
280 if (*pathStr == 0) {
281 return nullptr;
282 }
283 return pathStr;
284 }
285
GetFieldInfoFromSchemaByPath(const reflection::Schema & schema,RawString pathStr)286 const reflection::Field *GetFieldInfoFromSchemaByPath(const reflection::Schema &schema, RawString pathStr)
287 {
288 auto rootTable = schema.root_table();
289 if (rootTable == nullptr) { // Unlikely
290 return nullptr;
291 }
292 auto rootFields = rootTable->fields();
293 if (rootFields == nullptr) { // Unlikely
294 return nullptr;
295 }
296 // Unlikely to return nullptr, except internal-error happened
297 return rootFields->LookupByKey(pathStr);
298 }
299
DoVerifyBeforeExtract(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo,const flatbuffers::Verifier & verifier)300 int DoVerifyBeforeExtract(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo,
301 const flatbuffers::Verifier &verifier)
302 {
303 auto type = fieldInfo.type();
304 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
305 bool verifyResult = true;
306 switch (type->base_type()) {
307 case reflection::Bool:
308 case reflection::Byte:
309 case reflection::UByte:
310 verifyResult = rootValue.VerifyField<int8_t>(verifier, fieldInfo.offset());
311 break;
312 case reflection::Short:
313 case reflection::UShort:
314 verifyResult = rootValue.VerifyField<int16_t>(verifier, fieldInfo.offset());
315 break;
316 case reflection::Int:
317 case reflection::UInt:
318 verifyResult = rootValue.VerifyField<int32_t>(verifier, fieldInfo.offset());
319 break;
320 case reflection::Long:
321 case reflection::ULong:
322 verifyResult = rootValue.VerifyField<uint64_t>(verifier, fieldInfo.offset());
323 break;
324 case reflection::Float:
325 verifyResult = rootValue.VerifyField<float>(verifier, fieldInfo.offset());
326 break;
327 case reflection::Double:
328 verifyResult = rootValue.VerifyField<double>(verifier, fieldInfo.offset());
329 break;
330 case reflection::String:
331 verifyResult = rootValue.VerifyField<flatbuffers::uoffset_t>(verifier, fieldInfo.offset()) &&
332 verifier.VerifyString(flatbuffers::GetFieldS(rootValue, fieldInfo)); // VerifyString can accept null
333 break;
334 default:
335 return -E_NOT_SUPPORT;
336 }
337 return (verifyResult ? E_OK : -E_FLATBUFFER_VERIFY_FAIL);
338 }
339
DoExtractString(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo)340 inline std::string DoExtractString(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo)
341 {
342 auto strVal = flatbuffers::GetFieldS(rootValue, fieldInfo);
343 if (strVal == nullptr) {
344 return "";
345 }
346 return strVal->str();
347 }
348
DoExtractValue(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo,TypeValue & outExtract)349 int DoExtractValue(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo, TypeValue &outExtract)
350 {
351 auto type = fieldInfo.type();
352 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
353 switch (type->base_type()) {
354 case reflection::Bool:
355 outExtract.second.boolValue = (flatbuffers::GetFieldI<int8_t>(rootValue, fieldInfo) != 0);
356 break;
357 case reflection::Byte:
358 outExtract.second.integerValue = flatbuffers::GetFieldI<int8_t>(rootValue, fieldInfo);
359 break;
360 case reflection::UByte:
361 outExtract.second.integerValue = flatbuffers::GetFieldI<uint8_t>(rootValue, fieldInfo);
362 break;
363 case reflection::Short:
364 outExtract.second.integerValue = flatbuffers::GetFieldI<int16_t>(rootValue, fieldInfo);
365 break;
366 case reflection::UShort:
367 outExtract.second.integerValue = flatbuffers::GetFieldI<uint16_t>(rootValue, fieldInfo);
368 break;
369 case reflection::Int:
370 outExtract.second.integerValue = flatbuffers::GetFieldI<int32_t>(rootValue, fieldInfo);
371 break;
372 case reflection::UInt:
373 outExtract.second.longValue = flatbuffers::GetFieldI<uint32_t>(rootValue, fieldInfo);
374 break;
375 case reflection::Long:
376 outExtract.second.longValue = flatbuffers::GetFieldI<int64_t>(rootValue, fieldInfo);
377 break;
378 case reflection::ULong:
379 outExtract.second.doubleValue = flatbuffers::GetFieldI<uint64_t>(rootValue, fieldInfo);
380 break;
381 case reflection::Float:
382 outExtract.second.doubleValue = flatbuffers::GetFieldF<float>(rootValue, fieldInfo);
383 break;
384 case reflection::Double:
385 outExtract.second.doubleValue = flatbuffers::GetFieldF<double>(rootValue, fieldInfo);
386 break;
387 case reflection::String:
388 outExtract.second.stringValue = DoExtractString(rootValue, fieldInfo);
389 break;
390 default:
391 return -E_NOT_SUPPORT;
392 }
393 return E_OK;
394 }
395
ExtractFlatBufferValueFinal(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo,const flatbuffers::Verifier & verifier,TypeValue & outExtract)396 int ExtractFlatBufferValueFinal(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo,
397 const flatbuffers::Verifier &verifier, TypeValue &outExtract)
398 {
399 auto type = fieldInfo.type();
400 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
401 auto baseType = type->base_type();
402 if (!IsIndexableType(baseType)) {
403 LOGE("[ExtractFinal] BaseType=%s not indexable.", reflection::EnumNameBaseType(baseType));
404 return -E_NOT_SUPPORT;
405 }
406 outExtract.first = MapFieldType(type->base_type());
407 int errCode = DoVerifyBeforeExtract(rootValue, fieldInfo, verifier);
408 if (errCode != E_OK) {
409 LOGE("[ExtractFinal] DoVerify fail, errCode=%d.", errCode);
410 return errCode;
411 }
412 errCode = DoExtractValue(rootValue, fieldInfo, outExtract);
413 if (errCode != E_OK) {
414 LOGE("[ExtractFinal] DoExtract fail, errCode=%d.", errCode);
415 return errCode;
416 }
417 return E_OK;
418 }
419 }
420
ExtractFlatBufferValue(RawString inPath,const RawValue & inValue,TypeValue & outExtract,bool tryNoSizePrefix) const421 int SchemaObject::FlatBufferSchema::ExtractFlatBufferValue(RawString inPath, const RawValue &inValue,
422 TypeValue &outExtract, bool tryNoSizePrefix) const
423 {
424 // NOTE!!! This function is performance sensitive !!! Carefully not to allocate memory often!!!
425 (void)tryNoSizePrefix; // Use it in the future, currently we demand value is sizePrefixed
426 int errCode = CheckSizePrefixRawValue(inValue);
427 if (errCode != E_OK) {
428 return errCode;
429 }
430 auto pathStr = CheckDollarDotAndSkipIt(inPath);
431 if (pathStr == nullptr) { // Unlikely
432 LOGE("[FBSchema][Extract] inPath not begin with $. or nothing after it.");
433 return -E_INVALID_ARGS;
434 }
435 auto schema = GetSchema();
436 CHECK_NULL_UNLIKELY_RETURN_ERROR(schema);
437 // Currently we don't support nest-path
438 auto fieldInfo = GetFieldInfoFromSchemaByPath(*schema, pathStr);
439 if (fieldInfo == nullptr) {
440 LOGW("[FBSchema][Extract] FieldInfo of path not found.");
441 return -E_INTERNAL_ERROR;
442 }
443 // Begin extract, we have to minimal verify if we don't trust value from database
444 auto valueRealBegin = inValue.first + SIZE_PREFIX_SIZE;
445 auto valueRealSize = inValue.second - SIZE_PREFIX_SIZE;
446 flatbuffers::Verifier verifier(valueRealBegin, valueRealSize);
447 auto offset = verifier.VerifyOffset(0); // Attention: Verify root offset before we call GetAnyRoot
448 if (offset == 0) {
449 LOGE("[FBSchema][Extract] Verity root offset failed.");
450 return -E_FLATBUFFER_VERIFY_FAIL;
451 }
452 auto rootValue = flatbuffers::GetAnyRoot(valueRealBegin);
453 if (rootValue == nullptr) {
454 LOGE("[FBSchema][Extract] Get rootTable from value fail.");
455 return -E_INVALID_DATA;
456 }
457 // Verity vTable of rootTable before we extract anything from rootValue by reflection
458 bool vTableOk = rootValue->VerifyTableStart(verifier);
459 if (!vTableOk) {
460 LOGE("[FBSchema][Extract] Verify vTable of rootTable of value fail.");
461 return -E_FLATBUFFER_VERIFY_FAIL;
462 }
463 errCode = ExtractFlatBufferValueFinal(*rootValue, *fieldInfo, verifier, outExtract);
464 if (errCode != E_OK) {
465 return errCode;
466 }
467 verifier.EndTable();
468 return E_OK;
469 }
470
GetSchema() const471 const reflection::Schema *SchemaObject::FlatBufferSchema::GetSchema() const
472 {
473 // This function is called after schemaString_ had been verified by flatbuffer
474 return reflection::GetSizePrefixedSchema(owner_.schemaString_.c_str());
475 }
476
ParseCheckRootTableAttribute(const reflection::Object & rootTable)477 int SchemaObject::FlatBufferSchema::ParseCheckRootTableAttribute(const reflection::Object &rootTable)
478 {
479 auto rootTableAttr = rootTable.attributes();
480 if (rootTableAttr == nullptr) {
481 LOGE("[FBSchema][ParseRootAttr] Root table no attribute.");
482 return -E_SCHEMA_PARSE_FAIL;
483 }
484
485 auto versionAttr = rootTableAttr->LookupByKey(SchemaConstant::KEYWORD_SCHEMA_VERSION.c_str());
486 if (!AttributeExistAndHasValue(versionAttr)) {
487 LOGE("[FBSchema][ParseRootAttr] No SCHEMA_VERSION attribute or no value.");
488 return -E_SCHEMA_PARSE_FAIL;
489 }
490 if (SchemaUtils::Strip(versionAttr->value()->str()) != SchemaConstant::SCHEMA_SUPPORT_VERSION) {
491 LOGE("[FBSchema][ParseRootAttr] Unexpect SCHEMA_VERSION=%s.", versionAttr->value()->c_str());
492 return -E_SCHEMA_PARSE_FAIL;
493 }
494 owner_.schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION;
495 description_ += (SchemaConstant::KEYWORD_SCHEMA_VERSION + "=" + SchemaConstant::SCHEMA_SUPPORT_VERSION + ";");
496
497 auto skipsizeAttr = rootTableAttr->LookupByKey(SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE.c_str());
498 if (!AttributeExistAndHasValue(skipsizeAttr)) {
499 LOGI("[FBSchema][ParseRootAttr] No SCHEMA_SKIPSIZE attribute or no value.");
500 owner_.schemaSkipSize_ = 0; // Default skipsize value
501 return E_OK;
502 }
503 std::string skipsizeStr = SchemaUtils::Strip(skipsizeAttr->value()->str());
504 int skipsizeInt = strtol(skipsizeStr.c_str(), nullptr, 10); // 10: decimal
505 if (std::to_string(skipsizeInt) != skipsizeStr || skipsizeInt < 0 ||
506 static_cast<uint32_t>(skipsizeInt) > SchemaConstant::SCHEMA_SKIPSIZE_MAX) {
507 LOGE("[FBSchema][ParseRootAttr] Unexpect SCHEMA_SKIPSIZE value=%s.", skipsizeAttr->value()->c_str());
508 return -E_SCHEMA_PARSE_FAIL;
509 }
510 owner_.schemaSkipSize_ = static_cast<uint32_t>(skipsizeInt);
511 description_ += (SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE + "=" + skipsizeStr + ";");
512 return E_OK;
513 }
514
ParseCheckRootTableDefine(const reflection::Schema & schema,const reflection::Object & rootTable,RawIndexInfos & indexCollect)515 int SchemaObject::FlatBufferSchema::ParseCheckRootTableDefine(const reflection::Schema &schema,
516 const reflection::Object &rootTable, RawIndexInfos &indexCollect)
517 {
518 // Clear schemaDefine_ to recover from a fail parse
519 owner_.schemaDefine_.clear();
520 auto fields = rootTable.fields();
521 if (fields == nullptr || fields->size() == 0) {
522 LOGE("[FBSchema][ParseRootDefine] Empty define.");
523 return -E_SCHEMA_PARSE_FAIL;
524 }
525 for (uint32_t i = 0; i < fields->size(); i++) {
526 auto eachField = (*fields)[i];
527 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachField);
528
529 auto name = eachField->name();
530 CHECK_NULL_UNLIKELY_RETURN_ERROR(name);
531 int errCode = SchemaUtils::CheckFieldName(name->str());
532 if (errCode != E_OK) {
533 LOGE("[FBSchema][ParseRootDefine] Invalid fieldName, errCode=%d.", errCode);
534 return -E_SCHEMA_PARSE_FAIL;
535 }
536 FieldPath path{name->str()};
537 if (owner_.schemaDefine_[ROOT_DEFINE_DEPTH].count(path) != 0) { // Unlikely
538 LOGE("[FBSchema][ParseRootDefine] FieldPath already exist at root.");
539 return -E_SCHEMA_PARSE_FAIL;
540 }
541
542 errCode = ParseCheckFieldInfo(schema, *eachField, path, indexCollect);
543 if (errCode != E_OK) {
544 LOGE("[FBSchema][ParseRootDefine] ParseFieldInfo errCode=%d", errCode);
545 return errCode;
546 }
547 }
548 uint32_t fieldPathCount = 0;
549 for (uint32_t depth = ROOT_DEFINE_DEPTH; depth < SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) {
550 if (owner_.schemaDefine_.count(depth) != 0) {
551 fieldPathCount += owner_.schemaDefine_[depth].size();
552 }
553 }
554 if (fieldPathCount > SchemaConstant::SCHEMA_FEILD_NAME_COUNT_MAX) {
555 LOGE("[FBSchema][ParseRootDefine] FieldPath count=%" PRIu32 " exceed the limitation.", fieldPathCount);
556 return -E_SCHEMA_PARSE_FAIL;
557 }
558 return E_OK;
559 }
560
561 namespace {
CheckFieldTypeSupport(const reflection::Type & inType,bool isRootField)562 bool CheckFieldTypeSupport(const reflection::Type &inType, bool isRootField)
563 {
564 auto baseType = inType.base_type();
565 if (isRootField) {
566 if (!IsSupportTypeAtRoot(baseType)) {
567 LOGE("[FBSchema][DecideType] BaseType=%s not support at root.", reflection::EnumNameBaseType(baseType));
568 return false;
569 }
570 if (IsIntegerType(baseType) && (inType.index() != INDEX_OF_NOT_ENUM)) {
571 LOGE("[FBSchema][DecideType] BaseType=%s is enum, not support.", reflection::EnumNameBaseType(baseType));
572 return false;
573 }
574 if (IsVectorType(baseType)) {
575 auto elementType = inType.element();
576 if (!IsIndexableType(elementType)) {
577 LOGE("[FBSchema][DecideType] ElementType=%s not support for vector.",
578 reflection::EnumNameBaseType(elementType));
579 return false;
580 }
581 }
582 } else {
583 // Currently only support nest in Struct, support only scalar and nest-struct
584 if (!IsScalarType(baseType) && !IsObjectType(baseType)) {
585 LOGE("[FBSchema][DecideType] BaseType=%s not support for struct.", reflection::EnumNameBaseType(baseType));
586 return false;
587 }
588 }
589 return true;
590 }
591 }
592
ParseCheckFieldInfo(const reflection::Schema & schema,const reflection::Field & field,const FieldPath & path,RawIndexInfos & indexCollect)593 int SchemaObject::FlatBufferSchema::ParseCheckFieldInfo(const reflection::Schema &schema,
594 const reflection::Field &field, const FieldPath &path, RawIndexInfos &indexCollect)
595 {
596 if (path.empty() || path.size() > SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) {
597 LOGE("[FBSchema][ParseField] FieldPath size=%zu invalid.", path.size());
598 return -E_SCHEMA_PARSE_FAIL;
599 }
600 uint32_t depth = path.size() - 1; // Depth count from zero
601 bool isRootField = (depth == ROOT_DEFINE_DEPTH);
602 SchemaAttribute &fieldInfo = owner_.schemaDefine_[depth][path]; // Create new entry in schemaDefine_
603
604 auto type = field.type();
605 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
606 if (!CheckFieldTypeSupport(*type, isRootField)) {
607 return -E_SCHEMA_PARSE_FAIL;
608 }
609 auto baseType = type->base_type();
610 // Only type and isIndexable of SchemaAttribute is necessary
611 fieldInfo.type = MapFieldType(baseType);
612 fieldInfo.isIndexable = (IsIndexableType(baseType) && isRootField);
613 description_ += (SchemaUtils::FieldPathString(path) + "=" + reflection::EnumNameBaseType(baseType) + ";");
614
615 if (IsRequiredSupportType(baseType)) {
616 if (IsConflict(field.deprecated(), field.required())) {
617 LOGE("[FBSchema][ParseField] Deprecated conflict with required.");
618 return -E_SCHEMA_PARSE_FAIL;
619 }
620 }
621 if (fieldInfo.isIndexable) {
622 CollectRawIndexInfos(field, indexCollect);
623 }
624 if (IsObjectType(baseType)) {
625 int errCode = ParseCheckStructDefine(schema, field, path);
626 if (errCode != E_OK) {
627 return errCode;
628 }
629 }
630 return E_OK;
631 }
632
CollectRawIndexInfos(const reflection::Field & field,RawIndexInfos & indexCollect) const633 void SchemaObject::FlatBufferSchema::CollectRawIndexInfos(const reflection::Field &field,
634 RawIndexInfos &indexCollect) const
635 {
636 auto name = field.name();
637 if (name == nullptr) { // Not possible
638 return;
639 }
640 auto fieldAttr = field.attributes();
641 if (fieldAttr == nullptr) {
642 return;
643 }
644 auto indexAttr = fieldAttr->LookupByKey(SchemaConstant::KEYWORD_INDEX.c_str());
645 if (indexAttr == nullptr) {
646 return;
647 }
648 if (indexAttr->value() == nullptr) {
649 indexCollect[name->str()] = ""; // Must be SingleField-Index
650 return;
651 }
652 indexCollect[name->str()] = indexAttr->value()->str(); // May still be empty string
653 }
654
ParseCheckStructDefine(const reflection::Schema & schema,const reflection::Field & field,const FieldPath & path)655 int SchemaObject::FlatBufferSchema::ParseCheckStructDefine(const reflection::Schema &schema,
656 const reflection::Field &field, const FieldPath &path)
657 {
658 if (path.size() >= SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) {
659 LOGE("[FBSchema][ParseStruct] Struct define at depth limitation.");
660 return -E_SCHEMA_PARSE_FAIL;
661 }
662 auto objects = schema.objects();
663 CHECK_NULL_UNLIKELY_RETURN_ERROR(objects);
664 auto type = field.type();
665 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
666 auto objIndex = type->index();
667 if (objIndex < 0 || static_cast<uint32_t>(objIndex) >= objects->size()) { // Unlikely
668 return -E_INTERNAL_ERROR;
669 }
670 auto structObj = (*objects)[objIndex];
671 CHECK_NULL_UNLIKELY_RETURN_ERROR(structObj);
672 auto structName = structObj->name();
673 CHECK_NULL_UNLIKELY_RETURN_ERROR(structName);
674 if (!structObj->is_struct()) {
675 LOGE("[FBSchema][ParseStruct] Nest table=%s not support.", structName->c_str());
676 return -E_SCHEMA_PARSE_FAIL;
677 }
678 description_ += ("StructName=" + SchemaUtils::StripNameSpace(structName->str()) + ";");
679
680 // Parse fields
681 auto structFields = structObj->fields();
682 CHECK_NULL_UNLIKELY_RETURN_ERROR(structFields);
683 // Flatbuffer guarantee that struct will not be empty size, even if it is empty, we just ignore it
684 for (uint32_t i = 0; i < structFields->size(); i++) {
685 auto eachField = (*structFields)[i];
686 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachField);
687 auto eachName = eachField->name();
688 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachName);
689 int errCode = SchemaUtils::CheckFieldName(eachName->str());
690 if (errCode != E_OK) {
691 LOGE("[FBSchema][ParseStruct] Invalid fieldName, errCode=%d.", errCode);
692 return -E_SCHEMA_PARSE_FAIL;
693 }
694 FieldPath eachPath = path;
695 eachPath.push_back(eachName->str());
696 RawIndexInfos notUsed;
697 errCode = ParseCheckFieldInfo(schema, *eachField, eachPath, notUsed);
698 if (errCode != E_OK) {
699 LOGE("[FBSchema][ParseStruct] ParseFieldInfo errCode=%d.", errCode);
700 return errCode;
701 }
702 }
703 return E_OK;
704 }
705
706 namespace {
IsNotCompositeIndex(const std::string & indexStr)707 inline bool IsNotCompositeIndex(const std::string &indexStr)
708 {
709 // In fact, test found that attrValue will be "0" if not exist
710 return indexStr.empty() || indexStr == std::string("0");
711 }
712 }
713
ParseCheckIndexes(const RawIndexInfos & indexCollect)714 int SchemaObject::FlatBufferSchema::ParseCheckIndexes(const RawIndexInfos &indexCollect)
715 {
716 for (const auto &entry : indexCollect) {
717 std::vector<std::string> indexStrArray{entry.first}; // Entry.first is fieldName at root that was checked valid
718 const std::string &rawIndexStr = entry.second;
719 if (IsNotCompositeIndex(rawIndexStr)) {
720 int errCode = owner_.ParseCheckEachIndexFromStringArray(indexStrArray);
721 if (errCode != E_OK) {
722 LOGE("[FBSchema][ParseIndex] Create single-index fail:%d.", errCode);
723 return errCode;
724 }
725 description_ += ("INDEX=" + entry.first + ";");
726 continue;
727 }
728 // Parse other indexField
729 for (uint32_t curPos = 0; curPos < rawIndexStr.size();) {
730 uint32_t nextCommaPos = rawIndexStr.find_first_of(',', curPos);
731 std::string eachIndexField = rawIndexStr.substr(curPos, nextCommaPos - curPos);
732 eachIndexField = SchemaUtils::Strip(eachIndexField);
733 if (!eachIndexField.empty()) { // Continuous ',' just ignore
734 indexStrArray.push_back(eachIndexField);
735 }
736 if (nextCommaPos >= rawIndexStr.size()) { // No ',' anymore
737 break;
738 }
739 curPos = nextCommaPos + 1;
740 }
741 int errCode = owner_.ParseCheckEachIndexFromStringArray(indexStrArray);
742 if (errCode != E_OK) {
743 LOGE("[FBSchema][ParseIndex] Create composite-index fail:%d.", errCode);
744 return errCode;
745 }
746 description_ += ("INDEX=" + entry.first + ";");
747 }
748 if (owner_.schemaIndexes_.size() > SchemaConstant::SCHEMA_INDEX_COUNT_MAX) {
749 LOGE("[FBSchema][ParseIndex] Index count=%zu exceed limitation.", owner_.schemaIndexes_.size());
750 return -E_SCHEMA_PARSE_FAIL;
751 }
752 return E_OK;
753 }
754
755 namespace {
IsNotEqualNotCompatible(int errCode)756 inline bool IsNotEqualNotCompatible(int errCode)
757 {
758 return (errCode != -E_SCHEMA_EQUAL_EXACTLY) && (errCode != -E_SCHEMA_UNEQUAL_COMPATIBLE) &&
759 (errCode != -E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE);
760 }
761
CompareFieldCount(bool isRoot,uint32_t selfCount,uint32_t otherCount)762 int CompareFieldCount(bool isRoot, uint32_t selfCount, uint32_t otherCount)
763 {
764 if (isRoot) {
765 if (otherCount < selfCount) {
766 LOGW("[FBSchema][CompareRoot] RootFieldSize: %" PRu32 " vs %" PRu32, selfCount, otherCount);
767 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
768 }
769 } else {
770 if (selfCount != otherCount) {
771 LOGW("[FBSchema][CompareRoot] StructFieldSize: %" PRu32 " vs %" PRu32, selfCount, otherCount);
772 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
773 }
774 }
775 return (selfCount == otherCount) ? -E_SCHEMA_EQUAL_EXACTLY : -E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE;
776 }
777
CompareFieldInfoBesideType(const reflection::Field & selfField,const reflection::Field & otherField,reflection::BaseType theType)778 int CompareFieldInfoBesideType(const reflection::Field &selfField, const reflection::Field &otherField,
779 reflection::BaseType theType)
780 {
781 // Compare offset
782 if (selfField.offset() != otherField.offset()) {
783 LOGW("[FBSchema][CompareField] Offset diff");
784 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
785 }
786 // Compare default value
787 if (selfField.default_integer() != otherField.default_integer()) {
788 LOGE("[FBSchema][CompareField] DefaultInteger diff");
789 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
790 }
791 // QUEER: for the same default_real value in fbs, flatbuffer will generate different value in binary ???
792 if (!IsDoubleNearlyEqual(selfField.default_real(), otherField.default_real())) {
793 LOGE("[FBSchema][CompareField] DefaultReal diff");
794 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
795 }
796 // Ignore deprecated, Compare required
797 if (IsRequiredSupportType(theType)) {
798 if (selfField.required() != otherField.required()) {
799 LOGE("[FBSchema][CompareField] Require diff");
800 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
801 }
802 }
803 return -E_SCHEMA_EQUAL_EXACTLY;
804 }
805
CompareFieldInfo(const reflection::Field & selfField,const reflection::Field & otherField,bool & isStruct)806 int CompareFieldInfo(const reflection::Field &selfField, const reflection::Field &otherField, bool &isStruct)
807 {
808 auto selfType = selfField.type();
809 auto otherType = otherField.type();
810 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfType);
811 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherType);
812 // Compare type
813 auto selfBaseType = selfType->base_type();
814 auto otherBaseType = otherType->base_type();
815 if (selfBaseType != otherBaseType) {
816 LOGE("[FBSchema][CompareField] BaseType diff:%s vs %s.", reflection::EnumNameBaseType(selfBaseType),
817 reflection::EnumNameBaseType(otherBaseType));
818 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
819 }
820 if (IsVectorType(selfBaseType)) {
821 auto selfElementType = selfType->element();
822 auto otherElementType = otherType->element();
823 if (selfElementType != otherElementType) {
824 LOGE("[FBSchema][CompareField] ElementType diff:%" PRu32 " vs %" PRu32, selfElementType, otherElementType);
825 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
826 }
827 }
828 if (IsObjectType(selfBaseType)) {
829 isStruct = true;
830 }
831 return CompareFieldInfoBesideType(selfField, otherField, selfBaseType);
832 }
833
834 // Split from original functions which would be longer than 50 line
CompareExtraField(const PairConstPointer<reflection::Object> & bothObject)835 int CompareExtraField(const PairConstPointer<reflection::Object> &bothObject)
836 {
837 // This is private function, the caller guarantee that inputParameter not nullptr
838 auto selfFields = bothObject.first->fields();
839 auto otherFields = bothObject.second->fields();
840 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfFields);
841 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherFields);
842 // Each field in other not in self, should not be required
843 for (uint32_t i = 0; i < otherFields->size(); i++) {
844 auto eachOtherField = (*otherFields)[i];
845 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachOtherField);
846 auto otherName = eachOtherField->name();
847 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherName);
848 auto correspondSelfField = selfFields->LookupByKey(otherName->c_str());
849 if (correspondSelfField != nullptr) {
850 continue;
851 }
852 if (eachOtherField->required()) {
853 LOGE("[FBSchema][CompareDefine] Extra field should not be required.");
854 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
855 }
856 }
857 return -E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE;
858 }
859 }
860
CompareTableOrStructDefine(const PairConstPointer<reflection::Schema> & bothSchema,const PairConstPointer<reflection::Object> & bothObject,bool isRoot,std::set<std::string> & compared) const861 int SchemaObject::FlatBufferSchema::CompareTableOrStructDefine(const PairConstPointer<reflection::Schema> &bothSchema,
862 const PairConstPointer<reflection::Object> &bothObject, bool isRoot, std::set<std::string> &compared) const
863 {
864 // This is private function, the caller guarantee that inputParameter not nullptr
865 auto selfFields = bothObject.first->fields();
866 auto otherFields = bothObject.second->fields();
867 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfFields);
868 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherFields);
869 int errCode = CompareFieldCount(isRoot, selfFields->size(), otherFields->size());
870 if (errCode == -E_SCHEMA_UNEQUAL_INCOMPATIBLE) {
871 return errCode;
872 }
873 // Each field in self should be in other, and they should be same
874 for (uint32_t i = 0; i < selfFields->size(); i++) {
875 auto eachSelfField = (*selfFields)[i];
876 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachSelfField);
877 auto selfName = eachSelfField->name();
878 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfName);
879 auto correspondOtherField = otherFields->LookupByKey(selfName->c_str());
880 if (correspondOtherField == nullptr) {
881 LOGE("[FBSchema][CompareDefine] SelfField not found in other.");
882 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
883 }
884 bool isStruct = false;
885 errCode = CompareFieldInfo(*eachSelfField, *correspondOtherField, isStruct);
886 if (IsNotEqualNotCompatible(errCode)) {
887 LOGE("[FBSchema][CompareDefine] Compare info of field fail, errCode=%d.", errCode);
888 return errCode;
889 }
890 if (isStruct) {
891 // Previous parse guarantee that recursion will not be unlimited, don't be afraid.
892 errCode = CompareStruct(bothSchema, {eachSelfField, correspondOtherField}, compared);
893 if (IsNotEqualNotCompatible(errCode)) {
894 return errCode;
895 }
896 }
897 }
898 if (selfFields->size() == otherFields->size()) {
899 return -E_SCHEMA_EQUAL_EXACTLY;
900 }
901 return CompareExtraField(bothObject);
902 }
903
CompareStruct(const PairConstPointer<reflection::Schema> & bothSchema,const PairConstPointer<reflection::Field> & bothField,std::set<std::string> & compared) const904 int SchemaObject::FlatBufferSchema::CompareStruct(const PairConstPointer<reflection::Schema> &bothSchema,
905 const PairConstPointer<reflection::Field> &bothField, std::set<std::string> &compared) const
906 {
907 // This is private function, the caller guarantee that inputParameter not nullptr
908 auto selfObjects = bothSchema.first->objects();
909 auto otherObjects = bothSchema.second->objects();
910 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfObjects);
911 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherObjects);
912 auto selfType = bothField.first->type();
913 auto otherType = bothField.second->type();
914 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfType);
915 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherType);
916 auto selfObjIndex = selfType->index();
917 auto otherObjIndex = otherType->index();
918 if (selfObjIndex < 0 || static_cast<uint32_t>(selfObjIndex) >= selfObjects->size()) { // Unlikely
919 return -E_INTERNAL_ERROR;
920 }
921 if (otherObjIndex < 0 || static_cast<uint32_t>(otherObjIndex) >= otherObjects->size()) { // Unlikely
922 return -E_INTERNAL_ERROR;
923 }
924 auto selfStructObj = (*selfObjects)[selfObjIndex];
925 auto otherStructObj = (*otherObjects)[otherObjIndex];
926 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfStructObj);
927 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherStructObj);
928 // Previous parse can guarantee that they are both struct, no need to check again
929 auto selfStructName = selfStructObj->name();
930 auto otherStructName = otherStructObj->name();
931 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfStructName);
932 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherStructName);
933 std::string selfName = SchemaUtils::StripNameSpace(selfStructName->str());
934 std::string otherName = SchemaUtils::StripNameSpace(otherStructName->str());
935 if (selfName != otherName) {
936 LOGE("[FBSchema][CompareStruct] The field is not of same struct type");
937 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
938 }
939 if (compared.count(selfName) != 0) { // This struct-type had already been compared, no need to do recurse again
940 return -E_SCHEMA_EQUAL_EXACTLY;
941 }
942 compared.insert(selfName);
943 // Compare struct detail
944 if (selfStructObj->minalign() != otherStructObj->minalign()) {
945 LOGE("[FBSchema][CompareStruct] The struct minalign differ, self=%d, other=%d.",
946 selfStructObj->minalign(), otherStructObj->minalign());
947 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
948 }
949 if (selfStructObj->bytesize() != otherStructObj->bytesize()) {
950 LOGE("[FBSchema][CompareStruct] The struct bytesize differ, self=%d, other=%d.",
951 selfStructObj->bytesize(), otherStructObj->bytesize());
952 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
953 }
954 // Previous parse guarantee that recursion will not be unlimited, don't be afraid.
955 return CompareTableOrStructDefine(bothSchema, {selfStructObj, otherStructObj}, false, compared);
956 }
957 #else // OMIT_FLATBUFFER
IsFlatBufferSchema(const std::string & inOriginal,std::string & outDecoded)958 bool SchemaObject::FlatBufferSchema::IsFlatBufferSchema(const std::string &inOriginal, std::string &outDecoded)
959 {
960 (void)inOriginal;
961 (void)outDecoded;
962 LOGW("FlatBuffer Omit From Compile.");
963 return false;
964 }
965
ParseFlatBufferSchema(const std::string & inDecoded)966 int SchemaObject::FlatBufferSchema::ParseFlatBufferSchema(const std::string &inDecoded)
967 {
968 (void)inDecoded;
969 owner_.schemaType_ = SchemaType::FLATBUFFER; // For fix compile warning
970 return -E_NOT_PERMIT;
971 }
972
CompareFlatBufferDefine(const FlatBufferSchema & other) const973 int SchemaObject::FlatBufferSchema::CompareFlatBufferDefine(const FlatBufferSchema &other) const
974 {
975 (void)other;
976 return -E_NOT_PERMIT;
977 }
978
VerifyFlatBufferValue(const RawValue & inValue,bool tryNoSizePrefix) const979 int SchemaObject::FlatBufferSchema::VerifyFlatBufferValue(const RawValue &inValue, bool tryNoSizePrefix) const
980 {
981 (void)inValue;
982 (void)tryNoSizePrefix;
983 return -E_NOT_PERMIT;
984 }
985
ExtractFlatBufferValue(RawString inPath,const RawValue & inValue,TypeValue & outExtract,bool tryNoSizePrefix) const986 int SchemaObject::FlatBufferSchema::ExtractFlatBufferValue(RawString inPath, const RawValue &inValue,
987 TypeValue &outExtract, bool tryNoSizePrefix) const
988 {
989 (void)inPath;
990 (void)inValue;
991 (void)outExtract;
992 (void)tryNoSizePrefix;
993 return -E_NOT_PERMIT;
994 }
995 #endif // OMIT_FLATBUFFER
996 } // namespace DistributedDB
997