• 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_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     if (fields_.size() > DBConstant::MAX_FIELD_NUM) {
294         LOGE("The number of fields is too large: %zu.", fields_.size());
295         fieldInfos_.clear();
296         return fieldInfos_;
297     }
298     fieldInfos_.resize(fields_.size());
299     if (fieldInfos_.size() != fields_.size()) {
300         LOGE("GetField error, alloc memory failed.");
301         return fieldInfos_;
302     }
303     for (const auto &entry : fields_) {
304         if (static_cast<size_t>(entry.second.GetColumnId()) >= fieldInfos_.size()) {
305             LOGE("Cid is over field size.");
306             fieldInfos_.clear();
307             return fieldInfos_;
308         }
309         fieldInfos_.at(entry.second.GetColumnId()) = entry.second;
310     }
311     return fieldInfos_;
312 }
313 
GetFieldName(uint32_t cid) const314 std::string TableInfo::GetFieldName(uint32_t cid) const
315 {
316     if (cid >= fields_.size() || GetFieldInfos().empty()) {
317         return {};
318     }
319     return GetFieldInfos().at(cid).GetFieldName();
320 }
321 
IsValid() const322 bool TableInfo::IsValid() const
323 {
324     return !tableName_.empty();
325 }
326 
AddField(const FieldInfo & field)327 void TableInfo::AddField(const FieldInfo &field)
328 {
329     fields_[field.GetFieldName()] = field;
330 }
331 
GetIndexDefine() const332 const IndexInfoMap &TableInfo::GetIndexDefine() const
333 {
334     return indexDefines_;
335 }
336 
GetUniqueDefine() const337 const std::vector<CompositeFields> &TableInfo::GetUniqueDefine() const
338 {
339     return uniqueDefines_;
340 }
341 
AddIndexDefine(const std::string & indexName,const CompositeFields & indexDefine)342 void TableInfo::AddIndexDefine(const std::string &indexName, const CompositeFields &indexDefine)
343 {
344     indexDefines_[indexName] = indexDefine;
345 }
346 
SetUniqueDefine(const std::vector<CompositeFields> & uniqueDefine)347 void TableInfo::SetUniqueDefine(const std::vector<CompositeFields> &uniqueDefine)
348 {
349     uniqueDefines_ = uniqueDefine;
350     std::sort(uniqueDefines_.begin(), uniqueDefines_.end());
351 }
352 
GetPrimaryKey() const353 const std::map<int, FieldName> &TableInfo::GetPrimaryKey() const
354 {
355     return primaryKey_;
356 }
357 
IsPrimaryKey(const std::string & colName) const358 bool TableInfo::IsPrimaryKey(const std::string &colName) const
359 {
360     for (const auto &item : primaryKey_) {
361         if (colName == item.second) {
362             return true;
363         }
364     }
365     return false;
366 }
367 
IsUniqueField(const std::string & colName) const368 bool TableInfo::IsUniqueField(const std::string &colName) const
369 {
370     for (const auto &unique : uniqueDefines_) {
371         for (const auto &it : unique) {
372             if (colName == it) {
373                 return true;
374             }
375         }
376     }
377     return false;
378 }
379 
GetIdentifyKey() const380 CompositeFields TableInfo::GetIdentifyKey() const
381 {
382     if (primaryKey_.size() == 1 && primaryKey_.at(0) == ROW_ID) {
383         if (!uniqueDefines_.empty()) { // LCOV_EXCL_BR_LINE
384             return uniqueDefines_.at(0);
385         }
386     }
387     CompositeFields key;
388     for (const auto &it : primaryKey_) {
389         key.emplace_back(it.second);
390     }
391     return key;
392 }
393 
SetPrimaryKey(const std::map<int,FieldName> & key)394 void TableInfo::SetPrimaryKey(const std::map<int, FieldName> &key)
395 {
396     primaryKey_ = key;
397 }
398 
SetPrimaryKey(const FieldName & fieldName,int keyIndex)399 void TableInfo::SetPrimaryKey(const FieldName &fieldName, int keyIndex)
400 {
401     if (keyIndex <= 0) {
402         LOGW("Set primary key index %d less than or equal to 0", keyIndex);
403         return;
404     }
405 
406     primaryKey_[keyIndex - 1] = fieldName;
407 }
408 
AddFieldDefineString(std::string & attrStr) const409 void TableInfo::AddFieldDefineString(std::string &attrStr) const
410 {
411     if (fields_.empty()) {
412         return;
413     }
414     attrStr += R"("DEFINE": {)";
415     for (auto itField = fields_.begin(); itField != fields_.end(); ++itField) {
416         attrStr += itField->second.ToAttributeString();
417         if (itField != std::prev(fields_.end(), 1)) {
418             attrStr += ",";
419         }
420     }
421     attrStr += "},";
422 }
423 
AddIndexDefineString(std::string & attrStr) const424 void TableInfo::AddIndexDefineString(std::string &attrStr) const
425 {
426     if (indexDefines_.empty()) {
427         return;
428     }
429     attrStr += R"(,"INDEX": {)";
430     for (auto itIndexDefine = indexDefines_.begin(); itIndexDefine != indexDefines_.end(); ++itIndexDefine) {
431         attrStr += "\"" + (*itIndexDefine).first + "\": [\"";
432         for (auto itField = itIndexDefine->second.begin(); itField != itIndexDefine->second.end(); ++itField) {
433             attrStr += *itField;
434             if (itField != itIndexDefine->second.end() - 1) {
435                 attrStr += "\",\"";
436             }
437         }
438         attrStr += "\"]";
439         if (itIndexDefine != std::prev(indexDefines_.end(), 1)) {
440             attrStr += ",";
441         }
442     }
443     attrStr += "}";
444 }
445 
AddUniqueDefineString(std::string & attrStr) const446 void TableInfo::AddUniqueDefineString(std::string &attrStr) const
447 {
448     if (uniqueDefines_.empty()) {
449         return;
450     }
451 
452     attrStr += R"("UNIQUE":[)";
453     for (const auto &unique : uniqueDefines_) {
454         attrStr += "[";
455         for (const auto &it : unique) {
456             attrStr += "\"" + it + "\",";
457         }
458         attrStr.pop_back();
459         attrStr += "],";
460     }
461     attrStr.pop_back();
462     attrStr += "],";
463 }
464 
CompareWithTable(const TableInfo & inTableInfo,const std::string & schemaVersion) const465 int TableInfo::CompareWithTable(const TableInfo &inTableInfo, const std::string &schemaVersion) const
466 {
467     if (!DBCommon::CaseInsensitiveCompare(tableName_, inTableInfo.GetTableName())) {
468         LOGW("[Relational][Compare] Table name is not same");
469         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
470     }
471 
472     int primaryKeyResult = CompareWithPrimaryKey(primaryKey_, inTableInfo.GetPrimaryKey());
473     if (primaryKeyResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
474         LOGW("[Relational][Compare] Table primary key is not same");
475         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
476     }
477 
478     int fieldCompareResult = CompareWithTableFields(inTableInfo.GetFields());
479     if (fieldCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
480         LOGW("[Relational][Compare] Compare table fields with in table, %d", fieldCompareResult);
481         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
482     }
483 
484     if (schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1) {
485         int uniqueCompareResult = CompareWithTableUnique(inTableInfo.GetUniqueDefine());
486         if (uniqueCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
487             LOGW("[Relational][Compare] Compare table unique with in table, %d", fieldCompareResult);
488             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
489         }
490 
491         if (autoInc_ != inTableInfo.GetAutoIncrement()) {
492             LOGW("[Relational][Compare] Compare table auto increment with in table");
493             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
494         }
495     }
496 
497     int indexCompareResult = CompareWithTableIndex(inTableInfo.GetIndexDefine());
498     return (fieldCompareResult == -E_RELATIONAL_TABLE_EQUAL) ? indexCompareResult : fieldCompareResult;
499 }
500 
CompareWithPrimaryKey(const std::map<int,FieldName> & local,const std::map<int,FieldName> & remote) const501 int TableInfo::CompareWithPrimaryKey(const std::map<int, FieldName> &local,
502     const std::map<int, FieldName> &remote) const
503 {
504     if (local.size() != remote.size()) {
505         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
506     }
507 
508     for (size_t i = 0; i < local.size(); i++) {
509         if (local.find(i) == local.end() || remote.find(i) == remote.end() ||
510             !DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
511             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
512         }
513     }
514 
515     return -E_RELATIONAL_TABLE_EQUAL;
516 }
517 
CompareWithTableFields(const FieldInfoMap & inTableFields,bool isLite) const518 int TableInfo::CompareWithTableFields(const FieldInfoMap &inTableFields, bool isLite) const
519 {
520     auto itLocal = fields_.begin();
521     auto itInTable = inTableFields.begin();
522     int errCode = -E_RELATIONAL_TABLE_EQUAL;
523     while (itLocal != fields_.end() && itInTable != inTableFields.end()) {
524         if (DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first)) { // Same field
525             if (!itLocal->second.CompareWithField(itInTable->second, isLite)) { // Compare field
526                 LOGW("[Relational][Compare] Table field is incompatible"); // not compatible
527                 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
528             }
529             itLocal++; // Compare next field
530         } else { // Assume local table fields is a subset of in table
531             if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) { // Upgrade field not compatible
532                 LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
533                 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
534             }
535             errCode = -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
536         }
537         itInTable++; // Next in table field
538     }
539 
540     if (itLocal != fields_.end()) {
541         LOGW("[Relational][Compare] Table field is missing");
542         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
543     }
544 
545     if (itInTable == inTableFields.end()) {
546         return errCode;
547     }
548 
549     while (itInTable != inTableFields.end()) {
550         if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) {
551             LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
552             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
553         }
554         itInTable++;
555     }
556     return -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
557 }
558 
CompareCompositeFields(const CompositeFields & local,const CompositeFields & remote) const559 int TableInfo::CompareCompositeFields(const CompositeFields &local, const CompositeFields &remote) const
560 {
561     if (local.size() != remote.size()) {
562         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
563     }
564 
565     for (size_t i = 0; i < local.size(); i++) {
566         if (!DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
567             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
568         }
569     }
570 
571     return -E_RELATIONAL_TABLE_EQUAL;
572 }
573 
RemovePKCompositeFields(const std::vector<CompositeFields> & uniqueFields) const574 std::vector<CompositeFields> TableInfo::RemovePKCompositeFields(const std::vector<CompositeFields> &uniqueFields) const
575 {
576     std::vector<CompositeFields> uniqueDefines;
577     for (const auto &compositeFields : uniqueFields) {
578         bool hasPrimaryKey = false;
579         for (const auto &fieldName : compositeFields) {
580             if (IsPrimaryKey(fieldName)) {
581                 hasPrimaryKey = true;
582                 break;
583             }
584         }
585         if (!hasPrimaryKey) {
586             uniqueDefines.push_back(compositeFields);
587         }
588     }
589     return uniqueDefines;
590 }
591 
CompareWithTableUnique(const std::vector<CompositeFields> & inTableUnique) const592 int TableInfo::CompareWithTableUnique(const std::vector<CompositeFields> &inTableUnique) const
593 {
594     std::vector<CompositeFields> uniqueDefines = RemovePKCompositeFields(uniqueDefines_);
595     std::vector<CompositeFields> curTableUnique = RemovePKCompositeFields(inTableUnique);
596     if (uniqueDefines.size() != curTableUnique.size()) {
597         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
598     }
599     auto itLocal = uniqueDefines.begin();
600     auto itInTable = curTableUnique.begin();
601     while (itLocal != uniqueDefines.end()) {
602         if (CompareCompositeFields(*itLocal, *itInTable) != -E_RELATIONAL_TABLE_EQUAL) {
603             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
604         }
605         itLocal++;
606         itInTable++;
607     }
608     return -E_RELATIONAL_TABLE_EQUAL;
609 }
610 
CompareWithTableIndex(const IndexInfoMap & inTableIndex) const611 int TableInfo::CompareWithTableIndex(const IndexInfoMap &inTableIndex) const
612 {
613     // Index comparison results do not affect synchronization decisions
614     auto itLocal = indexDefines_.begin();
615     auto itInTable = inTableIndex.begin();
616     while (itLocal != indexDefines_.end() && itInTable != inTableIndex.end()) {
617         if (!DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first) ||
618             !CompareCompositeFields(itLocal->second, itInTable->second)) {
619             return -E_RELATIONAL_TABLE_COMPATIBLE;
620         }
621         itLocal++;
622         itInTable++;
623     }
624     return (itLocal == indexDefines_.end() && itInTable == inTableIndex.end()) ? -E_RELATIONAL_TABLE_EQUAL :
625         -E_RELATIONAL_TABLE_COMPATIBLE;
626 }
627 
628 namespace {
Difference(const FieldInfoMap & first,const FieldInfoMap & second,FieldInfoMap & orphanFst,FieldInfoMap & orphanSnd,FieldInfoMap & bothAppear)629 void Difference(const FieldInfoMap &first, const FieldInfoMap &second, FieldInfoMap &orphanFst, FieldInfoMap &orphanSnd,
630     FieldInfoMap &bothAppear)
631 {
632     auto itFirst = first.begin();
633     auto itSecond = second.begin();
634     while (itFirst != first.end()) { // LCOV_EXCL_BR_LINE
635         if (itSecond == second.end()) { // LCOV_EXCL_BR_LINE
636             break;
637         }
638         if (itFirst->first == itSecond->first) { // LCOV_EXCL_BR_LINE
639             bothAppear.insert(*itFirst);
640             itFirst++;
641             itSecond++;
642             continue;
643         } else if (itFirst->first < itSecond->first) {
644             orphanFst.insert(*itFirst++);
645         } else {
646             orphanSnd.insert(*itSecond++);
647         }
648     }
649 
650     while (itFirst != first.end()) { // LCOV_EXCL_BR_LINE
651         orphanFst.insert(*itFirst++);
652     }
653 
654     while (itSecond != second.end()) { // LCOV_EXCL_BR_LINE
655         orphanSnd.insert(*itSecond++);
656     }
657 }
658 }
659 
CompareWithLiteTableFields(const FieldInfoMap & liteTableFields) const660 int TableInfo::CompareWithLiteTableFields(const FieldInfoMap &liteTableFields) const
661 {
662     FieldInfoMap orphanLocal;
663     FieldInfoMap orphanLite;
664     FieldInfoMap bothAppear;
665     Difference(fields_, liteTableFields, orphanLocal, orphanLite, bothAppear);
666 
667     if (!orphanLocal.empty() && !orphanLite.empty()) { // LCOV_EXCL_BR_LINE
668         LOGE("[Relational][Compare] Only one side should have upgrade fields");
669         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
670     }
671 
672     for (const auto &it : bothAppear) {
673         if (!it.second.CompareWithField(liteTableFields.at(it.first), true)) { // LCOV_EXCL_BR_LINE
674             LOGE("[Relational][Compare] field is incompatible");
675             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
676         }
677     }
678 
679     for (const auto &it : orphanLocal) {
680         if (it.second.IsNotNull() && !it.second.HasDefaultValue()) { // LCOV_EXCL_BR_LINE
681             LOGE("[Relational][Compare] field is upgrade incompatible");
682             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
683         }
684     }
685 
686     for (const auto &it : orphanLite) {
687         if (it.second.IsNotNull() && !it.second.HasDefaultValue()) { // LCOV_EXCL_BR_LINE
688             LOGE("[Relational][Compare] field is upgrade incompatible");
689             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
690         }
691     }
692 
693     return E_OK;
694 }
695 
CompareWithLiteSchemaTable(const TableInfo & liteTableInfo) const696 int TableInfo::CompareWithLiteSchemaTable(const TableInfo &liteTableInfo) const
697 {
698     if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) &&
699         !CompareWithPrimaryKey(primaryKey_, liteTableInfo.GetPrimaryKey())) { // LCOV_EXCL_BR_LINE
700         LOGE("[Relational][Compare] Table primary key is not same");
701         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
702     }
703     if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) == ROW_ID)) { // LCOV_EXCL_BR_LINE
704         LOGE("[Relational][Compare] Table primary key is not same");
705         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
706     }
707     if ((liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != ROW_ID) && !autoInc_)) { // LCOV_EXCL_BR_LINE
708         LOGE("[Relational][Compare] Table primary key is not same");
709         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
710     }
711 
712     return CompareWithLiteTableFields(liteTableInfo.GetFields());
713 }
714 
ToTableInfoString(const std::string & schemaVersion) const715 std::string TableInfo::ToTableInfoString(const std::string &schemaVersion) const
716 {
717     std::string attrStr;
718     attrStr += "{";
719     attrStr += R"("NAME": ")" + tableName_ + "\",";
720     AddFieldDefineString(attrStr);
721     attrStr += R"("ORIGINTABLENAME": ")" + originTableName_ + "\",";
722     attrStr += R"("AUTOINCREMENT": )";
723     if (autoInc_) {
724         attrStr += "true,";
725     } else {
726         attrStr += "false,";
727     }
728     attrStr += R"("SHAREDTABLEMARK": )";
729     if (sharedTableMark_) {
730         attrStr += "true,";
731     } else {
732         attrStr += "false,";
733     }
734     AddUniqueDefineString(attrStr);
735     if (primaryKey_.size() == 1 && schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) {
736         attrStr += R"("PRIMARY_KEY": ")" + primaryKey_.at(0) + "\"";
737     } else {
738         if (!primaryKey_.empty()) {
739             std::string primaryKey;
740             for (const auto &item : primaryKey_) {
741                 primaryKey += "\"" + item.second + "\",";
742             }
743             primaryKey.pop_back(); // remove the last comma
744             attrStr += R"("PRIMARY_KEY": [)" + primaryKey + "]";
745         }
746     }
747     attrStr += R"(,"TABLE_SYNC_TYPE": )" + std::to_string(static_cast<int>(tableSyncType_));
748     AddIndexDefineString(attrStr);
749     attrStr += "}";
750     return attrStr;
751 }
752 
GetSchemaDefine() const753 std::map<FieldPath, SchemaAttribute> TableInfo::GetSchemaDefine() const
754 {
755     std::map<FieldPath, SchemaAttribute> schemaDefine;
756     for (const auto &[fieldName, fieldInfo] : GetFields()) {
757         FieldValue defaultValue;
758         defaultValue.stringValue = fieldInfo.GetDefaultValue();
759         schemaDefine[std::vector { DBCommon::ToLowerCase(fieldName) }] = SchemaAttribute {
760             .type = FieldType::LEAF_FIELD_NULL,     // For relational schema, the json field type is unimportant.
761             .isIndexable = true,                    // For relational schema, all field is indexable.
762             .hasNotNullConstraint = fieldInfo.IsNotNull(),
763             .hasDefaultValue = fieldInfo.HasDefaultValue(),
764             .defaultValue = defaultValue,
765             .customFieldType = {}
766         };
767     }
768     return schemaDefine;
769 }
770 
SetTableId(int id)771 void TableInfo::SetTableId(int id)
772 {
773     id_ = id;
774 }
775 
GetTableId() const776 int TableInfo::GetTableId() const
777 {
778     return id_;
779 }
780 
Empty() const781 bool TableInfo::Empty() const
782 {
783     return tableName_.empty() || fields_.empty();
784 }
785 
SetTrackerTable(const TrackerTable & table)786 void TableInfo::SetTrackerTable(const TrackerTable &table)
787 {
788     trackerTable_ = table;
789 }
790 
CheckTrackerTable()791 int TableInfo::CheckTrackerTable()
792 {
793     if (tableName_ != trackerTable_.GetTableName()) {
794         LOGE("the table name in schema is different from tracker table.");
795         return -E_NOT_FOUND;
796     }
797     const std::string tableName = DBCommon::StringMiddleMasking(tableName_);
798     size_t nameLength = tableName_.size();
799     for (const auto &colName: trackerTable_.GetTrackerColNames()) {
800         if (colName.empty()) {
801             LOGE("[%s [%zu]] tracker col cannot be empty.", tableName.c_str(), nameLength);
802             return -E_INVALID_ARGS;
803         }
804         if (GetFields().find(colName) == GetFields().end()) {
805             LOGE("[%s [%zu]] unable to match the tracker col from table schema.", tableName.c_str(), nameLength);
806             return -E_SCHEMA_MISMATCH;
807         }
808     }
809     for (const auto &colName : trackerTable_.GetExtendNames()) {
810         if (colName.empty()) {
811             LOGE("[%s [%zu]] extend col cannot be empty.", tableName.c_str(), nameLength);
812             return -E_INVALID_ARGS;
813         }
814         auto iter = GetFields().find(colName);
815         if (iter == GetFields().end()) {
816             LOGE("[%s [%zu]] unable to match the extend col from table schema.", tableName.c_str(), nameLength);
817             return -E_SCHEMA_MISMATCH;
818         } else {
819             if (iter->second.IsAssetType() || iter->second.IsAssetsType()) {
820                 LOGE("[%s [%zu]] extend col is not allowed to be set as asset field.", tableName.c_str(), nameLength);
821                 return -E_INVALID_ARGS;
822             }
823         }
824     }
825     return E_OK;
826 }
827 
GetTrackerTable() const828 const TrackerTable &TableInfo::GetTrackerTable() const
829 {
830     return trackerTable_;
831 }
832 
AddTableReferenceProperty(const TableReferenceProperty & tableRefProperty)833 void TableInfo::AddTableReferenceProperty(const TableReferenceProperty &tableRefProperty)
834 {
835     sourceTableReferenced_.push_back(tableRefProperty);
836 }
837 
SetSourceTableReference(const std::vector<TableReferenceProperty> & tableReference)838 void TableInfo::SetSourceTableReference(const std::vector<TableReferenceProperty> &tableReference)
839 {
840     sourceTableReferenced_ = tableReference;
841 }
842 
GetTableReference() const843 const std::vector<TableReferenceProperty> &TableInfo::GetTableReference() const
844 {
845     return sourceTableReferenced_;
846 }
847 
IsNoPkTable() const848 bool TableInfo::IsNoPkTable() const
849 {
850     if (primaryKey_.size() == 1 && primaryKey_.at(0) == ROW_ID) {
851         return true;
852     }
853     return false;
854 }
855 
IsMultiPkTable() const856 bool TableInfo::IsMultiPkTable() const
857 {
858     return primaryKey_.size() > 1;
859 }
860 
IsFieldExist(const std::string & fieldName) const861 bool TableInfo::IsFieldExist(const std::string &fieldName) const
862 {
863     if (fields_.find(fieldName) != fields_.end()) {
864         return true;
865     }
866     LOGE("[TableInfo][IsFieldExist] table %s table len %zu not exist field %s",
867         DBCommon::StringMiddleMasking(tableName_).c_str(), tableName_.size(),
868         DBCommon::StringMiddleMasking(fieldName).c_str());
869     return false;
870 }
871 
SetDistributedTable(const DistributedTable & distributedTable)872 void TableInfo::SetDistributedTable(const DistributedTable &distributedTable)
873 {
874     distributedTable_ = distributedTable;
875 }
876 
GetSyncField() const877 std::vector<std::string> TableInfo::GetSyncField() const
878 {
879     std::vector<std::string> res;
880     for (const auto &item : distributedTable_.fields) {
881         if (item.isP2pSync) {
882             res.push_back(item.colName);
883         }
884     }
885     return res;
886 }
887 
GetSyncDistributedPk() const888 std::vector<std::string> TableInfo::GetSyncDistributedPk() const
889 {
890     std::vector<std::string> res;
891     for (const auto &item : distributedTable_.fields) {
892         if (item.isP2pSync && item.isSpecified) {
893             res.push_back(item.colName);
894         }
895     }
896     return res;
897 }
898 
GetUniqueAndPkDefine() const899 const std::vector<CompositeFields> TableInfo::GetUniqueAndPkDefine() const
900 {
901     std::vector<CompositeFields> res = uniqueDefines_;
902     res.push_back(GetIdentifyKey());
903     return res;
904 }
905 } // namespace DistributeDB