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