• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #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 = "asset";
25 constexpr const char *ASSETS = "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 {
106         storageType_ = AffinityType(dataType_);
107     }
108 }
109 
IsNotNull() const110 bool FieldInfo::IsNotNull() const
111 {
112     return isNotNull_;
113 }
114 
SetNotNull(bool isNotNull)115 void FieldInfo::SetNotNull(bool isNotNull)
116 {
117     isNotNull_ = isNotNull;
118 }
119 
HasDefaultValue() const120 bool FieldInfo::HasDefaultValue() const
121 {
122     return hasDefaultValue_;
123 }
124 
GetDefaultValue() const125 const std::string &FieldInfo::GetDefaultValue() const
126 {
127     return defaultValue_;
128 }
129 
SetDefaultValue(const std::string & value)130 void FieldInfo::SetDefaultValue(const std::string &value)
131 {
132     hasDefaultValue_ = true;
133     defaultValue_ = value;
134 }
135 
136 // convert to StorageType according "Determination Of Column Affinity"
GetStorageType() const137 StorageType FieldInfo::GetStorageType() const
138 {
139     return storageType_;
140 }
141 
SetStorageType(StorageType storageType)142 void FieldInfo::SetStorageType(StorageType storageType)
143 {
144     storageType_ = storageType;
145 }
146 
GetColumnId() const147 int FieldInfo::GetColumnId() const
148 {
149     return cid_;
150 }
151 
SetColumnId(int cid)152 void FieldInfo::SetColumnId(int cid)
153 {
154     cid_ = cid;
155 }
156 
ToAttributeString() const157 std::string FieldInfo::ToAttributeString() const
158 {
159     std::string attrStr = "\"" + fieldName_ + "\": {";
160     attrStr += "\"COLUMN_ID\":" + std::to_string(cid_) + ",";
161     attrStr += "\"TYPE\":\"" + dataType_ + "\",";
162     attrStr += "\"NOT_NULL\":" + std::string(isNotNull_ ? "true" : "false");
163     if (hasDefaultValue_) {
164         attrStr += ",";
165         attrStr += "\"DEFAULT\":\"" + defaultValue_ + "\"";
166     }
167     attrStr += "}";
168     return attrStr;
169 }
170 
CompareWithField(const FieldInfo & inField,bool isLite) const171 int FieldInfo::CompareWithField(const FieldInfo &inField, bool isLite) const
172 {
173     if (!DBCommon::CaseInsensitiveCompare(fieldName_, inField.GetFieldName()) || isNotNull_ != inField.IsNotNull()) {
174         return false;
175     }
176     if (isLite) {
177         if (storageType_ != inField.GetStorageType()) {
178             return false;
179         }
180     } else {
181         if (dataType_ != inField.GetDataType()) {
182             return false;
183         }
184     }
185     if (hasDefaultValue_ && inField.HasDefaultValue()) {
186         // lite schema only uses NULL as default value
187         return (isLite && DBCommon::CaseInsensitiveCompare(defaultValue_, "NULL")) ||
188             (DBCommon::CaseInsensitiveCompare(defaultValue_, "NULL") &&
189             DBCommon::CaseInsensitiveCompare(inField.GetDefaultValue(), "NULL")) ||
190             (defaultValue_ == inField.GetDefaultValue());
191     }
192     return hasDefaultValue_ == inField.HasDefaultValue();
193 }
194 
IsAssetType() const195 bool FieldInfo::IsAssetType() const
196 {
197     return strcasecmp(dataType_.c_str(), ASSET) == 0;
198 }
199 
IsAssetsType() const200 bool FieldInfo::IsAssetsType() const
201 {
202     return strcasecmp(dataType_.c_str(), ASSETS) == 0;
203 }
204 
GetCollateType() const205 CollateType FieldInfo::GetCollateType() const
206 {
207     return collateType_;
208 }
209 
SetCollateType(CollateType collateType)210 void FieldInfo::SetCollateType(CollateType collateType)
211 {
212     collateType_ = collateType;
213 }
214 
GetTableName() const215 const std::string &TableInfo::GetTableName() const
216 {
217     return tableName_;
218 }
219 
SetTableName(const std::string & tableName)220 void TableInfo::SetTableName(const std::string &tableName)
221 {
222     tableName_ = tableName;
223 }
224 
GetOriginTableName() const225 const std::string &TableInfo::GetOriginTableName() const
226 {
227     return originTableName_;
228 }
229 
SetOriginTableName(const std::string & originTableName)230 void TableInfo::SetOriginTableName(const std::string &originTableName)
231 {
232     originTableName_ = originTableName;
233 }
234 
SetSharedTableMark(bool sharedTableMark)235 void TableInfo::SetSharedTableMark(bool sharedTableMark)
236 {
237     sharedTableMark_ = sharedTableMark;
238 }
239 
GetSharedTableMark() const240 bool TableInfo::GetSharedTableMark() const
241 {
242     return sharedTableMark_;
243 }
244 
SetAutoIncrement(bool autoInc)245 void TableInfo::SetAutoIncrement(bool autoInc)
246 {
247     autoInc_ = autoInc;
248 }
249 
GetAutoIncrement() const250 bool TableInfo::GetAutoIncrement() const
251 {
252     return autoInc_;
253 }
254 
SetTableSyncType(TableSyncType tableSyncType)255 void TableInfo::SetTableSyncType(TableSyncType tableSyncType)
256 {
257     tableSyncType_ = tableSyncType;
258 }
259 
GetTableSyncType() const260 TableSyncType TableInfo::GetTableSyncType() const
261 {
262     return tableSyncType_;
263 }
264 
GetCreateTableSql() const265 const std::string &TableInfo::GetCreateTableSql() const
266 {
267     return sql_;
268 }
269 
SetCreateTableSql(const std::string & sql)270 void TableInfo::SetCreateTableSql(const std::string &sql)
271 {
272     sql_ = sql;
273     for (auto &c : sql_) {
274         c = static_cast<char>(std::toupper(c));
275     }
276     if (DBCommon::HasConstraint(DBCommon::TrimSpace(sql_), "AUTOINCREMENT", " ", " ,)")) {
277         autoInc_ = true;
278     }
279 }
280 
GetFields() const281 const FieldInfoMap &TableInfo::GetFields() const
282 {
283     return fields_;
284 }
285 
GetFieldInfos() const286 const std::vector<FieldInfo> &TableInfo::GetFieldInfos() const
287 {
288     if (!fieldInfos_.empty() && fieldInfos_.size() == fields_.size()) {
289         return fieldInfos_;
290     }
291     fieldInfos_.resize(fields_.size());
292     if (fieldInfos_.size() != fields_.size()) {
293         LOGE("GetField error, alloc memory failed.");
294         return fieldInfos_;
295     }
296     for (const auto &entry : fields_) {
297         if (static_cast<size_t>(entry.second.GetColumnId()) >= fieldInfos_.size()) {
298             LOGE("Cid is over field size.");
299             fieldInfos_.clear();
300             return fieldInfos_;
301         }
302         fieldInfos_.at(entry.second.GetColumnId()) = entry.second;
303     }
304     return fieldInfos_;
305 }
306 
GetFieldName(uint32_t cid) const307 std::string TableInfo::GetFieldName(uint32_t cid) const
308 {
309     if (cid >= fields_.size() || GetFieldInfos().empty()) {
310         return {};
311     }
312     return GetFieldInfos().at(cid).GetFieldName();
313 }
314 
IsValid() const315 bool TableInfo::IsValid() const
316 {
317     return !tableName_.empty();
318 }
319 
AddField(const FieldInfo & field)320 void TableInfo::AddField(const FieldInfo &field)
321 {
322     fields_[field.GetFieldName()] = field;
323 }
324 
GetIndexDefine() const325 const IndexInfoMap &TableInfo::GetIndexDefine() const
326 {
327     return indexDefines_;
328 }
329 
GetUniqueDefine() const330 const std::vector<CompositeFields> &TableInfo::GetUniqueDefine() const
331 {
332     return uniqueDefines_;
333 }
334 
AddIndexDefine(const std::string & indexName,const CompositeFields & indexDefine)335 void TableInfo::AddIndexDefine(const std::string &indexName, const CompositeFields &indexDefine)
336 {
337     indexDefines_[indexName] = indexDefine;
338 }
339 
SetUniqueDefine(const std::vector<CompositeFields> & uniqueDefine)340 void TableInfo::SetUniqueDefine(const std::vector<CompositeFields> &uniqueDefine)
341 {
342     uniqueDefines_ = uniqueDefine;
343     std::sort(uniqueDefines_.begin(), uniqueDefines_.end());
344 }
345 
GetPrimaryKey() const346 const std::map<int, FieldName> &TableInfo::GetPrimaryKey() const
347 {
348     return primaryKey_;
349 }
350 
GetIdentifyKey() const351 CompositeFields TableInfo::GetIdentifyKey() const
352 {
353     if (primaryKey_.size() == 1 && primaryKey_.at(0) == ROW_ID) {
354         if (!uniqueDefines_.empty()) {
355             return uniqueDefines_.at(0);
356         }
357     }
358     CompositeFields key;
359     for (const auto &it : primaryKey_) {
360         key.emplace_back(it.second);
361     }
362     return key;
363 }
364 
SetPrimaryKey(const std::map<int,FieldName> & key)365 void TableInfo::SetPrimaryKey(const std::map<int, FieldName> &key)
366 {
367     primaryKey_ = key;
368 }
369 
SetPrimaryKey(const FieldName & fieldName,int keyIndex)370 void TableInfo::SetPrimaryKey(const FieldName &fieldName, int keyIndex)
371 {
372     if (keyIndex <= 0) {
373         LOGW("Set primary key index %d less than or equal to 0", keyIndex);
374         return;
375     }
376 
377     primaryKey_[keyIndex - 1] = fieldName;
378 }
379 
AddFieldDefineString(std::string & attrStr) const380 void TableInfo::AddFieldDefineString(std::string &attrStr) const
381 {
382     if (fields_.empty()) {
383         return;
384     }
385     attrStr += R"("DEFINE": {)";
386     for (auto itField = fields_.begin(); itField != fields_.end(); ++itField) {
387         attrStr += itField->second.ToAttributeString();
388         if (itField != std::prev(fields_.end(), 1)) {
389             attrStr += ",";
390         }
391     }
392     attrStr += "},";
393 }
394 
AddIndexDefineString(std::string & attrStr) const395 void TableInfo::AddIndexDefineString(std::string &attrStr) const
396 {
397     if (indexDefines_.empty()) {
398         return;
399     }
400     attrStr += R"(,"INDEX": {)";
401     for (auto itIndexDefine = indexDefines_.begin(); itIndexDefine != indexDefines_.end(); ++itIndexDefine) {
402         attrStr += "\"" + (*itIndexDefine).first + "\": [\"";
403         for (auto itField = itIndexDefine->second.begin(); itField != itIndexDefine->second.end(); ++itField) {
404             attrStr += *itField;
405             if (itField != itIndexDefine->second.end() - 1) {
406                 attrStr += "\",\"";
407             }
408         }
409         attrStr += "\"]";
410         if (itIndexDefine != std::prev(indexDefines_.end(), 1)) {
411             attrStr += ",";
412         }
413     }
414     attrStr += "}";
415 }
416 
AddUniqueDefineString(std::string & attrStr) const417 void TableInfo::AddUniqueDefineString(std::string &attrStr) const
418 {
419     if (uniqueDefines_.empty()) {
420         return;
421     }
422 
423     attrStr += R"("UNIQUE":[)";
424     for (const auto &unique : uniqueDefines_) {
425         attrStr += "[";
426         for (const auto &it : unique) {
427             attrStr += "\"" + it + "\",";
428         }
429         attrStr.pop_back();
430         attrStr += "],";
431     }
432     attrStr.pop_back();
433     attrStr += "],";
434 }
435 
CompareWithTable(const TableInfo & inTableInfo,const std::string & schemaVersion) const436 int TableInfo::CompareWithTable(const TableInfo &inTableInfo, const std::string &schemaVersion) const
437 {
438     if (!DBCommon::CaseInsensitiveCompare(tableName_, inTableInfo.GetTableName())) {
439         LOGW("[Relational][Compare] Table name is not same");
440         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
441     }
442 
443     int primaryKeyResult = CompareWithPrimaryKey(primaryKey_, inTableInfo.GetPrimaryKey());
444     if (primaryKeyResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
445         LOGW("[Relational][Compare] Table primary key is not same");
446         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
447     }
448 
449     int fieldCompareResult = CompareWithTableFields(inTableInfo.GetFields());
450     if (fieldCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
451         LOGW("[Relational][Compare] Compare table fields with in table, %d", fieldCompareResult);
452         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
453     }
454 
455     if (schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1) {
456         int uniqueCompareResult = CompareWithTableUnique(inTableInfo.GetUniqueDefine());
457         if (uniqueCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
458             LOGW("[Relational][Compare] Compare table unique with in table, %d", fieldCompareResult);
459             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
460         }
461 
462         if (autoInc_ != inTableInfo.GetAutoIncrement()) {
463             LOGW("[Relational][Compare] Compare table auto increment with in table");
464             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
465         }
466     }
467 
468     int indexCompareResult = CompareWithTableIndex(inTableInfo.GetIndexDefine());
469     return (fieldCompareResult == -E_RELATIONAL_TABLE_EQUAL) ? indexCompareResult : fieldCompareResult;
470 }
471 
CompareWithPrimaryKey(const std::map<int,FieldName> & local,const std::map<int,FieldName> & remote) const472 int TableInfo::CompareWithPrimaryKey(const std::map<int, FieldName> &local,
473     const std::map<int, FieldName> &remote) const
474 {
475     if (local.size() != remote.size()) {
476         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
477     }
478 
479     for (size_t i = 0; i < local.size(); i++) {
480         if (local.find(i) == local.end() || remote.find(i) == remote.end() ||
481             !DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
482             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
483         }
484     }
485 
486     return -E_RELATIONAL_TABLE_EQUAL;
487 }
488 
CompareWithTableFields(const FieldInfoMap & inTableFields,bool isLite) const489 int TableInfo::CompareWithTableFields(const FieldInfoMap &inTableFields, bool isLite) const
490 {
491     auto itLocal = fields_.begin();
492     auto itInTable = inTableFields.begin();
493     int errCode = -E_RELATIONAL_TABLE_EQUAL;
494     while (itLocal != fields_.end() && itInTable != inTableFields.end()) {
495         if (DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first)) { // Same field
496             if (!itLocal->second.CompareWithField(itInTable->second, isLite)) { // Compare field
497                 LOGW("[Relational][Compare] Table field is incompatible"); // not compatible
498                 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
499             }
500             itLocal++; // Compare next field
501         } else { // Assume local table fields is a subset of in table
502             if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) { // Upgrade field not compatible
503                 LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
504                 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
505             }
506             errCode = -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
507         }
508         itInTable++; // Next in table field
509     }
510 
511     if (itLocal != fields_.end()) {
512         LOGW("[Relational][Compare] Table field is missing");
513         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
514     }
515 
516     if (itInTable == inTableFields.end()) {
517         return errCode;
518     }
519 
520     while (itInTable != inTableFields.end()) {
521         if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) {
522             LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
523             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
524         }
525         itInTable++;
526     }
527     return -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
528 }
529 
CompareCompositeFields(const CompositeFields & local,const CompositeFields & remote) const530 int TableInfo::CompareCompositeFields(const CompositeFields &local, const CompositeFields &remote) const
531 {
532     if (local.size() != remote.size()) {
533         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
534     }
535 
536     for (size_t i = 0; i < local.size(); i++) {
537         if (!DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
538             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
539         }
540     }
541 
542     return -E_RELATIONAL_TABLE_EQUAL;
543 }
544 
CompareWithTableUnique(const std::vector<CompositeFields> & inTableUnique) const545 int TableInfo::CompareWithTableUnique(const std::vector<CompositeFields> &inTableUnique) const
546 {
547     if (uniqueDefines_.size() != inTableUnique.size()) {
548         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
549     }
550 
551     auto itLocal = uniqueDefines_.begin();
552     auto itInTable = inTableUnique.begin();
553     while (itLocal != uniqueDefines_.end()) {
554         if (CompareCompositeFields(*itLocal, *itInTable) != -E_RELATIONAL_TABLE_EQUAL) {
555             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
556         }
557         itLocal++;
558         itInTable++;
559     }
560     return -E_RELATIONAL_TABLE_EQUAL;
561 }
562 
CompareWithTableIndex(const IndexInfoMap & inTableIndex) const563 int TableInfo::CompareWithTableIndex(const IndexInfoMap &inTableIndex) const
564 {
565     // Index comparison results do not affect synchronization decisions
566     auto itLocal = indexDefines_.begin();
567     auto itInTable = inTableIndex.begin();
568     while (itLocal != indexDefines_.end() && itInTable != inTableIndex.end()) {
569         if (!DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first) ||
570             !CompareCompositeFields(itLocal->second, itInTable->second)) {
571             return -E_RELATIONAL_TABLE_COMPATIBLE;
572         }
573         itLocal++;
574         itInTable++;
575     }
576     return (itLocal == indexDefines_.end() && itInTable == inTableIndex.end()) ? -E_RELATIONAL_TABLE_EQUAL :
577         -E_RELATIONAL_TABLE_COMPATIBLE;
578 }
579 
580 
581 namespace {
Difference(const FieldInfoMap & first,const FieldInfoMap & second,FieldInfoMap & orphanFst,FieldInfoMap & orphanSnd,FieldInfoMap & bothAppear)582 void Difference(const FieldInfoMap &first, const FieldInfoMap &second, FieldInfoMap &orphanFst, FieldInfoMap &orphanSnd,
583     FieldInfoMap &bothAppear)
584 {
585     auto itFirst = first.begin();
586     auto itSecond = second.begin();
587     while (itFirst != first.end()) {
588         if (itSecond == second.end()) {
589             break;
590         }
591         if (itFirst->first == itSecond->first) {
592             bothAppear.insert(*itFirst);
593             itFirst++;
594             itSecond++;
595             continue;
596         } else if (itFirst->first < itSecond->first) {
597             orphanFst.insert(*itFirst++);
598         } else {
599             orphanSnd.insert(*itSecond++);
600         }
601     }
602 
603     while (itFirst != first.end()) {
604         orphanFst.insert(*itFirst++);
605     }
606 
607     while (itSecond != second.end()) {
608         orphanSnd.insert(*itSecond++);
609     }
610 }
611 }
612 
CompareWithLiteTableFields(const FieldInfoMap & liteTableFields) const613 int TableInfo::CompareWithLiteTableFields(const FieldInfoMap &liteTableFields) const
614 {
615     FieldInfoMap orphanLocal;
616     FieldInfoMap orphanLite;
617     FieldInfoMap bothAppear;
618     Difference(fields_, liteTableFields, orphanLocal, orphanLite, bothAppear);
619 
620     if (!orphanLocal.empty() && !orphanLite.empty()) {
621         LOGE("[Relational][Compare] Only one side should have upgrade fields");
622         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
623     }
624 
625     for (const auto &it : bothAppear) {
626         if (!it.second.CompareWithField(liteTableFields.at(it.first), true)) {
627             LOGE("[Relational][Compare] field is incompatible");
628             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
629         }
630     }
631 
632     for (const auto &it : orphanLocal) {
633         if (it.second.IsNotNull() && !it.second.HasDefaultValue()) {
634             LOGE("[Relational][Compare] field is upgrade incompatible");
635             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
636         }
637     }
638 
639     for (const auto &it : orphanLite) {
640         if (it.second.IsNotNull() && !it.second.HasDefaultValue()) {
641             LOGE("[Relational][Compare] field is upgrade incompatible");
642             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
643         }
644     }
645 
646     return E_OK;
647 }
648 
CompareWithLiteSchemaTable(const TableInfo & liteTableInfo) const649 int TableInfo::CompareWithLiteSchemaTable(const TableInfo &liteTableInfo) const
650 {
651     if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) &&
652         !CompareWithPrimaryKey(primaryKey_, liteTableInfo.GetPrimaryKey())) {
653         LOGE("[Relational][Compare] Table primary key is not same");
654         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
655     }
656     if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) == ROW_ID)) {
657         LOGE("[Relational][Compare] Table primary key is not same");
658         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
659     }
660     if ((liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) && !autoInc_)) {
661         LOGE("[Relational][Compare] Table primary key is not same");
662         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
663     }
664 
665     return CompareWithLiteTableFields(liteTableInfo.GetFields());
666 }
667 
ToTableInfoString(const std::string & schemaVersion) const668 std::string TableInfo::ToTableInfoString(const std::string &schemaVersion) const
669 {
670     std::string attrStr;
671     attrStr += "{";
672     attrStr += R"("NAME": ")" + tableName_ + "\",";
673     AddFieldDefineString(attrStr);
674     attrStr += R"("ORIGINTABLENAME": ")" + originTableName_ + "\",";
675     attrStr += R"("AUTOINCREMENT": )";
676     if (autoInc_) {
677         attrStr += "true,";
678     } else {
679         attrStr += "false,";
680     }
681     attrStr += R"("SHAREDTABLEMARK": )";
682     if (sharedTableMark_) {
683         attrStr += "true,";
684     } else {
685         attrStr += "false,";
686     }
687     AddUniqueDefineString(attrStr);
688     if (primaryKey_.size() == 1 && schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) {
689         attrStr += R"("PRIMARY_KEY": ")" + primaryKey_.at(0) + "\"";
690     } else {
691         if (!primaryKey_.empty()) {
692             std::string primaryKey;
693             for (const auto &item : primaryKey_) {
694                 primaryKey += "\"" + item.second + "\",";
695             }
696             primaryKey.pop_back(); // remove the last comma
697             attrStr += R"("PRIMARY_KEY": [)" + primaryKey + "]";
698         }
699     }
700     attrStr += R"(,"TABLE_SYNC_TYPE": )" + std::to_string(static_cast<int>(tableSyncType_));
701     AddIndexDefineString(attrStr);
702     attrStr += "}";
703     return attrStr;
704 }
705 
GetSchemaDefine() const706 std::map<FieldPath, SchemaAttribute> TableInfo::GetSchemaDefine() const
707 {
708     std::map<FieldPath, SchemaAttribute> schemaDefine;
709     for (const auto &[fieldName, fieldInfo] : GetFields()) {
710         FieldValue defaultValue;
711         defaultValue.stringValue = fieldInfo.GetDefaultValue();
712         schemaDefine[std::vector { DBCommon::ToLowerCase(fieldName) }] = SchemaAttribute {
713             .type = FieldType::LEAF_FIELD_NULL,     // For relational schema, the json field type is unimportant.
714             .isIndexable = true,                    // For relational schema, all field is indexable.
715             .hasNotNullConstraint = fieldInfo.IsNotNull(),
716             .hasDefaultValue = fieldInfo.HasDefaultValue(),
717             .defaultValue = defaultValue,
718             .customFieldType = {}
719         };
720     }
721     return schemaDefine;
722 }
723 
SetTableId(int id)724 void TableInfo::SetTableId(int id)
725 {
726     id_ = id;
727 }
728 
GetTableId() const729 int TableInfo::GetTableId() const
730 {
731     return id_;
732 }
733 
Empty() const734 bool TableInfo::Empty() const
735 {
736     return tableName_.empty() || fields_.empty();
737 }
738 
SetTrackerTable(const TrackerTable & table)739 void TableInfo::SetTrackerTable(const TrackerTable &table)
740 {
741     trackerTable_ = table;
742 }
743 
CheckTrackerTable()744 int TableInfo::CheckTrackerTable()
745 {
746     if (tableName_ != trackerTable_.GetTableName()) {
747         LOGE("the table name in schema is different from tracker table.");
748         return -E_NOT_FOUND;
749     }
750     if (trackerTable_.GetTrackerColNames().empty()) {
751         return E_OK;
752     }
753     for (const auto &colName: trackerTable_.GetTrackerColNames()) {
754         if (colName.empty()) {
755             LOGE("tracker col cannot be empty.");
756             return -E_INVALID_ARGS;
757         }
758         if (GetFields().find(colName) == GetFields().end()) {
759             LOGE("unable to match the tracker col from table schema.");
760             return -E_SCHEMA_MISMATCH;
761         }
762     }
763     if (trackerTable_.GetExtendName().empty()) {
764         return E_OK;
765     }
766     auto iter = GetFields().find(trackerTable_.GetExtendName());
767     if (iter == GetFields().end()) {
768         LOGE("unable to match the extend col from table schema.");
769         return -E_SCHEMA_MISMATCH;
770     } else {
771         if (iter->second.IsAssetType() || iter->second.IsAssetsType()) {
772             LOGE("extend col is not allowed to be set as an asset field.");
773             return -E_INVALID_ARGS;
774         }
775     }
776     return E_OK;
777 }
778 
GetTrackerTable() const779 const TrackerTable &TableInfo::GetTrackerTable() const
780 {
781     return trackerTable_;
782 }
783 
AddTableReferenceProperty(const TableReferenceProperty & tableRefProperty)784 void TableInfo::AddTableReferenceProperty(const TableReferenceProperty &tableRefProperty)
785 {
786     sourceTableReferenced_.push_back(tableRefProperty);
787 }
788 
SetSourceTableReference(const std::vector<TableReferenceProperty> & tableReference)789 void TableInfo::SetSourceTableReference(const std::vector<TableReferenceProperty> &tableReference)
790 {
791     sourceTableReferenced_ = tableReference;
792 }
793 
GetTableReference() const794 const std::vector<TableReferenceProperty> &TableInfo::GetTableReference() const
795 {
796     return sourceTableReferenced_;
797 }
798 
IsNoPkTable() const799 bool TableInfo::IsNoPkTable() const
800 {
801     if (primaryKey_.size() == 1 && primaryKey_.at(0) == ROW_ID) {
802         return true;
803     }
804     return false;
805 }
806 } // namespace DistributeDB