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