• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "sqlite_relational_utils.h"
17 #include "cloud/cloud_db_constant.h"
18 #include "cloud/cloud_db_types.h"
19 #include "cloud/cloud_storage_utils.h"
20 #include "db_common.h"
21 #include "db_errno.h"
22 #include "res_finalizer.h"
23 #include "runtime_context.h"
24 #include "sqlite_utils.h"
25 #include "time_helper.h"
26 
27 namespace DistributedDB {
GetDataValueByType(sqlite3_stmt * statement,int cid,DataValue & value)28 int SQLiteRelationalUtils::GetDataValueByType(sqlite3_stmt *statement, int cid, DataValue &value)
29 {
30     if (statement == nullptr || cid < 0 || cid >= sqlite3_column_count(statement)) {
31         return -E_INVALID_ARGS;
32     }
33 
34     int errCode = E_OK;
35     int storageType = sqlite3_column_type(statement, cid);
36     switch (storageType) {
37         case SQLITE_INTEGER:
38             value = static_cast<int64_t>(sqlite3_column_int64(statement, cid));
39             break;
40         case SQLITE_FLOAT:
41             value = sqlite3_column_double(statement, cid);
42             break;
43         case SQLITE_BLOB: {
44             std::vector<uint8_t> blobValue;
45             errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
46             if (errCode != E_OK) {
47                 return errCode;
48             }
49             auto blob = new (std::nothrow) Blob;
50             if (blob == nullptr) {
51                 return -E_OUT_OF_MEMORY;
52             }
53             blob->WriteBlob(blobValue.data(), static_cast<uint32_t>(blobValue.size()));
54             errCode = value.Set(blob);
55             if (errCode != E_OK) {
56                 delete blob;
57                 blob = nullptr;
58             }
59             break;
60         }
61         case SQLITE_NULL:
62             break;
63         case SQLITE3_TEXT: {
64             std::string str;
65             (void)SQLiteUtils::GetColumnTextValue(statement, cid, str);
66             value = str;
67             if (value.GetType() != StorageType::STORAGE_TYPE_TEXT) {
68                 errCode = -E_OUT_OF_MEMORY;
69             }
70             break;
71         }
72         default:
73             break;
74     }
75     return errCode;
76 }
77 
GetSelectValues(sqlite3_stmt * stmt)78 std::vector<DataValue> SQLiteRelationalUtils::GetSelectValues(sqlite3_stmt *stmt)
79 {
80     std::vector<DataValue> values;
81     for (int cid = 0, colCount = sqlite3_column_count(stmt); cid < colCount; ++cid) {
82         DataValue value;
83         (void)GetDataValueByType(stmt, cid, value);
84         values.emplace_back(std::move(value));
85     }
86     return values;
87 }
88 
GetCloudValueByType(sqlite3_stmt * statement,int type,int cid,Type & cloudValue)89 int SQLiteRelationalUtils::GetCloudValueByType(sqlite3_stmt *statement, int type, int cid, Type &cloudValue)
90 {
91     if (statement == nullptr || cid < 0 || cid >= sqlite3_column_count(statement)) {
92         return -E_INVALID_ARGS;
93     }
94     switch (sqlite3_column_type(statement, cid)) {
95         case SQLITE_INTEGER: {
96             if (type == TYPE_INDEX<bool>) {
97                 cloudValue = static_cast<bool>(sqlite3_column_int(statement, cid));
98                 break;
99             }
100             cloudValue = static_cast<int64_t>(sqlite3_column_int64(statement, cid));
101             break;
102         }
103         case SQLITE_FLOAT: {
104             cloudValue = sqlite3_column_double(statement, cid);
105             break;
106         }
107         case SQLITE_BLOB: {
108             std::vector<uint8_t> blobValue;
109             int errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
110             if (errCode != E_OK) {
111                 return errCode;
112             }
113             cloudValue = blobValue;
114             break;
115         }
116         case SQLITE3_TEXT: {
117             bool isBlob = (type == TYPE_INDEX<Bytes> || type == TYPE_INDEX<Asset> || type == TYPE_INDEX<Assets>);
118             if (isBlob) {
119                 std::vector<uint8_t> blobValue;
120                 int errCode = SQLiteUtils::GetColumnBlobValue(statement, cid, blobValue);
121                 if (errCode != E_OK) {
122                     return errCode;
123                 }
124                 cloudValue = blobValue;
125                 break;
126             }
127             std::string str;
128             (void)SQLiteUtils::GetColumnTextValue(statement, cid, str);
129             cloudValue = str;
130             break;
131         }
132         default: {
133             cloudValue = Nil();
134         }
135     }
136     return E_OK;
137 }
138 
CalCloudValueLen(Type & cloudValue,uint32_t & totalSize)139 void SQLiteRelationalUtils::CalCloudValueLen(Type &cloudValue, uint32_t &totalSize)
140 {
141     switch (cloudValue.index()) {
142         case TYPE_INDEX<int64_t>:
143             totalSize += sizeof(int64_t);
144             break;
145         case TYPE_INDEX<double>:
146             totalSize += sizeof(double);
147             break;
148         case TYPE_INDEX<std::string>:
149             totalSize += std::get<std::string>(cloudValue).size();
150             break;
151         case TYPE_INDEX<bool>:
152             totalSize += sizeof(int32_t);
153             break;
154         case TYPE_INDEX<Bytes>:
155         case TYPE_INDEX<Asset>:
156         case TYPE_INDEX<Assets>:
157             totalSize += std::get<Bytes>(cloudValue).size();
158             break;
159         default: {
160             break;
161         }
162     }
163 }
164 
BindStatementByType(sqlite3_stmt * statement,int cid,Type & typeVal)165 int SQLiteRelationalUtils::BindStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal)
166 {
167     int errCode = E_OK;
168     switch (typeVal.index()) {
169         case TYPE_INDEX<int64_t>: {
170             int64_t value = 0;
171             (void)CloudStorageUtils::GetValueFromType(typeVal, value);
172             errCode = SQLiteUtils::BindInt64ToStatement(statement, cid, value);
173             break;
174         }
175         case TYPE_INDEX<bool>: {
176             bool value = false;
177             (void)CloudStorageUtils::GetValueFromType<bool>(typeVal, value);
178             errCode = SQLiteUtils::BindInt64ToStatement(statement, cid, value);
179             break;
180         }
181         case TYPE_INDEX<double>: {
182             double value = 0.0;
183             (void)CloudStorageUtils::GetValueFromType<double>(typeVal, value);
184             errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_double(statement, cid, value));
185             break;
186         }
187         case TYPE_INDEX<std::string>: {
188             std::string value;
189             (void)CloudStorageUtils::GetValueFromType<std::string>(typeVal, value);
190             errCode = SQLiteUtils::BindTextToStatement(statement, cid, value);
191             break;
192         }
193         default: {
194             errCode = BindExtendStatementByType(statement, cid, typeVal);
195             break;
196         }
197     }
198     return errCode;
199 }
200 
BindExtendStatementByType(sqlite3_stmt * statement,int cid,Type & typeVal)201 int SQLiteRelationalUtils::BindExtendStatementByType(sqlite3_stmt *statement, int cid, Type &typeVal)
202 {
203     int errCode = E_OK;
204     switch (typeVal.index()) {
205         case TYPE_INDEX<Bytes>: {
206             Bytes value;
207             (void)CloudStorageUtils::GetValueFromType<Bytes>(typeVal, value);
208             errCode = SQLiteUtils::BindBlobToStatement(statement, cid, value);
209             break;
210         }
211         case TYPE_INDEX<Asset>: {
212             Asset value;
213             (void)CloudStorageUtils::GetValueFromType<Asset>(typeVal, value);
214             Bytes val;
215             errCode = RuntimeContext::GetInstance()->AssetToBlob(value, val);
216             if (errCode != E_OK) {
217                 break;
218             }
219             errCode = SQLiteUtils::BindBlobToStatement(statement, cid, val);
220             break;
221         }
222         case TYPE_INDEX<Assets>: {
223             Assets value;
224             (void)CloudStorageUtils::GetValueFromType<Assets>(typeVal, value);
225             Bytes val;
226             errCode = RuntimeContext::GetInstance()->AssetsToBlob(value, val);
227             if (errCode != E_OK) {
228                 break;
229             }
230             errCode = SQLiteUtils::BindBlobToStatement(statement, cid, val);
231             break;
232         }
233         default: {
234             errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(statement, cid));
235             break;
236         }
237     }
238     return errCode;
239 }
240 
GetSelectVBucket(sqlite3_stmt * stmt,VBucket & bucket)241 int SQLiteRelationalUtils::GetSelectVBucket(sqlite3_stmt *stmt, VBucket &bucket)
242 {
243     if (stmt == nullptr) {
244         return -E_INVALID_ARGS;
245     }
246     for (int cid = 0, colCount = sqlite3_column_count(stmt); cid < colCount; ++cid) {
247         Type typeVal;
248         int errCode = GetTypeValByStatement(stmt, cid, typeVal);
249         if (errCode != E_OK) {
250             LOGE("get typeVal from stmt failed");
251             return errCode;
252         }
253         const char *colName = sqlite3_column_name(stmt, cid);
254         bucket.insert_or_assign(colName, std::move(typeVal));
255     }
256     return E_OK;
257 }
258 
GetDbFileName(sqlite3 * db,std::string & fileName)259 bool SQLiteRelationalUtils::GetDbFileName(sqlite3 *db, std::string &fileName)
260 {
261     if (db == nullptr) {
262         return false;
263     }
264 
265     auto dbFilePath = sqlite3_db_filename(db, nullptr);
266     if (dbFilePath == nullptr) {
267         return false;
268     }
269     fileName = std::string(dbFilePath);
270     return true;
271 }
272 
GetTypeValByStatement(sqlite3_stmt * stmt,int cid,Type & typeVal)273 int SQLiteRelationalUtils::GetTypeValByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal)
274 {
275     if (stmt == nullptr || cid < 0 || cid >= sqlite3_column_count(stmt)) {
276         return -E_INVALID_ARGS;
277     }
278     int errCode = E_OK;
279     switch (sqlite3_column_type(stmt, cid)) {
280         case SQLITE_INTEGER: {
281             const char *declType = sqlite3_column_decltype(stmt, cid);
282             if (declType == nullptr) { // LCOV_EXCL_BR_LINE
283                 typeVal = static_cast<int64_t>(sqlite3_column_int64(stmt, cid));
284                 break;
285             }
286             if (strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOL) == 0 ||
287                 strcasecmp(declType, SchemaConstant::KEYWORD_TYPE_BOOLEAN) == 0) { // LCOV_EXCL_BR_LINE
288                 typeVal = static_cast<bool>(sqlite3_column_int(stmt, cid));
289                 break;
290             }
291             typeVal = static_cast<int64_t>(sqlite3_column_int64(stmt, cid));
292             break;
293         }
294         case SQLITE_FLOAT: {
295             typeVal = sqlite3_column_double(stmt, cid);
296             break;
297         }
298         case SQLITE_BLOB: {
299             errCode = GetBlobByStatement(stmt, cid, typeVal);
300             break;
301         }
302         case SQLITE3_TEXT: {
303             errCode = GetBlobByStatement(stmt, cid, typeVal);
304             if (errCode != E_OK || typeVal.index() != TYPE_INDEX<Nil>) { // LCOV_EXCL_BR_LINE
305                 break;
306             }
307             std::string str;
308             (void)SQLiteUtils::GetColumnTextValue(stmt, cid, str);
309             typeVal = str;
310             break;
311         }
312         default: {
313             typeVal = Nil();
314         }
315     }
316     return errCode;
317 }
318 
GetBlobByStatement(sqlite3_stmt * stmt,int cid,Type & typeVal)319 int SQLiteRelationalUtils::GetBlobByStatement(sqlite3_stmt *stmt, int cid, Type &typeVal)
320 {
321     const char *declType = sqlite3_column_decltype(stmt, cid);
322     int errCode = E_OK;
323     if (declType != nullptr && strcasecmp(declType, CloudDbConstant::ASSET) == 0) { // LCOV_EXCL_BR_LINE
324         std::vector<uint8_t> blobValue;
325         errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue);
326         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
327             return errCode;
328         }
329         Asset asset;
330         errCode = RuntimeContext::GetInstance()->BlobToAsset(blobValue, asset);
331         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
332             return errCode;
333         }
334         typeVal = asset;
335     } else if (declType != nullptr && strcasecmp(declType, CloudDbConstant::ASSETS) == 0) {
336         std::vector<uint8_t> blobValue;
337         errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue);
338         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
339             return errCode;
340         }
341         Assets assets;
342         errCode = RuntimeContext::GetInstance()->BlobToAssets(blobValue, assets);
343         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
344             return errCode;
345         }
346         typeVal = assets;
347     } else if (sqlite3_column_type(stmt, cid) == SQLITE_BLOB) {
348         std::vector<uint8_t> blobValue;
349         errCode = SQLiteUtils::GetColumnBlobValue(stmt, cid, blobValue);
350         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
351             return errCode;
352         }
353         typeVal = blobValue;
354     }
355     return E_OK;
356 }
357 
SelectServerObserver(sqlite3 * db,const std::string & tableName,bool isChanged)358 int SQLiteRelationalUtils::SelectServerObserver(sqlite3 *db, const std::string &tableName, bool isChanged)
359 {
360     if (db == nullptr || tableName.empty()) {
361         return -E_INVALID_ARGS;
362     }
363     std::string sql;
364     if (isChanged) {
365         sql = "SELECT server_observer('" + tableName + "', 1);";
366     } else {
367         sql = "SELECT server_observer('" + tableName + "', 0);";
368     }
369     sqlite3_stmt *stmt = nullptr;
370     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
371     if (errCode != E_OK) {
372         LOGE("get select server observer stmt failed. %d", errCode);
373         return errCode;
374     }
375     errCode = SQLiteUtils::StepWithRetry(stmt, false);
376     int ret = E_OK;
377     SQLiteUtils::ResetStatement(stmt, true, ret);
378     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
379         LOGE("select server observer failed. %d", errCode);
380         return SQLiteUtils::MapSQLiteErrno(errCode);
381     }
382     return ret == E_OK ? E_OK : ret;
383 }
384 
AddUpgradeSqlToList(const TableInfo & tableInfo,const std::vector<std::pair<std::string,std::string>> & fieldList,std::vector<std::string> & sqlList)385 void SQLiteRelationalUtils::AddUpgradeSqlToList(const TableInfo &tableInfo,
386     const std::vector<std::pair<std::string, std::string>> &fieldList, std::vector<std::string> &sqlList)
387 {
388     for (const auto &[colName, colType] : fieldList) {
389         auto it = tableInfo.GetFields().find(colName);
390         if (it != tableInfo.GetFields().end()) {
391             continue;
392         }
393         sqlList.push_back("alter table " + tableInfo.GetTableName() + " add " + colName +
394             " " + colType + ";");
395     }
396 }
397 
QueryCount(sqlite3 * db,const std::string & tableName,int64_t & count)398 int SQLiteRelationalUtils::QueryCount(sqlite3 *db, const std::string &tableName, int64_t &count)
399 {
400     std::string sql = "SELECT COUNT(1) FROM " + tableName ;
401     sqlite3_stmt *stmt = nullptr;
402     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
403     if (errCode != E_OK) {
404         LOGE("Query count failed. %d", errCode);
405         return errCode;
406     }
407     errCode = SQLiteUtils::StepWithRetry(stmt, false);
408     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
409         count = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
410         errCode = E_OK;
411     } else {
412         LOGE("Failed to get the count. %d", errCode);
413     }
414     int ret = E_OK;
415     SQLiteUtils::ResetStatement(stmt, true, ret);
416     return errCode != E_OK ? errCode : ret;
417 }
418 
GetCursor(sqlite3 * db,const std::string & tableName,uint64_t & cursor)419 int SQLiteRelationalUtils::GetCursor(sqlite3 *db, const std::string &tableName, uint64_t &cursor)
420 {
421     cursor = DBConstant::INVALID_CURSOR;
422     std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata where key = ?;";
423     sqlite3_stmt *stmt = nullptr;
424     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
425     if (errCode != E_OK) {
426         LOGE("[Storage Executor] Get cursor of table[%s length[%u]] failed=%d",
427             DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), errCode);
428         return errCode;
429     }
430     ResFinalizer finalizer([stmt]() {
431         sqlite3_stmt *statement = stmt;
432         int ret = E_OK;
433         SQLiteUtils::ResetStatement(statement, true, ret);
434         if (ret != E_OK) {
435             LOGW("Reset stmt failed %d when get cursor", ret);
436         }
437     });
438     Key key;
439     DBCommon::StringToVector(DBCommon::GetCursorKey(tableName), key);
440     errCode = SQLiteUtils::BindBlobToStatement(stmt, 1, key, false); // first arg.
441     if (errCode != E_OK) {
442         LOGE("[Storage Executor] Bind failed when get cursor of table[%s length[%u]] failed=%d",
443             DBCommon::StringMiddleMasking(tableName).c_str(), tableName.length(), errCode);
444         return errCode;
445     }
446     errCode = SQLiteUtils::StepWithRetry(stmt, false);
447     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
448         int64_t tmpCursor = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
449         if (tmpCursor >= 0) {
450             cursor = static_cast<uint64_t>(tmpCursor);
451         }
452     }
453     return cursor == DBConstant::INVALID_CURSOR ? errCode : E_OK;
454 }
455 
GetFieldsNeedContain(const TableInfo & tableInfo,const std::vector<FieldInfo> & syncFields,std::set<std::string> & fieldsNeedContain,std::set<std::string> & fieldsNotDecrease,std::set<std::string> & requiredNotNullFields)456 void GetFieldsNeedContain(const TableInfo &tableInfo, const std::vector<FieldInfo> &syncFields,
457     std::set<std::string> &fieldsNeedContain, std::set<std::string> &fieldsNotDecrease,
458     std::set<std::string> &requiredNotNullFields)
459 {
460     // should not decrease distributed field
461     for (const auto &field : tableInfo.GetSyncField()) {
462         fieldsNotDecrease.insert(field);
463     }
464     const std::vector<CompositeFields> &uniqueDefines = tableInfo.GetUniqueDefine();
465     for (const auto &compositeFields : uniqueDefines) {
466         for (const auto &fieldName : compositeFields) {
467             if (tableInfo.IsPrimaryKey(fieldName)) {
468                 continue;
469             }
470             fieldsNeedContain.insert(fieldName);
471         }
472     }
473     const FieldInfoMap &fieldInfoMap = tableInfo.GetFields();
474     for (const auto &entry : fieldInfoMap) {
475         const FieldInfo &fieldInfo = entry.second;
476         if (fieldInfo.IsNotNull() && fieldInfo.GetDefaultValue().empty()) {
477             requiredNotNullFields.insert(fieldInfo.GetFieldName());
478         }
479     }
480 }
481 
CheckRequireFieldsInMap(const std::set<std::string> & fieldsNeedContain,const std::map<std::string,bool> & fieldsMap)482 bool CheckRequireFieldsInMap(const std::set<std::string> &fieldsNeedContain,
483     const std::map<std::string, bool> &fieldsMap)
484 {
485     for (auto &fieldNeedContain : fieldsNeedContain) {
486         if (fieldsMap.find(fieldNeedContain) == fieldsMap.end()) {
487             LOGE("Required column[%s [%zu]] not found", DBCommon::StringMiddleMasking(fieldNeedContain).c_str(),
488                 fieldNeedContain.size());
489             return false;
490         }
491         if (!fieldsMap.at(fieldNeedContain)) {
492             LOGE("The isP2pSync of required column[%s [%zu]] is false",
493                 DBCommon::StringMiddleMasking(fieldNeedContain).c_str(), fieldNeedContain.size());
494             return false;
495         }
496     }
497     return true;
498 }
499 
IsMarkUniqueColumnInvalid(const TableInfo & tableInfo,const std::vector<DistributedField> & originFields)500 bool IsMarkUniqueColumnInvalid(const TableInfo &tableInfo, const std::vector<DistributedField> &originFields)
501 {
502     int count = 0;
503     for (const auto &field : originFields) {
504         if (field.isSpecified && tableInfo.IsUniqueField(field.colName)) {
505             count++;
506             if (count > 1) {
507                 return true;
508             }
509         }
510     }
511     return false;
512 }
513 
IsDistributedPKInvalidInAutoIncrementTable(const TableInfo & tableInfo,const std::set<std::string,CaseInsensitiveComparator> & distributedPk,const std::vector<DistributedField> & originFields)514 bool IsDistributedPKInvalidInAutoIncrementTable(const TableInfo &tableInfo,
515     const std::set<std::string, CaseInsensitiveComparator> &distributedPk,
516     const std::vector<DistributedField> &originFields)
517 {
518     if (distributedPk.empty()) {
519         return false;
520     }
521     auto uniqueAndPkDefine = tableInfo.GetUniqueAndPkDefine();
522     if (IsMarkUniqueColumnInvalid(tableInfo, originFields)) {
523         LOGE("Mark more than one unique column specified in auto increment table: %s, tableName len: %zu",
524             DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str(), tableInfo.GetTableName().length());
525         return true;
526     }
527     auto find = std::any_of(uniqueAndPkDefine.begin(), uniqueAndPkDefine.end(), [&distributedPk](const auto &item) {
528         // unique index field count should be same
529         return item.size() == distributedPk.size() && distributedPk == DBCommon::TransformToCaseInsensitive(item);
530     });
531     bool isMissMatch = !find;
532     if (isMissMatch) {
533         LOGE("Miss match distributed pk size %zu in auto increment table %s", distributedPk.size(),
534             DBCommon::StringMiddleMasking(tableInfo.GetTableName()).c_str());
535     }
536     return isMissMatch;
537 }
538 
IsDistributedPkInvalid(const TableInfo & tableInfo,const std::set<std::string,CaseInsensitiveComparator> & distributedPk,const std::vector<DistributedField> & originFields,bool isForceUpgrade)539 bool IsDistributedPkInvalid(const TableInfo &tableInfo,
540     const std::set<std::string, CaseInsensitiveComparator> &distributedPk,
541     const std::vector<DistributedField> &originFields, bool isForceUpgrade)
542 {
543     auto lastDistributedPk = DBCommon::TransformToCaseInsensitive(tableInfo.GetSyncDistributedPk());
544     if (!isForceUpgrade && !lastDistributedPk.empty() && distributedPk != lastDistributedPk) {
545         LOGE("distributed pk has change last %zu now %zu", lastDistributedPk.size(), distributedPk.size());
546         return true;
547     }
548     // check pk is same or local pk is auto increase and set pk is unique
549     if (tableInfo.IsNoPkTable()) {
550         return false;
551     }
552     if (!distributedPk.empty() && distributedPk.size() != tableInfo.GetPrimaryKey().size()) {
553         return true;
554     }
555     if (tableInfo.GetAutoIncrement()) {
556         return IsDistributedPKInvalidInAutoIncrementTable(tableInfo, distributedPk, originFields);
557     }
558     for (const auto &field : originFields) {
559         bool isLocalPk = tableInfo.IsPrimaryKey(field.colName);
560         if (field.isSpecified && !isLocalPk) {
561             LOGE("Column[%s [%zu]] is not primary key but mark specified",
562                 DBCommon::StringMiddleMasking(field.colName).c_str(), field.colName.size());
563             return true;
564         }
565         if (isLocalPk && !field.isP2pSync) {
566             LOGE("Column[%s [%zu]] is primary key but set isP2pSync false",
567                 DBCommon::StringMiddleMasking(field.colName).c_str(), field.colName.size());
568             return true;
569         }
570     }
571     return false;
572 }
573 
IsDistributedSchemaSupport(const TableInfo & tableInfo,const std::vector<DistributedField> & fields)574 bool IsDistributedSchemaSupport(const TableInfo &tableInfo, const std::vector<DistributedField> &fields)
575 {
576     if (!tableInfo.GetAutoIncrement()) {
577         return true;
578     }
579     bool isSyncPk = false;
580     bool isSyncOtherSpecified = false;
581     for (const auto &item : fields) {
582         if (tableInfo.IsPrimaryKey(item.colName) && item.isP2pSync) {
583             isSyncPk = true;
584         } else if (item.isSpecified && item.isP2pSync) {
585             isSyncOtherSpecified = true;
586         }
587     }
588     if (isSyncPk && isSyncOtherSpecified) {
589         LOGE("Not support sync with auto increment pk and other specified col");
590         return false;
591     }
592     return true;
593 }
594 
CheckDistributedSchemaFields(const TableInfo & tableInfo,const std::vector<FieldInfo> & syncFields,const std::vector<DistributedField> & fields,bool isForceUpgrade)595 int CheckDistributedSchemaFields(const TableInfo &tableInfo, const std::vector<FieldInfo> &syncFields,
596     const std::vector<DistributedField> &fields, bool isForceUpgrade)
597 {
598     if (fields.empty()) {
599         LOGE("fields cannot be empty");
600         return -E_SCHEMA_MISMATCH;
601     }
602     if (!IsDistributedSchemaSupport(tableInfo, fields)) {
603         return -E_NOT_SUPPORT;
604     }
605     std::set<std::string, CaseInsensitiveComparator> distributedPk;
606     bool isNoPrimaryKeyTable = tableInfo.IsNoPkTable();
607     for (const auto &field : fields) {
608         if (!tableInfo.IsFieldExist(field.colName)) {
609             LOGE("Column[%s [%zu]] not found in table", DBCommon::StringMiddleMasking(field.colName).c_str(),
610                  field.colName.size());
611             return -E_SCHEMA_MISMATCH;
612         }
613         if (isNoPrimaryKeyTable && field.isSpecified) {
614             return -E_SCHEMA_MISMATCH;
615         }
616         if (field.isSpecified && field.isP2pSync) {
617             distributedPk.insert(field.colName);
618         }
619     }
620     if (IsDistributedPkInvalid(tableInfo, distributedPk, fields, isForceUpgrade)) {
621         return -E_SCHEMA_MISMATCH;
622     }
623     std::set<std::string> fieldsNeedContain;
624     std::set<std::string> fieldsNotDecrease;
625     std::set<std::string> requiredNotNullFields;
626     GetFieldsNeedContain(tableInfo, syncFields, fieldsNeedContain, fieldsNotDecrease, requiredNotNullFields);
627     std::map<std::string, bool> fieldsMap;
628     for (auto &field : fields) {
629         fieldsMap.insert({field.colName, field.isP2pSync});
630     }
631     if (!CheckRequireFieldsInMap(fieldsNeedContain, fieldsMap)) {
632         LOGE("The required fields are not found in fieldsMap");
633         return -E_SCHEMA_MISMATCH;
634     }
635     if (!isForceUpgrade && !CheckRequireFieldsInMap(fieldsNotDecrease, fieldsMap)) {
636         LOGE("The fields should not decrease");
637         return -E_DISTRIBUTED_FIELD_DECREASE;
638     }
639     if (!CheckRequireFieldsInMap(requiredNotNullFields, fieldsMap)) {
640         LOGE("The required not-null fields are not found in fieldsMap");
641         return -E_SCHEMA_MISMATCH;
642     }
643     return E_OK;
644 }
645 
CheckDistributedSchemaValid(const RelationalSchemaObject & schemaObj,const DistributedSchema & schema,bool isForceUpgrade,SQLiteSingleVerRelationalStorageExecutor * executor)646 int SQLiteRelationalUtils::CheckDistributedSchemaValid(const RelationalSchemaObject &schemaObj,
647     const DistributedSchema &schema, bool isForceUpgrade, SQLiteSingleVerRelationalStorageExecutor *executor)
648 {
649     if (executor == nullptr) {
650         LOGE("[RDBUtils][CheckDistributedSchemaValid] executor is null");
651         return -E_INVALID_ARGS;
652     }
653     sqlite3 *db;
654     int errCode = executor->GetDbHandle(db);
655     if (errCode != E_OK) {
656         LOGE("[RDBUtils][CheckDistributedSchemaValid] sqlite handle failed %d", errCode);
657         return errCode;
658     }
659     for (const auto &table : schema.tables) {
660         if (table.tableName.empty()) {
661             LOGE("[RDBUtils][CheckDistributedSchemaValid] Table name cannot be empty");
662             return -E_SCHEMA_MISMATCH;
663         }
664         TableInfo tableInfo;
665         errCode = SQLiteUtils::AnalysisSchema(db, table.tableName, tableInfo);
666         if (errCode != E_OK) {
667             LOGE("[RDBUtils][CheckDistributedSchemaValid] analyze table %s failed %d",
668                 DBCommon::StringMiddleMasking(table.tableName).c_str(), errCode);
669             return errCode == -E_NOT_FOUND ? -E_SCHEMA_MISMATCH : errCode;
670         }
671         tableInfo.SetDistributedTable(schemaObj.GetDistributedTable(table.tableName));
672         errCode = CheckDistributedSchemaFields(tableInfo, schemaObj.GetSyncFieldInfo(table.tableName, false),
673             table.fields, isForceUpgrade);
674         if (errCode != E_OK) {
675             LOGE("[CheckDistributedSchema] Check fields of [%s [%zu]] fail",
676                 DBCommon::StringMiddleMasking(table.tableName).c_str(), table.tableName.size());
677             return errCode;
678         }
679     }
680     return E_OK;
681 }
682 
FilterRepeatDefine(const DistributedSchema & schema)683 DistributedSchema SQLiteRelationalUtils::FilterRepeatDefine(const DistributedSchema &schema)
684 {
685     DistributedSchema res;
686     res.version = schema.version;
687     std::set<std::string> tableName;
688     std::list<DistributedTable> tableList;
689     for (auto it = schema.tables.rbegin();it != schema.tables.rend(); it++) {
690         if (tableName.find(it->tableName) != tableName.end()) {
691             continue;
692         }
693         tableName.insert(it->tableName);
694         tableList.push_front(FilterRepeatDefine(*it));
695     }
696     for (auto &item : tableList) {
697         res.tables.push_back(std::move(item));
698     }
699     return res;
700 }
701 
FilterRepeatDefine(const DistributedTable & table)702 DistributedTable SQLiteRelationalUtils::FilterRepeatDefine(const DistributedTable &table)
703 {
704     DistributedTable res;
705     res.tableName = table.tableName;
706     std::set<std::string> fieldName;
707     std::list<DistributedField> fieldList;
708     for (auto it = table.fields.rbegin();it != table.fields.rend(); it++) {
709         if (fieldName.find(it->colName) != fieldName.end()) {
710             continue;
711         }
712         fieldName.insert(it->colName);
713         fieldList.push_front(*it);
714     }
715     for (auto &item : fieldList) {
716         res.fields.push_back(std::move(item));
717     }
718     return res;
719 }
720 
GetLogData(sqlite3_stmt * logStatement,LogInfo & logInfo)721 int SQLiteRelationalUtils::GetLogData(sqlite3_stmt *logStatement, LogInfo &logInfo)
722 {
723     logInfo.dataKey = sqlite3_column_int64(logStatement, 0);  // 0 means dataKey index
724 
725     std::vector<uint8_t> dev;
726     int errCode = SQLiteUtils::GetColumnBlobValue(logStatement, 1, dev);  // 1 means dev index
727     if (errCode != E_OK) {
728         LOGE("[SQLiteRDBUtils] Get dev failed %d", errCode);
729         return errCode;
730     }
731     logInfo.device = std::string(dev.begin(), dev.end());
732 
733     std::vector<uint8_t> oriDev;
734     errCode = SQLiteUtils::GetColumnBlobValue(logStatement, 2, oriDev);  // 2 means ori_dev index
735     if (errCode != E_OK) {
736         LOGE("[SQLiteRDBUtils] Get ori dev failed %d", errCode);
737         return errCode;
738     }
739     logInfo.originDev = std::string(oriDev.begin(), oriDev.end());
740     logInfo.timestamp = static_cast<uint64_t>(sqlite3_column_int64(logStatement, 3));  // 3 means timestamp index
741     logInfo.wTimestamp = static_cast<uint64_t>(sqlite3_column_int64(logStatement, 4));  // 4 means w_timestamp index
742     logInfo.flag = static_cast<uint64_t>(sqlite3_column_int64(logStatement, 5));  // 5 means flag index
743     logInfo.flag &= (~DataItem::LOCAL_FLAG);
744     logInfo.flag &= (~DataItem::UPDATE_FLAG);
745     errCode = SQLiteUtils::GetColumnBlobValue(logStatement, 6, logInfo.hashKey);  // 6 means hashKey index
746     if (errCode != E_OK) {
747         LOGE("[SQLiteRDBUtils] Get hashKey failed %d", errCode);
748     }
749     return errCode;
750 }
751 
GetLogInfoPre(sqlite3_stmt * queryStmt,DistributedTableMode mode,const DataItem & dataItem,LogInfo & logInfoGet)752 int SQLiteRelationalUtils::GetLogInfoPre(sqlite3_stmt *queryStmt, DistributedTableMode mode, const DataItem &dataItem,
753     LogInfo &logInfoGet)
754 {
755     if (queryStmt == nullptr) {
756         return -E_INVALID_ARGS;
757     }
758     int errCode = SQLiteUtils::BindBlobToStatement(queryStmt, 1, dataItem.hashKey);  // 1 means hash key index.
759     if (errCode != E_OK) {
760         LOGE("[SQLiteRDBUtils] Bind hashKey failed %d", errCode);
761         return errCode;
762     }
763     if (mode != DistributedTableMode::COLLABORATION) {
764         errCode = SQLiteUtils::BindTextToStatement(queryStmt, 2, dataItem.dev);  // 2 means device index.
765         if (errCode != E_OK) {
766             LOGE("[SQLiteRDBUtils] Bind dev failed %d", errCode);
767             return errCode;
768         }
769     }
770 
771     errCode = SQLiteUtils::StepWithRetry(queryStmt, false); // rdb not exist mem db
772     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
773         errCode = -E_NOT_FOUND;
774     } else {
775         errCode = SQLiteRelationalUtils::GetLogData(queryStmt, logInfoGet);
776     }
777     return errCode;
778 }
779 
OperateDataStatus(sqlite3 * db,const std::vector<std::string> & tables,uint64_t virtualTime)780 int SQLiteRelationalUtils::OperateDataStatus(sqlite3 *db, const std::vector<std::string> &tables, uint64_t virtualTime)
781 {
782     auto time = std::to_string(virtualTime);
783     LOGI("[SQLiteRDBUtils] %zu tables wait for update time to %s", tables.size(), time.c_str());
784     int errCode = E_OK;
785     for (const auto &table : tables) {
786         errCode = UpdateLocalDataModifyTime(db, table, time);
787         if (errCode != E_OK) {
788             LOGE("[SQLiteRDBUtils] %s table len %zu operate failed %d", DBCommon::StringMiddleMasking(table).c_str(),
789                 table.size(), errCode);
790             break;
791         }
792     }
793     if (errCode == E_OK) {
794         LOGI("[SQLiteRDBUtils] Operate data all success");
795     }
796     return errCode;
797 }
798 
UpdateLocalDataModifyTime(sqlite3 * db,const std::string & table,const std::string & modifyTime)799 int SQLiteRelationalUtils::UpdateLocalDataModifyTime(sqlite3 *db, const std::string &table,
800     const std::string &modifyTime)
801 {
802     auto logTable = DBCommon::GetLogTableName(table);
803     bool isCreate = false;
804     auto errCode = SQLiteUtils::CheckTableExists(db, logTable, isCreate);
805     if (errCode != E_OK) {
806         LOGE("[SQLiteRDBUtils] Check table exist failed %d when update time", errCode);
807         return errCode;
808     }
809     if (!isCreate) {
810         LOGW("[SQLiteRDBUtils] Skip non exist log table %s len %zu when update time",
811             DBCommon::StringMiddleMasking(table).c_str(), table.size());
812         return E_OK;
813     }
814     std::string operateSql = "UPDATE " + logTable +
815         " SET timestamp= _rowid_ + " + modifyTime + " WHERE flag & 0x02 != 0";
816     errCode = SQLiteUtils::ExecuteRawSQL(db, operateSql);
817     if (errCode != E_OK) {
818         LOGE("[SQLiteRDBUtils] Update %s len %zu modify time failed %d", DBCommon::StringMiddleMasking(table).c_str(),
819             table.size(), errCode);
820     }
821     return errCode;
822 }
823 
CheckExistDirtyLog(sqlite3 * db,const std::string & oriTable)824 std::pair<int, bool> SQLiteRelationalUtils::CheckExistDirtyLog(sqlite3 *db, const std::string &oriTable)
825 {
826     std::pair<int, bool> res;
827     auto &[errCode, isExist] = res;
828     if (db == nullptr) {
829         errCode = -E_INVALID_DB;
830         return res;
831     }
832     auto logTable = DBCommon::GetLogTableName(oriTable);
833     bool isCreate = false;
834     errCode = SQLiteUtils::CheckTableExists(db, logTable, isCreate);
835     if (!isCreate) {
836         return res;
837     }
838     std::string sql = "SELECT count(1) FROM (SELECT data_key FROM " + logTable + " "
839         "WHERE data_key != -1 GROUP BY data_key HAVING count(1) > 1)";
840     return ExecuteCheckSql(db, sql);
841 }
842 
ExecuteCheckSql(sqlite3 * db,const std::string & sql)843 std::pair<int, bool> SQLiteRelationalUtils::ExecuteCheckSql(sqlite3 *db, const std::string &sql)
844 {
845     bool isExist = false;
846     int errCode = ExecuteSql(db, sql, [&isExist](sqlite3_stmt *stmt) {
847         auto count = static_cast<int64_t>(sqlite3_column_int64(stmt, 0));
848         if (count > 0) {
849             isExist = true;
850             LOGW("[SQLiteRDBUtils] Exist %" PRId64 " duplicate log", count);
851         }
852     });
853     return {errCode, isExist};
854 }
855 
ExecuteSql(sqlite3 * db,const std::string & sql,const std::function<void (sqlite3_stmt *)> & checkFunc)856 int SQLiteRelationalUtils::ExecuteSql(sqlite3 *db, const std::string &sql,
857     const std::function<void(sqlite3_stmt *)> &checkFunc)
858 {
859     sqlite3_stmt *stmt = nullptr;
860     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
861     if (errCode != E_OK) {
862         LOGE("[SQLiteRDBUtils] Get check stmt failed %d", errCode);
863         return errCode;
864     }
865     ResFinalizer finalizer([stmt]() {
866         int resetRet = E_OK;
867         sqlite3_stmt *releaseStmt = stmt;
868         SQLiteUtils::ResetStatement(releaseStmt, true, resetRet);
869     });
870     errCode = SQLiteUtils::StepNext(stmt);
871     if (errCode == E_OK) {
872         if (checkFunc != nullptr) {
873             checkFunc(stmt);
874         }
875     } else if (errCode == -E_FINISHED) {
876         errCode = E_OK;
877     }
878     return errCode;
879 }
880 
CleanDirtyLog(sqlite3 * db,const std::string & oriTable,const RelationalSchemaObject & obj)881 int SQLiteRelationalUtils::CleanDirtyLog(sqlite3 *db, const std::string &oriTable, const RelationalSchemaObject &obj)
882 {
883     TableInfo tableInfo;
884     tableInfo.SetDistributedTable(obj.GetDistributedTable(oriTable));
885     auto distributedPk = tableInfo.GetSyncDistributedPk();
886     if (distributedPk.empty()) {
887         return E_OK;
888     }
889     auto logTable = DBCommon::GetLogTableName(oriTable);
890     int errCode = E_OK;
891     std::string sql = "DELETE FROM " + logTable + " WHERE hash_key IN "
892           "(SELECT hash_key FROM (SELECT data_key, hash_key, extend_field FROM " + logTable +
893           " WHERE data_key IN(SELECT data_key FROM " + logTable + " GROUP BY data_key HAVING count(1)>1)"
894           " AND data_key != -1) AS log, '" + oriTable +
895           "' WHERE log.data_key = '" + oriTable + "'.rowid AND log.hash_key != " +
896           SqliteLogTableManager::CalcPkHash(oriTable + ".", distributedPk) + ")";
897     errCode = ExecuteSql(db, sql, nullptr);
898     if (errCode == E_OK) {
899         LOGI("[SQLiteRDBUtils] Clean %d dirty hash log", sqlite3_changes(db));
900     }
901     return errCode;
902 }
903 
ExecuteListAction(const std::vector<std::function<int ()>> & actions)904 int SQLiteRelationalUtils::ExecuteListAction(const std::vector<std::function<int()>> &actions)
905 {
906     int errCode = E_OK;
907     for (const auto &action : actions) {
908         if (action == nullptr) {
909             continue;
910         }
911         errCode = action();
912         if (errCode != E_OK) {
913             return errCode;
914         }
915     }
916     return errCode;
917 }
918 
GetLocalLogInfo(const RelationalSyncDataInserter & inserter,const DataItem & dataItem,DistributedTableMode mode,LogInfo & logInfoGet,SaveSyncDataStmt & saveStmt)919 int SQLiteRelationalUtils::GetLocalLogInfo(const RelationalSyncDataInserter &inserter, const DataItem &dataItem,
920     DistributedTableMode mode, LogInfo &logInfoGet, SaveSyncDataStmt &saveStmt)
921 {
922     int errCode = SQLiteRelationalUtils::GetLogInfoPre(saveStmt.queryStmt, mode, dataItem, logInfoGet);
923     int ret = E_OK;
924     SQLiteUtils::ResetStatement(saveStmt.queryStmt, false, ret);
925     if (errCode == -E_NOT_FOUND) {
926         int res = GetLocalLog(dataItem, inserter, saveStmt.queryByFieldStmt, logInfoGet);
927         SQLiteUtils::ResetStatement(saveStmt.queryByFieldStmt, false, ret);
928         errCode = (res == E_OK) ? E_OK : errCode;
929     }
930     return errCode;
931 }
932 
GetLocalLog(const DataItem & dataItem,const RelationalSyncDataInserter & inserter,sqlite3_stmt * stmt,LogInfo & logInfo)933 int SQLiteRelationalUtils::GetLocalLog(const DataItem &dataItem, const RelationalSyncDataInserter &inserter,
934     sqlite3_stmt *stmt, LogInfo &logInfo)
935 {
936     if (stmt == nullptr) {
937         // no need to get log by distributed pk
938         return -E_NOT_FOUND;
939     }
940     if ((dataItem.flag & DataItem::DELETE_FLAG) != 0 ||
941         (dataItem.flag & DataItem::REMOTE_DEVICE_DATA_MISS_QUERY) != 0) {
942         return -E_NOT_FOUND;
943     }
944     auto [errCode, distributedPk] = SQLiteRelationalUtils::GetDistributedPk(dataItem, inserter);
945     if (errCode != E_OK) {
946         LOGE("[SQLiteRDBUtils] Get distributed pk failed[%d]", errCode);
947         return errCode;
948     }
949     errCode = BindDistributedPk(stmt, inserter, distributedPk);
950     if (errCode != E_OK) {
951         LOGE("[SQLiteRDBUtils] Bind distributed pk stmt failed[%d]", errCode);
952         return errCode;
953     }
954     errCode = SQLiteUtils::StepWithRetry(stmt, false); // rdb not exist mem db
955     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
956         errCode = -E_NOT_FOUND;
957     } else {
958         errCode = SQLiteRelationalUtils::GetLogData(stmt, logInfo);
959     }
960     return errCode;
961 }
962 
GetDistributedPk(const DataItem & dataItem,const RelationalSyncDataInserter & inserter)963 std::pair<int, VBucket> SQLiteRelationalUtils::GetDistributedPk(const DataItem &dataItem,
964     const RelationalSyncDataInserter &inserter)
965 {
966     std::pair<int, VBucket> res;
967     auto &[errCode, distributedPk] = res;
968     OptRowDataWithLog data;
969     // deserialize by remote field info
970     errCode = DataTransformer::DeSerializeDataItem(dataItem, data, inserter.GetRemoteFields());
971     if (errCode != E_OK) {
972         LOGE("[SQLiteRDBUtils] DeSerialize dataItem failed! errCode[%d]", errCode);
973         return res;
974     }
975     size_t dataIdx = 0;
976     const auto &localTableFields = inserter.GetLocalTable().GetFields();
977     auto pkFields = inserter.GetLocalTable().GetSyncDistributedPk();
978     std::set<std::string> distributedPkFields(pkFields.begin(), pkFields.end());
979     for (const auto &it : inserter.GetRemoteFields()) {
980         if (distributedPkFields.find(it.GetFieldName()) == distributedPkFields.end()) {
981             dataIdx++;
982             continue;
983         }
984         if (localTableFields.find(it.GetFieldName()) == localTableFields.end()) {
985             LOGW("[SQLiteRDBUtils] field[%s][%zu] not found in local schema.",
986                  DBCommon::StringMiddleMasking(it.GetFieldName()).c_str(),
987                  it.GetFieldName().size());
988             dataIdx++;
989             continue; // skip fields which is orphaned in remote
990         }
991         if (dataIdx >= data.optionalData.size()) {
992             LOGE("[SQLiteRDBUtils] field over size. cnt[%d] data size[%d]", dataIdx, data.optionalData.size());
993             errCode = -E_INTERNAL_ERROR;
994             break; // cnt should less than optionalData size.
995         }
996         Type saveVal;
997         CloudStorageUtils::SaveChangedDataByType(data.optionalData[dataIdx], saveVal);
998         distributedPk[it.GetFieldName()] = std::move(saveVal);
999         dataIdx++;
1000     }
1001     return res;
1002 }
1003 
BindDistributedPk(sqlite3_stmt * stmt,const RelationalSyncDataInserter & inserter,VBucket & distributedPk)1004 int SQLiteRelationalUtils::BindDistributedPk(sqlite3_stmt *stmt, const RelationalSyncDataInserter &inserter,
1005     VBucket &distributedPk)
1006 {
1007     const auto &table = inserter.GetLocalTable();
1008     const auto distributedPkFields = table.GetSyncDistributedPk();
1009     auto &fields = table.GetFields();
1010     int bindIdx = 1;
1011     for (const auto &fieldName : distributedPkFields) {
1012         auto field = fields.find(fieldName);
1013         if (field == fields.end()) {
1014             LOGE("[SQLiteRDBUtils] bind no exist field[%s][%zu]", DBCommon::StringMiddleMasking(fieldName).c_str(),
1015                 fieldName.size());
1016             return -E_INTERNAL_ERROR;
1017         }
1018         auto errCode = BindOneField(stmt, bindIdx, field->second, distributedPk);
1019         if (errCode != E_OK) {
1020             LOGE("[SQLiteRDBUtils] bind field[%s][%zu] type[%d] failed[%d]",
1021                 DBCommon::StringMiddleMasking(fieldName).c_str(), fieldName.size(),
1022                 static_cast<int>(field->second.GetStorageType()), errCode);
1023             return errCode;
1024         }
1025         bindIdx++;
1026     }
1027     return E_OK;
1028 }
1029 
BindOneField(sqlite3_stmt * stmt,int bindIdx,const FieldInfo & fieldInfo,VBucket & distributedPk)1030 int SQLiteRelationalUtils::BindOneField(sqlite3_stmt *stmt, int bindIdx, const FieldInfo &fieldInfo,
1031     VBucket &distributedPk)
1032 {
1033     Field field;
1034     field.colName = fieldInfo.GetFieldName();
1035     field.nullable = !fieldInfo.IsNotNull();
1036     switch (fieldInfo.GetStorageType()) {
1037         case StorageType::STORAGE_TYPE_INTEGER:
1038             field.type = TYPE_INDEX<int64_t>;
1039             return CloudStorageUtils::BindInt64(bindIdx, distributedPk, field, stmt);
1040         case StorageType::STORAGE_TYPE_BLOB:
1041             field.type = TYPE_INDEX<Bytes>;
1042             return CloudStorageUtils::BindBlob(bindIdx, distributedPk, field, stmt);
1043         case StorageType::STORAGE_TYPE_TEXT:
1044             field.type = TYPE_INDEX<std::string>;
1045             return CloudStorageUtils::BindText(bindIdx, distributedPk, field, stmt);
1046         case StorageType::STORAGE_TYPE_REAL:
1047             field.type = TYPE_INDEX<double>;
1048             return CloudStorageUtils::BindDouble(bindIdx, distributedPk, field, stmt);
1049         default:
1050             return -E_INTERNAL_ERROR;
1051     }
1052 }
1053 } // namespace DistributedDB