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 #ifdef RELATIONAL_STORE
16 #include "relational_schema_object.h"
17
18 #include <algorithm>
19
20 #include "db_common.h"
21 #include "json_object.h"
22 #include "schema_constant.h"
23 #include "schema_utils.h"
24
25 namespace DistributedDB {
GetFieldName() const26 const std::string &FieldInfo::GetFieldName() const
27 {
28 return fieldName_;
29 }
30
SetFieldName(const std::string & fileName)31 void FieldInfo::SetFieldName(const std::string &fileName)
32 {
33 fieldName_ = fileName;
34 }
35
GetDataType() const36 const std::string &FieldInfo::GetDataType() const
37 {
38 return dataType_;
39 }
40
AffinityType(const std::string & dataType)41 static StorageType AffinityType(const std::string &dataType)
42 {
43 return StorageType::STORAGE_TYPE_NULL;
44 }
45
SetDataType(const std::string & dataType)46 void FieldInfo::SetDataType(const std::string &dataType)
47 {
48 dataType_ = dataType;
49 transform(dataType_.begin(), dataType_.end(), dataType_.begin(), ::tolower);
50 storageType_ = AffinityType(dataType_);
51 }
52
IsNotNull() const53 bool FieldInfo::IsNotNull() const
54 {
55 return isNotNull_;
56 }
57
SetNotNull(bool isNotNull)58 void FieldInfo::SetNotNull(bool isNotNull)
59 {
60 isNotNull_ = isNotNull;
61 }
62
HasDefaultValue() const63 bool FieldInfo::HasDefaultValue() const
64 {
65 return hasDefaultValue_;
66 }
67
GetDefaultValue() const68 const std::string &FieldInfo::GetDefaultValue() const
69 {
70 return defaultValue_;
71 }
72
SetDefaultValue(const std::string & value)73 void FieldInfo::SetDefaultValue(const std::string &value)
74 {
75 hasDefaultValue_ = true;
76 defaultValue_ = value;
77 }
78
79 // convert to StorageType according "Determination Of Column Affinity"
GetStorageType() const80 StorageType FieldInfo::GetStorageType() const
81 {
82 return storageType_;
83 }
84
SetStorageType(StorageType storageType)85 void FieldInfo::SetStorageType(StorageType storageType)
86 {
87 storageType_ = storageType;
88 }
89
GetColumnId() const90 int FieldInfo::GetColumnId() const
91 {
92 return cid_;
93 }
94
SetColumnId(int cid)95 void FieldInfo::SetColumnId(int cid)
96 {
97 cid_ = cid;
98 }
99
ToAttributeString() const100 std::string FieldInfo::ToAttributeString() const
101 {
102 std::string attrStr = "\"" + fieldName_ + "\": {";
103 attrStr += "\"COLUMN_ID\":" + std::to_string(cid_) + ",";
104 attrStr += "\"TYPE\":\"" + dataType_ + "\",";
105 attrStr += "\"NOT_NULL\":" + std::string(isNotNull_ ? "true" : "false");
106 if (hasDefaultValue_) {
107 attrStr += ",";
108 attrStr += "\"DEFAULT\":\"" + defaultValue_ + "\"";
109 }
110 attrStr += "}";
111 return attrStr;
112 }
113
CompareWithField(const FieldInfo & inField) const114 int FieldInfo::CompareWithField(const FieldInfo &inField) const
115 {
116 if (fieldName_ != inField.GetFieldName() || dataType_ != inField.GetDataType() ||
117 isNotNull_ != inField.IsNotNull()) {
118 return false;
119 }
120 if (hasDefaultValue_ && inField.HasDefaultValue()) {
121 return defaultValue_ == inField.GetDefaultValue();
122 }
123 return hasDefaultValue_ == inField.HasDefaultValue();
124 }
125
GetTableName() const126 const std::string &TableInfo::GetTableName() const
127 {
128 return tableName_;
129 }
130
SetTableName(const std::string & tableName)131 void TableInfo::SetTableName(const std::string &tableName)
132 {
133 tableName_ = tableName;
134 }
135
SetAutoIncrement(bool autoInc)136 void TableInfo::SetAutoIncrement(bool autoInc)
137 {
138 autoInc_ = autoInc;
139 }
140
GetAutoIncrement() const141 bool TableInfo::GetAutoIncrement() const
142 {
143 return autoInc_;
144 }
145
GetCreateTableSql() const146 const std::string &TableInfo::GetCreateTableSql() const
147 {
148 return sql_;
149 }
150
SetCreateTableSql(std::string sql)151 void TableInfo::SetCreateTableSql(std::string sql)
152 {
153 sql_ = sql;
154 for (auto &c : sql) {
155 c = static_cast<char>(std::toupper(c));
156 }
157 if (sql.find("AUTOINCREMENT") != std::string::npos) {
158 autoInc_ = true;
159 }
160 }
161
GetFields() const162 const std::map<std::string, FieldInfo> &TableInfo::GetFields() const
163 {
164 return fields_;
165 }
166
GetFieldInfos() const167 const std::vector<FieldInfo> &TableInfo::GetFieldInfos() const
168 {
169 if (!fieldInfos_.empty() && fieldInfos_.size() == fields_.size()) {
170 return fieldInfos_;
171 }
172 fieldInfos_.resize(fields_.size());
173 if (fieldInfos_.size() != fields_.size()) {
174 LOGE("GetField error, alloc memory failed.");
175 return fieldInfos_;
176 }
177 for (const auto &entry : fields_) {
178 if (static_cast<size_t>(entry.second.GetColumnId()) >= fieldInfos_.size()) {
179 LOGE("Cid is over field size.");
180 fieldInfos_.clear();
181 return fieldInfos_;
182 }
183 fieldInfos_.at(entry.second.GetColumnId()) = entry.second;
184 }
185 return fieldInfos_;
186 }
187
GetFieldName(uint32_t cid) const188 std::string TableInfo::GetFieldName(uint32_t cid) const
189 {
190 if (cid >= fields_.size() || GetFieldInfos().empty()) {
191 return {};
192 }
193 return GetFieldInfos().at(cid).GetFieldName();
194 }
195
IsValid() const196 bool TableInfo::IsValid() const
197 {
198 return !tableName_.empty();
199 }
200
AddField(const FieldInfo & field)201 void TableInfo::AddField(const FieldInfo &field)
202 {
203 fields_[field.GetFieldName()] = field;
204 }
205
GetIndexDefine() const206 const std::map<std::string, CompositeFields> &TableInfo::GetIndexDefine() const
207 {
208 return indexDefines_;
209 }
210
AddIndexDefine(const std::string & indexName,const CompositeFields & indexDefine)211 void TableInfo::AddIndexDefine(const std::string &indexName, const CompositeFields &indexDefine)
212 {
213 indexDefines_[indexName] = indexDefine;
214 }
215
GetPrimaryKey() const216 const FieldName &TableInfo::GetPrimaryKey() const
217 {
218 return primaryKey_;
219 }
220
SetPrimaryKey(const FieldName & fieldName)221 void TableInfo::SetPrimaryKey(const FieldName &fieldName)
222 {
223 primaryKey_ = fieldName;
224 }
225
AddFieldDefineString(std::string & attrStr) const226 void TableInfo::AddFieldDefineString(std::string &attrStr) const
227 {
228 if (fields_.empty()) {
229 return;
230 }
231 attrStr += R"("DEFINE": {)";
232 for (auto itField = fields_.begin(); itField != fields_.end(); ++itField) {
233 attrStr += itField->second.ToAttributeString();
234 if (itField != std::prev(fields_.end(), 1)) {
235 attrStr += ",";
236 }
237 }
238 attrStr += "},";
239 }
240
AddIndexDefineString(std::string & attrStr) const241 void TableInfo::AddIndexDefineString(std::string &attrStr) const
242 {
243 if (indexDefines_.empty()) {
244 return;
245 }
246 attrStr += R"(,"INDEX": {)";
247 for (auto itIndexDefine = indexDefines_.begin(); itIndexDefine != indexDefines_.end(); ++itIndexDefine) {
248 attrStr += "\"" + (*itIndexDefine).first + "\": [\"";
249 for (auto itField = itIndexDefine->second.begin(); itField != itIndexDefine->second.end(); ++itField) {
250 attrStr += *itField;
251 if (itField != itIndexDefine->second.end() - 1) {
252 attrStr += "\",\"";
253 }
254 }
255 attrStr += "\"]";
256 if (itIndexDefine != std::prev(indexDefines_.end(), 1)) {
257 attrStr += ",";
258 }
259 }
260 attrStr += "}";
261 }
262
CompareWithTable(const TableInfo & inTableInfo) const263 int TableInfo::CompareWithTable(const TableInfo &inTableInfo) const
264 {
265 if (tableName_ != inTableInfo.GetTableName()) {
266 LOGW("[Relational][Compare] Table name is not same");
267 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
268 }
269
270 if (primaryKey_ != inTableInfo.GetPrimaryKey()) {
271 LOGW("[Relational][Compare] Table primary key is not same");
272 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
273 }
274
275 int fieldCompareResult = CompareWithTableFields(inTableInfo.GetFields());
276 if (fieldCompareResult == -E_RELATIONAL_TABLE_INCOMPATIBLE) {
277 LOGW("[Relational][Compare] Compare table fields with in table, %d", fieldCompareResult);
278 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
279 }
280
281 int indexCompareResult = CompareWithTableIndex(inTableInfo.GetIndexDefine());
282 return (fieldCompareResult == -E_RELATIONAL_TABLE_EQUAL) ? indexCompareResult : fieldCompareResult;
283 }
284
CompareWithTableFields(const std::map<std::string,FieldInfo> & inTableFields) const285 int TableInfo::CompareWithTableFields(const std::map<std::string, FieldInfo> &inTableFields) const
286 {
287 auto itLocal = fields_.begin();
288 auto itInTable = inTableFields.begin();
289 int errCode = -E_RELATIONAL_TABLE_EQUAL;
290 while (itLocal != fields_.end() && itInTable != inTableFields.end()) {
291 if (itLocal->first == itInTable->first) { // Same field
292 if (!itLocal->second.CompareWithField(itInTable->second)) { // Compare field
293 LOGW("[Relational][Compare] Table field is incompatible"); // not compatible
294 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
295 }
296 itLocal++; // Compare next field
297 } else { // Assume local table fields is a subset of in table
298 if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) { // Upgrade field not compatible
299 LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
300 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
301 }
302 errCode = -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
303 }
304 itInTable++; // Next in table field
305 }
306
307 if (itLocal != fields_.end()) {
308 LOGW("[Relational][Compare] Table field is missing");
309 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
310 }
311
312 if (itInTable == inTableFields.end()) {
313 return errCode;
314 }
315
316 while (itInTable != inTableFields.end()) {
317 if (itInTable->second.IsNotNull() && !itInTable->second.HasDefaultValue()) {
318 LOGW("[Relational][Compare] Table upgrade field should allowed to be empty or have default value.");
319 return -E_RELATIONAL_TABLE_INCOMPATIBLE;
320 }
321 itInTable++;
322 }
323 return -E_RELATIONAL_TABLE_COMPATIBLE_UPGRADE;
324 }
325
CompareWithTableIndex(const std::map<std::string,CompositeFields> & inTableIndex) const326 int TableInfo::CompareWithTableIndex(const std::map<std::string, CompositeFields> &inTableIndex) const
327 {
328 // Index comparison results do not affect synchronization decisions
329 auto itLocal = indexDefines_.begin();
330 auto itInTable = inTableIndex.begin();
331 while (itLocal != indexDefines_.end() && itInTable != inTableIndex.end()) {
332 if (itLocal->first != itInTable->first || itLocal->second != itInTable->second) {
333 return -E_RELATIONAL_TABLE_COMPATIBLE;
334 }
335 itLocal++;
336 itInTable++;
337 }
338 return (itLocal == indexDefines_.end() && itInTable == inTableIndex.end()) ? -E_RELATIONAL_TABLE_EQUAL :
339 -E_RELATIONAL_TABLE_COMPATIBLE;
340 }
341
ToTableInfoString() const342 std::string TableInfo::ToTableInfoString() const
343 {
344 std::string attrStr;
345 attrStr += "{";
346 attrStr += R"("NAME": ")" + tableName_ + "\",";
347 AddFieldDefineString(attrStr);
348 attrStr += R"("AUTOINCREMENT": )";
349 if (autoInc_) {
350 attrStr += "true,";
351 } else {
352 attrStr += "false,";
353 }
354 if (!primaryKey_.empty()) {
355 attrStr += R"("PRIMARY_KEY": ")" + primaryKey_ + "\"";
356 }
357 AddIndexDefineString(attrStr);
358 attrStr += "}";
359 return attrStr;
360 }
361
GetSchemaDefine() const362 std::map<FieldPath, SchemaAttribute> TableInfo::GetSchemaDefine() const
363 {
364 std::map<FieldPath, SchemaAttribute> schemaDefine;
365 for (const auto &[fieldName, fieldInfo] : GetFields()) {
366 FieldValue defaultValue;
367 defaultValue.stringValue = fieldInfo.GetDefaultValue();
368 schemaDefine[std::vector { fieldName }] = SchemaAttribute {
369 .type = FieldType::LEAF_FIELD_NULL, // For relational schema, the json field type is unimportant.
370 .isIndexable = true, // For relational schema, all field is indexable.
371 .hasNotNullConstraint = fieldInfo.IsNotNull(),
372 .hasDefaultValue = fieldInfo.HasDefaultValue(),
373 .defaultValue = defaultValue,
374 .customFieldType = {}
375 };
376 }
377 return schemaDefine;
378 }
379
380 namespace {
381 const std::string MAGIC = "relational_opinion";
382 }
383
IsSchemaValid() const384 bool RelationalSchemaObject::IsSchemaValid() const
385 {
386 return isValid_;
387 }
388
GetSchemaType() const389 SchemaType RelationalSchemaObject::GetSchemaType() const
390 {
391 return schemaType_;
392 }
393
ToSchemaString() const394 std::string RelationalSchemaObject::ToSchemaString() const
395 {
396 return schemaString_;
397 }
398
ParseFromSchemaString(const std::string & inSchemaString)399 int RelationalSchemaObject::ParseFromSchemaString(const std::string &inSchemaString)
400 {
401 if (isValid_) {
402 return -E_NOT_PERMIT;
403 }
404
405 if (inSchemaString.empty() || inSchemaString.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT) {
406 LOGE("[RelationalSchema][Parse] SchemaSize=%zu is invalid.", inSchemaString.size());
407 return -E_INVALID_ARGS;
408 }
409 JsonObject schemaObj;
410 int errCode = schemaObj.Parse(inSchemaString);
411 if (errCode != E_OK) {
412 LOGE("[RelationalSchema][Parse] Schema json string parse failed: %d.", errCode);
413 return errCode;
414 }
415
416 errCode = ParseRelationalSchema(schemaObj);
417 if (errCode != E_OK) {
418 LOGE("[RelationalSchema][Parse] Parse to relational schema failed: %d.", errCode);
419 return errCode;
420 }
421
422 schemaType_ = SchemaType::RELATIVE;
423 schemaString_ = schemaObj.ToString();
424 isValid_ = true;
425 return E_OK;
426 }
427
GenerateSchemaString()428 void RelationalSchemaObject::GenerateSchemaString()
429 {
430 schemaString_ = {};
431 schemaString_ += "{";
432 schemaString_ += R"("SCHEMA_VERSION":"2.0",)";
433 schemaString_ += R"("SCHEMA_TYPE":"RELATIVE",)";
434 schemaString_ += R"("TABLES":[)";
435 for (auto it = tables_.begin(); it != tables_.end(); it++) {
436 if (it != tables_.begin()) {
437 schemaString_ += ",";
438 }
439 schemaString_ += it->second.ToTableInfoString();
440 }
441 schemaString_ += R"(])";
442 schemaString_ += "}";
443 }
444
AddRelationalTable(const TableInfo & tb)445 void RelationalSchemaObject::AddRelationalTable(const TableInfo &tb)
446 {
447 tables_[tb.GetTableName()] = tb;
448 isValid_ = true;
449 GenerateSchemaString();
450 }
451
452
RemoveRelationalTable(const std::string & tableName)453 void RelationalSchemaObject::RemoveRelationalTable(const std::string &tableName)
454 {
455 tables_.erase(tableName);
456 GenerateSchemaString();
457 }
458
GetTables() const459 const std::map<std::string, TableInfo> &RelationalSchemaObject::GetTables() const
460 {
461 return tables_;
462 }
463
GetTableNames() const464 std::vector<std::string> RelationalSchemaObject::GetTableNames() const
465 {
466 std::vector<std::string> tableNames;
467 for (const auto &it : tables_) {
468 tableNames.emplace_back(it.first);
469 }
470 return tableNames;
471 }
472
GetTable(const std::string & tableName) const473 TableInfo RelationalSchemaObject::GetTable(const std::string &tableName) const
474 {
475 auto it = tables_.find(tableName);
476 if (it != tables_.end()) {
477 return it->second;
478 }
479 return {};
480 }
481
CompareAgainstSchemaObject(const std::string & inSchemaString,std::map<std::string,int> & cmpRst) const482 int RelationalSchemaObject::CompareAgainstSchemaObject(const std::string &inSchemaString,
483 std::map<std::string, int> &cmpRst) const
484 {
485 return E_OK;
486 }
487
CompareAgainstSchemaObject(const RelationalSchemaObject & inSchemaObject,std::map<std::string,int> & cmpRst) const488 int RelationalSchemaObject::CompareAgainstSchemaObject(const RelationalSchemaObject &inSchemaObject,
489 std::map<std::string, int> &cmpRst) const
490 {
491 return E_OK;
492 }
493
494 namespace {
GetMemberFromJsonObject(const JsonObject & inJsonObject,const std::string & fieldName,FieldType expectType,bool isNecessary,FieldValue & fieldValue)495 int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &fieldName, FieldType expectType,
496 bool isNecessary, FieldValue &fieldValue)
497 {
498 if (!inJsonObject.IsFieldPathExist(FieldPath {fieldName})) {
499 if (isNecessary) {
500 LOGE("[RelationalSchema][Parse] Get schema %s not exist. isNecessary: %d", fieldName.c_str(), isNecessary);
501 return -E_SCHEMA_PARSE_FAIL;
502 }
503 return -E_NOT_FOUND;
504 }
505
506 FieldType fieldType;
507 int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {fieldName}, fieldType);
508 if (errCode != E_OK) {
509 LOGE("[RelationalSchema][Parse] Get schema %s fieldType failed: %d.", fieldName.c_str(), errCode);
510 return -E_SCHEMA_PARSE_FAIL;
511 }
512
513 if (fieldType != expectType) {
514 LOGE("[RelationalSchema][Parse] Expect %s fieldType %d but: %d.", fieldName.c_str(), expectType, fieldType);
515 return -E_SCHEMA_PARSE_FAIL;
516 }
517
518 errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath {fieldName}, fieldValue);
519 if (errCode != E_OK) {
520 LOGE("[RelationalSchema][Parse] Get schema %s value failed: %d.", fieldName.c_str(), errCode);
521 return -E_SCHEMA_PARSE_FAIL;
522 }
523 return E_OK;
524 }
525 }
526
ParseRelationalSchema(const JsonObject & inJsonObject)527 int RelationalSchemaObject::ParseRelationalSchema(const JsonObject &inJsonObject)
528 {
529 int errCode = ParseCheckSchemaVersion(inJsonObject);
530 if (errCode != E_OK) {
531 return errCode;
532 }
533 errCode = ParseCheckSchemaType(inJsonObject);
534 if (errCode != E_OK) {
535 return errCode;
536 }
537 return ParseCheckSchemaTableDefine(inJsonObject);
538 }
539
ParseCheckSchemaVersion(const JsonObject & inJsonObject)540 int RelationalSchemaObject::ParseCheckSchemaVersion(const JsonObject &inJsonObject)
541 {
542 FieldValue fieldValue;
543 int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_VERSION,
544 FieldType::LEAF_FIELD_STRING, true, fieldValue);
545 if (errCode != E_OK) {
546 return errCode;
547 }
548
549 if (SchemaUtils::Strip(fieldValue.stringValue) != SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) {
550 LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_VERSION=%s.", fieldValue.stringValue.c_str());
551 return -E_SCHEMA_PARSE_FAIL;
552 }
553 schemaVersion_ = SchemaConstant::SCHEMA_SUPPORT_VERSION_V2;
554 return E_OK;
555 }
556
ParseCheckSchemaType(const JsonObject & inJsonObject)557 int RelationalSchemaObject::ParseCheckSchemaType(const JsonObject &inJsonObject)
558 {
559 FieldValue fieldValue;
560 int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_TYPE,
561 FieldType::LEAF_FIELD_STRING, true, fieldValue);
562 if (errCode != E_OK) {
563 return errCode;
564 }
565
566 if (SchemaUtils::Strip(fieldValue.stringValue) != SchemaConstant::KEYWORD_TYPE_RELATIVE) {
567 LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_TYPE=%s.", fieldValue.stringValue.c_str());
568 return -E_SCHEMA_PARSE_FAIL;
569 }
570 schemaType_ = SchemaType::RELATIVE;
571 return E_OK;
572 }
573
ParseCheckSchemaTableDefine(const JsonObject & inJsonObject)574 int RelationalSchemaObject::ParseCheckSchemaTableDefine(const JsonObject &inJsonObject)
575 {
576 FieldType fieldType;
577 int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, fieldType);
578 if (errCode != E_OK) {
579 LOGE("[RelationalSchema][Parse] Get schema TABLES fieldType failed: %d.", errCode);
580 return -E_SCHEMA_PARSE_FAIL;
581 }
582 if (FieldType::LEAF_FIELD_ARRAY != fieldType) {
583 LOGE("[RelationalSchema][Parse] Expect TABLES fieldType ARRAY but %s.",
584 SchemaUtils::FieldTypeString(fieldType).c_str());
585 return -E_SCHEMA_PARSE_FAIL;
586 }
587 std::vector<JsonObject> tables;
588 errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::KEYWORD_SCHEMA_TABLE}, tables);
589 if (errCode != E_OK) {
590 LOGE("[RelationalSchema][Parse] Get schema TABLES value failed: %d.", errCode);
591 return -E_SCHEMA_PARSE_FAIL;
592 }
593 for (const JsonObject &table : tables) {
594 errCode = ParseCheckTableInfo(table);
595 if (errCode != E_OK) {
596 LOGE("[RelationalSchema][Parse] Parse schema TABLES failed: %d.", errCode);
597 return errCode;
598 }
599 }
600 return E_OK;
601 }
602
ParseCheckTableInfo(const JsonObject & inJsonObject)603 int RelationalSchemaObject::ParseCheckTableInfo(const JsonObject &inJsonObject)
604 {
605 TableInfo resultTable;
606 int errCode = ParseCheckTableName(inJsonObject, resultTable);
607 if (errCode != E_OK) {
608 return errCode;
609 }
610 errCode = ParseCheckTableDefine(inJsonObject, resultTable);
611 if (errCode != E_OK) {
612 return errCode;
613 }
614 errCode = ParseCheckTableAutoInc(inJsonObject, resultTable);
615 if (errCode != E_OK) {
616 return errCode;
617 }
618 errCode = ParseCheckTablePrimaryKey(inJsonObject, resultTable);
619 if (errCode != E_OK) {
620 return errCode;
621 }
622 errCode = ParseCheckTableIndex(inJsonObject, resultTable);
623 if (errCode != E_OK) {
624 return errCode;
625 }
626 tables_[resultTable.GetTableName()] = resultTable;
627 return E_OK;
628 }
629
ParseCheckTableName(const JsonObject & inJsonObject,TableInfo & resultTable)630 int RelationalSchemaObject::ParseCheckTableName(const JsonObject &inJsonObject, TableInfo &resultTable)
631 {
632 FieldValue fieldValue;
633 int errCode = GetMemberFromJsonObject(inJsonObject, "NAME", FieldType::LEAF_FIELD_STRING,
634 true, fieldValue);
635 if (errCode == E_OK) {
636 if (!DBCommon::CheckIsAlnumAndUnderscore(fieldValue.stringValue)) {
637 LOGE("[RelationalSchema][Parse] Invalid characters in table name, err=%d.", errCode);
638 return -E_SCHEMA_PARSE_FAIL;
639 }
640 resultTable.SetTableName(fieldValue.stringValue);
641 }
642 return errCode;
643 }
644
ParseCheckTableDefine(const JsonObject & inJsonObject,TableInfo & resultTable)645 int RelationalSchemaObject::ParseCheckTableDefine(const JsonObject &inJsonObject, TableInfo &resultTable)
646 {
647 std::map<FieldPath, FieldType> tableFields;
648 int errCode = inJsonObject.GetSubFieldPathAndType(FieldPath {"DEFINE"}, tableFields);
649 if (errCode != E_OK) {
650 LOGE("[RelationalSchema][Parse] Get schema TABLES DEFINE failed: %d.", errCode);
651 return -E_SCHEMA_PARSE_FAIL;
652 }
653
654 for (const auto &field : tableFields) {
655 if (field.second != FieldType::INTERNAL_FIELD_OBJECT) {
656 LOGE("[RelationalSchema][Parse] Expect schema TABLES DEFINE fieldType INTERNAL OBJECT but : %s.",
657 SchemaUtils::FieldTypeString(field.second).c_str());
658 return -E_SCHEMA_PARSE_FAIL;
659 }
660
661 JsonObject fieldObj;
662 errCode = inJsonObject.GetObjectByFieldPath(field.first, fieldObj);
663 if (errCode != E_OK) {
664 LOGE("[RelationalSchema][Parse] Get table field object failed. %d", errCode);
665 return errCode;
666 }
667
668 if (!DBCommon::CheckIsAlnumAndUnderscore(field.first[1])) {
669 LOGE("[RelationalSchema][Parse] Invalid characters in field name, err=%d.", errCode);
670 return -E_SCHEMA_PARSE_FAIL;
671 }
672
673 FieldInfo fieldInfo;
674 fieldInfo.SetFieldName(field.first[1]); // 1 : table name element in path
675 errCode = ParseCheckTableFieldInfo(fieldObj, field.first, fieldInfo);
676 if (errCode != E_OK) {
677 LOGE("[RelationalSchema][Parse] Parse table field info failed. %d", errCode);
678 return -E_SCHEMA_PARSE_FAIL;
679 }
680 resultTable.AddField(fieldInfo);
681 }
682 return E_OK;
683 }
684
ParseCheckTableFieldInfo(const JsonObject & inJsonObject,const FieldPath & path,FieldInfo & field)685 int RelationalSchemaObject::ParseCheckTableFieldInfo(const JsonObject &inJsonObject, const FieldPath &path,
686 FieldInfo &field)
687 {
688 FieldValue fieldValue;
689 int errCode = GetMemberFromJsonObject(inJsonObject, "COLUMN_ID", FieldType::LEAF_FIELD_INTEGER, true, fieldValue);
690 if (errCode != E_OK) {
691 return errCode;
692 }
693 field.SetColumnId(fieldValue.integerValue);
694
695 errCode = GetMemberFromJsonObject(inJsonObject, "TYPE", FieldType::LEAF_FIELD_STRING, true, fieldValue);
696 if (errCode != E_OK) {
697 return errCode;
698 }
699 field.SetDataType(fieldValue.stringValue);
700
701 errCode = GetMemberFromJsonObject(inJsonObject, "NOT_NULL", FieldType::LEAF_FIELD_BOOL, true, fieldValue);
702 if (errCode != E_OK) {
703 return errCode;
704 }
705 field.SetNotNull(fieldValue.boolValue);
706
707 errCode = GetMemberFromJsonObject(inJsonObject, "DEFAULT", FieldType::LEAF_FIELD_STRING, false, fieldValue);
708 if (errCode == E_OK) {
709 field.SetDefaultValue(fieldValue.stringValue);
710 } else if (errCode != -E_NOT_FOUND) {
711 return errCode;
712 }
713
714 return E_OK;
715 }
716
ParseCheckTableAutoInc(const JsonObject & inJsonObject,TableInfo & resultTable)717 int RelationalSchemaObject::ParseCheckTableAutoInc(const JsonObject &inJsonObject, TableInfo &resultTable)
718 {
719 FieldValue fieldValue;
720 int errCode = GetMemberFromJsonObject(inJsonObject, "AUTOINCREMENT", FieldType::LEAF_FIELD_BOOL, false, fieldValue);
721 if (errCode == E_OK) {
722 resultTable.SetAutoIncrement(fieldValue.boolValue);
723 } else if (errCode != -E_NOT_FOUND) {
724 return errCode;
725 }
726 return E_OK;
727 }
728
ParseCheckTablePrimaryKey(const JsonObject & inJsonObject,TableInfo & resultTable)729 int RelationalSchemaObject::ParseCheckTablePrimaryKey(const JsonObject &inJsonObject, TableInfo &resultTable)
730 {
731 FieldValue fieldValue;
732 int errCode = GetMemberFromJsonObject(inJsonObject, "PRIMARY_KEY", FieldType::LEAF_FIELD_STRING, false, fieldValue);
733 if (errCode == E_OK) {
734 resultTable.SetPrimaryKey(fieldValue.stringValue);
735 }
736 return errCode;
737 }
738
ParseCheckTableIndex(const JsonObject & inJsonObject,TableInfo & resultTable)739 int RelationalSchemaObject::ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable)
740 {
741 if (!inJsonObject.IsFieldPathExist(FieldPath {"INDEX"})) { // INDEX is not necessary
742 return E_OK;
743 }
744 std::map<FieldPath, FieldType> tableFields;
745 int errCode = inJsonObject.GetSubFieldPathAndType(FieldPath {"INDEX"}, tableFields);
746 if (errCode != E_OK) {
747 LOGE("[RelationalSchema][Parse] Get schema TABLES INDEX failed: %d.", errCode);
748 return -E_SCHEMA_PARSE_FAIL;
749 }
750
751 for (const auto &field : tableFields) {
752 if (field.second != FieldType::LEAF_FIELD_ARRAY) {
753 LOGE("[RelationalSchema][Parse] Expect schema TABLES INDEX fieldType ARRAY but : %s.",
754 SchemaUtils::FieldTypeString(field.second).c_str());
755 return -E_SCHEMA_PARSE_FAIL;
756 }
757 CompositeFields indexDefine;
758 errCode = inJsonObject.GetStringArrayByFieldPath(field.first, indexDefine);
759 if (errCode != E_OK) {
760 LOGE("[RelationalSchema][Parse] Get schema TABLES INDEX field value failed: %d.", errCode);
761 return -E_SCHEMA_PARSE_FAIL;
762 }
763 resultTable.AddIndexDefine(field.first[1], indexDefine); // 1 : second element in path
764 }
765 return E_OK;
766 }
767 }
768 #endif
769