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 #include "table_info.h"
16
17 #include <algorithm>
18
19 #include "db_common.h"
20 #include "db_errno.h"
21 #include "log_print.h"
22
23 namespace DistributedDB {
24 constexpr const char *ASSET_STR = "asset";
25 constexpr const char *ASSETS_STR = "assets";
26 constexpr const char *ROW_ID = "rowid";
27
GetFieldName() const28 const std::string &FieldInfo::GetFieldName() const
29 {
30 return fieldName_;
31 }
32
SetFieldName(const std::string & fileName)33 void FieldInfo::SetFieldName(const std::string &fileName)
34 {
35 fieldName_ = fileName;
36 }
37
GetDataType() const38 const std::string &FieldInfo::GetDataType() const
39 {
40 return dataType_;
41 }
42
43 namespace {
AffinityPatternHex(const std::string & ss)44 inline uint32_t AffinityPatternHex(const std::string &ss)
45 {
46 uint32_t res = 0;
47 for (const auto &c : ss) {
48 res = (res << 8) + c; // 8: shift length
49 }
50 return res;
51 }
52
53 static uint32_t affinityTable[] = {
54 AffinityPatternHex("char"), AffinityPatternHex("clob"), AffinityPatternHex("text"),
55 AffinityPatternHex("blob"), AffinityPatternHex("real"), AffinityPatternHex("floa"),
56 AffinityPatternHex("doub"), AffinityPatternHex("int"),
57 };
58
59 enum AffinityPattern : uint32_t {
60 AFFINITY_CHAR,
61 AFFINITY_CLOB,
62 AFFINITY_TEXT,
63 AFFINITY_BLOB,
64 AFFINITY_REAL,
65 AFFINITY_FLOA,
66 AFFINITY_DOUB,
67 AFFINITY_INT,
68 };
69 }
70
AffinityType(const std::string & dataType)71 static StorageType AffinityType(const std::string &dataType)
72 {
73 StorageType type = StorageType::STORAGE_TYPE_NULL;
74 uint32_t hex = 0;
75 for (uint32_t i = 0; i < dataType.length(); i++) {
76 hex = (hex << 8) + static_cast<uint32_t>((std::tolower(dataType[i]))); // 8: shift length
77 if (hex == affinityTable[AFFINITY_CHAR]) {
78 type = StorageType::STORAGE_TYPE_TEXT;
79 } else if (hex == affinityTable[AFFINITY_CLOB]) {
80 type = StorageType::STORAGE_TYPE_TEXT;
81 } else if (hex == affinityTable[AFFINITY_TEXT]) {
82 type = StorageType::STORAGE_TYPE_TEXT;
83 } else if (hex == affinityTable[AFFINITY_BLOB] && (type == StorageType::STORAGE_TYPE_NULL ||
84 type == StorageType::STORAGE_TYPE_REAL)) {
85 type = StorageType::STORAGE_TYPE_BLOB;
86 } else if (hex == affinityTable[AFFINITY_REAL] && type == StorageType::STORAGE_TYPE_NULL) {
87 type = StorageType::STORAGE_TYPE_REAL;
88 } else if (hex == affinityTable[AFFINITY_FLOA] && type == StorageType::STORAGE_TYPE_NULL) {
89 type = StorageType::STORAGE_TYPE_REAL;
90 } else if (hex == affinityTable[AFFINITY_DOUB] && type == StorageType::STORAGE_TYPE_NULL) {
91 type = StorageType::STORAGE_TYPE_REAL;
92 } else if ((hex & 0x00ffffff) == affinityTable[AFFINITY_INT]) { // 0x00ffffff: mask for 3 byte
93 type = StorageType::STORAGE_TYPE_INTEGER;
94 }
95 }
96 return type;
97 }
98
SetDataType(const std::string & dataType)99 void FieldInfo::SetDataType(const std::string &dataType)
100 {
101 dataType_ = dataType;
102 std::transform(dataType_.begin(), dataType_.end(), dataType_.begin(), ::tolower);
103 if (IsAssetType() || IsAssetsType()) {
104 storageType_ = StorageType::STORAGE_TYPE_BLOB; // use for cloud sync
105 } else if (dataType_ == DBConstant::STORAGE_TYPE_LONG) {
106 storageType_ = StorageType::STORAGE_TYPE_INTEGER;
107 } else {
108 storageType_ = AffinityType(dataType_);
109 }
110 }
111
IsNotNull() const112 bool FieldInfo::IsNotNull() const
113 {
114 return isNotNull_;
115 }
116
SetNotNull(bool isNotNull)117 void FieldInfo::SetNotNull(bool isNotNull)
118 {
119 isNotNull_ = isNotNull;
120 }
121
HasDefaultValue() const122 bool FieldInfo::HasDefaultValue() const
123 {
124 return hasDefaultValue_;
125 }
126
GetDefaultValue() const127 const std::string &FieldInfo::GetDefaultValue() const
128 {
129 return defaultValue_;
130 }
131
SetDefaultValue(const std::string & value)132 void FieldInfo::SetDefaultValue(const std::string &value)
133 {
134 hasDefaultValue_ = true;
135 defaultValue_ = value;
136 }
137
138 // convert to StorageType according "Determination Of Column Affinity"
GetStorageType() const139 StorageType FieldInfo::GetStorageType() const
140 {
141 return storageType_;
142 }
143
SetStorageType(StorageType storageType)144 void FieldInfo::SetStorageType(StorageType storageType)
145 {
146 storageType_ = storageType;
147 }
148
GetColumnId() const149 int FieldInfo::GetColumnId() const
150 {
151 return cid_;
152 }
153
SetColumnId(int cid)154 void FieldInfo::SetColumnId(int cid)
155 {
156 cid_ = cid;
157 }
158
ToAttributeString() const159 std::string FieldInfo::ToAttributeString() const
160 {
161 std::string attrStr = "\"" + fieldName_ + "\": {";
162 attrStr += "\"COLUMN_ID\":" + std::to_string(cid_) + ",";
163 attrStr += "\"TYPE\":\"" + dataType_ + "\",";
164 attrStr += "\"NOT_NULL\":" + std::string(isNotNull_ ? "true" : "false");
165 if (hasDefaultValue_) {
166 attrStr += ",";
167 attrStr += "\"DEFAULT\":\"" + defaultValue_ + "\"";
168 }
169 attrStr += "}";
170 return attrStr;
171 }
172
CompareWithField(const FieldInfo & inField,bool isLite) const173 int FieldInfo::CompareWithField(const FieldInfo &inField, bool isLite) const
174 {
175 if (!DBCommon::CaseInsensitiveCompare(fieldName_, inField.GetFieldName()) || isNotNull_ != inField.IsNotNull()) {
176 return false;
177 }
178 if (isLite) {
179 if (storageType_ != inField.GetStorageType()) {
180 return false;
181 }
182 } else {
183 if (dataType_ != inField.GetDataType()) {
184 return false;
185 }
186 }
187 if (hasDefaultValue_ && inField.HasDefaultValue()) {
188 // lite schema only uses NULL as default value
189 return (isLite && DBCommon::CaseInsensitiveCompare(defaultValue_, "NULL")) ||
190 (DBCommon::CaseInsensitiveCompare(defaultValue_, "NULL") &&
191 DBCommon::CaseInsensitiveCompare(inField.GetDefaultValue(), "NULL")) ||
192 (defaultValue_ == inField.GetDefaultValue());
193 }
194 return hasDefaultValue_ == inField.HasDefaultValue();
195 }
196
IsAssetType() const197 bool FieldInfo::IsAssetType() const
198 {
199 return strcasecmp(dataType_.c_str(), ASSET_STR) == 0;
200 }
201
IsAssetsType() const202 bool FieldInfo::IsAssetsType() const
203 {
204 return strcasecmp(dataType_.c_str(), ASSETS_STR) == 0;
205 }
206
GetCollateType() const207 CollateType FieldInfo::GetCollateType() const
208 {
209 return collateType_;
210 }
211
SetCollateType(CollateType collateType)212 void FieldInfo::SetCollateType(CollateType collateType)
213 {
214 collateType_ = collateType;
215 }
216
GetTableName() const217 const std::string &TableInfo::GetTableName() const
218 {
219 return tableName_;
220 }
221
SetTableName(const std::string & tableName)222 void TableInfo::SetTableName(const std::string &tableName)
223 {
224 tableName_ = tableName;
225 }
226
GetOriginTableName() const227 const std::string &TableInfo::GetOriginTableName() const
228 {
229 return originTableName_;
230 }
231
SetOriginTableName(const std::string & originTableName)232 void TableInfo::SetOriginTableName(const std::string &originTableName)
233 {
234 originTableName_ = originTableName;
235 }
236
SetSharedTableMark(bool sharedTableMark)237 void TableInfo::SetSharedTableMark(bool sharedTableMark)
238 {
239 sharedTableMark_ = sharedTableMark;
240 }
241
GetSharedTableMark() const242 bool TableInfo::GetSharedTableMark() const
243 {
244 return sharedTableMark_;
245 }
246
SetAutoIncrement(bool autoInc)247 void TableInfo::SetAutoIncrement(bool autoInc)
248 {
249 autoInc_ = autoInc;
250 }
251
GetAutoIncrement() const252 bool TableInfo::GetAutoIncrement() const
253 {
254 return autoInc_;
255 }
256
SetTableSyncType(TableSyncType tableSyncType)257 void TableInfo::SetTableSyncType(TableSyncType tableSyncType)
258 {
259 tableSyncType_ = tableSyncType;
260 }
261
GetTableSyncType() const262 TableSyncType TableInfo::GetTableSyncType() const
263 {
264 return tableSyncType_;
265 }
266
GetCreateTableSql() const267 const std::string &TableInfo::GetCreateTableSql() const
268 {
269 return sql_;
270 }
271
SetCreateTableSql(const std::string & sql)272 void TableInfo::SetCreateTableSql(const std::string &sql)
273 {
274 sql_ = sql;
275 for (auto &c : sql_) {
276 c = static_cast<char>(std::toupper(c));
277 }
278 if (DBCommon::HasConstraint(DBCommon::TrimSpace(sql_), "AUTOINCREMENT", " ", " ,)")) {
279 autoInc_ = true;
280 }
281 }
282
GetFields() const283 const FieldInfoMap &TableInfo::GetFields() const
284 {
285 return fields_;
286 }
287
GetFieldInfos() const288 const std::vector<FieldInfo> &TableInfo::GetFieldInfos() const
289 {
290 if (!fieldInfos_.empty() && fieldInfos_.size() == fields_.size()) {
291 return fieldInfos_;
292 }
293 fieldInfos_.resize(fields_.size());
294 if (fieldInfos_.size() != fields_.size()) {
295 LOGE("GetField error, alloc memory failed.");
296 return fieldInfos_;
297 }
298 for (const auto &entry : fields_) {
299 if (static_cast<size_t>(entry.second.GetColumnId()) >= fieldInfos_.size()) {
300 LOGE("Cid is over field size.");
301 fieldInfos_.clear();
302 return fieldInfos_;
303 }
304 fieldInfos_.at(entry.second.GetColumnId()) = entry.second;
305 }
306 return fieldInfos_;
307 }
308
GetFieldName(uint32_t cid) const309 std::string TableInfo::GetFieldName(uint32_t cid) const
310 {
311 if (cid >= fields_.size() || GetFieldInfos().empty()) {
312 return {};
313 }
314 return GetFieldInfos().at(cid).GetFieldName();
315 }
316
IsValid() const317 bool TableInfo::IsValid() const
318 {
319 return !tableName_.empty();
320 }
321
AddField(const FieldInfo & field)322 void TableInfo::AddField(const FieldInfo &field)
323 {
324 fields_[field.GetFieldName()] = field;
325 }
326
GetIndexDefine() const327 const IndexInfoMap &TableInfo::GetIndexDefine() const
328 {
329 return indexDefines_;
330 }
331
GetUniqueDefine() const332 const std::vector<CompositeFields> &TableInfo::GetUniqueDefine() const
333 {
334 return uniqueDefines_;
335 }
336
AddIndexDefine(const std::string & indexName,const CompositeFields & indexDefine)337 void TableInfo::AddIndexDefine(const std::string &indexName, const CompositeFields &indexDefine)
338 {
339 indexDefines_[indexName] = indexDefine;
340 }
341
SetUniqueDefine(const std::vector<CompositeFields> & uniqueDefine)342 void TableInfo::SetUniqueDefine(const std::vector<CompositeFields> &uniqueDefine)
343 {
344 uniqueDefines_ = uniqueDefine;
345 std::sort(uniqueDefines_.begin(), uniqueDefines_.end());
346 }
347
GetPrimaryKey() const348 const std::map<int, FieldName> &TableInfo::GetPrimaryKey() const
349 {
350 return primaryKey_;
351 }
352
IsPrimaryKey(const std::string & colName) const353 bool TableInfo::IsPrimaryKey(const std::string &colName) const
354 {
355 for (const auto &item : primaryKey_) {
356 if (colName == item.second) {
357 return true;
358 }
359 }
360 return false;
361 }
362
IsUniqueField(const std::string & colName) const363 bool TableInfo::IsUniqueField(const std::string &colName) const
364 {
365 for (const auto &unique : uniqueDefines_) {
366 for (const auto &it : unique) {
367 if (colName == it) {
368 return true;
369 }
370 }
371 }
372 return false;
373 }
374
GetIdentifyKey() const375 CompositeFields TableInfo::GetIdentifyKey() const
376 {
377 if (primaryKey_.size() == 1 && primaryKey_.at(0) == ROW_ID) {
378 if (!uniqueDefines_.empty()) { // LCOV_EXCL_BR_LINE
379 return uniqueDefines_.at(0);
380 }
381 }
382 CompositeFields key;
383 for (const auto &it : primaryKey_) {
384 key.emplace_back(it.second);
385 }
386 return key;
387 }
388
SetPrimaryKey(const std::map<int,FieldName> & key)389 void TableInfo::SetPrimaryKey(const std::map<int, FieldName> &key)
390 {
391 primaryKey_ = key;
392 }
393
SetPrimaryKey(const FieldName & fieldName,int keyIndex)394 void TableInfo::SetPrimaryKey(const FieldName &fieldName, int keyIndex)
395 {
396 if (keyIndex <= 0) {
397 LOGW("Set primary key index %d less than or equal to 0", keyIndex);
398 return;
399 }
400
401 primaryKey_[keyIndex - 1] = fieldName;
402 }
403
AddFieldDefineString(std::string & attrStr) const404 void TableInfo::AddFieldDefineString(std::string &attrStr) const
405 {
406 if (fields_.empty()) {
407 return;
408 }
409 attrStr += R"("DEFINE": {)";
410 for (auto itField = fields_.begin(); itField != fields_.end(); ++itField) {
411 attrStr += itField->second.ToAttributeString();
412 if (itField != std::prev(fields_.end(), 1)) {
413 attrStr += ",";
414 }
415 }
416 attrStr += "},";
417 }
418
AddIndexDefineString(std::string & attrStr) const419 void TableInfo::AddIndexDefineString(std::string &attrStr) const
420 {
421 if (indexDefines_.empty()) {
422 return;
423 }
424 attrStr += R"(,"INDEX": {)";
425 for (auto itIndexDefine = indexDefines_.begin(); itIndexDefine != indexDefines_.end(); ++itIndexDefine) {
426 attrStr += "\"" + (*itIndexDefine).first + "\": [\"";
427 for (auto itField = itIndexDefine->second.begin(); itField != itIndexDefine->second.end(); ++itField) {
428 attrStr += *itField;
429 if (itField != itIndexDefine->second.end() - 1) {
430 attrStr += "\",\"";
431 }
432 }
433 attrStr += "\"]";
434 if (itIndexDefine != std::prev(indexDefines_.end(), 1)) {
435 attrStr += ",";
436 }
437 }
438 attrStr += "}";
439 }
440
AddUniqueDefineString(std::string & attrStr) const441 void TableInfo::AddUniqueDefineString(std::string &attrStr) const
442 {
443 if (uniqueDefines_.empty()) {
444 return;
445 }
446
447 attrStr += R"("UNIQUE":[)";
448 for (const auto &unique : uniqueDefines_) {
449 attrStr += "[";
450 for (const auto &it : unique) {
451 attrStr += "\"" + it + "\",";
452 }
453 attrStr.pop_back();
454 attrStr += "],";
455 }
456 attrStr.pop_back();
457 attrStr += "],";
458 }
459
CompareWithTable(const TableInfo & inTableInfo,const std::string & schemaVersion) const460 int TableInfo::CompareWithTable(const TableInfo &inTableInfo, const std::string &schemaVersion) const
461 {
462 if (!DBCommon::CaseInsensitiveCompare(tableName_, inTableInfo.GetTableName())) {
463 LOGW("[Relational][Compare] Table name is not same");
464 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
465 }
466
467 int primaryKeyResult = CompareWithPrimaryKey(primaryKey_, inTableInfo.GetPrimaryKey());
468 if (primaryKeyResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
469 LOGW("[Relational][Compare] Table primary key is not same");
470 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
471 }
472
473 int fieldCompareResult = CompareWithTableFields(inTableInfo.GetFields());
474 if (fieldCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
475 LOGW("[Relational][Compare] Compare table fields with in table, %d", fieldCompareResult);
476 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
477 }
478
479 if (schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1) {
480 int uniqueCompareResult = CompareWithTableUnique(inTableInfo.GetUniqueDefine());
481 if (uniqueCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
482 LOGW("[Relational][Compare] Compare table unique with in table, %d", fieldCompareResult);
483 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
484 }
485
486 if (autoInc_ != inTableInfo.GetAutoIncrement()) {
487 LOGW("[Relational][Compare] Compare table auto increment with in table");
488 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
489 }
490 }
491
492 int indexCompareResult = CompareWithTableIndex(inTableInfo.GetIndexDefine());
493 return (fieldCompareResult == -E_RELATIONAL_TABLE_EQUAL) ? indexCompareResult : fieldCompareResult;
494 }
495
CompareWithPrimaryKey(const std::map<int,FieldName> & local,const std::map<int,FieldName> & remote) const496 int TableInfo::CompareWithPrimaryKey(const std::map<int, FieldName> &local,
497 const std::map<int, FieldName> &remote) const
498 {
499 if (local.size() != remote.size()) {
500 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
501 }
502
503 for (size_t i = 0; i < local.size(); i++) {
504 if (local.find(i) == local.end() || remote.find(i) == remote.end() ||
505 !DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
506 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
507 }
508 }
509
510 return -E_RELATIONAL_TABLE_EQUAL;
511 }
512
CompareWithTableFields(const FieldInfoMap & inTableFields,bool isLite) const513 int TableInfo::CompareWithTableFields(const FieldInfoMap &inTableFields, bool isLite) const
514 {
515 auto itLocal = fields_.begin();
516 auto itInTable = inTableFields.begin();
517 int errCode = -E_RELATIONAL_TABLE_EQUAL;
518 while (itLocal != fields_.end() && itInTable != inTableFields.end()) {
519 if (DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first)) { // Same field
520 if (!itLocal->second.CompareWithField(itInTable->second, isLite)) { // Compare field
521 LOGW("[Relational][Compare] Table field is incompatible"); // not compatible
522 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
523 }
524 itLocal++; // Compare next field
525 } else { // Assume local table fields is a subset of in table
526 if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) { // Upgrade field not compatible
527 LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
528 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
529 }
530 errCode = -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
531 }
532 itInTable++; // Next in table field
533 }
534
535 if (itLocal != fields_.end()) {
536 LOGW("[Relational][Compare] Table field is missing");
537 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
538 }
539
540 if (itInTable == inTableFields.end()) {
541 return errCode;
542 }
543
544 while (itInTable != inTableFields.end()) {
545 if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) {
546 LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
547 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
548 }
549 itInTable++;
550 }
551 return -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
552 }
553
CompareCompositeFields(const CompositeFields & local,const CompositeFields & remote) const554 int TableInfo::CompareCompositeFields(const CompositeFields &local, const CompositeFields &remote) const
555 {
556 if (local.size() != remote.size()) {
557 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
558 }
559
560 for (size_t i = 0; i < local.size(); i++) {
561 if (!DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
562 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
563 }
564 }
565
566 return -E_RELATIONAL_TABLE_EQUAL;
567 }
568
CompareWithTableUnique(const std::vector<CompositeFields> & inTableUnique) const569 int TableInfo::CompareWithTableUnique(const std::vector<CompositeFields> &inTableUnique) const
570 {
571 if (uniqueDefines_.size() != inTableUnique.size()) {
572 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
573 }
574
575 auto itLocal = uniqueDefines_.begin();
576 auto itInTable = inTableUnique.begin();
577 while (itLocal != uniqueDefines_.end()) {
578 if (CompareCompositeFields(*itLocal, *itInTable) != -E_RELATIONAL_TABLE_EQUAL) {
579 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
580 }
581 itLocal++;
582 itInTable++;
583 }
584 return -E_RELATIONAL_TABLE_EQUAL;
585 }
586
CompareWithTableIndex(const IndexInfoMap & inTableIndex) const587 int TableInfo::CompareWithTableIndex(const IndexInfoMap &inTableIndex) const
588 {
589 // Index comparison results do not affect synchronization decisions
590 auto itLocal = indexDefines_.begin();
591 auto itInTable = inTableIndex.begin();
592 while (itLocal != indexDefines_.end() && itInTable != inTableIndex.end()) {
593 if (!DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first) ||
594 !CompareCompositeFields(itLocal->second, itInTable->second)) {
595 return -E_RELATIONAL_TABLE_COMPATIBLE;
596 }
597 itLocal++;
598 itInTable++;
599 }
600 return (itLocal == indexDefines_.end() && itInTable == inTableIndex.end()) ? -E_RELATIONAL_TABLE_EQUAL :
601 -E_RELATIONAL_TABLE_COMPATIBLE;
602 }
603
604 namespace {
Difference(const FieldInfoMap & first,const FieldInfoMap & second,FieldInfoMap & orphanFst,FieldInfoMap & orphanSnd,FieldInfoMap & bothAppear)605 void Difference(const FieldInfoMap &first, const FieldInfoMap &second, FieldInfoMap &orphanFst, FieldInfoMap &orphanSnd,
606 FieldInfoMap &bothAppear)
607 {
608 auto itFirst = first.begin();
609 auto itSecond = second.begin();
610 while (itFirst != first.end()) { // LCOV_EXCL_BR_LINE
611 if (itSecond == second.end()) { // LCOV_EXCL_BR_LINE
612 break;
613 }
614 if (itFirst->first == itSecond->first) { // LCOV_EXCL_BR_LINE
615 bothAppear.insert(*itFirst);
616 itFirst++;
617 itSecond++;
618 continue;
619 } else if (itFirst->first < itSecond->first) {
620 orphanFst.insert(*itFirst++);
621 } else {
622 orphanSnd.insert(*itSecond++);
623 }
624 }
625
626 while (itFirst != first.end()) { // LCOV_EXCL_BR_LINE
627 orphanFst.insert(*itFirst++);
628 }
629
630 while (itSecond != second.end()) { // LCOV_EXCL_BR_LINE
631 orphanSnd.insert(*itSecond++);
632 }
633 }
634 }
635
CompareWithLiteTableFields(const FieldInfoMap & liteTableFields) const636 int TableInfo::CompareWithLiteTableFields(const FieldInfoMap &liteTableFields) const
637 {
638 FieldInfoMap orphanLocal;
639 FieldInfoMap orphanLite;
640 FieldInfoMap bothAppear;
641 Difference(fields_, liteTableFields, orphanLocal, orphanLite, bothAppear);
642
643 if (!orphanLocal.empty() && !orphanLite.empty()) { // LCOV_EXCL_BR_LINE
644 LOGE("[Relational][Compare] Only one side should have upgrade fields");
645 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
646 }
647
648 for (const auto &it : bothAppear) {
649 if (!it.second.CompareWithField(liteTableFields.at(it.first), true)) { // LCOV_EXCL_BR_LINE
650 LOGE("[Relational][Compare] field is incompatible");
651 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
652 }
653 }
654
655 for (const auto &it : orphanLocal) {
656 if (it.second.IsNotNull() && !it.second.HasDefaultValue()) { // LCOV_EXCL_BR_LINE
657 LOGE("[Relational][Compare] field is upgrade incompatible");
658 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
659 }
660 }
661
662 for (const auto &it : orphanLite) {
663 if (it.second.IsNotNull() && !it.second.HasDefaultValue()) { // LCOV_EXCL_BR_LINE
664 LOGE("[Relational][Compare] field is upgrade incompatible");
665 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
666 }
667 }
668
669 return E_OK;
670 }
671
CompareWithLiteSchemaTable(const TableInfo & liteTableInfo) const672 int TableInfo::CompareWithLiteSchemaTable(const TableInfo &liteTableInfo) const
673 {
674 if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) &&
675 !CompareWithPrimaryKey(primaryKey_, liteTableInfo.GetPrimaryKey())) { // LCOV_EXCL_BR_LINE
676 LOGE("[Relational][Compare] Table primary key is not same");
677 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
678 }
679 if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) == ROW_ID)) { // LCOV_EXCL_BR_LINE
680 LOGE("[Relational][Compare] Table primary key is not same");
681 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
682 }
683 if ((liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) && !autoInc_)) { // LCOV_EXCL_BR_LINE
684 LOGE("[Relational][Compare] Table primary key is not same");
685 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
686 }
687
688 return CompareWithLiteTableFields(liteTableInfo.GetFields());
689 }
690
ToTableInfoString(const std::string & schemaVersion) const691 std::string TableInfo::ToTableInfoString(const std::string &schemaVersion) const
692 {
693 std::string attrStr;
694 attrStr += "{";
695 attrStr += R"("NAME": ")" + tableName_ + "\",";
696 AddFieldDefineString(attrStr);
697 attrStr += R"("ORIGINTABLENAME": ")" + originTableName_ + "\",";
698 attrStr += R"("AUTOINCREMENT": )";
699 if (autoInc_) {
700 attrStr += "true,";
701 } else {
702 attrStr += "false,";
703 }
704 attrStr += R"("SHAREDTABLEMARK": )";
705 if (sharedTableMark_) {
706 attrStr += "true,";
707 } else {
708 attrStr += "false,";
709 }
710 AddUniqueDefineString(attrStr);
711 if (primaryKey_.size() == 1 && schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) {
712 attrStr += R"("PRIMARY_KEY": ")" + primaryKey_.at(0) + "\"";
713 } else {
714 if (!primaryKey_.empty()) {
715 std::string primaryKey;
716 for (const auto &item : primaryKey_) {
717 primaryKey += "\"" + item.second + "\",";
718 }
719 primaryKey.pop_back(); // remove the last comma
720 attrStr += R"("PRIMARY_KEY": [)" + primaryKey + "]";
721 }
722 }
723 attrStr += R"(,"TABLE_SYNC_TYPE": )" + std::to_string(static_cast<int>(tableSyncType_));
724 AddIndexDefineString(attrStr);
725 attrStr += "}";
726 return attrStr;
727 }
728
GetSchemaDefine() const729 std::map<FieldPath, SchemaAttribute> TableInfo::GetSchemaDefine() const
730 {
731 std::map<FieldPath, SchemaAttribute> schemaDefine;
732 for (const auto &[fieldName, fieldInfo] : GetFields()) {
733 FieldValue defaultValue;
734 defaultValue.stringValue = fieldInfo.GetDefaultValue();
735 schemaDefine[std::vector { DBCommon::ToLowerCase(fieldName) }] = SchemaAttribute {
736 .type = FieldType::LEAF_FIELD_NULL, // For relational schema, the json field type is unimportant.
737 .isIndexable = true, // For relational schema, all field is indexable.
738 .hasNotNullConstraint = fieldInfo.IsNotNull(),
739 .hasDefaultValue = fieldInfo.HasDefaultValue(),
740 .defaultValue = defaultValue,
741 .customFieldType = {}
742 };
743 }
744 return schemaDefine;
745 }
746
SetTableId(int id)747 void TableInfo::SetTableId(int id)
748 {
749 id_ = id;
750 }
751
GetTableId() const752 int TableInfo::GetTableId() const
753 {
754 return id_;
755 }
756
Empty() const757 bool TableInfo::Empty() const
758 {
759 return tableName_.empty() || fields_.empty();
760 }
761
SetTrackerTable(const TrackerTable & table)762 void TableInfo::SetTrackerTable(const TrackerTable &table)
763 {
764 trackerTable_ = table;
765 }
766
CheckTrackerTable()767 int TableInfo::CheckTrackerTable()
768 {
769 if (tableName_ != trackerTable_.GetTableName()) {
770 LOGE("the table name in schema is different from tracker table.");
771 return -E_NOT_FOUND;
772 }
773 const std::string tableName = DBCommon::StringMiddleMasking(tableName_);
774 size_t nameLength = tableName_.size();
775 for (const auto &colName: trackerTable_.GetTrackerColNames()) {
776 if (colName.empty()) {
777 LOGE("[%s [%zu]] tracker col cannot be empty.", tableName.c_str(), nameLength);
778 return -E_INVALID_ARGS;
779 }
780 if (GetFields().find(colName) == GetFields().end()) {
781 LOGE("[%s [%zu]] unable to match the tracker col from table schema.", tableName.c_str(), nameLength);
782 return -E_SCHEMA_MISMATCH;
783 }
784 }
785 for (const auto &colName : trackerTable_.GetExtendNames()) {
786 if (colName.empty()) {
787 LOGE("[%s [%zu]] extend col cannot be empty.", tableName.c_str(), nameLength);
788 return -E_INVALID_ARGS;
789 }
790 auto iter = GetFields().find(colName);
791 if (iter == GetFields().end()) {
792 LOGE("[%s [%zu]] unable to match the extend col from table schema.", tableName.c_str(), nameLength);
793 return -E_SCHEMA_MISMATCH;
794 } else {
795 if (iter->second.IsAssetType() || iter->second.IsAssetsType()) {
796 LOGE("[%s [%zu]] extend col is not allowed to be set as asset field.", tableName.c_str(), nameLength);
797 return -E_INVALID_ARGS;
798 }
799 }
800 }
801 return E_OK;
802 }
803
GetTrackerTable() const804 const TrackerTable &TableInfo::GetTrackerTable() const
805 {
806 return trackerTable_;
807 }
808
AddTableReferenceProperty(const TableReferenceProperty & tableRefProperty)809 void TableInfo::AddTableReferenceProperty(const TableReferenceProperty &tableRefProperty)
810 {
811 sourceTableReferenced_.push_back(tableRefProperty);
812 }
813
SetSourceTableReference(const std::vector<TableReferenceProperty> & tableReference)814 void TableInfo::SetSourceTableReference(const std::vector<TableReferenceProperty> &tableReference)
815 {
816 sourceTableReferenced_ = tableReference;
817 }
818
GetTableReference() const819 const std::vector<TableReferenceProperty> &TableInfo::GetTableReference() const
820 {
821 return sourceTableReferenced_;
822 }
823
IsNoPkTable() const824 bool TableInfo::IsNoPkTable() const
825 {
826 if (primaryKey_.size() == 1 && primaryKey_.at(0) == ROW_ID) {
827 return true;
828 }
829 return false;
830 }
831
IsMultiPkTable() const832 bool TableInfo::IsMultiPkTable() const
833 {
834 return primaryKey_.size() > 1;
835 }
836
IsFieldExist(const std::string & fieldName) const837 bool TableInfo::IsFieldExist(const std::string &fieldName) const
838 {
839 if (fields_.find(fieldName) != fields_.end()) {
840 return true;
841 }
842 LOGE("[TableInfo][IsFieldExist] table %s table len %zu not exist field %s",
843 DBCommon::StringMiddleMasking(tableName_).c_str(), tableName_.size(),
844 DBCommon::StringMiddleMasking(fieldName).c_str());
845 return false;
846 }
847
SetDistributedTable(const DistributedTable & distributedTable)848 void TableInfo::SetDistributedTable(const DistributedTable &distributedTable)
849 {
850 distributedTable_ = distributedTable;
851 }
852
GetSyncField() const853 std::vector<std::string> TableInfo::GetSyncField() const
854 {
855 std::vector<std::string> res;
856 for (const auto &item : distributedTable_.fields) {
857 if (item.isP2pSync) {
858 res.push_back(item.colName);
859 }
860 }
861 return res;
862 }
863
GetSyncDistributedPk() const864 std::vector<std::string> TableInfo::GetSyncDistributedPk() const
865 {
866 std::vector<std::string> res;
867 for (const auto &item : distributedTable_.fields) {
868 if (item.isP2pSync && item.isSpecified) {
869 res.push_back(item.colName);
870 }
871 }
872 return res;
873 }
874
GetUniqueAndPkDefine() const875 const std::vector<CompositeFields> TableInfo::GetUniqueAndPkDefine() const
876 {
877 std::vector<CompositeFields> res = uniqueDefines_;
878 res.push_back(GetIdentifyKey());
879 return res;
880 }
881 } // namespace DistributeDB