• 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 #ifdef RELATIONAL_STORE
16 #include "relational_schema_object.h"
17 
18 #include <algorithm>
19 
20 #include "db_common.h"
21 #include "json_object.h"
22 #include "schema_constant.h"
23 #include "schema_utils.h"
24 
25 namespace DistributedDB {
IsSchemaValid() const26 bool RelationalSchemaObject::IsSchemaValid() const
27 {
28     return isValid_;
29 }
30 
GetSchemaType() const31 SchemaType RelationalSchemaObject::GetSchemaType() const
32 {
33     return schemaType_;
34 }
35 
ToSchemaString() const36 std::string RelationalSchemaObject::ToSchemaString() const
37 {
38     return schemaString_;
39 }
40 
ParseFromSchemaString(const std::string & inSchemaString)41 int RelationalSchemaObject::ParseFromSchemaString(const std::string &inSchemaString)
42 {
43     if (isValid_) {
44         return -E_NOT_PERMIT;
45     }
46 
47     if (inSchemaString.empty() || inSchemaString.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT) {
48         LOGE("[RelationalSchema][Parse] SchemaSize=%zu is invalid.", inSchemaString.size());
49         return -E_INVALID_ARGS;
50     }
51     JsonObject schemaObj;
52     int errCode = schemaObj.Parse(inSchemaString);
53     if (errCode != E_OK) {
54         LOGE("[RelationalSchema][Parse] Schema json string parse failed: %d.", errCode);
55         return errCode;
56     }
57 
58     errCode = ParseRelationalSchema(schemaObj);
59     if (errCode != E_OK) {
60         LOGE("[RelationalSchema][Parse] Parse to relational schema failed: %d.", errCode);
61         return errCode;
62     }
63 
64     schemaType_ = SchemaType::RELATIVE;
65     schemaString_ = schemaObj.ToString();
66     isValid_ = true;
67     return E_OK;
68 }
69 
GenerateSchemaString()70 void RelationalSchemaObject::GenerateSchemaString()
71 {
72     schemaString_ = {};
73     schemaString_ += "{";
74     schemaString_ += R"("SCHEMA_VERSION":")" + schemaVersion_ + R"(",)";
75     schemaString_ += R"("SCHEMA_TYPE":"RELATIVE",)";
76     if (schemaVersion_ == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1) {
77         std::string modeString = tableMode_ == DistributedTableMode::COLLABORATION ?
78             SchemaConstant::KEYWORD_TABLE_COLLABORATION : SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE;
79         schemaString_ += R"("TABLE_MODE":")" + modeString + R"(",)";
80     }
81     schemaString_ += R"("TABLES":[)";
82     for (auto it = tables_.begin(); it != tables_.end(); it++) {
83         if (it != tables_.begin()) {
84             schemaString_ += ",";
85         }
86         schemaString_ += it->second.ToTableInfoString(schemaVersion_);
87     }
88     schemaString_ += R"(])";
89     schemaString_ += GetReferencePropertyString();
90     schemaString_ += "}";
91 }
92 
AddRelationalTable(const TableInfo & table)93 void RelationalSchemaObject::AddRelationalTable(const TableInfo &table)
94 {
95     tables_[table.GetTableName()] = table;
96     isValid_ = true;
97     if (table.GetPrimaryKey().size() > 1 && table.GetTableSyncType() != CLOUD_COOPERATION) {
98         // Table with composite primary keys
99         // Composite primary keys are supported since version 2.1
100         schemaVersion_ = SchemaConstant::SCHEMA_CURRENT_VERSION;
101     }
102     GenerateSchemaString();
103 }
104 
RemoveRelationalTable(const std::string & tableName)105 void RelationalSchemaObject::RemoveRelationalTable(const std::string &tableName)
106 {
107     tables_.erase(tableName);
108     GenerateSchemaString();
109 }
110 
GetTables() const111 const TableInfoMap &RelationalSchemaObject::GetTables() const
112 {
113     return tables_;
114 }
115 
GetTableNames() const116 std::vector<std::string> RelationalSchemaObject::GetTableNames() const
117 {
118     std::vector<std::string> tableNames;
119     for (const auto &it : tables_) {
120         tableNames.emplace_back(it.first);
121     }
122     return tableNames;
123 }
124 
GetTable(const std::string & tableName) const125 TableInfo RelationalSchemaObject::GetTable(const std::string &tableName) const
126 {
127     auto it = tables_.find(tableName);
128     if (it != tables_.end()) {
129         return it->second;
130     }
131     return {};
132 }
133 
GetSchemaVersion() const134 std::string RelationalSchemaObject::GetSchemaVersion() const
135 {
136     return schemaVersion_;
137 }
138 
GetTableMode() const139 DistributedTableMode RelationalSchemaObject::GetTableMode() const
140 {
141     return tableMode_;
142 }
143 
SetTableMode(DistributedTableMode mode)144 void RelationalSchemaObject::SetTableMode(DistributedTableMode mode)
145 {
146     tableMode_ = mode;
147     if (tableMode_ == DistributedTableMode::COLLABORATION) {
148         schemaVersion_ = SchemaConstant::SCHEMA_CURRENT_VERSION;
149     }
150     GenerateSchemaString();
151 }
152 
InsertTrackerSchema(const TrackerSchema & schema)153 void RelationalSchemaObject::InsertTrackerSchema(const TrackerSchema &schema)
154 {
155     TrackerTable table;
156     table.Init(schema);
157     trackerTables_[schema.tableName].SetTrackerTable(table);
158     GenerateTrackerSchemaString();
159 }
160 
RemoveTrackerSchema(const TrackerSchema & schema)161 void RelationalSchemaObject::RemoveTrackerSchema(const TrackerSchema &schema)
162 {
163     trackerTables_.erase(schema.tableName);
164     GenerateTrackerSchemaString();
165 }
166 
GenerateTrackerSchemaString()167 void RelationalSchemaObject::GenerateTrackerSchemaString()
168 {
169     schemaString_ = {};
170     schemaString_ += "{";
171     schemaString_ += R"("SCHEMA_TYPE":"TRACKER",)";
172     schemaString_ += R"("TABLES":[)";
173     for (auto it = trackerTables_.begin(); it != trackerTables_.end(); it++) {
174         if (it != trackerTables_.begin()) {
175             schemaString_ += ",";
176         }
177         schemaString_ += it->second.GetTrackerTable().ToString();
178     }
179     schemaString_ += R"(])";
180     schemaString_ += "}";
181 }
182 
GetReferencePropertyString()183 std::string RelationalSchemaObject::GetReferencePropertyString()
184 {
185     std::string res;
186     if (!referenceProperty_.empty()) {
187         res += R"(,"REFERENCE_PROPERTY":[)";
188         for (const auto &reference : referenceProperty_) {
189             res += GetOneReferenceString(reference) + ",";
190         }
191         res.pop_back();
192         res += R"(])";
193     }
194     return res;
195 }
196 
GetOneReferenceString(const TableReferenceProperty & reference)197 std::string RelationalSchemaObject::GetOneReferenceString(const TableReferenceProperty &reference)
198 {
199     std::string res = R"({"SOURCE_TABLE_NAME":")";
200     res += reference.sourceTableName;
201     res += R"(","TARGET_TABLE_NAME":")";
202     res += reference.targetTableName;
203     res += R"(","COLUMNS":[)";
204     for (const auto &item : reference.columns) {
205         res += R"({"SOURCE_COL":")";
206         res += item.first;
207         res += R"(","TARGET_COL":")";
208         res += item.second;
209         res += R"("},)";
210     }
211     res.pop_back();
212     res += R"(]})";
213     return res;
214 }
215 
ColumnsCompare(const std::map<std::string,std::string> & left,const std::map<std::string,std::string> & right)216 static bool ColumnsCompare(const std::map<std::string, std::string> &left,
217     const std::map<std::string, std::string> &right)
218 {
219     if (left.size() != right.size()) {
220         LOGE("[ColumnsCompare] column size not equal");
221         return false;
222     }
223     std::map<std::string, std::string>::const_iterator leftIt = left.begin();
224     std::map<std::string, std::string>::const_iterator rightIt = right.begin();
225     for (; leftIt != left.end() && rightIt != right.end(); leftIt++, rightIt++) {
226         if (strcasecmp(leftIt->first.c_str(), rightIt->first.c_str()) != 0 ||
227             strcasecmp(leftIt->second.c_str(), rightIt->second.c_str()) != 0) {
228             LOGE("[ColumnsCompare] column not equal");
229             return false;
230         }
231     }
232     return true;
233 }
234 
ReferenceCompare(const TableReferenceProperty & left,const TableReferenceProperty & right)235 static bool ReferenceCompare(const TableReferenceProperty &left, const TableReferenceProperty &right)
236 {
237     if (strcasecmp(left.sourceTableName.c_str(), right.sourceTableName.c_str()) == 0 &&
238         strcasecmp(left.targetTableName.c_str(), right.targetTableName.c_str()) == 0 &&
239         ColumnsCompare(left.columns, right.columns)) {
240         return true;
241     }
242     return false;
243 }
244 
PropertyCompare(const std::vector<TableReferenceProperty> & left,const std::vector<TableReferenceProperty> & right,std::set<std::string> & changeTables)245 static void PropertyCompare(const std::vector<TableReferenceProperty> &left,
246     const std::vector<TableReferenceProperty> &right, std::set<std::string> &changeTables)
247 {
248     for (const auto &reference : left) {
249         bool found = false;
250         for (const auto &otherRef : right) {
251             if (ReferenceCompare(reference, otherRef)) {
252                 found = true;
253                 break;
254             }
255         }
256         if (!found) {
257             changeTables.insert(reference.sourceTableName);
258             changeTables.insert(reference.targetTableName);
259         }
260     }
261 }
262 
GetSharedTableForChangeTable(std::set<std::string> & changeTables) const263 std::set<std::string> RelationalSchemaObject::GetSharedTableForChangeTable(std::set<std::string> &changeTables) const
264 {
265     std::set<std::string> res;
266     TableInfoMap tableInfos = GetTables();
267     for (const auto &changeName : changeTables) {
268         for (const auto &item : tableInfos) {
269             if (item.second.GetSharedTableMark() &&
270                 (strcasecmp(item.second.GetOriginTableName().c_str(), changeName.c_str()) == 0)) {
271                 res.insert(item.second.GetTableName()); // get shared table name
272             }
273         }
274     }
275     return res;
276 }
277 
CompareReferenceProperty(const std::vector<TableReferenceProperty> & others) const278 std::set<std::string> RelationalSchemaObject::CompareReferenceProperty(
279     const std::vector<TableReferenceProperty> &others) const
280 {
281     std::set<std::string> changeTables;
282     PropertyCompare(referenceProperty_, others, changeTables);
283     PropertyCompare(others, referenceProperty_, changeTables);
284     if (!changeTables.empty()) { // get shared tables
285         std::set<std::string> sharedTables = GetSharedTableForChangeTable(changeTables);
286         changeTables.insert(sharedTables.begin(), sharedTables.end());
287     }
288     LOGI("[CompareReferenceProperty] changeTables size = %zu", changeTables.size());
289     return changeTables;
290 }
291 
GetReachableRef()292 std::map<std::string, std::map<std::string, bool>> RelationalSchemaObject::GetReachableRef()
293 {
294     return reachableReference_;
295 }
296 
GetTableWeight()297 std::map<std::string, int> RelationalSchemaObject::GetTableWeight()
298 {
299     return tableWeight_;
300 }
301 
GetTrackerTable(const std::string & tableName) const302 TrackerTable RelationalSchemaObject::GetTrackerTable(const std::string &tableName) const
303 {
304     auto it = trackerTables_.find(tableName);
305     if (it != trackerTables_.end()) {
306         return it->second.GetTrackerTable();
307     }
308     return {};
309 }
310 
ParseFromTrackerSchemaString(const std::string & inSchemaString)311 int RelationalSchemaObject::ParseFromTrackerSchemaString(const std::string &inSchemaString)
312 {
313     JsonObject schemaObj;
314     int errCode = schemaObj.Parse(inSchemaString);
315     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
316         LOGE("[RelationalSchema][Parse] Schema json string parse failed: %d.", errCode);
317         return errCode;
318     }
319 
320     errCode = ParseTrackerSchema(schemaObj);
321     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
322         LOGE("[RelationalSchema][Parse] Parse to tracker schema failed: %d.", errCode);
323         return errCode;
324     }
325 
326     schemaString_ = schemaObj.ToString();
327     return E_OK;
328 }
329 
GetTrackerTables() const330 const TableInfoMap &RelationalSchemaObject::GetTrackerTables() const
331 {
332     return trackerTables_;
333 }
334 
SetReferenceProperty(const std::vector<TableReferenceProperty> & referenceProperty)335 void RelationalSchemaObject::SetReferenceProperty(const std::vector<TableReferenceProperty> &referenceProperty)
336 {
337     referenceProperty_ = referenceProperty;
338     GenerateSchemaString();
339     GenerateReachableRef();
340     GenerateTableInfoReferenced();
341 }
342 
GetReferenceProperty() const343 const std::vector<TableReferenceProperty> &RelationalSchemaObject::GetReferenceProperty() const
344 {
345     return referenceProperty_;
346 }
347 
CompareAgainstSchemaObject(const std::string & inSchemaString,std::map<std::string,int> & cmpRst) const348 int RelationalSchemaObject::CompareAgainstSchemaObject(const std::string &inSchemaString,
349     std::map<std::string, int> &cmpRst) const
350 {
351     return E_OK;
352 }
353 
CompareAgainstSchemaObject(const RelationalSchemaObject & inSchemaObject,std::map<std::string,int> & cmpRst) const354 int RelationalSchemaObject::CompareAgainstSchemaObject(const RelationalSchemaObject &inSchemaObject,
355     std::map<std::string, int> &cmpRst) const
356 {
357     return E_OK;
358 }
359 
360 namespace {
GetMemberFromJsonObject(const JsonObject & inJsonObject,const std::string & fieldName,FieldType expectType,bool isNecessary,FieldValue & fieldValue)361 int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &fieldName, FieldType expectType,
362     bool isNecessary, FieldValue &fieldValue)
363 {
364     if (!inJsonObject.IsFieldPathExist(FieldPath {fieldName})) {
365         if (isNecessary) {
366             LOGE("[RelationalSchema][Parse] Get schema %s not exist. isNecessary: %d", fieldName.c_str(), isNecessary);
367             return -E_SCHEMA_PARSE_FAIL;
368         }
369         return -E_NOT_FOUND;
370     }
371 
372     FieldType fieldType;
373     int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {fieldName}, fieldType);
374     if (errCode != E_OK) {
375         LOGE("[RelationalSchema][Parse] Get schema %s fieldType failed: %d.", fieldName.c_str(), errCode);
376         return -E_SCHEMA_PARSE_FAIL;
377     }
378 
379     if (fieldType != expectType) {
380         LOGE("[RelationalSchema][Parse] Expect %s fieldType %d but: %d.", fieldName.c_str(),
381             static_cast<int>(expectType), static_cast<int>(fieldType));
382         return -E_SCHEMA_PARSE_FAIL;
383     }
384 
385     errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath {fieldName}, fieldValue);
386     if (errCode != E_OK) {
387         LOGE("[RelationalSchema][Parse] Get schema %s value failed: %d.", fieldName.c_str(), errCode);
388         return -E_SCHEMA_PARSE_FAIL;
389     }
390     return E_OK;
391 }
392 }
393 
ParseTrackerSchema(const JsonObject & inJsonObject)394 int RelationalSchemaObject::ParseTrackerSchema(const JsonObject &inJsonObject)
395 {
396     FieldType fieldType;
397     int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, fieldType);
398     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
399         LOGE("[RelationalSchema][Parse] Get tracker schema TABLES fieldType failed: %d.", errCode);
400         return -E_SCHEMA_PARSE_FAIL;
401     }
402     if (FieldType::LEAF_FIELD_ARRAY != fieldType) { // LCOV_EXCL_BR_LINE
403         LOGE("[RelationalSchema][Parse] Expect tracker TABLES fieldType ARRAY but %s.",
404              SchemaUtils::FieldTypeString(fieldType).c_str());
405         return -E_SCHEMA_PARSE_FAIL;
406     }
407     std::vector<JsonObject> tables;
408     errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, tables);
409     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
410         LOGE("[RelationalSchema][Parse] Get tracker schema TABLES value failed: %d.", errCode);
411         return -E_SCHEMA_PARSE_FAIL;
412     }
413     for (const JsonObject &table : tables) {
414         errCode = ParseCheckTrackerTable(table);
415         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
416             LOGE("[RelationalSchema][Parse] Parse schema TABLES failed: %d.", errCode);
417             return -E_SCHEMA_PARSE_FAIL;
418         }
419     }
420     return E_OK;
421 }
422 
ParseCheckTrackerTable(const JsonObject & inJsonObject)423 int RelationalSchemaObject::ParseCheckTrackerTable(const JsonObject &inJsonObject)
424 {
425     TrackerTable table;
426     int errCode = ParseCheckTrackerTableName(inJsonObject, table);
427     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
428         return errCode;
429     }
430     errCode = ParseCheckTrackerExtendName(inJsonObject, table);
431     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
432         return errCode;
433     }
434     errCode = ParseCheckTrackerName(inJsonObject, table);
435     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
436         return errCode;
437     }
438     trackerTables_[table.GetTableName()].SetTrackerTable(table);
439     return E_OK;
440 }
441 
ParseCheckTrackerTableName(const JsonObject & inJsonObject,TrackerTable & resultTable)442 int RelationalSchemaObject::ParseCheckTrackerTableName(const JsonObject &inJsonObject, TrackerTable &resultTable)
443 {
444     FieldValue fieldValue;
445     int errCode = GetMemberFromJsonObject(inJsonObject, "NAME", FieldType::LEAF_FIELD_STRING,
446         true, fieldValue);
447     if (errCode == E_OK) { // LCOV_EXCL_BR_LINE
448         if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { // LCOV_EXCL_BR_LINE
449             LOGE("[RelationalSchema][Parse] Invalid characters in table name, err=%d.", errCode);
450             return -E_SCHEMA_PARSE_FAIL;
451         }
452         resultTable.SetTableName(fieldValue.stringValue);
453     }
454     return errCode;
455 }
456 
ParseCheckTrackerExtendName(const JsonObject & inJsonObject,TrackerTable & resultTable)457 int RelationalSchemaObject::ParseCheckTrackerExtendName(const JsonObject &inJsonObject, TrackerTable &resultTable)
458 {
459     FieldValue fieldValue;
460     int errCode = GetMemberFromJsonObject(inJsonObject, "EXTEND_NAME", FieldType::LEAF_FIELD_STRING,
461         true, fieldValue);
462     if (errCode == E_OK) { // LCOV_EXCL_BR_LINE
463         if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) { // LCOV_EXCL_BR_LINE
464             LOGE("[RelationalSchema][Parse] Invalid characters in extend name, err=%d.", errCode);
465             return -E_SCHEMA_PARSE_FAIL;
466         }
467         resultTable.SetExtendName(fieldValue.stringValue);
468     }
469     return errCode;
470 }
471 
ParseCheckTrackerName(const JsonObject & inJsonObject,TrackerTable & resultTable)472 int RelationalSchemaObject::ParseCheckTrackerName(const JsonObject &inJsonObject, TrackerTable &resultTable)
473 {
474     FieldType fieldType;
475     int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {"TRACKER_NAMES"}, fieldType);
476     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
477         LOGE("[RelationalSchema][Parse] Get tracker col names fieldType failed: %d.", errCode);
478         return -E_SCHEMA_PARSE_FAIL;
479     }
480     if (FieldType::LEAF_FIELD_ARRAY != fieldType) { // LCOV_EXCL_BR_LINE
481         LOGE("[RelationalSchema][Parse] Expect tracker TABLES fieldType ARRAY but %s.",
482             SchemaUtils::FieldTypeString(fieldType).c_str());
483         return -E_SCHEMA_PARSE_FAIL;
484     }
485     std::vector<JsonObject> fieldValues;
486     errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{"TRACKER_NAMES"}, fieldValues);
487     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
488         LOGE("[RelationalSchema][Parse] Get tracker col names value failed: %d.", errCode);
489         return -E_SCHEMA_PARSE_FAIL;
490     }
491     std::set<std::string> colNames;
492     for (const JsonObject &value : fieldValues) {
493         FieldValue fieldValue;
494         errCode = value.GetFieldValueByFieldPath(FieldPath {}, fieldValue);
495         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
496             LOGE("[RelationalSchema][Parse] Parse tracker col name failed: %d.", errCode);
497             return -E_SCHEMA_PARSE_FAIL;
498         }
499         colNames.insert(fieldValue.stringValue);
500     }
501     resultTable.SetTrackerNames(colNames);
502     return errCode;
503 }
504 
ParseRelationalSchema(const JsonObject & inJsonObject)505 int RelationalSchemaObject::ParseRelationalSchema(const JsonObject &inJsonObject)
506 {
507     int errCode = ParseCheckSchemaVersion(inJsonObject);
508     if (errCode != E_OK) {
509         return errCode;
510     }
511     errCode = ParseCheckSchemaType(inJsonObject);
512     if (errCode != E_OK) {
513         return errCode;
514     }
515     errCode = ParseCheckTableMode(inJsonObject);
516     if (errCode != E_OK) {
517         return errCode;
518     }
519     errCode = ParseCheckSchemaTableDefine(inJsonObject);
520     if (errCode != E_OK) {
521         return errCode;
522     }
523     return ParseCheckReferenceProperty(inJsonObject);
524 }
525 
526 namespace {
IsSchemaVersionValid(const std::string & version)527 inline bool IsSchemaVersionValid(const std::string &version)
528 {
529     std::string stripedVersion = SchemaUtils::Strip(version);
530     return stripedVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2 ||
531         stripedVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1;
532 }
533 }
534 
ParseCheckSchemaVersion(const JsonObject & inJsonObject)535 int RelationalSchemaObject::ParseCheckSchemaVersion(const JsonObject &inJsonObject)
536 {
537     FieldValue fieldValue;
538     int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_VERSION,
539         FieldType::LEAF_FIELD_STRING, true, fieldValue);
540     if (errCode != E_OK) {
541         return errCode;
542     }
543 
544     if (IsSchemaVersionValid(fieldValue.stringValue)) {
545         schemaVersion_ = fieldValue.stringValue;
546         return E_OK;
547     }
548 
549     LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_VERSION=%s.", fieldValue.stringValue.c_str());
550     return -E_SCHEMA_PARSE_FAIL;
551 }
552 
ParseCheckSchemaType(const JsonObject & inJsonObject)553 int RelationalSchemaObject::ParseCheckSchemaType(const JsonObject &inJsonObject)
554 {
555     FieldValue fieldValue;
556     int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_TYPE,
557         FieldType::LEAF_FIELD_STRING, true, fieldValue);
558     if (errCode != E_OK) {
559         return errCode;
560     }
561 
562     if (SchemaUtils::Strip(fieldValue.stringValue) != SchemaConstant::KEYWORD_TYPE_RELATIVE) {
563         LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_TYPE=%s.", fieldValue.stringValue.c_str());
564         return -E_SCHEMA_PARSE_FAIL;
565     }
566     schemaType_ = SchemaType::RELATIVE;
567     return E_OK;
568 }
569 
570 namespace {
IsTableModeValid(const std::string & mode)571 inline bool IsTableModeValid(const std::string &mode)
572 {
573     std::string stripedMode = SchemaUtils::Strip(mode);
574     return stripedMode == SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE ||
575         stripedMode == SchemaConstant::KEYWORD_TABLE_COLLABORATION;
576 }
577 }
578 
ParseCheckTableMode(const JsonObject & inJsonObject)579 int RelationalSchemaObject::ParseCheckTableMode(const JsonObject &inJsonObject)
580 {
581     if (schemaVersion_ == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) {
582         return E_OK; // version 2 has no table mode, no parsing required
583     }
584 
585     FieldValue fieldValue;
586     int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_TABLE_MODE,
587         FieldType::LEAF_FIELD_STRING, true, fieldValue);
588     if (errCode != E_OK) {
589         return errCode;
590     }
591 
592     if (!IsTableModeValid(fieldValue.stringValue)) {
593         LOGE("[RelationalSchema][Parse] Unexpected TABLE_MODE=%s.", fieldValue.stringValue.c_str());
594         return -E_SCHEMA_PARSE_FAIL;
595     }
596 
597     tableMode_ = SchemaUtils::Strip(fieldValue.stringValue) == SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE ?
598         DistributedDB::SPLIT_BY_DEVICE : DistributedTableMode::COLLABORATION;
599     return E_OK;
600 }
601 
ParseCheckSchemaTableDefine(const JsonObject & inJsonObject)602 int RelationalSchemaObject::ParseCheckSchemaTableDefine(const JsonObject &inJsonObject)
603 {
604     FieldType fieldType;
605     int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, fieldType);
606     if (errCode != E_OK) {
607         LOGE("[RelationalSchema][Parse] Get schema TABLES fieldType failed: %d.", errCode);
608         return -E_SCHEMA_PARSE_FAIL;
609     }
610     if (FieldType::LEAF_FIELD_ARRAY != fieldType) {
611         LOGE("[RelationalSchema][Parse] Expect TABLES fieldType ARRAY but %s.",
612             SchemaUtils::FieldTypeString(fieldType).c_str());
613         return -E_SCHEMA_PARSE_FAIL;
614     }
615     std::vector<JsonObject> tables;
616     errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, tables);
617     if (errCode != E_OK) {
618         LOGE("[RelationalSchema][Parse] Get schema TABLES value failed: %d.", errCode);
619         return -E_SCHEMA_PARSE_FAIL;
620     }
621     for (const JsonObject &table : tables) {
622         errCode = ParseCheckTableInfo(table);
623         if (errCode != E_OK) {
624             LOGE("[RelationalSchema][Parse] Parse schema TABLES failed: %d.", errCode);
625             return -E_SCHEMA_PARSE_FAIL;
626         }
627     }
628     return E_OK;
629 }
630 
ParseCheckTableInfo(const JsonObject & inJsonObject)631 int RelationalSchemaObject::ParseCheckTableInfo(const JsonObject &inJsonObject)
632 {
633     TableInfo resultTable;
634     int errCode = ParseCheckTableName(inJsonObject, resultTable);
635     if (errCode != E_OK) {
636         return errCode;
637     }
638     errCode = ParseCheckTableDefine(inJsonObject, resultTable);
639     if (errCode != E_OK) {
640         return errCode;
641     }
642     errCode = ParseCheckOriginTableName(inJsonObject, resultTable);
643     if (errCode != E_OK) {
644         return errCode;
645     }
646     errCode = ParseCheckTableAutoInc(inJsonObject, resultTable);
647     if (errCode != E_OK) {
648         return errCode;
649     }
650     errCode = ParseCheckSharedTableMark(inJsonObject, resultTable);
651     if (errCode != E_OK) {
652         return errCode;
653     }
654     errCode = ParseCheckTablePrimaryKey(inJsonObject, resultTable);
655     if (errCode != E_OK) {
656         return errCode;
657     }
658 
659     errCode = ParseCheckTableSyncType(inJsonObject, resultTable);
660     if (errCode != E_OK) {
661         return errCode;
662     }
663     errCode = ParseCheckTableIndex(inJsonObject, resultTable);
664     if (errCode != E_OK) {
665         return errCode;
666     }
667     errCode = ParseCheckTableUnique(inJsonObject, resultTable);
668     if (errCode != E_OK) {
669         return errCode;
670     }
671     tables_[resultTable.GetTableName()] = resultTable;
672     return E_OK;
673 }
674 
ParseCheckTableName(const JsonObject & inJsonObject,TableInfo & resultTable)675 int RelationalSchemaObject::ParseCheckTableName(const JsonObject &inJsonObject, TableInfo &resultTable)
676 {
677     FieldValue fieldValue;
678     int errCode = GetMemberFromJsonObject(inJsonObject, "NAME", FieldType::LEAF_FIELD_STRING,
679         true, fieldValue);
680     if (errCode == E_OK) {
681         if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) {
682             LOGE("[RelationalSchema][Parse] Invalid characters in table name, err=%d.", errCode);
683             return -E_SCHEMA_PARSE_FAIL;
684         }
685         resultTable.SetTableName(fieldValue.stringValue);
686     }
687     return errCode;
688 }
689 
ParseCheckTableDefine(const JsonObject & inJsonObject,TableInfo & resultTable)690 int RelationalSchemaObject::ParseCheckTableDefine(const JsonObject &inJsonObject, TableInfo &resultTable)
691 {
692     std::map<FieldPath, FieldType> tableFields;
693     int errCode = inJsonObject.GetSubFieldPathAndType(FieldPath {"DEFINE"}, tableFields);
694     if (errCode != E_OK) {
695         LOGE("[RelationalSchema][Parse] Get schema TABLES DEFINE failed: %d.", errCode);
696         return -E_SCHEMA_PARSE_FAIL;
697     }
698 
699     for (const auto &field : tableFields) {
700         if (field.second != FieldType::INTERNAL_FIELD_OBJECT) {
701             LOGE("[RelationalSchema][Parse] Expect schema TABLES DEFINE fieldType INTERNAL OBJECT but : %s.",
702                 SchemaUtils::FieldTypeString(field.second).c_str());
703             return -E_SCHEMA_PARSE_FAIL;
704         }
705 
706         JsonObject fieldObj;
707         errCode = inJsonObject.GetObjectByFieldPath(field.first, fieldObj);
708         if (errCode != E_OK) {
709             LOGE("[RelationalSchema][Parse] Get table field object failed. %d", errCode);
710             return errCode;
711         }
712 
713         if (!DBCommon::CheckIsAlnumOrUnderscore(field.first[1])) {
714             LOGE("[RelationalSchema][Parse] Invalid characters in field name, err=%d.", errCode);
715             return -E_SCHEMA_PARSE_FAIL;
716         }
717 
718         FieldInfo fieldInfo;
719         fieldInfo.SetFieldName(field.first[1]); // 1 : table name element in path
720         errCode = ParseCheckTableFieldInfo(fieldObj, field.first, fieldInfo);
721         if (errCode != E_OK) {
722             LOGE("[RelationalSchema][Parse] Parse table field info failed. %d", errCode);
723             return -E_SCHEMA_PARSE_FAIL;
724         }
725         resultTable.AddField(fieldInfo);
726     }
727     return E_OK;
728 }
729 
ParseCheckTableFieldInfo(const JsonObject & inJsonObject,const FieldPath & path,FieldInfo & field)730 int RelationalSchemaObject::ParseCheckTableFieldInfo(const JsonObject &inJsonObject, const FieldPath &path,
731     FieldInfo &field)
732 {
733     FieldValue fieldValue;
734     int errCode = GetMemberFromJsonObject(inJsonObject, "COLUMN_ID", FieldType::LEAF_FIELD_INTEGER, true, fieldValue);
735     if (errCode != E_OK) {
736         return errCode;
737     }
738     field.SetColumnId(fieldValue.integerValue);
739 
740     errCode = GetMemberFromJsonObject(inJsonObject, "TYPE", FieldType::LEAF_FIELD_STRING, true, fieldValue);
741     if (errCode != E_OK) {
742         return errCode;
743     }
744     field.SetDataType(fieldValue.stringValue);
745 
746     errCode = GetMemberFromJsonObject(inJsonObject, "NOT_NULL", FieldType::LEAF_FIELD_BOOL, true, fieldValue);
747     if (errCode != E_OK) {
748         return errCode;
749     }
750     field.SetNotNull(fieldValue.boolValue);
751 
752     errCode = GetMemberFromJsonObject(inJsonObject, "DEFAULT", FieldType::LEAF_FIELD_STRING, false, fieldValue);
753     if (errCode == E_OK) {
754         field.SetDefaultValue(fieldValue.stringValue);
755     } else if (errCode != -E_NOT_FOUND) {
756         return errCode;
757     }
758 
759     return E_OK;
760 }
761 
ParseCheckOriginTableName(const JsonObject & inJsonObject,TableInfo & resultTable)762 int RelationalSchemaObject::ParseCheckOriginTableName(const JsonObject &inJsonObject, TableInfo &resultTable)
763 {
764     FieldValue fieldValue;
765     int errCode = GetMemberFromJsonObject(inJsonObject, "ORIGINTABLENAME", FieldType::LEAF_FIELD_STRING,
766         false, fieldValue);
767     if (errCode == E_OK) {
768         if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) {
769             LOGE("[RelationalSchema][Parse] Invalid characters in origin table name, err=%d.", errCode);
770             return -E_SCHEMA_PARSE_FAIL;
771         }
772         resultTable.SetOriginTableName(fieldValue.stringValue);
773     } else if (errCode != -E_NOT_FOUND) {
774         LOGE("[RelationalSchema][Parse] Get schema orgin table name failed: %d", errCode);
775         return errCode;
776     }
777     return E_OK;
778 }
779 
ParseCheckTableAutoInc(const JsonObject & inJsonObject,TableInfo & resultTable)780 int RelationalSchemaObject::ParseCheckTableAutoInc(const JsonObject &inJsonObject, TableInfo &resultTable)
781 {
782     FieldValue fieldValue;
783     int errCode = GetMemberFromJsonObject(inJsonObject, "AUTOINCREMENT", FieldType::LEAF_FIELD_BOOL, false, fieldValue);
784     if (errCode == E_OK) {
785         resultTable.SetAutoIncrement(fieldValue.boolValue);
786     } else if (errCode != -E_NOT_FOUND) {
787         return errCode;
788     }
789     return E_OK;
790 }
791 
ParseCheckSharedTableMark(const JsonObject & inJsonObject,TableInfo & resultTable)792 int RelationalSchemaObject::ParseCheckSharedTableMark(const JsonObject &inJsonObject, TableInfo &resultTable)
793 {
794     FieldValue fieldValue;
795     int errCode = GetMemberFromJsonObject(inJsonObject, "SHAREDTABLEMARK", FieldType::LEAF_FIELD_BOOL, false,
796         fieldValue);
797     if (errCode == E_OK) {
798         resultTable.SetSharedTableMark(fieldValue.boolValue);
799     } else if (errCode != -E_NOT_FOUND) {
800         return errCode;
801     }
802     return E_OK;
803 }
804 
ParseCheckTablePrimaryKey(const JsonObject & inJsonObject,TableInfo & resultTable)805 int RelationalSchemaObject::ParseCheckTablePrimaryKey(const JsonObject &inJsonObject, TableInfo &resultTable)
806 {
807     if (!inJsonObject.IsFieldPathExist(FieldPath {"PRIMARY_KEY"})) {
808         return E_OK;
809     }
810 
811     FieldType type;
812     int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {"PRIMARY_KEY"}, type);
813     if (errCode != E_OK) {
814         return errCode;
815     }
816 
817     if (type == FieldType::LEAF_FIELD_STRING) { // Compatible with schema 2.0
818         FieldValue fieldValue;
819         errCode = GetMemberFromJsonObject(inJsonObject, "PRIMARY_KEY", FieldType::LEAF_FIELD_STRING, false, fieldValue);
820         if (errCode == E_OK) {
821             resultTable.SetPrimaryKey(fieldValue.stringValue, 1);
822         }
823     } else if (type == FieldType::LEAF_FIELD_ARRAY) {
824         CompositeFields multiPrimaryKey;
825         errCode = inJsonObject.GetStringArrayByFieldPath(FieldPath {"PRIMARY_KEY"}, multiPrimaryKey);
826         if (errCode == E_OK) {
827             int index = 1; // primary key index
828             for (const auto &item : multiPrimaryKey) {
829                 resultTable.SetPrimaryKey(item, index++);
830             }
831         }
832     } else {
833         errCode = -E_SCHEMA_PARSE_FAIL;
834     }
835     return errCode;
836 }
837 
ParseCheckReferenceProperty(const JsonObject & inJsonObject)838 int RelationalSchemaObject::ParseCheckReferenceProperty(const JsonObject &inJsonObject)
839 {
840     if (!inJsonObject.IsFieldPathExist(FieldPath {SchemaConstant::REFERENCE_PROPERTY})) {
841         return E_OK;
842     }
843 
844     FieldType fieldType;
845     int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::REFERENCE_PROPERTY}, fieldType);
846     if (errCode != E_OK) {
847         LOGE("[RelationalSchema][Parse] Get schema REFERENCE_PROPERTY fieldType failed: %d.", errCode);
848         return -E_SCHEMA_PARSE_FAIL;
849     }
850     if (FieldType::LEAF_FIELD_ARRAY != fieldType) {
851         LOGE("[RelationalSchema][Parse] Expect TABLES REFERENCE_PROPERTY ARRAY but %s.",
852              SchemaUtils::FieldTypeString(fieldType).c_str());
853         return -E_SCHEMA_PARSE_FAIL;
854     }
855     std::vector<JsonObject> references;
856     errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::REFERENCE_PROPERTY}, references);
857     if (errCode != E_OK) {
858         LOGE("[RelationalSchema][Parse] Get schema REFERENCE_PROPERTY value failed: %d.", errCode);
859         return -E_SCHEMA_PARSE_FAIL;
860     }
861     for (const JsonObject &reference : references) {
862         errCode = ParseCheckReference(reference);
863         if (errCode != E_OK) {
864             LOGE("[RelationalSchema][Parse] Parse schema reference failed: %d.", errCode);
865             return -E_SCHEMA_PARSE_FAIL;
866         }
867     }
868     return E_OK;
869 }
870 
ParseCheckReference(const JsonObject & inJsonObject)871 int RelationalSchemaObject::ParseCheckReference(const JsonObject &inJsonObject)
872 {
873     FieldValue fieldValue;
874     int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::SOURCE_TABLE_NAME, FieldType::LEAF_FIELD_STRING,
875         true, fieldValue);
876     if (errCode != E_OK) {
877         LOGE("[RelationalSchema][Parse] Get source table name failed, errCode = %d", errCode);
878         return errCode;
879     }
880     if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) {
881         LOGE("[RelationalSchema][Parse] Invalid characters in source table name.");
882         return -E_SCHEMA_PARSE_FAIL;
883     }
884 
885     TableReferenceProperty referenceProperty;
886     referenceProperty.sourceTableName = fieldValue.stringValue;
887     errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::TARGET_TABLE_NAME, FieldType::LEAF_FIELD_STRING,
888         true, fieldValue);
889     if (errCode != E_OK) {
890         LOGE("[RelationalSchema][Parse] Get target table name failed, errCode = %d", errCode);
891         return errCode;
892     }
893     if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) {
894         LOGE("[RelationalSchema][Parse] Invalid characters in target table name.");
895         return -E_SCHEMA_PARSE_FAIL;
896     }
897 
898     referenceProperty.targetTableName = fieldValue.stringValue;
899     errCode = ParseCheckReferenceColumns(inJsonObject, referenceProperty);
900     if (errCode != E_OK) {
901         LOGE("[RelationalSchema][Parse] Parse reference columns failed, errCode = %d", errCode);
902         return errCode;
903     }
904     referenceProperty_.emplace_back(referenceProperty);
905     tables_[referenceProperty.targetTableName].AddTableReferenceProperty(referenceProperty);
906     return E_OK;
907 }
908 
ParseCheckReferenceColumns(const JsonObject & inJsonObject,TableReferenceProperty & tableReferenceProperty)909 int RelationalSchemaObject::ParseCheckReferenceColumns(const JsonObject &inJsonObject,
910     TableReferenceProperty &tableReferenceProperty)
911 {
912     // parse columns
913     FieldType fieldType;
914     int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::COLUMNS}, fieldType);
915     if (errCode != E_OK) {
916         LOGE("[RelationalSchema][Parse] Get schema reference COLUMNS fieldType failed: %d.", errCode);
917         return -E_SCHEMA_PARSE_FAIL;
918     }
919     if (FieldType::LEAF_FIELD_ARRAY != fieldType) {
920         LOGE("[RelationalSchema][Parse] Expect reference COLUMNS ARRAY but %s.",
921              SchemaUtils::FieldTypeString(fieldType).c_str());
922         return -E_SCHEMA_PARSE_FAIL;
923     }
924     std::vector<JsonObject> columns;
925     errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::COLUMNS}, columns);
926     if (errCode != E_OK) {
927         LOGE("[RelationalSchema][Parse] Get schema reference COLUMNS value failed: %d.", errCode);
928         return -E_SCHEMA_PARSE_FAIL;
929     }
930 
931     for (const JsonObject &column : columns) {
932         errCode = ParseCheckReferenceColumn(column, tableReferenceProperty);
933         if (errCode != E_OK) {
934             LOGE("[RelationalSchema][Parse] Parse reference one COLUMN failed: %d.", errCode);
935             return -E_SCHEMA_PARSE_FAIL;
936         }
937     }
938     return E_OK;
939 }
940 
ParseCheckReferenceColumn(const JsonObject & inJsonObject,TableReferenceProperty & tableReferenceProperty)941 int RelationalSchemaObject::ParseCheckReferenceColumn(const JsonObject &inJsonObject,
942     TableReferenceProperty &tableReferenceProperty)
943 {
944     FieldValue fieldValue;
945     int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::SOURCE_COL, FieldType::LEAF_FIELD_STRING,
946         true, fieldValue);
947     if (errCode != E_OK) {
948         LOGE("[RelationalSchema][Parse] Get source col failed, errCode = %d", errCode);
949         return errCode;
950     }
951     if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) {
952         LOGE("[RelationalSchema][Parse] Invalid characters in source col name.");
953         return -E_SCHEMA_PARSE_FAIL;
954     }
955 
956     std::string sourceCol = fieldValue.stringValue;
957     errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::TARGET_COL, FieldType::LEAF_FIELD_STRING,
958         true, fieldValue);
959     if (errCode != E_OK) {
960         LOGE("[RelationalSchema][Parse] Get target col failed, errCode = %d", errCode);
961         return errCode;
962     }
963     if (!DBCommon::CheckIsAlnumOrUnderscore(fieldValue.stringValue)) {
964         LOGE("[RelationalSchema][Parse] Invalid characters in target col name.");
965         return -E_SCHEMA_PARSE_FAIL;
966     }
967     std::string targetCol = fieldValue.stringValue;
968     tableReferenceProperty.columns[sourceCol] = targetCol;
969     return E_OK;
970 }
971 
ParseCheckTableSyncType(const JsonObject & inJsonObject,TableInfo & resultTable)972 int RelationalSchemaObject::ParseCheckTableSyncType(const JsonObject &inJsonObject, TableInfo &resultTable)
973 {
974     FieldValue fieldValue;
975     int errCode = GetMemberFromJsonObject(inJsonObject, "TABLE_SYNC_TYPE", FieldType::LEAF_FIELD_INTEGER,
976         false, fieldValue);
977     if (errCode == E_OK) {
978         resultTable.SetTableSyncType(static_cast<TableSyncType>(fieldValue.integerValue));
979     } else if (errCode != -E_NOT_FOUND) {
980         return errCode;
981     }
982     return E_OK; // if there is no "TABLE_SYNC_TYPE" filed, the table_sync_type is DEVICE_COOPERATION
983 }
984 
ParseCheckTableIndex(const JsonObject & inJsonObject,TableInfo & resultTable)985 int RelationalSchemaObject::ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable)
986 {
987     if (!inJsonObject.IsFieldPathExist(FieldPath {"INDEX"})) { // INDEX is not necessary
988         return E_OK;
989     }
990     std::map<FieldPath, FieldType> tableFields;
991     int errCode = inJsonObject.GetSubFieldPathAndType(FieldPath {"INDEX"}, tableFields);
992     if (errCode != E_OK) {
993         LOGE("[RelationalSchema][Parse] Get schema TABLES INDEX failed: %d.", errCode);
994         return -E_SCHEMA_PARSE_FAIL;
995     }
996 
997     for (const auto &field : tableFields) {
998         if (field.second != FieldType::LEAF_FIELD_ARRAY) {
999             LOGE("[RelationalSchema][Parse] Expect schema TABLES INDEX fieldType ARRAY but : %s.",
1000                 SchemaUtils::FieldTypeString(field.second).c_str());
1001             return -E_SCHEMA_PARSE_FAIL;
1002         }
1003         CompositeFields indexDefine;
1004         errCode = inJsonObject.GetStringArrayByFieldPath(field.first, indexDefine);
1005         if (errCode != E_OK) {
1006             LOGE("[RelationalSchema][Parse] Get schema TABLES INDEX field value failed: %d.", errCode);
1007             return -E_SCHEMA_PARSE_FAIL;
1008         }
1009         resultTable.AddIndexDefine(field.first[1], indexDefine); // 1 : second element in path
1010     }
1011     return E_OK;
1012 }
1013 
ParseCheckTableUnique(const JsonObject & inJsonObject,TableInfo & resultTable)1014 int RelationalSchemaObject::ParseCheckTableUnique(const JsonObject &inJsonObject, TableInfo &resultTable)
1015 {
1016     if (!inJsonObject.IsFieldPathExist(FieldPath {"UNIQUE"})) { // UNIQUE is not necessary
1017         return E_OK;
1018     }
1019 
1020     std::vector<CompositeFields> uniques;
1021     int errCode = inJsonObject.GetArrayContentOfStringOrStringArray(FieldPath {"UNIQUE"}, uniques);
1022     if (errCode != E_OK) {
1023         LOGE("[RelationalSchema][Parse] Get schema TABLES UNIQUE failed: %d.", errCode);
1024         return -E_SCHEMA_PARSE_FAIL;
1025     }
1026     resultTable.SetUniqueDefine(uniques);
1027     return E_OK;
1028 }
1029 
GenerateReachableRef()1030 void RelationalSchemaObject::GenerateReachableRef()
1031 {
1032     reachableReference_.clear();
1033     tableWeight_.clear();
1034     std::set<std::string> startNodes; // such as {a->b->c,d->e}, record {a,d}
1035     std::map<std::string, std::set<std::string>> nextNodes; // such as {a->b->c}, record {{a,{b}}, {b, {c}}}
1036     // we need to record all table reachable reference here
1037     for (const auto &tableRef : referenceProperty_) {
1038         // they also can reach target
1039         RefreshReachableRef(tableRef);
1040         startNodes.insert(tableRef.sourceTableName);
1041         startNodes.erase(tableRef.targetTableName);
1042         nextNodes[tableRef.sourceTableName].insert(tableRef.targetTableName);
1043     }
1044     CalculateTableWeight(startNodes, nextNodes);
1045 }
1046 
GenerateTableInfoReferenced()1047 void RelationalSchemaObject::GenerateTableInfoReferenced()
1048 {
1049     for (auto &table : tables_) {
1050         table.second.SetSourceTableReference({});
1051     }
1052     for (const auto &reference : referenceProperty_) {
1053         tables_[reference.targetTableName].AddTableReferenceProperty(reference);
1054     }
1055 }
1056 
RefreshReachableRef(const TableReferenceProperty & referenceProperty)1057 void RelationalSchemaObject::RefreshReachableRef(const TableReferenceProperty &referenceProperty)
1058 {
1059     // such as source:A target:B
1060     std::set<std::string> recordSources;
1061     // find all node which can reach source as collection recordSources
1062     for (const auto &[start, end] : reachableReference_) {
1063         auto node = end.find(referenceProperty.sourceTableName);
1064         // find the node and it can reach
1065         if (node != end.end() && node->second) {
1066             recordSources.insert(start);
1067         }
1068     }
1069     recordSources.insert(referenceProperty.sourceTableName);
1070     // find all node which start with target as collection recordTargets
1071     std::set<std::string> recordTargets;
1072     for (auto &[entry, reach] : reachableReference_[referenceProperty.targetTableName]) {
1073         if (reach) {
1074             recordTargets.insert(entry);
1075         }
1076     }
1077     recordTargets.insert(referenceProperty.targetTableName);
1078     for (const auto &source : recordSources) {
1079         for (const auto &target : recordTargets) {
1080             reachableReference_[source][target] = true;
1081         }
1082     }
1083 }
1084 
CalculateTableWeight(const std::set<std::string> & startNodes,const std::map<std::string,std::set<std::string>> & nextNodes)1085 void RelationalSchemaObject::CalculateTableWeight(const std::set<std::string> &startNodes,
1086     const std::map<std::string, std::set<std::string>> &nextNodes)
1087 {
1088     // record the max long path as table weight
1089     for (const auto &start : startNodes) {
1090         std::map<std::string, int> tmpTableWeight;
1091         tmpTableWeight[start] = 1;
1092         if (nextNodes.find(start) == nextNodes.end()) {
1093             continue;
1094         }
1095         std::list<std::string> queue;
1096         for (const auto &target : nextNodes.at(start)) {
1097             queue.push_back(target);
1098             tmpTableWeight[target] = 2; // this path contain 2 nodes
1099         }
1100         // bfs all the path which start from startNodes
1101         while (!queue.empty()) {
1102             auto node = queue.front();
1103             queue.pop_front();
1104             if (nextNodes.find(node) == nextNodes.end()) {
1105                 continue;
1106             }
1107             for (const auto &item : nextNodes.at(node)) {
1108                 queue.push_back(item);
1109                 tmpTableWeight[item] = std::max(tmpTableWeight[item], tmpTableWeight[node] + 1);
1110             }
1111         }
1112         for (const auto &[table, weight] : tmpTableWeight) {
1113             tableWeight_[table] = std::max(tableWeight_[table], weight);
1114         }
1115     }
1116 }
1117 }
1118 #endif