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 {
IsSchemaValid() const26 bool RelationalSchemaObject::IsSchemaValid() const
27 {
28 return isValid_;
29 }
30
GetSchemaType() const31 SchemaType RelationalSchemaObject::GetSchemaType() const
32 {
33 return schemaType_;
34 }
35
ToSchemaString() const36 std::string RelationalSchemaObject::ToSchemaString() const
37 {
38 return schemaString_;
39 }
40
ParseFromSchemaString(const std::string & inSchemaString)41 int RelationalSchemaObject::ParseFromSchemaString(const std::string &inSchemaString)
42 {
43 if (isValid_) {
44 return -E_NOT_PERMIT;
45 }
46
47 if (inSchemaString.empty() || inSchemaString.size() > SchemaConstant::SCHEMA_STRING_SIZE_LIMIT) {
48 LOGE("[RelationalSchema][Parse] SchemaSize=%zu is invalid.", inSchemaString.size());
49 return -E_INVALID_ARGS;
50 }
51 JsonObject schemaObj;
52 int errCode = schemaObj.Parse(inSchemaString);
53 if (errCode != E_OK) {
54 LOGE("[RelationalSchema][Parse] Schema json string parse failed: %d.", errCode);
55 return errCode;
56 }
57
58 errCode = ParseRelationalSchema(schemaObj);
59 if (errCode != E_OK) {
60 LOGE("[RelationalSchema][Parse] Parse to relational schema failed: %d.", errCode);
61 return errCode;
62 }
63
64 schemaType_ = SchemaType::RELATIVE;
65 schemaString_ = schemaObj.ToString();
66 isValid_ = true;
67 return E_OK;
68 }
69
GenerateSchemaString()70 void RelationalSchemaObject::GenerateSchemaString()
71 {
72 schemaString_ = {};
73 schemaString_ += "{";
74 schemaString_ += R"("SCHEMA_VERSION":")" + schemaVersion_ + R"(",)";
75 schemaString_ += R"("SCHEMA_TYPE":"RELATIVE",)";
76 if (schemaVersion_ == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1) {
77 std::string modeString = tableMode_ == DistributedTableMode::COLLABORATION ?
78 SchemaConstant::KEYWORD_TABLE_COLLABORATION : SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE;
79 schemaString_ += R"("TABLE_MODE":")" + modeString + R"(",)";
80 }
81 schemaString_ += R"("TABLES":[)";
82 for (auto it = tables_.begin(); it != tables_.end(); it++) {
83 if (it != tables_.begin()) {
84 schemaString_ += ",";
85 }
86 schemaString_ += it->second.ToTableInfoString(schemaVersion_);
87 }
88 schemaString_ += R"(])";
89 schemaString_ += "}";
90 }
91
AddRelationalTable(const TableInfo & table)92 void RelationalSchemaObject::AddRelationalTable(const TableInfo &table)
93 {
94 tables_[table.GetTableName()] = table;
95 isValid_ = true;
96 if (table.GetPrimaryKey().size() > 1) { // Table with composite primary keys
97 // Composite primary keys are supported since version 2.1
98 schemaVersion_ = SchemaConstant::SCHEMA_CURRENT_VERSION;
99 }
100 GenerateSchemaString();
101 }
102
RemoveRelationalTable(const std::string & tableName)103 void RelationalSchemaObject::RemoveRelationalTable(const std::string &tableName)
104 {
105 tables_.erase(tableName);
106 GenerateSchemaString();
107 }
108
GetTables() const109 const TableInfoMap &RelationalSchemaObject::GetTables() const
110 {
111 return tables_;
112 }
113
GetTableNames() const114 std::vector<std::string> RelationalSchemaObject::GetTableNames() const
115 {
116 std::vector<std::string> tableNames;
117 for (const auto &it : tables_) {
118 tableNames.emplace_back(it.first);
119 }
120 return tableNames;
121 }
122
GetTable(const std::string & tableName) const123 TableInfo RelationalSchemaObject::GetTable(const std::string &tableName) const
124 {
125 auto it = tables_.find(tableName);
126 if (it != tables_.end()) {
127 return it->second;
128 }
129 return {};
130 }
131
GetSchemaVersion() const132 std::string RelationalSchemaObject::GetSchemaVersion() const
133 {
134 return schemaVersion_;
135 }
136
GetTableMode() const137 DistributedTableMode RelationalSchemaObject::GetTableMode() const
138 {
139 return tableMode_;
140 }
141
SetTableMode(DistributedTableMode mode)142 void RelationalSchemaObject::SetTableMode(DistributedTableMode mode)
143 {
144 tableMode_ = mode;
145 if (tableMode_ == DistributedTableMode::COLLABORATION) {
146 schemaVersion_ = SchemaConstant::SCHEMA_CURRENT_VERSION;
147 }
148 GenerateSchemaString();
149 }
150
CompareAgainstSchemaObject(const std::string & inSchemaString,std::map<std::string,int> & cmpRst) const151 int RelationalSchemaObject::CompareAgainstSchemaObject(const std::string &inSchemaString,
152 std::map<std::string, int> &cmpRst) const
153 {
154 return E_OK;
155 }
156
CompareAgainstSchemaObject(const RelationalSchemaObject & inSchemaObject,std::map<std::string,int> & cmpRst) const157 int RelationalSchemaObject::CompareAgainstSchemaObject(const RelationalSchemaObject &inSchemaObject,
158 std::map<std::string, int> &cmpRst) const
159 {
160 return E_OK;
161 }
162
163 namespace {
GetMemberFromJsonObject(const JsonObject & inJsonObject,const std::string & fieldName,FieldType expectType,bool isNecessary,FieldValue & fieldValue)164 int GetMemberFromJsonObject(const JsonObject &inJsonObject, const std::string &fieldName, FieldType expectType,
165 bool isNecessary, FieldValue &fieldValue)
166 {
167 if (!inJsonObject.IsFieldPathExist(FieldPath {fieldName})) {
168 if (isNecessary) {
169 LOGE("[RelationalSchema][Parse] Get schema %s not exist. isNecessary: %d", fieldName.c_str(), isNecessary);
170 return -E_SCHEMA_PARSE_FAIL;
171 }
172 return -E_NOT_FOUND;
173 }
174
175 FieldType fieldType;
176 int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {fieldName}, fieldType);
177 if (errCode != E_OK) {
178 LOGE("[RelationalSchema][Parse] Get schema %s fieldType failed: %d.", fieldName.c_str(), errCode);
179 return -E_SCHEMA_PARSE_FAIL;
180 }
181
182 if (fieldType != expectType) {
183 LOGE("[RelationalSchema][Parse] Expect %s fieldType %d but: %d.", fieldName.c_str(),
184 static_cast<int>(expectType), static_cast<int>(fieldType));
185 return -E_SCHEMA_PARSE_FAIL;
186 }
187
188 errCode = inJsonObject.GetFieldValueByFieldPath(FieldPath {fieldName}, fieldValue);
189 if (errCode != E_OK) {
190 LOGE("[RelationalSchema][Parse] Get schema %s value failed: %d.", fieldName.c_str(), errCode);
191 return -E_SCHEMA_PARSE_FAIL;
192 }
193 return E_OK;
194 }
195 }
196
ParseRelationalSchema(const JsonObject & inJsonObject)197 int RelationalSchemaObject::ParseRelationalSchema(const JsonObject &inJsonObject)
198 {
199 int errCode = ParseCheckSchemaVersion(inJsonObject);
200 if (errCode != E_OK) {
201 return errCode;
202 }
203 errCode = ParseCheckSchemaType(inJsonObject);
204 if (errCode != E_OK) {
205 return errCode;
206 }
207 errCode = ParseCheckTableMode(inJsonObject);
208 if (errCode != E_OK) {
209 return errCode;
210 }
211 return ParseCheckSchemaTableDefine(inJsonObject);
212 }
213
214 namespace {
IsSchemaVersionValid(const std::string & version)215 inline bool IsSchemaVersionValid(const std::string &version)
216 {
217 std::string stripedVersion = SchemaUtils::Strip(version);
218 return stripedVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2 ||
219 stripedVersion == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2_1;
220 }
221 }
222
ParseCheckSchemaVersion(const JsonObject & inJsonObject)223 int RelationalSchemaObject::ParseCheckSchemaVersion(const JsonObject &inJsonObject)
224 {
225 FieldValue fieldValue;
226 int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_VERSION,
227 FieldType::LEAF_FIELD_STRING, true, fieldValue);
228 if (errCode != E_OK) {
229 return errCode;
230 }
231
232 if (IsSchemaVersionValid(fieldValue.stringValue)) {
233 schemaVersion_ = fieldValue.stringValue;
234 return E_OK;
235 }
236
237 LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_VERSION=%s.", fieldValue.stringValue.c_str());
238 return -E_SCHEMA_PARSE_FAIL;
239 }
240
ParseCheckSchemaType(const JsonObject & inJsonObject)241 int RelationalSchemaObject::ParseCheckSchemaType(const JsonObject &inJsonObject)
242 {
243 FieldValue fieldValue;
244 int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_SCHEMA_TYPE,
245 FieldType::LEAF_FIELD_STRING, true, fieldValue);
246 if (errCode != E_OK) {
247 return errCode;
248 }
249
250 if (SchemaUtils::Strip(fieldValue.stringValue) != SchemaConstant::KEYWORD_TYPE_RELATIVE) {
251 LOGE("[RelationalSchema][Parse] Unexpected SCHEMA_TYPE=%s.", fieldValue.stringValue.c_str());
252 return -E_SCHEMA_PARSE_FAIL;
253 }
254 schemaType_ = SchemaType::RELATIVE;
255 return E_OK;
256 }
257
258 namespace {
IsTableModeValid(const std::string & mode)259 inline bool IsTableModeValid(const std::string &mode)
260 {
261 std::string stripedMode = SchemaUtils::Strip(mode);
262 return stripedMode == SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE ||
263 stripedMode == SchemaConstant::KEYWORD_TABLE_COLLABORATION;
264 }
265 }
266
ParseCheckTableMode(const JsonObject & inJsonObject)267 int RelationalSchemaObject::ParseCheckTableMode(const JsonObject &inJsonObject)
268 {
269 if (schemaVersion_ == SchemaConstant::SCHEMA_SUPPORT_VERSION_V2) {
270 return E_OK; // version 2 has no table mode, no parsing required
271 }
272
273 FieldValue fieldValue;
274 int errCode = GetMemberFromJsonObject(inJsonObject, SchemaConstant::KEYWORD_TABLE_MODE,
275 FieldType::LEAF_FIELD_STRING, true, fieldValue);
276 if (errCode != E_OK) {
277 return errCode;
278 }
279
280 if (!IsTableModeValid(fieldValue.stringValue)) {
281 LOGE("[RelationalSchema][Parse] Unexpected TABLE_MODE=%s.", fieldValue.stringValue.c_str());
282 return -E_SCHEMA_PARSE_FAIL;
283 }
284
285 tableMode_ = SchemaUtils::Strip(fieldValue.stringValue) == SchemaConstant::KEYWORD_TABLE_SPLIT_DEVICE ?
286 DistributedDB::SPLIT_BY_DEVICE : DistributedTableMode::COLLABORATION;
287 return E_OK;
288 }
289
ParseCheckSchemaTableDefine(const JsonObject & inJsonObject)290 int RelationalSchemaObject::ParseCheckSchemaTableDefine(const JsonObject &inJsonObject)
291 {
292 FieldType fieldType;
293 int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {SchemaConstant::KEYWORD_SCHEMA_TABLE}, fieldType);
294 if (errCode != E_OK) {
295 LOGE("[RelationalSchema][Parse] Get schema TABLES fieldType failed: %d.", errCode);
296 return -E_SCHEMA_PARSE_FAIL;
297 }
298 if (FieldType::LEAF_FIELD_ARRAY != fieldType) {
299 LOGE("[RelationalSchema][Parse] Expect TABLES fieldType ARRAY but %s.",
300 SchemaUtils::FieldTypeString(fieldType).c_str());
301 return -E_SCHEMA_PARSE_FAIL;
302 }
303 std::vector<JsonObject> tables;
304 errCode = inJsonObject.GetObjectArrayByFieldPath(FieldPath{SchemaConstant::KEYWORD_SCHEMA_TABLE}, tables);
305 if (errCode != E_OK) {
306 LOGE("[RelationalSchema][Parse] Get schema TABLES value failed: %d.", errCode);
307 return -E_SCHEMA_PARSE_FAIL;
308 }
309 for (const JsonObject &table : tables) {
310 errCode = ParseCheckTableInfo(table);
311 if (errCode != E_OK) {
312 LOGE("[RelationalSchema][Parse] Parse schema TABLES failed: %d.", errCode);
313 return -E_SCHEMA_PARSE_FAIL;
314 }
315 }
316 return E_OK;
317 }
318
ParseCheckTableInfo(const JsonObject & inJsonObject)319 int RelationalSchemaObject::ParseCheckTableInfo(const JsonObject &inJsonObject)
320 {
321 TableInfo resultTable;
322 int errCode = ParseCheckTableName(inJsonObject, resultTable);
323 if (errCode != E_OK) {
324 return errCode;
325 }
326 errCode = ParseCheckTableDefine(inJsonObject, resultTable);
327 if (errCode != E_OK) {
328 return errCode;
329 }
330 errCode = ParseCheckTableAutoInc(inJsonObject, resultTable);
331 if (errCode != E_OK) {
332 return errCode;
333 }
334 errCode = ParseCheckTablePrimaryKey(inJsonObject, resultTable);
335 if (errCode != E_OK) {
336 return errCode;
337 }
338
339 errCode = ParseCheckTableSyncType(inJsonObject, resultTable);
340 if (errCode != E_OK) {
341 return errCode;
342 }
343 errCode = ParseCheckTableIndex(inJsonObject, resultTable);
344 if (errCode != E_OK) {
345 return errCode;
346 }
347 errCode = ParseCheckTableUnique(inJsonObject, resultTable);
348 if (errCode != E_OK) {
349 return errCode;
350 }
351 tables_[resultTable.GetTableName()] = resultTable;
352 return E_OK;
353 }
354
ParseCheckTableName(const JsonObject & inJsonObject,TableInfo & resultTable)355 int RelationalSchemaObject::ParseCheckTableName(const JsonObject &inJsonObject, TableInfo &resultTable)
356 {
357 FieldValue fieldValue;
358 int errCode = GetMemberFromJsonObject(inJsonObject, "NAME", FieldType::LEAF_FIELD_STRING,
359 true, fieldValue);
360 if (errCode == E_OK) {
361 if (!DBCommon::CheckIsAlnumAndUnderscore(fieldValue.stringValue)) {
362 LOGE("[RelationalSchema][Parse] Invalid characters in table name, err=%d.", errCode);
363 return -E_SCHEMA_PARSE_FAIL;
364 }
365 resultTable.SetTableName(fieldValue.stringValue);
366 }
367 return errCode;
368 }
369
ParseCheckTableDefine(const JsonObject & inJsonObject,TableInfo & resultTable)370 int RelationalSchemaObject::ParseCheckTableDefine(const JsonObject &inJsonObject, TableInfo &resultTable)
371 {
372 std::map<FieldPath, FieldType> tableFields;
373 int errCode = inJsonObject.GetSubFieldPathAndType(FieldPath {"DEFINE"}, tableFields);
374 if (errCode != E_OK) {
375 LOGE("[RelationalSchema][Parse] Get schema TABLES DEFINE failed: %d.", errCode);
376 return -E_SCHEMA_PARSE_FAIL;
377 }
378
379 for (const auto &field : tableFields) {
380 if (field.second != FieldType::INTERNAL_FIELD_OBJECT) {
381 LOGE("[RelationalSchema][Parse] Expect schema TABLES DEFINE fieldType INTERNAL OBJECT but : %s.",
382 SchemaUtils::FieldTypeString(field.second).c_str());
383 return -E_SCHEMA_PARSE_FAIL;
384 }
385
386 JsonObject fieldObj;
387 errCode = inJsonObject.GetObjectByFieldPath(field.first, fieldObj);
388 if (errCode != E_OK) {
389 LOGE("[RelationalSchema][Parse] Get table field object failed. %d", errCode);
390 return errCode;
391 }
392
393 if (!DBCommon::CheckIsAlnumAndUnderscore(field.first[1])) {
394 LOGE("[RelationalSchema][Parse] Invalid characters in field name, err=%d.", errCode);
395 return -E_SCHEMA_PARSE_FAIL;
396 }
397
398 FieldInfo fieldInfo;
399 fieldInfo.SetFieldName(field.first[1]); // 1 : table name element in path
400 errCode = ParseCheckTableFieldInfo(fieldObj, field.first, fieldInfo);
401 if (errCode != E_OK) {
402 LOGE("[RelationalSchema][Parse] Parse table field info failed. %d", errCode);
403 return -E_SCHEMA_PARSE_FAIL;
404 }
405 resultTable.AddField(fieldInfo);
406 }
407 return E_OK;
408 }
409
ParseCheckTableFieldInfo(const JsonObject & inJsonObject,const FieldPath & path,FieldInfo & field)410 int RelationalSchemaObject::ParseCheckTableFieldInfo(const JsonObject &inJsonObject, const FieldPath &path,
411 FieldInfo &field)
412 {
413 FieldValue fieldValue;
414 int errCode = GetMemberFromJsonObject(inJsonObject, "COLUMN_ID", FieldType::LEAF_FIELD_INTEGER, true, fieldValue);
415 if (errCode != E_OK) {
416 return errCode;
417 }
418 field.SetColumnId(fieldValue.integerValue);
419
420 errCode = GetMemberFromJsonObject(inJsonObject, "TYPE", FieldType::LEAF_FIELD_STRING, true, fieldValue);
421 if (errCode != E_OK) {
422 return errCode;
423 }
424 field.SetDataType(fieldValue.stringValue);
425
426 errCode = GetMemberFromJsonObject(inJsonObject, "NOT_NULL", FieldType::LEAF_FIELD_BOOL, true, fieldValue);
427 if (errCode != E_OK) {
428 return errCode;
429 }
430 field.SetNotNull(fieldValue.boolValue);
431
432 errCode = GetMemberFromJsonObject(inJsonObject, "DEFAULT", FieldType::LEAF_FIELD_STRING, false, fieldValue);
433 if (errCode == E_OK) {
434 field.SetDefaultValue(fieldValue.stringValue);
435 } else if (errCode != -E_NOT_FOUND) {
436 return errCode;
437 }
438
439 return E_OK;
440 }
441
ParseCheckTableAutoInc(const JsonObject & inJsonObject,TableInfo & resultTable)442 int RelationalSchemaObject::ParseCheckTableAutoInc(const JsonObject &inJsonObject, TableInfo &resultTable)
443 {
444 FieldValue fieldValue;
445 int errCode = GetMemberFromJsonObject(inJsonObject, "AUTOINCREMENT", FieldType::LEAF_FIELD_BOOL, false, fieldValue);
446 if (errCode == E_OK) {
447 resultTable.SetAutoIncrement(fieldValue.boolValue);
448 } else if (errCode != -E_NOT_FOUND) {
449 return errCode;
450 }
451 return E_OK;
452 }
453
ParseCheckTablePrimaryKey(const JsonObject & inJsonObject,TableInfo & resultTable)454 int RelationalSchemaObject::ParseCheckTablePrimaryKey(const JsonObject &inJsonObject, TableInfo &resultTable)
455 {
456 if (!inJsonObject.IsFieldPathExist(FieldPath {"PRIMARY_KEY"})) {
457 return E_OK;
458 }
459
460 FieldType type;
461 int errCode = inJsonObject.GetFieldTypeByFieldPath(FieldPath {"PRIMARY_KEY"}, type);
462 if (errCode != E_OK) {
463 return errCode;
464 }
465
466 if (type == FieldType::LEAF_FIELD_STRING) { // Compatible with schema 2.0
467 FieldValue fieldValue;
468 errCode = GetMemberFromJsonObject(inJsonObject, "PRIMARY_KEY", FieldType::LEAF_FIELD_STRING, false, fieldValue);
469 if (errCode == E_OK) {
470 resultTable.SetPrimaryKey(fieldValue.stringValue, 1);
471 }
472 } else if (type == FieldType::LEAF_FIELD_ARRAY) {
473 CompositeFields multiPrimaryKey;
474 errCode = inJsonObject.GetStringArrayByFieldPath(FieldPath {"PRIMARY_KEY"}, multiPrimaryKey);
475 if (errCode == E_OK) {
476 int index = 1; // primary key index
477 for (const auto &item : multiPrimaryKey) {
478 resultTable.SetPrimaryKey(item, index++);
479 }
480 }
481 } else {
482 errCode = -E_SCHEMA_PARSE_FAIL;
483 }
484 return errCode;
485 }
486
ParseCheckTableSyncType(const JsonObject & inJsonObject,TableInfo & resultTable)487 int RelationalSchemaObject::ParseCheckTableSyncType(const JsonObject &inJsonObject, TableInfo &resultTable)
488 {
489 FieldValue fieldValue;
490 int errCode = GetMemberFromJsonObject(inJsonObject, "TABLE_SYNC_TYPE", FieldType::LEAF_FIELD_INTEGER,
491 false, fieldValue);
492 if (errCode == E_OK) {
493 resultTable.SetTableSyncType(static_cast<TableSyncType>(fieldValue.integerValue));
494 } else if (errCode != -E_NOT_FOUND) {
495 return errCode;
496 }
497 return E_OK; // if there is no "TABLE_SYNC_TYPE" filed, the table_sync_type is DEVICE_COOPERATION
498 }
499
ParseCheckTableIndex(const JsonObject & inJsonObject,TableInfo & resultTable)500 int RelationalSchemaObject::ParseCheckTableIndex(const JsonObject &inJsonObject, TableInfo &resultTable)
501 {
502 if (!inJsonObject.IsFieldPathExist(FieldPath {"INDEX"})) { // INDEX is not necessary
503 return E_OK;
504 }
505 std::map<FieldPath, FieldType> tableFields;
506 int errCode = inJsonObject.GetSubFieldPathAndType(FieldPath {"INDEX"}, tableFields);
507 if (errCode != E_OK) {
508 LOGE("[RelationalSchema][Parse] Get schema TABLES INDEX failed: %d.", errCode);
509 return -E_SCHEMA_PARSE_FAIL;
510 }
511
512 for (const auto &field : tableFields) {
513 if (field.second != FieldType::LEAF_FIELD_ARRAY) {
514 LOGE("[RelationalSchema][Parse] Expect schema TABLES INDEX fieldType ARRAY but : %s.",
515 SchemaUtils::FieldTypeString(field.second).c_str());
516 return -E_SCHEMA_PARSE_FAIL;
517 }
518 CompositeFields indexDefine;
519 errCode = inJsonObject.GetStringArrayByFieldPath(field.first, indexDefine);
520 if (errCode != E_OK) {
521 LOGE("[RelationalSchema][Parse] Get schema TABLES INDEX field value failed: %d.", errCode);
522 return -E_SCHEMA_PARSE_FAIL;
523 }
524 resultTable.AddIndexDefine(field.first[1], indexDefine); // 1 : second element in path
525 }
526 return E_OK;
527 }
528
ParseCheckTableUnique(const JsonObject & inJsonObject,TableInfo & resultTable)529 int RelationalSchemaObject::ParseCheckTableUnique(const JsonObject &inJsonObject, TableInfo &resultTable)
530 {
531 if (!inJsonObject.IsFieldPathExist(FieldPath {"UNIQUE"})) { // UNIQUE is not necessary
532 return E_OK;
533 }
534
535 std::vector<CompositeFields> uniques;
536 int errCode = inJsonObject.GetArrayContentOfStringOrStringArray(FieldPath {"UNIQUE"}, uniques);
537 if (errCode != E_OK) {
538 LOGE("[RelationalSchema][Parse] Get schema TABLES UNIQUE failed: %d.", errCode);
539 return -E_SCHEMA_PARSE_FAIL;
540 }
541 resultTable.SetUniqueDefine(uniques);
542 return E_OK;
543 }
544 }
545 #endif