• 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 
GetFieldName() const27 const std::string &FieldInfo::GetFieldName() const
28 {
29     return fieldName_;
30 }
31 
SetFieldName(const std::string & fileName)32 void FieldInfo::SetFieldName(const std::string &fileName)
33 {
34     fieldName_ = fileName;
35 }
36 
GetDataType() const37 const std::string &FieldInfo::GetDataType() const
38 {
39     return dataType_;
40 }
41 
42 namespace {
AffinityPatternHex(const std::string & ss)43 inline uint32_t AffinityPatternHex(const std::string &ss)
44 {
45     uint32_t res = 0;
46     for (const auto &c : ss) {
47         res = (res << 8) + c; // 8: shift length
48     }
49     return res;
50 }
51 
52 static uint32_t affinityTable[] = {
53     AffinityPatternHex("char"), AffinityPatternHex("clob"), AffinityPatternHex("text"),
54     AffinityPatternHex("blob"), AffinityPatternHex("real"), AffinityPatternHex("floa"),
55     AffinityPatternHex("doub"), AffinityPatternHex("int"),
56 };
57 
58 enum AffinityPattern : uint32_t {
59     AFFINITY_CHAR,
60     AFFINITY_CLOB,
61     AFFINITY_TEXT,
62     AFFINITY_BLOB,
63     AFFINITY_REAL,
64     AFFINITY_FLOA,
65     AFFINITY_DOUB,
66     AFFINITY_INT,
67 };
68 }
69 
AffinityType(const std::string & dataType)70 static StorageType AffinityType(const std::string &dataType)
71 {
72     StorageType type = StorageType::STORAGE_TYPE_NULL;
73     uint32_t hex = 0;
74     for (uint32_t i = 0; i < dataType.length(); i++) {
75         hex = (hex << 8) + (std::tolower(dataType[i])); // 8: shift length
76         if (hex == affinityTable[AFFINITY_CHAR]) {
77             type = StorageType::STORAGE_TYPE_TEXT;
78         } else if (hex == affinityTable[AFFINITY_CLOB]) {
79             type = StorageType::STORAGE_TYPE_TEXT;
80         } else if (hex == affinityTable[AFFINITY_TEXT]) {
81             type = StorageType::STORAGE_TYPE_TEXT;
82         } else if (hex == affinityTable[AFFINITY_BLOB] && (type == StorageType::STORAGE_TYPE_NULL ||
83             type == StorageType::STORAGE_TYPE_REAL)) {
84             type = StorageType::STORAGE_TYPE_BLOB;
85         } else if (hex == affinityTable[AFFINITY_REAL] && type == StorageType::STORAGE_TYPE_NULL) {
86             type = StorageType::STORAGE_TYPE_REAL;
87         } else if (hex == affinityTable[AFFINITY_FLOA] && type == StorageType::STORAGE_TYPE_NULL) {
88             type = StorageType::STORAGE_TYPE_REAL;
89         } else if (hex == affinityTable[AFFINITY_DOUB] && type == StorageType::STORAGE_TYPE_NULL) {
90             type = StorageType::STORAGE_TYPE_REAL;
91         } else if ((hex & 0x00ffffff) == affinityTable[AFFINITY_INT]) { // 0x00ffffff: mask for 3 byte
92             type = StorageType::STORAGE_TYPE_INTEGER;
93         }
94     }
95     return type;
96 }
97 
SetDataType(const std::string & dataType)98 void FieldInfo::SetDataType(const std::string &dataType)
99 {
100     dataType_ = dataType;
101     std::transform(dataType_.begin(), dataType_.end(), dataType_.begin(), ::tolower);
102     if (IsAssetType() || IsAssetsType()) {
103         storageType_ = StorageType::STORAGE_TYPE_BLOB; // use for cloud sync
104     } else {
105         storageType_ = AffinityType(dataType_);
106     }
107 }
108 
IsNotNull() const109 bool FieldInfo::IsNotNull() const
110 {
111     return isNotNull_;
112 }
113 
SetNotNull(bool isNotNull)114 void FieldInfo::SetNotNull(bool isNotNull)
115 {
116     isNotNull_ = isNotNull;
117 }
118 
HasDefaultValue() const119 bool FieldInfo::HasDefaultValue() const
120 {
121     return hasDefaultValue_;
122 }
123 
GetDefaultValue() const124 const std::string &FieldInfo::GetDefaultValue() const
125 {
126     return defaultValue_;
127 }
128 
SetDefaultValue(const std::string & value)129 void FieldInfo::SetDefaultValue(const std::string &value)
130 {
131     hasDefaultValue_ = true;
132     defaultValue_ = value;
133 }
134 
135 // convert to StorageType according "Determination Of Column Affinity"
GetStorageType() const136 StorageType FieldInfo::GetStorageType() const
137 {
138     return storageType_;
139 }
140 
SetStorageType(StorageType storageType)141 void FieldInfo::SetStorageType(StorageType storageType)
142 {
143     storageType_ = storageType;
144 }
145 
GetColumnId() const146 int FieldInfo::GetColumnId() const
147 {
148     return cid_;
149 }
150 
SetColumnId(int cid)151 void FieldInfo::SetColumnId(int cid)
152 {
153     cid_ = cid;
154 }
155 
ToAttributeString() const156 std::string FieldInfo::ToAttributeString() const
157 {
158     std::string attrStr = "\"" + fieldName_ + "\": {";
159     attrStr += "\"COLUMN_ID\":" + std::to_string(cid_) + ",";
160     attrStr += "\"TYPE\":\"" + dataType_ + "\",";
161     attrStr += "\"NOT_NULL\":" + std::string(isNotNull_ ? "true" : "false");
162     if (hasDefaultValue_) {
163         attrStr += ",";
164         attrStr += "\"DEFAULT\":\"" + defaultValue_ + "\"";
165     }
166     attrStr += "}";
167     return attrStr;
168 }
169 
CompareWithField(const FieldInfo & inField,bool isLite) const170 int FieldInfo::CompareWithField(const FieldInfo &inField, bool isLite) const
171 {
172     if (!DBCommon::CaseInsensitiveCompare(fieldName_, inField.GetFieldName()) || isNotNull_ != inField.IsNotNull()) {
173         return false;
174     }
175     if (isLite) {
176         if (storageType_ != inField.GetStorageType()) {
177             return false;
178         }
179     } else {
180         if (dataType_ != inField.GetDataType()) {
181             return false;
182         }
183     }
184     if (hasDefaultValue_ && inField.HasDefaultValue()) {
185         // lite schema only uses NULL as default value
186         return (isLite && defaultValue_ == "NULL") || defaultValue_ == inField.GetDefaultValue();
187     }
188     return hasDefaultValue_ == inField.HasDefaultValue();
189 }
190 
IsAssetType() const191 bool FieldInfo::IsAssetType() const
192 {
193     return strcasecmp(dataType_.c_str(), ASSET) == 0;
194 }
195 
IsAssetsType() const196 bool FieldInfo::IsAssetsType() const
197 {
198     return strcasecmp(dataType_.c_str(), ASSETS) == 0;
199 }
200 
GetTableName() const201 const std::string &TableInfo::GetTableName() const
202 {
203     return tableName_;
204 }
205 
SetTableName(const std::string & tableName)206 void TableInfo::SetTableName(const std::string &tableName)
207 {
208     tableName_ = tableName;
209 }
210 
SetAutoIncrement(bool autoInc)211 void TableInfo::SetAutoIncrement(bool autoInc)
212 {
213     autoInc_ = autoInc;
214 }
215 
GetAutoIncrement() const216 bool TableInfo::GetAutoIncrement() const
217 {
218     return autoInc_;
219 }
220 
SetTableSyncType(TableSyncType tableSyncType)221 void TableInfo::SetTableSyncType(TableSyncType tableSyncType)
222 {
223     tableSyncType_ = tableSyncType;
224 }
225 
GetTableSyncType() const226 TableSyncType TableInfo::GetTableSyncType() const
227 {
228     return tableSyncType_;
229 }
230 
GetCreateTableSql() const231 const std::string &TableInfo::GetCreateTableSql() const
232 {
233     return sql_;
234 }
235 
SetCreateTableSql(const std::string & sql)236 void TableInfo::SetCreateTableSql(const std::string &sql)
237 {
238     sql_ = sql;
239     for (auto &c : sql_) {
240         c = static_cast<char>(std::toupper(c));
241     }
242     if (DBCommon::HasConstraint(DBCommon::TrimSpace(sql_), "AUTOINCREMENT", " ", " ,)")) {
243         autoInc_ = true;
244     }
245 }
246 
GetFields() const247 const FieldInfoMap &TableInfo::GetFields() const
248 {
249     return fields_;
250 }
251 
GetFieldInfos() const252 const std::vector<FieldInfo> &TableInfo::GetFieldInfos() const
253 {
254     if (!fieldInfos_.empty() && fieldInfos_.size() == fields_.size()) {
255         return fieldInfos_;
256     }
257     fieldInfos_.resize(fields_.size());
258     if (fieldInfos_.size() != fields_.size()) {
259         LOGE("GetField error, alloc memory failed.");
260         return fieldInfos_;
261     }
262     for (const auto &entry : fields_) {
263         if (static_cast<size_t>(entry.second.GetColumnId()) >= fieldInfos_.size()) {
264             LOGE("Cid is over field size.");
265             fieldInfos_.clear();
266             return fieldInfos_;
267         }
268         fieldInfos_.at(entry.second.GetColumnId()) = entry.second;
269     }
270     return fieldInfos_;
271 }
272 
GetFieldName(uint32_t cid) const273 std::string TableInfo::GetFieldName(uint32_t cid) const
274 {
275     if (cid >= fields_.size() || GetFieldInfos().empty()) {
276         return {};
277     }
278     return GetFieldInfos().at(cid).GetFieldName();
279 }
280 
IsValid() const281 bool TableInfo::IsValid() const
282 {
283     return !tableName_.empty();
284 }
285 
AddField(const FieldInfo & field)286 void TableInfo::AddField(const FieldInfo &field)
287 {
288     fields_[field.GetFieldName()] = field;
289 }
290 
GetIndexDefine() const291 const IndexInfoMap &TableInfo::GetIndexDefine() const
292 {
293     return indexDefines_;
294 }
295 
GetUniqueDefine() const296 const std::vector<CompositeFields> &TableInfo::GetUniqueDefine() const
297 {
298     return uniqueDefines_;
299 }
300 
AddIndexDefine(const std::string & indexName,const CompositeFields & indexDefine)301 void TableInfo::AddIndexDefine(const std::string &indexName, const CompositeFields &indexDefine)
302 {
303     indexDefines_[indexName] = indexDefine;
304 }
305 
SetUniqueDefine(const std::vector<CompositeFields> & uniqueDefine)306 void TableInfo::SetUniqueDefine(const std::vector<CompositeFields> &uniqueDefine)
307 {
308     uniqueDefines_ = uniqueDefine;
309     std::sort(uniqueDefines_.begin(), uniqueDefines_.end());
310 }
311 
GetPrimaryKey() const312 const std::map<int, FieldName> &TableInfo::GetPrimaryKey() const
313 {
314     return primaryKey_;
315 }
316 
GetIdentifyKey() const317 CompositeFields TableInfo::GetIdentifyKey() const
318 {
319     if (primaryKey_.size() == 1 && primaryKey_.at(0) == "rowid") {
320         if (!uniqueDefines_.empty()) {
321             return uniqueDefines_.at(0);
322         }
323     }
324     CompositeFields key;
325     for (const auto &it : primaryKey_) {
326         key.emplace_back(it.second);
327     }
328     return key;
329 }
330 
SetPrimaryKey(const std::map<int,FieldName> & key)331 void TableInfo::SetPrimaryKey(const std::map<int, FieldName> &key)
332 {
333     primaryKey_ = key;
334 }
335 
SetPrimaryKey(const FieldName & fieldName,int keyIndex)336 void TableInfo::SetPrimaryKey(const FieldName &fieldName, int keyIndex)
337 {
338     if (keyIndex <= 0) {
339         LOGW("Set primary key index %d less than or equal to 0", keyIndex);
340         return;
341     }
342 
343     primaryKey_[keyIndex - 1] = fieldName;
344 }
345 
AddFieldDefineString(std::string & attrStr) const346 void TableInfo::AddFieldDefineString(std::string &attrStr) const
347 {
348     if (fields_.empty()) {
349         return;
350     }
351     attrStr += R"("DEFINE": {)";
352     for (auto itField = fields_.begin(); itField != fields_.end(); ++itField) {
353         attrStr += itField->second.ToAttributeString();
354         if (itField != std::prev(fields_.end(), 1)) {
355             attrStr += ",";
356         }
357     }
358     attrStr += "},";
359 }
360 
AddIndexDefineString(std::string & attrStr) const361 void TableInfo::AddIndexDefineString(std::string &attrStr) const
362 {
363     if (indexDefines_.empty()) {
364         return;
365     }
366     attrStr += R"(,"INDEX": {)";
367     for (auto itIndexDefine = indexDefines_.begin(); itIndexDefine != indexDefines_.end(); ++itIndexDefine) {
368         attrStr += "\"" + (*itIndexDefine).first + "\": [\"";
369         for (auto itField = itIndexDefine->second.begin(); itField != itIndexDefine->second.end(); ++itField) {
370             attrStr += *itField;
371             if (itField != itIndexDefine->second.end() - 1) {
372                 attrStr += "\",\"";
373             }
374         }
375         attrStr += "\"]";
376         if (itIndexDefine != std::prev(indexDefines_.end(), 1)) {
377             attrStr += ",";
378         }
379     }
380     attrStr += "}";
381 }
382 
AddUniqueDefineString(std::string & attrStr) const383 void TableInfo::AddUniqueDefineString(std::string &attrStr) const
384 {
385     if (uniqueDefines_.empty()) {
386         return;
387     }
388 
389     attrStr += R"("UNIQUE":[)";
390     for (const auto &unique : uniqueDefines_) {
391         attrStr += "[";
392         for (const auto &it : unique) {
393             attrStr += "\"" + it + "\",";
394         }
395         attrStr.pop_back();
396         attrStr += "],";
397     }
398     attrStr.pop_back();
399     attrStr += "],";
400 }
401 
CompareWithTable(const TableInfo & inTableInfo,const std::string & schemaVersion) const402 int TableInfo::CompareWithTable(const TableInfo &inTableInfo, const std::string &schemaVersion) const
403 {
404     if (!DBCommon::CaseInsensitiveCompare(tableName_, inTableInfo.GetTableName())) {
405         LOGW("[Relational][Compare] Table name is not same");
406         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
407     }
408 
409     int primaryKeyResult = CompareWithPrimaryKey(primaryKey_, inTableInfo.GetPrimaryKey());
410     if (primaryKeyResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
411         LOGW("[Relational][Compare] Table primary key is not same");
412         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
413     }
414 
415     int fieldCompareResult = CompareWithTableFields(inTableInfo.GetFields());
416     if (fieldCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
417         LOGW("[Relational][Compare] Compare table fields with in table, %d", fieldCompareResult);
418         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
419     }
420 
421     if (schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1) {
422         int uniqueCompareResult = CompareWithTableUnique(inTableInfo.GetUniqueDefine());
423         if (uniqueCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
424             LOGW("[Relational][Compare] Compare table unique with in table, %d", fieldCompareResult);
425             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
426         }
427 
428         if (autoInc_ != inTableInfo.GetAutoIncrement()) {
429             LOGW("[Relational][Compare] Compare table auto increment with in table");
430             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
431         }
432     }
433 
434     int indexCompareResult = CompareWithTableIndex(inTableInfo.GetIndexDefine());
435     return (fieldCompareResult == -E_RELATIONAL_TABLE_EQUAL) ? indexCompareResult : fieldCompareResult;
436 }
437 
CompareWithPrimaryKey(const std::map<int,FieldName> & local,const std::map<int,FieldName> & remote) const438 int TableInfo::CompareWithPrimaryKey(const std::map<int, FieldName> &local,
439     const std::map<int, FieldName> &remote) const
440 {
441     if (local.size() != remote.size()) {
442         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
443     }
444 
445     for (size_t i = 0; i < local.size(); i++) {
446         if (local.find(i) == local.end() || remote.find(i) == remote.end() ||
447             !DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
448             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
449         }
450     }
451 
452     return -E_RELATIONAL_TABLE_EQUAL;
453 }
454 
CompareWithTableFields(const FieldInfoMap & inTableFields,bool isLite) const455 int TableInfo::CompareWithTableFields(const FieldInfoMap &inTableFields, bool isLite) const
456 {
457     auto itLocal = fields_.begin();
458     auto itInTable = inTableFields.begin();
459     int errCode = -E_RELATIONAL_TABLE_EQUAL;
460     while (itLocal != fields_.end() && itInTable != inTableFields.end()) {
461         if (DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first)) { // Same field
462             if (!itLocal->second.CompareWithField(itInTable->second, isLite)) { // Compare field
463                 LOGW("[Relational][Compare] Table field is incompatible"); // not compatible
464                 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
465             }
466             itLocal++; // Compare next field
467         } else { // Assume local table fields is a subset of in table
468             if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) { // Upgrade field not compatible
469                 LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
470                 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
471             }
472             errCode = -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
473         }
474         itInTable++; // Next in table field
475     }
476 
477     if (itLocal != fields_.end()) {
478         LOGW("[Relational][Compare] Table field is missing");
479         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
480     }
481 
482     if (itInTable == inTableFields.end()) {
483         return errCode;
484     }
485 
486     while (itInTable != inTableFields.end()) {
487         if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) {
488             LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
489             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
490         }
491         itInTable++;
492     }
493     return -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
494 }
495 
CompareCompositeFields(const CompositeFields & local,const CompositeFields & remote) const496 int TableInfo::CompareCompositeFields(const CompositeFields &local, const CompositeFields &remote) const
497 {
498     if (local.size() != remote.size()) {
499         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
500     }
501 
502     for (size_t i = 0; i < local.size(); i++) {
503         if (!DBCommon::CaseInsensitiveCompare(local.at(i), remote.at(i))) {
504             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
505         }
506     }
507 
508     return -E_RELATIONAL_TABLE_EQUAL;
509 }
510 
CompareWithTableUnique(const std::vector<CompositeFields> & inTableUnique) const511 int TableInfo::CompareWithTableUnique(const std::vector<CompositeFields> &inTableUnique) const
512 {
513     if (uniqueDefines_.size() != inTableUnique.size()) {
514         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
515     }
516 
517     auto itLocal = uniqueDefines_.begin();
518     auto itInTable = inTableUnique.begin();
519     while (itLocal != uniqueDefines_.end()) {
520         if (CompareCompositeFields(*itLocal, *itInTable) != -E_RELATIONAL_TABLE_EQUAL) {
521             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
522         }
523         itLocal++;
524         itInTable++;
525     }
526     return -E_RELATIONAL_TABLE_EQUAL;
527 }
528 
CompareWithTableIndex(const IndexInfoMap & inTableIndex) const529 int TableInfo::CompareWithTableIndex(const IndexInfoMap &inTableIndex) const
530 {
531     // Index comparison results do not affect synchronization decisions
532     auto itLocal = indexDefines_.begin();
533     auto itInTable = inTableIndex.begin();
534     while (itLocal != indexDefines_.end() && itInTable != inTableIndex.end()) {
535         if (!DBCommon::CaseInsensitiveCompare(itLocal->first, itInTable->first) ||
536             !CompareCompositeFields(itLocal->second, itInTable->second)) {
537             return -E_RELATIONAL_TABLE_COMPATIBLE;
538         }
539         itLocal++;
540         itInTable++;
541     }
542     return (itLocal == indexDefines_.end() && itInTable == inTableIndex.end()) ? -E_RELATIONAL_TABLE_EQUAL :
543         -E_RELATIONAL_TABLE_COMPATIBLE;
544 }
545 
546 
547 namespace {
Difference(const FieldInfoMap & first,const FieldInfoMap & second,FieldInfoMap & orphanFst,FieldInfoMap & orphanSnd,FieldInfoMap & bothAppear)548 void Difference(const FieldInfoMap &first, const FieldInfoMap &second, FieldInfoMap &orphanFst, FieldInfoMap &orphanSnd,
549     FieldInfoMap &bothAppear)
550 {
551     auto itFirst = first.begin();
552     auto itSecond = second.begin();
553     while (itFirst != first.end()) {
554         if (itSecond == second.end()) {
555             break;
556         }
557         if (itFirst->first == itSecond->first) {
558             bothAppear.insert(*itFirst);
559             itFirst++;
560             itSecond++;
561             continue;
562         } else if (itFirst->first < itSecond->first) {
563             orphanFst.insert(*itFirst++);
564         } else {
565             orphanSnd.insert(*itSecond++);
566         }
567     }
568 
569     while (itFirst != first.end()) {
570         orphanFst.insert(*itFirst++);
571     }
572 
573     while (itSecond != second.end()) {
574         orphanSnd.insert(*itSecond++);
575     }
576 }
577 }
578 
CompareWithLiteTableFields(const FieldInfoMap & liteTableFields) const579 int TableInfo::CompareWithLiteTableFields(const FieldInfoMap &liteTableFields) const
580 {
581     FieldInfoMap orphanLocal;
582     FieldInfoMap orphanLite;
583     FieldInfoMap bothAppear;
584     Difference(fields_, liteTableFields, orphanLocal, orphanLite, bothAppear);
585 
586     if (!orphanLocal.empty() && !orphanLite.empty()) {
587         LOGE("[Relational][Compare] Only one side should have upgrade fields");
588         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
589     }
590 
591     for (const auto &it : bothAppear) {
592         if (!it.second.CompareWithField(liteTableFields.at(it.first), true)) {
593             LOGE("[Relational][Compare] field is incompatible");
594             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
595         }
596     }
597 
598     for (const auto &it : orphanLocal) {
599         if (it.second.IsNotNull() && !it.second.HasDefaultValue()) {
600             LOGE("[Relational][Compare] field is upgrade incompatible");
601             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
602         }
603     }
604 
605     for (const auto &it : orphanLite) {
606         if (it.second.IsNotNull() && !it.second.HasDefaultValue()) {
607             LOGE("[Relational][Compare] field is upgrade incompatible");
608             return -E_RELATIONAL_TABLE_INCOMPATIBLE;
609         }
610     }
611 
612     return E_OK;
613 }
614 
CompareWithLiteSchemaTable(const TableInfo & liteTableInfo) const615 int TableInfo::CompareWithLiteSchemaTable(const TableInfo &liteTableInfo) const
616 {
617     if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != "rowid") &&
618         !CompareWithPrimaryKey(primaryKey_, liteTableInfo.GetPrimaryKey())) {
619         LOGE("[Relational][Compare] Table primary key is not same");
620         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
621     }
622     if (!liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) == "rowid")) {
623         LOGE("[Relational][Compare] Table primary key is not same");
624         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
625     }
626     if ((liteTableInfo.GetPrimaryKey().empty() && (primaryKey_.at(0) != "rowid") && !autoInc_)) {
627         LOGE("[Relational][Compare] Table primary key is not same");
628         return -E_RELATIONAL_TABLE_INCOMPATIBLE;
629     }
630 
631     return CompareWithLiteTableFields(liteTableInfo.GetFields());
632 }
633 
ToTableInfoString(const std::string & schemaVersion) const634 std::string TableInfo::ToTableInfoString(const std::string &schemaVersion) const
635 {
636     std::string attrStr;
637     attrStr += "{";
638     attrStr += R"("NAME": ")" + tableName_ + "\",";
639     AddFieldDefineString(attrStr);
640     attrStr += R"("AUTOINCREMENT": )";
641     if (autoInc_) {
642         attrStr += "true,";
643     } else {
644         attrStr += "false,";
645     }
646     AddUniqueDefineString(attrStr);
647     if (primaryKey_.size() == 1 && schemaVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) {
648         attrStr += R"("PRIMARY_KEY": ")" + primaryKey_.at(0) + "\"";
649     } else {
650         if (!primaryKey_.empty()) {
651             std::string primaryKey;
652             for (const auto &item : primaryKey_) {
653                 primaryKey += "\"" + item.second + "\",";
654             }
655             primaryKey.pop_back(); // remove the last comma
656             attrStr += R"("PRIMARY_KEY": [)" + primaryKey + "]";
657         }
658     }
659     attrStr += R"(,"TABLE_SYNC_TYPE": )" + std::to_string(static_cast<int>(tableSyncType_));
660     AddIndexDefineString(attrStr);
661     attrStr += "}";
662     return attrStr;
663 }
664 
GetSchemaDefine() const665 std::map<FieldPath, SchemaAttribute> TableInfo::GetSchemaDefine() const
666 {
667     std::map<FieldPath, SchemaAttribute> schemaDefine;
668     for (const auto &[fieldName, fieldInfo] : GetFields()) {
669         FieldValue defaultValue;
670         defaultValue.stringValue = fieldInfo.GetDefaultValue();
671         schemaDefine[std::vector { DBCommon::ToLowerCase(fieldName) }] = SchemaAttribute {
672             .type = FieldType::LEAF_FIELD_NULL,     // For relational schema, the json field type is unimportant.
673             .isIndexable = true,                    // For relational schema, all field is indexable.
674             .hasNotNullConstraint = fieldInfo.IsNotNull(),
675             .hasDefaultValue = fieldInfo.HasDefaultValue(),
676             .defaultValue = defaultValue,
677             .customFieldType = {}
678         };
679     }
680     return schemaDefine;
681 }
682 
SetTableId(int id)683 void TableInfo::SetTableId(int id)
684 {
685     id_ = id;
686 }
687 
GetTableId() const688 int TableInfo::GetTableId() const
689 {
690     return id_;
691 }
692 
Empty() const693 bool TableInfo::Empty() const
694 {
695     return tableName_.empty() || fields_.empty();
696 }
697 } // namespace DistributeDB