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