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