• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #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