• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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_utils.h"
17 
18 #include "db_common.h"
19 #include "platform_specific.h"
20 
21 namespace DistributedDB {
22 namespace {
23     const int BUSY_SLEEP_TIME = 50; // sleep for 50us
24     const int NO_SIZE_LIMIT = -1;
25     const int MAX_STEP_TIMES = 8000;
26     const std::string BEGIN_SQL = "BEGIN TRANSACTION";
27     const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION";
28     const std::string COMMIT_SQL = "COMMIT TRANSACTION";
29     const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION";
30     const int MAX_BLOB_READ_SIZE = 64 * 1024 * 1024; // 64M limit
31     const int MAX_TEXT_READ_SIZE = 5 * 1024 * 1024; // 5M limit
32 
33     const constexpr char *CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \
34         "type='table' AND (tbl_name=? COLLATE NOCASE));";
35     const constexpr char *CHECK_META_DB_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM meta.sqlite_master WHERE " \
36         "type='table' AND (tbl_name=? COLLATE NOCASE));";
37 }
38 
39 namespace TriggerMode {
40 const std::map<TriggerModeEnum, std::string> TRIGGER_MODE_MAP = {
41     {TriggerModeEnum::NONE,   ""},
42     {TriggerModeEnum::INSERT, "INSERT"},
43     {TriggerModeEnum::UPDATE, "UPDATE"},
44     {TriggerModeEnum::DELETE, "DELETE"},
45 };
46 
GetTriggerModeString(TriggerModeEnum mode)47 std::string GetTriggerModeString(TriggerModeEnum mode)
48 {
49     auto it = TRIGGER_MODE_MAP.find(mode);
50     return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second;
51 }
52 }
53 
StepWithRetry(sqlite3_stmt * statement,bool isMemDb)54 int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb)
55 {
56     if (statement == nullptr) {
57         return -E_INVALID_ARGS;
58     }
59 
60     int errCode = E_OK;
61     int retryCount = 0;
62     do {
63         errCode = sqlite3_step(statement);
64         if ((errCode == SQLITE_LOCKED) && isMemDb) {
65             std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME));
66             retryCount++;
67         } else {
68             break;
69         }
70     } while (retryCount <= MAX_STEP_TIMES);
71 
72     if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) {
73         LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno);
74     }
75 
76     return SQLiteUtils::MapSQLiteErrno(errCode);
77 }
78 
BeginTransaction(sqlite3 * db,TransactType type)79 int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type)
80 {
81     if (type == TransactType::IMMEDIATE) {
82         return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL, true);
83     }
84 
85     return ExecuteRawSQL(db, BEGIN_SQL, true);
86 }
87 
CommitTransaction(sqlite3 * db)88 int SQLiteUtils::CommitTransaction(sqlite3 *db)
89 {
90     return ExecuteRawSQL(db, COMMIT_SQL, true);
91 }
92 
RollbackTransaction(sqlite3 * db)93 int SQLiteUtils::RollbackTransaction(sqlite3 *db)
94 {
95     return ExecuteRawSQL(db, ROLLBACK_SQL, true);
96 }
97 
ExecuteRawSQL(sqlite3 * db,const std::string & sql,bool ignoreResetFail)98 int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql, bool ignoreResetFail)
99 {
100     if (db == nullptr) {
101         return -E_INVALID_DB;
102     }
103 
104     sqlite3_stmt *stmt = nullptr;
105     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
106     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
107         LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno);
108         return errCode;
109     }
110 
111     do {
112         errCode = SQLiteUtils::StepWithRetry(stmt);
113         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
114             errCode = E_OK;
115             break;
116         } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
117             LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno);
118             break;
119         }
120     } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
121 
122     int ret = E_OK;
123     SQLiteUtils::ResetStatement(stmt, true, ret);
124     if (!ignoreResetFail && ret != E_OK) {
125         return errCode != E_OK ? errCode : ret;
126     }
127     return errCode;
128 }
129 
MapSQLiteErrno(int errCode)130 int SQLiteUtils::MapSQLiteErrno(int errCode)
131 {
132     switch (errCode) {
133         case SQLITE_OK:
134             return E_OK;
135         case SQLITE_IOERR:
136             if (errno == EKEYREVOKED) {
137                 return -E_EKEYREVOKED;
138             }
139             break;
140         case SQLITE_CORRUPT:
141         case SQLITE_NOTADB:
142             return -E_INVALID_PASSWD_OR_CORRUPTED_DB;
143         case SQLITE_LOCKED:
144         case SQLITE_BUSY:
145             return -E_BUSY;
146         case SQLITE_ERROR:
147             if (errno == EKEYREVOKED) {
148                 return -E_EKEYREVOKED;
149             }
150             break;
151         case SQLITE_AUTH:
152             return -E_DENIED_SQL;
153         case SQLITE_CONSTRAINT:
154             return -E_CONSTRAINT;
155         case SQLITE_CANTOPEN:
156             return -E_SQLITE_CANT_OPEN;
157         default:
158             break;
159     }
160     return -errCode;
161 }
162 
GetStatement(sqlite3 * db,const std::string & sql,sqlite3_stmt * & statement)163 int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement)
164 {
165     if (db == nullptr) {
166         LOGE("Invalid db for statement");
167         return -E_INVALID_DB;
168     }
169     // Prepare the new statement only when the input parameter is not null
170     if (statement != nullptr) {
171         return E_OK;
172     }
173     int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr);
174     if (errCode != SQLITE_OK) {
175         LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno);
176         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
177         SQLiteUtils::ResetStatement(statement, true, errCode);
178         return errCode;
179     }
180 
181     if (statement == nullptr) {
182         return -E_INVALID_DB;
183     }
184 
185     return E_OK;
186 }
187 
ResetStatement(sqlite3_stmt * & statement,bool isNeedFinalize,int & errCode)188 void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode)
189 {
190     ResetStatement(statement, isNeedFinalize, false, errCode);
191 }
192 
ResetStatement(sqlite3_stmt * & statement,bool isNeedFinalize,bool isIgnoreResetRet,int & errCode)193 void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, bool isIgnoreResetRet, int &errCode)
194 {
195     if (statement == nullptr) {
196         return;
197     }
198 
199     int innerCode = SQLITE_OK;
200     // if need finalize the statement, just goto finalize.
201     if (!isNeedFinalize) {
202         // reset the statement firstly.
203         innerCode = sqlite3_reset(statement);
204         if (innerCode != SQLITE_OK && !isIgnoreResetRet) {
205             LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno);
206             isNeedFinalize = true;
207         } else {
208             sqlite3_clear_bindings(statement);
209         }
210     }
211 
212     if (isNeedFinalize) {
213         int finalizeResult = sqlite3_finalize(statement);
214         if (finalizeResult != SQLITE_OK) {
215             LOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno);
216             innerCode = finalizeResult;
217         }
218         statement = nullptr;
219     }
220 
221     if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority.
222         errCode = SQLiteUtils::MapSQLiteErrno(innerCode);
223     }
224 }
225 
226 #ifdef RELATIONAL_STORE
227 namespace { // anonymous namespace for schema analysis
AnalysisSchemaSqlAndTrigger(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)228 int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
229 {
230     std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? ";
231     if (!caseSensitive) {
232         sql += "COLLATE NOCASE";
233     }
234     sqlite3_stmt *statement = nullptr;
235     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
236     if (errCode != E_OK) {
237         LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode);
238         return errCode;
239     }
240     errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName);
241     int ret = E_OK;
242     if (errCode != E_OK) {
243         LOGE("[AnalysisSchema] Bind table name failed:%d", errCode);
244         SQLiteUtils::ResetStatement(statement, true, ret);
245         return errCode;
246     }
247 
248     errCode = -E_NOT_FOUND;
249     int err = SQLiteUtils::MapSQLiteErrno(SQLITE_ROW);
250     do {
251         err = SQLiteUtils::StepWithRetry(statement);
252         if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
253             break;
254         } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
255             errCode = E_OK;
256             std::string type;
257             (void) SQLiteUtils::GetColumnTextValue(statement, 0, type);
258             if (type == "table") {
259                 std::string createTableSql;
260                 (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql
261                 table.SetCreateTableSql(createTableSql);
262             }
263         } else {
264             LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err);
265             errCode = err;
266             break;
267         }
268     } while (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
269     SQLiteUtils::ResetStatement(statement, true, ret);
270     return errCode != E_OK ? errCode : ret;
271 }
272 
AnalysisSchemaIndexDefine(sqlite3 * db,const std::string & indexName,CompositeFields & indexDefine)273 int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine)
274 {
275     auto sql = "pragma index_info('" + indexName + "')";
276     sqlite3_stmt *statement = nullptr;
277     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
278     if (errCode != E_OK) {
279         LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode);
280         return errCode;
281     }
282 
283     do {
284         errCode = SQLiteUtils::StepWithRetry(statement);
285         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
286             errCode = E_OK;
287             break;
288         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
289             std::string indexField;
290             (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField);  // 2 means index's column name.
291             indexDefine.push_back(indexField);
292         } else {
293             LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode);
294             break;
295         }
296     } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
297 
298     int ret = E_OK;
299     SQLiteUtils::ResetStatement(statement, true, ret);
300     return errCode != E_OK ? errCode : ret;
301 }
302 
GetSchemaIndexList(sqlite3 * db,const std::string & tableName,std::vector<std::string> & indexList,std::vector<std::string> & uniqueList)303 int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector<std::string> &indexList,
304     std::vector<std::string> &uniqueList)
305 {
306     std::string sql = "pragma index_list('" + tableName + "')";
307     sqlite3_stmt *statement = nullptr;
308     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
309     if (errCode != E_OK) {
310         LOGE("[AnalysisSchema] Prepare the get schema index list statement error:%d", errCode);
311         return errCode;
312     }
313 
314     do {
315         errCode = SQLiteUtils::StepWithRetry(statement);
316         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
317             errCode = E_OK;
318             break;
319         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
320             std::string indexName;
321             (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName);  // 1 means index name
322             int unique = sqlite3_column_int64(statement, 2);  // 2 means index type, whether unique
323             if (unique == 0) { // 0 means index created by user declare
324                 indexList.push_back(indexName);
325             } else if (unique == 1) { // 1 means an unique define
326                 uniqueList.push_back(indexName);
327             }
328         } else {
329             LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode);
330             break;
331         }
332     } while (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW));
333     int ret = E_OK;
334     SQLiteUtils::ResetStatement(statement, true, ret);
335     return errCode != E_OK ? errCode : ret;
336 }
337 
AnalysisSchemaIndex(sqlite3 * db,const std::string & tableName,TableInfo & table)338 int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table)
339 {
340     std::vector<std::string> indexList;
341     std::vector<std::string> uniqueList;
342     int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList);
343     if (errCode != E_OK) {
344         LOGE("[AnalysisSchema] get schema index list failed.");
345         return errCode;
346     }
347 
348     for (const auto &indexName : indexList) {
349         CompositeFields indexDefine;
350         errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine);
351         if (errCode != E_OK) {
352             LOGE("[AnalysisSchema] analysis schema index columns failed.");
353             return errCode;
354         }
355         table.AddIndexDefine(indexName, indexDefine);
356     }
357 
358     std::vector<CompositeFields> uniques;
359     for (const auto &uniqueName : uniqueList) {
360         CompositeFields uniqueDefine;
361         errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine);
362         if (errCode != E_OK) {
363             LOGE("[AnalysisSchema] analysis schema unique columns failed.");
364             return errCode;
365         }
366         uniques.push_back(uniqueDefine);
367     }
368     table.SetUniqueDefine(uniques);
369     return E_OK;
370 }
371 
SetPrimaryKeyCollateType(const std::string & sql,FieldInfo & field)372 void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field)
373 {
374     std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName());
375     if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") ||
376         DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) {
377         field.SetCollateType(CollateType::COLLATE_NOCASE);
378     } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") ||
379         DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) {
380         field.SetCollateType(CollateType::COLLATE_RTRIM);
381     }
382 }
383 
SetFieldInfo(sqlite3_stmt * statement,TableInfo & table)384 int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table)
385 {
386     FieldInfo field;
387     field.SetColumnId(sqlite3_column_int(statement, 0));  // 0 means column id index
388 
389     std::string tmpString;
390     (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString);  // 1 means column name index
391     if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) {
392         LOGE("[AnalysisSchema] unsupported field name.");
393         return -E_NOT_SUPPORT;
394     }
395     field.SetFieldName(tmpString);
396 
397     (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString);  // 2 means datatype index
398     field.SetDataType(tmpString);
399 
400     field.SetNotNull(static_cast<bool>(sqlite3_column_int64(statement, 3)));  // 3 means whether null index
401 
402     (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString);  // 4 means default value index
403     if (!tmpString.empty()) {
404         field.SetDefaultValue(tmpString);
405     }
406 
407     int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index
408     if (keyIndex != 0) {  // not 0 means is a primary key
409         table.SetPrimaryKey(field.GetFieldName(), keyIndex);
410         SetPrimaryKeyCollateType(table.GetCreateTableSql(), field);
411     }
412     table.AddField(field);
413     return E_OK;
414 }
415 } // end of anonymous namespace for schema analysis
416 
AnalysisSchemaFieldDefine(sqlite3 * db,const std::string & tableName,TableInfo & table)417 int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table)
418 {
419     std::string sql = "pragma table_info('" + tableName + "')";
420     sqlite3_stmt *statement = nullptr;
421     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
422     if (errCode != E_OK) {
423         LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode);
424         return errCode;
425     }
426 
427     do {
428         errCode = SQLiteUtils::StepWithRetry(statement);
429         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
430             errCode = E_OK;
431             break;
432         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
433             errCode = SetFieldInfo(statement, table);
434             if (errCode != E_OK) {
435                 break;
436             }
437         } else {
438             LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode);
439             break;
440         }
441     } while (errCode == E_OK);
442 
443     if (table.GetPrimaryKey().empty()) {
444         table.SetPrimaryKey("rowid", 1);
445     }
446 
447     int ret = E_OK;
448     SQLiteUtils::ResetStatement(statement, true, ret);
449     return errCode != E_OK ? errCode : ret;
450 }
451 
AnalysisSchema(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)452 int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
453 {
454     if (db == nullptr) {
455         return -E_INVALID_DB;
456     }
457 
458     if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) {
459         LOGE("[AnalysisSchema] unsupported table name.");
460         return -E_NOT_SUPPORT;
461     }
462 
463     int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive);
464     if (errCode != E_OK) {
465         LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode);
466         return errCode;
467     }
468 
469     errCode = AnalysisSchemaIndex(db, tableName, table);
470     if (errCode != E_OK) {
471         LOGE("[AnalysisSchema] Analysis index failed.");
472         return errCode;
473     }
474 
475     errCode = AnalysisSchemaFieldDefine(db, tableName, table);
476     if (errCode != E_OK) {
477         LOGE("[AnalysisSchema] Analysis field failed.");
478         return errCode;
479     }
480 
481     table.SetTableName(tableName);
482     return E_OK;
483 }
484 #endif
485 
BindTextToStatement(sqlite3_stmt * statement,int index,const std::string & str)486 int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str)
487 {
488     if (statement == nullptr) {
489         return -E_INVALID_ARGS;
490     }
491 
492     int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
493     if (errCode != SQLITE_OK) {
494         LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode);
495         return SQLiteUtils::MapSQLiteErrno(errCode);
496     }
497 
498     return E_OK;
499 }
500 
ProcessStatementErrCode(sqlite3_stmt * & statement,bool isNeedFinalize,int errCode)501 int SQLiteUtils::ProcessStatementErrCode(sqlite3_stmt *&statement, bool isNeedFinalize, int errCode)
502 {
503     int ret = E_OK;
504     SQLiteUtils::ResetStatement(statement, isNeedFinalize, ret);
505     return errCode != E_OK ? errCode : ret;
506 }
507 
CheckTableExists(sqlite3 * db,const std::string & tableName,bool & isCreated,bool isCheckMeta)508 int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta)
509 {
510     if (db == nullptr) {
511         return -1;
512     }
513 
514     sqlite3_stmt *stmt = nullptr;
515     int errCode = SQLiteUtils::GetStatement(db, isCheckMeta ? CHECK_META_DB_TABLE_CREATED : CHECK_TABLE_CREATED, stmt);
516     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
517         LOGE("Get check table statement failed. err=%d", errCode);
518         return errCode;
519     }
520 
521     errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName);
522     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
523         LOGE("Bind table name to statement failed. err=%d", errCode);
524         return ProcessStatementErrCode(stmt, true, errCode);
525     }
526 
527     errCode = SQLiteUtils::StepWithRetry(stmt);
528     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
529         LOGE("Check table exists failed. err=%d", errCode); // should always return a row data
530         return ProcessStatementErrCode(stmt, true, errCode);
531     }
532     errCode = E_OK;
533     isCreated = (sqlite3_column_int(stmt, 0) == 1);
534     return ProcessStatementErrCode(stmt, true, errCode);
535 }
536 
BindBlobToStatement(sqlite3_stmt * statement,int index,const std::vector<uint8_t> & value,bool permEmpty)537 int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector<uint8_t> &value,
538     bool permEmpty)
539 {
540     if (statement == nullptr) {
541         return -E_INVALID_ARGS;
542     }
543 
544     // Check empty value.
545     if (value.empty() && !permEmpty) {
546         LOGI("[SQLiteUtil][Bind blob]Invalid value");
547         return -E_INVALID_ARGS;
548     }
549 
550     int errCode;
551     if (value.empty()) {
552         errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob.
553     } else {
554         errCode = sqlite3_bind_blob(statement, index, static_cast<const void *>(value.data()),
555             value.size(), SQLITE_TRANSIENT);
556     }
557 
558     if (errCode != SQLITE_OK) {
559         LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode);
560         return SQLiteUtils::MapSQLiteErrno(errCode);
561     }
562 
563     return E_OK;
564 }
565 
GetColumnTextValue(sqlite3_stmt * statement,int index,std::string & value)566 int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value)
567 {
568     if (statement == nullptr) {
569         return -E_INVALID_ARGS;
570     }
571 
572     int valSize = sqlite3_column_bytes(statement, index);
573     if (valSize < 0) {
574         LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize);
575         value = {};
576         return E_OK;
577     }
578     const unsigned char *val = sqlite3_column_text(statement, index);
579     if (valSize == 0 || val == nullptr) {
580         value = {};
581         return E_OK;
582     }
583     value = std::string(reinterpret_cast<const char *>(val));
584     if (valSize > MAX_TEXT_READ_SIZE) {
585         LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize);
586         value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid
587     }
588     return E_OK;
589 }
590 
GetColumnBlobValue(sqlite3_stmt * statement,int index,std::vector<uint8_t> & value)591 int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector<uint8_t> &value)
592 {
593     if (statement == nullptr) {
594         return -E_INVALID_ARGS;
595     }
596 
597     int keySize = sqlite3_column_bytes(statement, index);
598     if (keySize < 0) {
599         LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize);
600         value.resize(0);
601         return E_OK;
602     }
603     auto keyRead = static_cast<const uint8_t *>(sqlite3_column_blob(statement, index));
604     if (keySize == 0 || keyRead == nullptr) {
605         value.resize(0);
606     } else {
607         if (keySize > MAX_BLOB_READ_SIZE) {
608             LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize);
609             keySize = MAX_BLOB_READ_SIZE + 1;
610         }
611         value.resize(keySize);
612         value.assign(keyRead, keyRead + keySize);
613     }
614     return E_OK;
615 }
616 
GetCountBySql(sqlite3 * db,const std::string & sql,int & count)617 int SQLiteUtils::GetCountBySql(sqlite3 *db, const std::string &sql, int &count)
618 {
619     sqlite3_stmt *stmt = nullptr;
620     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
621     if (errCode != E_OK) {
622         LOGE("[SQLiteUtils][GetCountBySql] Get stmt failed when get local data count: %d", errCode);
623         return errCode;
624     }
625     errCode = SQLiteUtils::StepWithRetry(stmt, false);
626     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
627         count = static_cast<int>(sqlite3_column_int(stmt, 0));
628         errCode = E_OK;
629     } else {
630         LOGE("[SQLiteUtils][GetCountBySql] Query local data count failed: %d", errCode);
631     }
632     int ret = E_OK;
633     SQLiteUtils::ResetStatement(stmt, true, ret);
634     if (ret != E_OK) {
635         LOGE("[SQLiteUtils][GetCountBySql] Reset stmt failed when get local data count: %d", ret);
636     }
637     return errCode != E_OK ? errCode : ret;
638 }
639 
BindInt64ToStatement(sqlite3_stmt * statement,int index,int64_t value)640 int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value)
641 {
642     // statement check outSide
643     int errCode = sqlite3_bind_int64(statement, index, value);
644     if (errCode != SQLITE_OK) {
645         LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode);
646         return SQLiteUtils::MapSQLiteErrno(errCode);
647     }
648 
649     return E_OK;
650 }
651 } // namespace DistributedDB
652