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 {
244 struct BaseTypeNode {
245 reflection::BaseType type;
246 FieldType fieldType;
247 };
248
MapFieldType(reflection::BaseType inType)249 FieldType MapFieldType(reflection::BaseType inType)
250 {
251 static const BaseTypeNode baseTypeNodes[] = {
252 {reflection::BaseType::Bool, FieldType::LEAF_FIELD_BOOL},
253 {reflection::BaseType::Byte, FieldType::LEAF_FIELD_INTEGER},
254 {reflection::BaseType::UByte, FieldType::LEAF_FIELD_INTEGER},
255 {reflection::BaseType::Short, FieldType::LEAF_FIELD_INTEGER},
256 {reflection::BaseType::UShort, FieldType::LEAF_FIELD_INTEGER},
257 {reflection::BaseType::Int, FieldType::LEAF_FIELD_INTEGER},
258 {reflection::BaseType::UInt, FieldType::LEAF_FIELD_LONG},
259 {reflection::BaseType::Long, FieldType::LEAF_FIELD_LONG},
260 {reflection::BaseType::ULong, FieldType::LEAF_FIELD_DOUBLE},
261 {reflection::BaseType::Float, FieldType::LEAF_FIELD_DOUBLE},
262 {reflection::BaseType::Double, FieldType::LEAF_FIELD_DOUBLE},
263 {reflection::BaseType::String, FieldType::LEAF_FIELD_STRING},
264 {reflection::BaseType::Vector, FieldType::LEAF_FIELD_ARRAY},
265 {reflection::BaseType::Obj, FieldType::INTERNAL_FIELD_OBJECT}
266 };
267 const auto &result = std::find_if(std::begin(baseTypeNodes), std::end(baseTypeNodes), [inType](const auto &node) {
268 return node.type == inType;
269 });
270 return result == std::end(baseTypeNodes) ? FieldType::LEAF_FIELD_NULL : (*result).fieldType;
271 }
272
CheckDollarDotAndSkipIt(RawString inPath)273 RawString CheckDollarDotAndSkipIt(RawString inPath)
274 {
275 if (inPath == nullptr) {
276 return nullptr;
277 }
278 auto pathStr = inPath;
279 if (*pathStr++ != '$') {
280 return nullptr;
281 }
282 if (*pathStr++ != '.') {
283 return nullptr;
284 }
285 if (*pathStr == 0) {
286 return nullptr;
287 }
288 return pathStr;
289 }
290
GetFieldInfoFromSchemaByPath(const reflection::Schema & schema,RawString pathStr)291 const reflection::Field *GetFieldInfoFromSchemaByPath(const reflection::Schema &schema, RawString pathStr)
292 {
293 auto rootTable = schema.root_table();
294 if (rootTable == nullptr) { // Unlikely
295 return nullptr;
296 }
297 auto rootFields = rootTable->fields();
298 if (rootFields == nullptr) { // Unlikely
299 return nullptr;
300 }
301 // Unlikely to return nullptr, except internal-error happened
302 return rootFields->LookupByKey(pathStr);
303 }
304
DoVerifyBeforeExtract(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo,const flatbuffers::Verifier & verifier)305 int DoVerifyBeforeExtract(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo,
306 const flatbuffers::Verifier &verifier)
307 {
308 auto type = fieldInfo.type();
309 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
310 bool verifyResult = true;
311 switch (type->base_type()) {
312 case reflection::Bool:
313 case reflection::Byte:
314 case reflection::UByte:
315 verifyResult = rootValue.VerifyField<int8_t>(verifier, fieldInfo.offset());
316 break;
317 case reflection::Short:
318 case reflection::UShort:
319 verifyResult = rootValue.VerifyField<int16_t>(verifier, fieldInfo.offset());
320 break;
321 case reflection::Int:
322 case reflection::UInt:
323 verifyResult = rootValue.VerifyField<int32_t>(verifier, fieldInfo.offset());
324 break;
325 case reflection::Long:
326 case reflection::ULong:
327 verifyResult = rootValue.VerifyField<uint64_t>(verifier, fieldInfo.offset());
328 break;
329 case reflection::Float:
330 verifyResult = rootValue.VerifyField<float>(verifier, fieldInfo.offset());
331 break;
332 case reflection::Double:
333 verifyResult = rootValue.VerifyField<double>(verifier, fieldInfo.offset());
334 break;
335 case reflection::String:
336 verifyResult = rootValue.VerifyField<flatbuffers::uoffset_t>(verifier, fieldInfo.offset()) &&
337 verifier.VerifyString(flatbuffers::GetFieldS(rootValue, fieldInfo)); // VerifyString can accept null
338 break;
339 default:
340 return -E_NOT_SUPPORT;
341 }
342 return (verifyResult ? E_OK : -E_FLATBUFFER_VERIFY_FAIL);
343 }
344
DoExtractString(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo)345 inline std::string DoExtractString(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo)
346 {
347 auto strVal = flatbuffers::GetFieldS(rootValue, fieldInfo);
348 if (strVal == nullptr) {
349 return "";
350 }
351 return strVal->str();
352 }
353
DoExtractValue(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo,TypeValue & outExtract)354 int DoExtractValue(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo, TypeValue &outExtract)
355 {
356 auto type = fieldInfo.type();
357 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
358 switch (type->base_type()) {
359 case reflection::Bool:
360 outExtract.second.boolValue = (flatbuffers::GetFieldI<int8_t>(rootValue, fieldInfo) != 0);
361 break;
362 case reflection::Byte:
363 outExtract.second.integerValue = flatbuffers::GetFieldI<int8_t>(rootValue, fieldInfo);
364 break;
365 case reflection::UByte:
366 outExtract.second.integerValue = flatbuffers::GetFieldI<uint8_t>(rootValue, fieldInfo);
367 break;
368 case reflection::Short:
369 outExtract.second.integerValue = flatbuffers::GetFieldI<int16_t>(rootValue, fieldInfo);
370 break;
371 case reflection::UShort:
372 outExtract.second.integerValue = flatbuffers::GetFieldI<uint16_t>(rootValue, fieldInfo);
373 break;
374 case reflection::Int:
375 outExtract.second.integerValue = flatbuffers::GetFieldI<int32_t>(rootValue, fieldInfo);
376 break;
377 case reflection::UInt:
378 outExtract.second.longValue = flatbuffers::GetFieldI<uint32_t>(rootValue, fieldInfo);
379 break;
380 case reflection::Long:
381 outExtract.second.longValue = flatbuffers::GetFieldI<int64_t>(rootValue, fieldInfo);
382 break;
383 case reflection::ULong:
384 outExtract.second.doubleValue = flatbuffers::GetFieldI<uint64_t>(rootValue, fieldInfo);
385 break;
386 case reflection::Float:
387 outExtract.second.doubleValue = flatbuffers::GetFieldF<float>(rootValue, fieldInfo);
388 break;
389 case reflection::Double:
390 outExtract.second.doubleValue = flatbuffers::GetFieldF<double>(rootValue, fieldInfo);
391 break;
392 case reflection::String:
393 outExtract.second.stringValue = DoExtractString(rootValue, fieldInfo);
394 break;
395 default:
396 return -E_NOT_SUPPORT;
397 }
398 return E_OK;
399 }
400
ExtractFlatBufferValueFinal(const flatbuffers::Table & rootValue,const reflection::Field & fieldInfo,const flatbuffers::Verifier & verifier,TypeValue & outExtract)401 int ExtractFlatBufferValueFinal(const flatbuffers::Table &rootValue, const reflection::Field &fieldInfo,
402 const flatbuffers::Verifier &verifier, TypeValue &outExtract)
403 {
404 auto type = fieldInfo.type();
405 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
406 auto baseType = type->base_type();
407 if (!IsIndexableType(baseType)) {
408 LOGE("[ExtractFinal] BaseType=%s not indexable.", reflection::EnumNameBaseType(baseType));
409 return -E_NOT_SUPPORT;
410 }
411 outExtract.first = MapFieldType(type->base_type());
412 int errCode = DoVerifyBeforeExtract(rootValue, fieldInfo, verifier);
413 if (errCode != E_OK) {
414 LOGE("[ExtractFinal] DoVerify fail, errCode=%d.", errCode);
415 return errCode;
416 }
417 errCode = DoExtractValue(rootValue, fieldInfo, outExtract);
418 if (errCode != E_OK) {
419 LOGE("[ExtractFinal] DoExtract fail, errCode=%d.", errCode);
420 return errCode;
421 }
422 return E_OK;
423 }
424 }
425
ExtractFlatBufferValue(RawString inPath,const RawValue & inValue,TypeValue & outExtract,bool tryNoSizePrefix) const426 int SchemaObject::FlatBufferSchema::ExtractFlatBufferValue(RawString inPath, const RawValue &inValue,
427 TypeValue &outExtract, bool tryNoSizePrefix) const
428 {
429 // NOTE!!! This function is performance sensitive !!! Carefully not to allocate memory often!!!
430 (void)tryNoSizePrefix; // Use it in the future, currently we demand value is sizePrefixed
431 int errCode = CheckSizePrefixRawValue(inValue);
432 if (errCode != E_OK) {
433 return errCode;
434 }
435 auto pathStr = CheckDollarDotAndSkipIt(inPath);
436 if (pathStr == nullptr) { // Unlikely
437 LOGE("[FBSchema][Extract] inPath not begin with $. or nothing after it.");
438 return -E_INVALID_ARGS;
439 }
440 auto schema = GetSchema();
441 CHECK_NULL_UNLIKELY_RETURN_ERROR(schema);
442 // Currently we don't support nest-path
443 auto fieldInfo = GetFieldInfoFromSchemaByPath(*schema, pathStr);
444 if (fieldInfo == nullptr) {
445 LOGW("[FBSchema][Extract] FieldInfo of path not found.");
446 return -E_INTERNAL_ERROR;
447 }
448 // Begin extract, we have to minimal verify if we don't trust value from database
449 auto valueRealBegin = inValue.first + SIZE_PREFIX_SIZE;
450 auto valueRealSize = inValue.second - SIZE_PREFIX_SIZE;
451 flatbuffers::Verifier verifier(valueRealBegin, valueRealSize);
452 auto offset = verifier.VerifyOffset(0); // Attention: Verify root offset before we call GetAnyRoot
453 if (offset == 0) {
454 LOGE("[FBSchema][Extract] Verity root offset failed.");
455 return -E_FLATBUFFER_VERIFY_FAIL;
456 }
457 auto rootValue = flatbuffers::GetAnyRoot(valueRealBegin);
458 if (rootValue == nullptr) {
459 LOGE("[FBSchema][Extract] Get rootTable from value fail.");
460 return -E_INVALID_DATA;
461 }
462 // Verity vTable of rootTable before we extract anything from rootValue by reflection
463 bool vTableOk = rootValue->VerifyTableStart(verifier);
464 if (!vTableOk) {
465 LOGE("[FBSchema][Extract] Verify vTable of rootTable of value fail.");
466 return -E_FLATBUFFER_VERIFY_FAIL;
467 }
468 errCode = ExtractFlatBufferValueFinal(*rootValue, *fieldInfo, verifier, outExtract);
469 if (errCode != E_OK) {
470 return errCode;
471 }
472 verifier.EndTable();
473 return E_OK;
474 }
475
GetSchema() const476 const reflection::Schema *SchemaObject::FlatBufferSchema::GetSchema() const
477 {
478 // This function is called after schemaString_ had been verified by flatbuffer
479 return reflection::GetSizePrefixedSchema(owner_.schemaString_.c_str());
480 }
481
ParseCheckRootTableAttribute(const reflection::Object & rootTable)482 int SchemaObject::FlatBufferSchema::ParseCheckRootTableAttribute(const reflection::Object &rootTable)
483 {
484 auto rootTableAttr = rootTable.attributes();
485 if (rootTableAttr == nullptr) {
486 LOGE("[FBSchema][ParseRootAttr] Root table no attribute.");
487 return -E_SCHEMA_PARSE_FAIL;
488 }
489
490 auto versionAttr = rootTableAttr->LookupByKey(SchemaConstant::KEYWORD_SCHEMA_VERSION.c_str());
491 if (!AttributeExistAndHasValue(versionAttr)) {
492 LOGE("[FBSchema][ParseRootAttr] No SCHEMA_VERSION attribute or no value.");
493 return -E_SCHEMA_PARSE_FAIL;
494 }
495 if (SchemaUtils::Strip(versionAttr->value()->str()) != SchemaConstant::SCHEMA_SUPPORT_VERSION) {
496 LOGE("[FBSchema][ParseRootAttr] Unexpect SCHEMA_VERSION=%s.", versionAttr->value()->c_str());
497 return -E_SCHEMA_PARSE_FAIL;
498 }
499 owner_.schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION;
500 description_ += (SchemaConstant::KEYWORD_SCHEMA_VERSION + "=" + SchemaConstant::SCHEMA_SUPPORT_VERSION + ";");
501
502 auto skipsizeAttr = rootTableAttr->LookupByKey(SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE.c_str());
503 if (!AttributeExistAndHasValue(skipsizeAttr)) {
504 LOGI("[FBSchema][ParseRootAttr] No SCHEMA_SKIPSIZE attribute or no value.");
505 owner_.schemaSkipSize_ = 0; // Default skipsize value
506 return E_OK;
507 }
508 std::string skipsizeStr = SchemaUtils::Strip(skipsizeAttr->value()->str());
509 int skipsizeInt = strtol(skipsizeStr.c_str(), nullptr, 10); // 10: decimal
510 if (std::to_string(skipsizeInt) != skipsizeStr || skipsizeInt < 0 ||
511 static_cast<uint32_t>(skipsizeInt) > SchemaConstant::SCHEMA_SKIPSIZE_MAX) {
512 LOGE("[FBSchema][ParseRootAttr] Unexpect SCHEMA_SKIPSIZE value=%s.", skipsizeAttr->value()->c_str());
513 return -E_SCHEMA_PARSE_FAIL;
514 }
515 owner_.schemaSkipSize_ = static_cast<uint32_t>(skipsizeInt);
516 description_ += (SchemaConstant::KEYWORD_SCHEMA_SKIPSIZE + "=" + skipsizeStr + ";");
517 return E_OK;
518 }
519
ParseCheckRootTableDefine(const reflection::Schema & schema,const reflection::Object & rootTable,RawIndexInfos & indexCollect)520 int SchemaObject::FlatBufferSchema::ParseCheckRootTableDefine(const reflection::Schema &schema,
521 const reflection::Object &rootTable, RawIndexInfos &indexCollect)
522 {
523 // Clear schemaDefine_ to recover from a fail parse
524 owner_.schemaDefine_.clear();
525 auto fields = rootTable.fields();
526 if (fields == nullptr || fields->size() == 0) {
527 LOGE("[FBSchema][ParseRootDefine] Empty define.");
528 return -E_SCHEMA_PARSE_FAIL;
529 }
530 for (uint32_t i = 0; i < fields->size(); i++) {
531 auto eachField = (*fields)[i];
532 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachField);
533
534 auto name = eachField->name();
535 CHECK_NULL_UNLIKELY_RETURN_ERROR(name);
536 int errCode = SchemaUtils::CheckFieldName(name->str());
537 if (errCode != E_OK) {
538 LOGE("[FBSchema][ParseRootDefine] Invalid fieldName, errCode=%d.", errCode);
539 return -E_SCHEMA_PARSE_FAIL;
540 }
541 FieldPath path{name->str()};
542 if (owner_.schemaDefine_[ROOT_DEFINE_DEPTH].count(path) != 0) { // Unlikely
543 LOGE("[FBSchema][ParseRootDefine] FieldPath already exist at root.");
544 return -E_SCHEMA_PARSE_FAIL;
545 }
546
547 errCode = ParseCheckFieldInfo(schema, *eachField, path, indexCollect);
548 if (errCode != E_OK) {
549 LOGE("[FBSchema][ParseRootDefine] ParseFieldInfo errCode=%d", errCode);
550 return errCode;
551 }
552 }
553 uint32_t fieldPathCount = 0;
554 for (uint32_t depth = ROOT_DEFINE_DEPTH; depth < SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX; depth++) {
555 if (owner_.schemaDefine_.count(depth) != 0) {
556 fieldPathCount += owner_.schemaDefine_[depth].size();
557 }
558 }
559 if (fieldPathCount > SchemaConstant::SCHEMA_FEILD_NAME_COUNT_MAX) {
560 LOGE("[FBSchema][ParseRootDefine] FieldPath count=%" PRIu32 " exceed the limitation.", fieldPathCount);
561 return -E_SCHEMA_PARSE_FAIL;
562 }
563 return E_OK;
564 }
565
566 namespace {
CheckFieldTypeSupport(const reflection::Type & inType,bool isRootField)567 bool CheckFieldTypeSupport(const reflection::Type &inType, bool isRootField)
568 {
569 auto baseType = inType.base_type();
570 if (isRootField) {
571 if (!IsSupportTypeAtRoot(baseType)) {
572 LOGE("[FBSchema][DecideType] BaseType=%s not support at root.", reflection::EnumNameBaseType(baseType));
573 return false;
574 }
575 if (IsIntegerType(baseType) && (inType.index() != INDEX_OF_NOT_ENUM)) {
576 LOGE("[FBSchema][DecideType] BaseType=%s is enum, not support.", reflection::EnumNameBaseType(baseType));
577 return false;
578 }
579 if (IsVectorType(baseType)) {
580 auto elementType = inType.element();
581 if (!IsIndexableType(elementType)) {
582 LOGE("[FBSchema][DecideType] ElementType=%s not support for vector.",
583 reflection::EnumNameBaseType(elementType));
584 return false;
585 }
586 }
587 } else {
588 // Currently only support nest in Struct, support only scalar and nest-struct
589 if (!IsScalarType(baseType) && !IsObjectType(baseType)) {
590 LOGE("[FBSchema][DecideType] BaseType=%s not support for struct.", reflection::EnumNameBaseType(baseType));
591 return false;
592 }
593 }
594 return true;
595 }
596 }
597
ParseCheckFieldInfo(const reflection::Schema & schema,const reflection::Field & field,const FieldPath & path,RawIndexInfos & indexCollect)598 int SchemaObject::FlatBufferSchema::ParseCheckFieldInfo(const reflection::Schema &schema,
599 const reflection::Field &field, const FieldPath &path, RawIndexInfos &indexCollect)
600 {
601 if (path.empty() || path.size() > SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) {
602 LOGE("[FBSchema][ParseField] FieldPath size=%zu invalid.", path.size());
603 return -E_SCHEMA_PARSE_FAIL;
604 }
605 uint32_t depth = path.size() - 1; // Depth count from zero
606 bool isRootField = (depth == ROOT_DEFINE_DEPTH);
607 SchemaAttribute &fieldInfo = owner_.schemaDefine_[depth][path]; // Create new entry in schemaDefine_
608
609 auto type = field.type();
610 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
611 if (!CheckFieldTypeSupport(*type, isRootField)) {
612 return -E_SCHEMA_PARSE_FAIL;
613 }
614 auto baseType = type->base_type();
615 // Only type and isIndexable of SchemaAttribute is necessary
616 fieldInfo.type = MapFieldType(baseType);
617 fieldInfo.isIndexable = (IsIndexableType(baseType) && isRootField);
618 description_ += (SchemaUtils::FieldPathString(path) + "=" + reflection::EnumNameBaseType(baseType) + ";");
619
620 if (IsRequiredSupportType(baseType)) {
621 if (IsConflict(field.deprecated(), field.required())) {
622 LOGE("[FBSchema][ParseField] Deprecated conflict with required.");
623 return -E_SCHEMA_PARSE_FAIL;
624 }
625 }
626 if (fieldInfo.isIndexable) {
627 CollectRawIndexInfos(field, indexCollect);
628 }
629 if (IsObjectType(baseType)) {
630 int errCode = ParseCheckStructDefine(schema, field, path);
631 if (errCode != E_OK) {
632 return errCode;
633 }
634 }
635 return E_OK;
636 }
637
CollectRawIndexInfos(const reflection::Field & field,RawIndexInfos & indexCollect) const638 void SchemaObject::FlatBufferSchema::CollectRawIndexInfos(const reflection::Field &field,
639 RawIndexInfos &indexCollect) const
640 {
641 auto name = field.name();
642 if (name == nullptr) { // Not possible
643 return;
644 }
645 auto fieldAttr = field.attributes();
646 if (fieldAttr == nullptr) {
647 return;
648 }
649 auto indexAttr = fieldAttr->LookupByKey(SchemaConstant::KEYWORD_INDEX.c_str());
650 if (indexAttr == nullptr) {
651 return;
652 }
653 if (indexAttr->value() == nullptr) {
654 indexCollect[name->str()] = ""; // Must be SingleField-Index
655 return;
656 }
657 indexCollect[name->str()] = indexAttr->value()->str(); // May still be empty string
658 }
659
ParseCheckStructDefine(const reflection::Schema & schema,const reflection::Field & field,const FieldPath & path)660 int SchemaObject::FlatBufferSchema::ParseCheckStructDefine(const reflection::Schema &schema,
661 const reflection::Field &field, const FieldPath &path)
662 {
663 if (path.size() >= SchemaConstant::SCHEMA_FEILD_PATH_DEPTH_MAX) {
664 LOGE("[FBSchema][ParseStruct] Struct define at depth limitation.");
665 return -E_SCHEMA_PARSE_FAIL;
666 }
667 auto objects = schema.objects();
668 CHECK_NULL_UNLIKELY_RETURN_ERROR(objects);
669 auto type = field.type();
670 CHECK_NULL_UNLIKELY_RETURN_ERROR(type);
671 auto objIndex = type->index();
672 if (objIndex < 0 || static_cast<uint32_t>(objIndex) >= objects->size()) { // Unlikely
673 return -E_INTERNAL_ERROR;
674 }
675 auto structObj = (*objects)[objIndex];
676 CHECK_NULL_UNLIKELY_RETURN_ERROR(structObj);
677 auto structName = structObj->name();
678 CHECK_NULL_UNLIKELY_RETURN_ERROR(structName);
679 if (!structObj->is_struct()) {
680 LOGE("[FBSchema][ParseStruct] Nest table=%s not support.", structName->c_str());
681 return -E_SCHEMA_PARSE_FAIL;
682 }
683 description_ += ("StructName=" + SchemaUtils::StripNameSpace(structName->str()) + ";");
684
685 // Parse fields
686 auto structFields = structObj->fields();
687 CHECK_NULL_UNLIKELY_RETURN_ERROR(structFields);
688 // Flatbuffer guarantee that struct will not be empty size, even if it is empty, we just ignore it
689 for (uint32_t i = 0; i < structFields->size(); i++) {
690 auto eachField = (*structFields)[i];
691 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachField);
692 auto eachName = eachField->name();
693 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachName);
694 int errCode = SchemaUtils::CheckFieldName(eachName->str());
695 if (errCode != E_OK) {
696 LOGE("[FBSchema][ParseStruct] Invalid fieldName, errCode=%d.", errCode);
697 return -E_SCHEMA_PARSE_FAIL;
698 }
699 FieldPath eachPath = path;
700 eachPath.push_back(eachName->str());
701 RawIndexInfos notUsed;
702 errCode = ParseCheckFieldInfo(schema, *eachField, eachPath, notUsed);
703 if (errCode != E_OK) {
704 LOGE("[FBSchema][ParseStruct] ParseFieldInfo errCode=%d.", errCode);
705 return errCode;
706 }
707 }
708 return E_OK;
709 }
710
711 namespace {
IsNotCompositeIndex(const std::string & indexStr)712 inline bool IsNotCompositeIndex(const std::string &indexStr)
713 {
714 // In fact, test found that attrValue will be "0" if not exist
715 return indexStr.empty() || indexStr == std::string("0");
716 }
717 }
718
ParseCheckIndexes(const RawIndexInfos & indexCollect)719 int SchemaObject::FlatBufferSchema::ParseCheckIndexes(const RawIndexInfos &indexCollect)
720 {
721 for (const auto &entry : indexCollect) {
722 std::vector<std::string> indexStrArray{entry.first}; // Entry.first is fieldName at root that was checked valid
723 const std::string &rawIndexStr = entry.second;
724 if (IsNotCompositeIndex(rawIndexStr)) {
725 int errCode = owner_.ParseCheckEachIndexFromStringArray(indexStrArray);
726 if (errCode != E_OK) {
727 LOGE("[FBSchema][ParseIndex] Create single-index fail:%d.", errCode);
728 return errCode;
729 }
730 description_ += ("INDEX=" + entry.first + ";");
731 continue;
732 }
733 // Parse other indexField
734 for (uint32_t curPos = 0; curPos < rawIndexStr.size();) {
735 uint32_t nextCommaPos = rawIndexStr.find_first_of(',', curPos);
736 std::string eachIndexField = rawIndexStr.substr(curPos, nextCommaPos - curPos);
737 eachIndexField = SchemaUtils::Strip(eachIndexField);
738 if (!eachIndexField.empty()) { // Continuous ',' just ignore
739 indexStrArray.push_back(eachIndexField);
740 }
741 if (nextCommaPos >= rawIndexStr.size()) { // No ',' anymore
742 break;
743 }
744 curPos = nextCommaPos + 1;
745 }
746 int errCode = owner_.ParseCheckEachIndexFromStringArray(indexStrArray);
747 if (errCode != E_OK) {
748 LOGE("[FBSchema][ParseIndex] Create composite-index fail:%d.", errCode);
749 return errCode;
750 }
751 description_ += ("INDEX=" + entry.first + ";");
752 }
753 if (owner_.schemaIndexes_.size() > SchemaConstant::SCHEMA_INDEX_COUNT_MAX) {
754 LOGE("[FBSchema][ParseIndex] Index count=%zu exceed limitation.", owner_.schemaIndexes_.size());
755 return -E_SCHEMA_PARSE_FAIL;
756 }
757 return E_OK;
758 }
759
760 namespace {
IsNotEqualNotCompatible(int errCode)761 inline bool IsNotEqualNotCompatible(int errCode)
762 {
763 return (errCode != -E_SCHEMA_EQUAL_EXACTLY) && (errCode != -E_SCHEMA_UNEQUAL_COMPATIBLE) &&
764 (errCode != -E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE);
765 }
766
CompareFieldCount(bool isRoot,uint32_t selfCount,uint32_t otherCount)767 int CompareFieldCount(bool isRoot, uint32_t selfCount, uint32_t otherCount)
768 {
769 if (isRoot) {
770 if (otherCount < selfCount) {
771 LOGW("[FBSchema][CompareRoot] RootFieldSize: %" PRIu32 " vs %" PRIu32, selfCount, otherCount);
772 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
773 }
774 } else {
775 if (selfCount != otherCount) {
776 LOGW("[FBSchema][CompareRoot] StructFieldSize: %" PRIu32 " vs %" PRIu32, selfCount, otherCount);
777 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
778 }
779 }
780 return (selfCount == otherCount) ? -E_SCHEMA_EQUAL_EXACTLY : -E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE;
781 }
782
CompareFieldInfoBesideType(const reflection::Field & selfField,const reflection::Field & otherField,reflection::BaseType theType)783 int CompareFieldInfoBesideType(const reflection::Field &selfField, const reflection::Field &otherField,
784 reflection::BaseType theType)
785 {
786 // Compare offset
787 if (selfField.offset() != otherField.offset()) {
788 LOGW("[FBSchema][CompareField] Offset diff");
789 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
790 }
791 // Compare default value
792 if (selfField.default_integer() != otherField.default_integer()) {
793 LOGE("[FBSchema][CompareField] DefaultInteger diff");
794 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
795 }
796 // QUEER: for the same default_real value in fbs, flatbuffer will generate different value in binary ???
797 if (!IsDoubleNearlyEqual(selfField.default_real(), otherField.default_real())) {
798 LOGE("[FBSchema][CompareField] DefaultReal diff");
799 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
800 }
801 // Ignore deprecated, Compare required
802 if (IsRequiredSupportType(theType)) {
803 if (selfField.required() != otherField.required()) {
804 LOGE("[FBSchema][CompareField] Require diff");
805 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
806 }
807 }
808 return -E_SCHEMA_EQUAL_EXACTLY;
809 }
810
CompareFieldInfo(const reflection::Field & selfField,const reflection::Field & otherField,bool & isStruct)811 int CompareFieldInfo(const reflection::Field &selfField, const reflection::Field &otherField, bool &isStruct)
812 {
813 auto selfType = selfField.type();
814 auto otherType = otherField.type();
815 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfType);
816 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherType);
817 // Compare type
818 auto selfBaseType = selfType->base_type();
819 auto otherBaseType = otherType->base_type();
820 if (selfBaseType != otherBaseType) {
821 LOGE("[FBSchema][CompareField] BaseType diff:%s vs %s.", reflection::EnumNameBaseType(selfBaseType),
822 reflection::EnumNameBaseType(otherBaseType));
823 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
824 }
825 if (IsVectorType(selfBaseType)) {
826 auto selfElementType = selfType->element();
827 auto otherElementType = otherType->element();
828 if (selfElementType != otherElementType) {
829 LOGE("[FBSchema][CompareField] ElementType diff:%" PRIu32 " vs %" PRIu32, selfElementType,
830 otherElementType);
831 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
832 }
833 }
834 if (IsObjectType(selfBaseType)) {
835 isStruct = true;
836 }
837 return CompareFieldInfoBesideType(selfField, otherField, selfBaseType);
838 }
839
840 // Split from original functions which would be longer than 50 line
CompareExtraField(const PairConstPointer<reflection::Object> & bothObject)841 int CompareExtraField(const PairConstPointer<reflection::Object> &bothObject)
842 {
843 // This is private function, the caller guarantee that inputParameter not nullptr
844 auto selfFields = bothObject.first->fields();
845 auto otherFields = bothObject.second->fields();
846 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfFields);
847 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherFields);
848 // Each field in other not in self, should not be required
849 for (uint32_t i = 0; i < otherFields->size(); i++) {
850 auto eachOtherField = (*otherFields)[i];
851 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachOtherField);
852 auto otherName = eachOtherField->name();
853 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherName);
854 auto correspondSelfField = selfFields->LookupByKey(otherName->c_str());
855 if (correspondSelfField != nullptr) {
856 continue;
857 }
858 if (eachOtherField->required()) {
859 LOGE("[FBSchema][CompareDefine] Extra field should not be required.");
860 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
861 }
862 }
863 return -E_SCHEMA_UNEQUAL_COMPATIBLE_UPGRADE;
864 }
865 }
866
CompareTableOrStructDefine(const PairConstPointer<reflection::Schema> & bothSchema,const PairConstPointer<reflection::Object> & bothObject,bool isRoot,std::set<std::string> & compared) const867 int SchemaObject::FlatBufferSchema::CompareTableOrStructDefine(const PairConstPointer<reflection::Schema> &bothSchema,
868 const PairConstPointer<reflection::Object> &bothObject, bool isRoot, std::set<std::string> &compared) const
869 {
870 // This is private function, the caller guarantee that inputParameter not nullptr
871 auto selfFields = bothObject.first->fields();
872 auto otherFields = bothObject.second->fields();
873 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfFields);
874 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherFields);
875 int errCode = CompareFieldCount(isRoot, selfFields->size(), otherFields->size());
876 if (errCode == -E_SCHEMA_UNEQUAL_INCOMPATIBLE) {
877 return errCode;
878 }
879 // Each field in self should be in other, and they should be same
880 for (uint32_t i = 0; i < selfFields->size(); i++) {
881 auto eachSelfField = (*selfFields)[i];
882 CHECK_NULL_UNLIKELY_RETURN_ERROR(eachSelfField);
883 auto selfName = eachSelfField->name();
884 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfName);
885 auto correspondOtherField = otherFields->LookupByKey(selfName->c_str());
886 if (correspondOtherField == nullptr) {
887 LOGE("[FBSchema][CompareDefine] SelfField not found in other.");
888 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
889 }
890 bool isStruct = false;
891 errCode = CompareFieldInfo(*eachSelfField, *correspondOtherField, isStruct);
892 if (IsNotEqualNotCompatible(errCode)) {
893 LOGE("[FBSchema][CompareDefine] Compare info of field fail, errCode=%d.", errCode);
894 return errCode;
895 }
896 if (isStruct) {
897 // Previous parse guarantee that recursion will not be unlimited, don't be afraid.
898 errCode = CompareStruct(bothSchema, {eachSelfField, correspondOtherField}, compared);
899 if (IsNotEqualNotCompatible(errCode)) {
900 return errCode;
901 }
902 }
903 }
904 if (selfFields->size() == otherFields->size()) {
905 return -E_SCHEMA_EQUAL_EXACTLY;
906 }
907 return CompareExtraField(bothObject);
908 }
909
CompareStruct(const PairConstPointer<reflection::Schema> & bothSchema,const PairConstPointer<reflection::Field> & bothField,std::set<std::string> & compared) const910 int SchemaObject::FlatBufferSchema::CompareStruct(const PairConstPointer<reflection::Schema> &bothSchema,
911 const PairConstPointer<reflection::Field> &bothField, std::set<std::string> &compared) const
912 {
913 // This is private function, the caller guarantee that inputParameter not nullptr
914 auto selfObjects = bothSchema.first->objects();
915 auto otherObjects = bothSchema.second->objects();
916 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfObjects);
917 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherObjects);
918 auto selfType = bothField.first->type();
919 auto otherType = bothField.second->type();
920 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfType);
921 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherType);
922 auto selfObjIndex = selfType->index();
923 auto otherObjIndex = otherType->index();
924 if (selfObjIndex < 0 || static_cast<uint32_t>(selfObjIndex) >= selfObjects->size()) { // Unlikely
925 return -E_INTERNAL_ERROR;
926 }
927 if (otherObjIndex < 0 || static_cast<uint32_t>(otherObjIndex) >= otherObjects->size()) { // Unlikely
928 return -E_INTERNAL_ERROR;
929 }
930 auto selfStructObj = (*selfObjects)[selfObjIndex];
931 auto otherStructObj = (*otherObjects)[otherObjIndex];
932 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfStructObj);
933 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherStructObj);
934 // Previous parse can guarantee that they are both struct, no need to check again
935 auto selfStructName = selfStructObj->name();
936 auto otherStructName = otherStructObj->name();
937 CHECK_NULL_UNLIKELY_RETURN_ERROR(selfStructName);
938 CHECK_NULL_UNLIKELY_RETURN_ERROR(otherStructName);
939 std::string selfName = SchemaUtils::StripNameSpace(selfStructName->str());
940 std::string otherName = SchemaUtils::StripNameSpace(otherStructName->str());
941 if (selfName != otherName) {
942 LOGE("[FBSchema][CompareStruct] The field is not of same struct type");
943 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
944 }
945 if (compared.count(selfName) != 0) { // This struct-type had already been compared, no need to do recurse again
946 return -E_SCHEMA_EQUAL_EXACTLY;
947 }
948 compared.insert(selfName);
949 // Compare struct detail
950 if (selfStructObj->minalign() != otherStructObj->minalign()) {
951 LOGE("[FBSchema][CompareStruct] The struct minalign differ, self=%d, other=%d.",
952 selfStructObj->minalign(), otherStructObj->minalign());
953 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
954 }
955 if (selfStructObj->bytesize() != otherStructObj->bytesize()) {
956 LOGE("[FBSchema][CompareStruct] The struct bytesize differ, self=%d, other=%d.",
957 selfStructObj->bytesize(), otherStructObj->bytesize());
958 return -E_SCHEMA_UNEQUAL_INCOMPATIBLE;
959 }
960 // Previous parse guarantee that recursion will not be unlimited, don't be afraid.
961 return CompareTableOrStructDefine(bothSchema, {selfStructObj, otherStructObj}, false, compared);
962 }
963 #else // OMIT_FLATBUFFER
IsFlatBufferSchema(const std::string & inOriginal,std::string & outDecoded)964 bool SchemaObject::FlatBufferSchema::IsFlatBufferSchema(const std::string &inOriginal, std::string &outDecoded)
965 {
966 (void)inOriginal;
967 (void)outDecoded;
968 LOGW("FlatBuffer Omit From Compile.");
969 return false;
970 }
971
ParseFlatBufferSchema(const std::string & inDecoded)972 int SchemaObject::FlatBufferSchema::ParseFlatBufferSchema(const std::string &inDecoded)
973 {
974 (void)inDecoded;
975 owner_.schemaType_ = SchemaType::FLATBUFFER; // For fix compile warning
976 return -E_NOT_PERMIT;
977 }
978
CompareFlatBufferDefine(const FlatBufferSchema & other) const979 int SchemaObject::FlatBufferSchema::CompareFlatBufferDefine(const FlatBufferSchema &other) const
980 {
981 (void)other;
982 return -E_NOT_PERMIT;
983 }
984
VerifyFlatBufferValue(const RawValue & inValue,bool tryNoSizePrefix) const985 int SchemaObject::FlatBufferSchema::VerifyFlatBufferValue(const RawValue &inValue, bool tryNoSizePrefix) const
986 {
987 (void)inValue;
988 (void)tryNoSizePrefix;
989 return -E_NOT_PERMIT;
990 }
991
ExtractFlatBufferValue(RawString inPath,const RawValue & inValue,TypeValue & outExtract,bool tryNoSizePrefix) const992 int SchemaObject::FlatBufferSchema::ExtractFlatBufferValue(RawString inPath, const RawValue &inValue,
993 TypeValue &outExtract, bool tryNoSizePrefix) const
994 {
995 (void)inPath;
996 (void)inValue;
997 (void)outExtract;
998 (void)tryNoSizePrefix;
999 return -E_NOT_PERMIT;
1000 }
1001 #endif // OMIT_FLATBUFFER
1002 } // namespace DistributedDB
1003