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