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