1  /*
2   * Copyright (c) 2021 Huawei Device Co., Ltd.
3   * Licensed under the Apache License, Version 2.0 (the "License");
4   * you may not use this file except in compliance with the License.
5   * You may obtain a copy of the License at
6   *
7   *     http://www.apache.org/licenses/LICENSE-2.0
8   *
9   * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  
16  #include "sqlite_utils.h"
17  
18  #include <climits>
19  #include <cstring>
20  #include <chrono>
21  #include <thread>
22  #include <mutex>
23  #include <map>
24  #include <algorithm>
25  
26  #include "sqlite_import.h"
27  #include "securec.h"
28  #include "db_constant.h"
29  #include "db_common.h"
30  #include "db_errno.h"
31  #include "log_print.h"
32  #include "value_object.h"
33  #include "schema_utils.h"
34  #include "schema_constant.h"
35  #include "time_helper.h"
36  #include "platform_specific.h"
37  #include "sqlite_relational_utils.h"
38  
39  namespace DistributedDB {
40      std::mutex SQLiteUtils::logMutex_;
41      std::string SQLiteUtils::lastErrorMsg_;
42  namespace {
43      const int BUSY_TIMEOUT_MS = 3000; // 3000ms for sqlite busy timeout.
44      const int BUSY_SLEEP_TIME = 50; // sleep for 50us
45      const int NO_SIZE_LIMIT = -1;
46      const int MAX_STEP_TIMES = 8000;
47      const int BIND_KEY_INDEX = 1;
48      const int BIND_VAL_INDEX = 2;
49      const int USING_STR_LEN = -1;
50      const int MAX_BLOB_READ_SIZE = 5 * 1024 * 1024; // 5M limit
51      const int MAX_TEXT_READ_SIZE = 5 * 1024 * 1024; // 5M limit
52      const int HEAD_SIZE = 3;
53      const int END_SIZE = 3;
54      constexpr int MIN_SIZE = HEAD_SIZE + END_SIZE + 3;
55      const std::string REPLACE_CHAIN = "***";
56      const std::string DEFAULT_ANONYMOUS = "******";
57      const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;";
58      const std::string SYNC_MODE_FULL_SQL = "PRAGMA synchronous=FULL;";
59      const std::string USER_VERSION_SQL = "PRAGMA user_version;";
60      const std::string BEGIN_SQL = "BEGIN TRANSACTION";
61      const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION";
62      const std::string COMMIT_SQL = "COMMIT TRANSACTION";
63      const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION";
64      const std::string DEFAULT_ATTACH_CIPHER = "PRAGMA cipher_default_attach_cipher=";
65      const std::string DEFAULT_ATTACH_KDF_ITER = "PRAGMA cipher_default_attach_kdf_iter=5000";
66      const std::string SHA1_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA1;";
67      const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;";
68      const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;";
69      const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;";
70      const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;";
71      const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');";
72      const std::string CIPHER_CONFIG_SQL = "PRAGMA codec_cipher=";
73      const std::string KDF_ITER_CONFIG_SQL = "PRAGMA codec_kdf_iter=";
74      const std::string BACK_CIPHER_CONFIG_SQL = "PRAGMA backup.codec_cipher=";
75      const std::string BACK_KDF_ITER_CONFIG_SQL = "PRAGMA backup.codec_kdf_iter=5000;";
76      const std::string META_CIPHER_CONFIG_SQL = "PRAGMA meta.codec_cipher=";
77      const std::string META_KDF_ITER_CONFIG_SQL = "PRAGMA meta.codec_kdf_iter=5000;";
78  
79      const constexpr char *DETACH_BACKUP_SQL = "DETACH 'backup'";
80      const constexpr char *UPDATE_META_SQL = "INSERT OR REPLACE INTO meta_data VALUES (?, ?);";
81      const constexpr char *CHECK_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM sqlite_master WHERE " \
82          "type='table' AND (tbl_name=? COLLATE NOCASE));";
83      const constexpr char *CHECK_META_DB_TABLE_CREATED = "SELECT EXISTS(SELECT 1 FROM meta.sqlite_master WHERE " \
84          "type='table' AND (tbl_name=? COLLATE NOCASE));";
85  
86      bool g_configLog = false;
87      std::mutex g_serverChangedDataMutex;
88      std::map<std::string, std::map<std::string, DistributedDB::ChangeProperties>> g_serverChangedDataMap;
89  }
90  
91  namespace TriggerMode {
92  const std::map<TriggerModeEnum, std::string> TRIGGER_MODE_MAP = {
93      {TriggerModeEnum::NONE,   ""},
94      {TriggerModeEnum::INSERT, "INSERT"},
95      {TriggerModeEnum::UPDATE, "UPDATE"},
96      {TriggerModeEnum::DELETE, "DELETE"},
97  };
98  
GetTriggerModeString(TriggerModeEnum mode)99  std::string GetTriggerModeString(TriggerModeEnum mode)
100  {
101      auto it = TRIGGER_MODE_MAP.find(mode);
102      return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second;
103  }
104  }
105  
Anonymous(const std::string & name)106  std::string SQLiteUtils::Anonymous(const std::string &name)
107  {
108      if (name.length() <= HEAD_SIZE) {
109          return DEFAULT_ANONYMOUS;
110      }
111  
112      if (name.length() < MIN_SIZE) {
113          return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN);
114      }
115  
116      return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE));
117  }
118  
IsNeedSkipLog(const unsigned int errType,const char * msg)119  bool IsNeedSkipLog(const unsigned int errType, const char *msg)
120  {
121      return errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr;
122  }
123  
SqliteLogCallback(void * data,int err,const char * msg)124  void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg)
125  {
126      bool verboseLog = (data != nullptr);
127      auto errType = static_cast<unsigned int>(err);
128      std::string logMsg = msg == nullptr ? "NULL" : msg;
129      errType &= 0xFF;
130      if (IsNeedSkipLog(errType, logMsg.c_str())) {
131          return;
132      }
133      if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA ||
134          errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) {
135          if (verboseLog) {
136              LOGD("[SQLite] Error[%d] sys[%d] %s ", err, errno, sqlite3_errstr(err));
137          }
138      } else if (errType == SQLITE_WARNING || errType == SQLITE_IOERR ||
139          errType == SQLITE_CORRUPT || errType == SQLITE_CANTOPEN) {
140          LOGI("[SQLite] Error[%d], sys[%d], %s, msg: %s ", err, errno,
141              sqlite3_errstr(err), SQLiteUtils::Anonymous(logMsg).c_str());
142      } else {
143          LOGE("[SQLite] Error[%d], sys[%d], msg: %s ", err, errno, logMsg.c_str());
144          return;
145      }
146  
147      const char *errMsg = sqlite3_errstr(err);
148      std::lock_guard<std::mutex> autoLock(logMutex_);
149      if (errMsg != nullptr) {
150          lastErrorMsg_ = std::string(errMsg);
151      }
152  }
153  
CreateDataBase(const OpenDbProperties & properties,sqlite3 * & dbTemp,bool setWal)154  int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal)
155  {
156      uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
157      if (properties.createIfNecessary) {
158          flag |= SQLITE_OPEN_CREATE;
159      }
160      std::string cipherName = GetCipherName(properties.cipherType);
161      if (cipherName.empty()) {
162          LOGE("[SQLite] GetCipherName failed");
163          return -E_INVALID_ARGS;
164      }
165      std::string defaultAttachCipher = DEFAULT_ATTACH_CIPHER + cipherName + ";";
166      std::vector<std::string> sqls {defaultAttachCipher, DEFAULT_ATTACH_KDF_ITER};
167      if (setWal) {
168          sqls.push_back(WAL_MODE_SQL);
169      }
170      std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
171      int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, flag, nullptr);
172      if (errCode != SQLITE_OK) {
173          LOGE("[SQLite] open database failed: %d - sys err(%d)", errCode, errno);
174          errCode = SQLiteUtils::MapSQLiteErrno(errCode);
175          goto END;
176      }
177  
178      errCode = SetDataBaseProperty(dbTemp, properties, setWal, sqls);
179      if (errCode != SQLITE_OK) {
180          LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode);
181          goto END;
182      }
183  
184  END:
185      if (errCode != E_OK && dbTemp != nullptr) {
186          (void)sqlite3_close_v2(dbTemp);
187          dbTemp = nullptr;
188      }
189  
190      return errCode;
191  }
192  
OpenDatabase(const OpenDbProperties & properties,sqlite3 * & db,bool setWal)193  int SQLiteUtils::OpenDatabase(const OpenDbProperties &properties, sqlite3 *&db, bool setWal)
194  {
195      {
196          // Only for register the sqlite3 log callback
197          std::lock_guard<std::mutex> lock(logMutex_);
198          if (!g_configLog) {
199              sqlite3_config(SQLITE_CONFIG_LOG, &SqliteLogCallback, &properties.createIfNecessary);
200              g_configLog = true;
201          }
202      }
203      sqlite3 *dbTemp = nullptr;
204      int errCode = CreateDataBase(properties, dbTemp, setWal);
205      if (errCode != E_OK) {
206          goto END;
207      }
208      errCode = RegisterJsonFunctions(dbTemp);
209      if (errCode != E_OK) {
210          goto END;
211      }
212      // Set the synchroized mode, default for full mode.
213      errCode = ExecuteRawSQL(dbTemp, SYNC_MODE_FULL_SQL);
214      if (errCode != E_OK) {
215          LOGE("SQLite sync mode failed: %d", errCode);
216          goto END;
217      }
218  
219      if (!properties.isMemDb) {
220          errCode = SQLiteUtils::SetPersistWalMode(dbTemp);
221          if (errCode != E_OK) {
222              LOGE("SQLite set persist wall mode failed: %d", errCode);
223          }
224      }
225  
226  END:
227      if (errCode != E_OK && dbTemp != nullptr) {
228          (void)sqlite3_close_v2(dbTemp);
229          dbTemp = nullptr;
230      }
231      if (errCode != E_OK && errno == EKEYREVOKED) {
232          errCode = -E_EKEYREVOKED;
233      }
234      db = dbTemp;
235      return errCode;
236  }
237  
GetStatement(sqlite3 * db,const std::string & sql,sqlite3_stmt * & statement)238  int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement)
239  {
240      if (db == nullptr) {
241          LOGE("Invalid db for statement");
242          return -E_INVALID_DB;
243      }
244      // Prepare the new statement only when the input parameter is not null
245      if (statement != nullptr) {
246          return E_OK;
247      }
248      int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr);
249      if (errCode != SQLITE_OK) {
250          LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno);
251          errCode = SQLiteUtils::MapSQLiteErrno(errCode);
252          SQLiteUtils::ResetStatement(statement, true, errCode);
253          return errCode;
254      }
255  
256      if (statement == nullptr) {
257          return -E_INVALID_DB;
258      }
259  
260      return E_OK;
261  }
262  
BindTextToStatement(sqlite3_stmt * statement,int index,const std::string & str)263  int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str)
264  {
265      if (statement == nullptr) {
266          return -E_INVALID_ARGS;
267      }
268  
269      int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
270      if (errCode != SQLITE_OK) {
271          LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode);
272          return SQLiteUtils::MapSQLiteErrno(errCode);
273      }
274  
275      return E_OK;
276  }
277  
BindInt64ToStatement(sqlite3_stmt * statement,int index,int64_t value)278  int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value)
279  {
280      // statement check outSide
281      int errCode = sqlite3_bind_int64(statement, index, value);
282      if (errCode != SQLITE_OK) {
283          LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode);
284          return SQLiteUtils::MapSQLiteErrno(errCode);
285      }
286  
287      return E_OK;
288  }
289  
BindBlobToStatement(sqlite3_stmt * statement,int index,const std::vector<uint8_t> & value,bool permEmpty)290  int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector<uint8_t> &value,
291      bool permEmpty)
292  {
293      if (statement == nullptr) {
294          return -E_INVALID_ARGS;
295      }
296  
297      // Check empty value.
298      if (value.empty() && !permEmpty) {
299          LOGI("[SQLiteUtil][Bind blob]Invalid value");
300          return -E_INVALID_ARGS;
301      }
302  
303      int errCode;
304      if (value.empty()) {
305          errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob.
306      } else {
307          errCode = sqlite3_bind_blob(statement, index, static_cast<const void *>(value.data()),
308              value.size(), SQLITE_TRANSIENT);
309      }
310  
311      if (errCode != SQLITE_OK) {
312          LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode);
313          return SQLiteUtils::MapSQLiteErrno(errCode);
314      }
315  
316      return E_OK;
317  }
318  
ResetStatement(sqlite3_stmt * & statement,bool isNeedFinalize,int & errCode)319  void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode)
320  {
321      if (statement == nullptr) {
322          return;
323      }
324  
325      int innerCode = SQLITE_OK;
326      // if need finalize the statement, just goto finalize.
327      if (!isNeedFinalize) {
328          // reset the statement firstly.
329          innerCode = sqlite3_reset(statement);
330          if (innerCode != SQLITE_OK) {
331              LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno);
332              isNeedFinalize = true;
333          } else {
334              sqlite3_clear_bindings(statement);
335          }
336      }
337  
338      if (isNeedFinalize) {
339          int finalizeResult = sqlite3_finalize(statement);
340          if (finalizeResult != SQLITE_OK) {
341              LOGD("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno);
342              innerCode = finalizeResult;
343          }
344          statement = nullptr;
345      }
346  
347      if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority.
348          errCode = SQLiteUtils::MapSQLiteErrno(innerCode);
349      }
350  }
351  
StepWithRetry(sqlite3_stmt * statement,bool isMemDb)352  int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb)
353  {
354      if (statement == nullptr) {
355          return -E_INVALID_ARGS;
356      }
357  
358      int errCode = E_OK;
359      int retryCount = 0;
360      do {
361          errCode = sqlite3_step(statement);
362          if ((errCode == SQLITE_LOCKED) && isMemDb) {
363              std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME));
364              retryCount++;
365          } else {
366              break;
367          }
368      } while (retryCount <= MAX_STEP_TIMES);
369  
370      if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) {
371          LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno);
372      }
373  
374      return SQLiteUtils::MapSQLiteErrno(errCode);
375  }
376  
BindPrefixKey(sqlite3_stmt * statement,int index,const Key & keyPrefix)377  int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &keyPrefix)
378  {
379      if (statement == nullptr) {
380          return -E_INVALID_ARGS;
381      }
382  
383      const size_t maxKeySize = DBConstant::MAX_KEY_SIZE;
384      // bind the first prefix key
385      int errCode = BindBlobToStatement(statement, index, keyPrefix, true);
386      if (errCode != SQLITE_OK) {
387          LOGE("Bind the prefix first error:%d", errCode);
388          return SQLiteUtils::MapSQLiteErrno(errCode);
389      }
390  
391      // bind the second prefix key
392      uint8_t end[maxKeySize];
393      errno_t status = memset_s(end, maxKeySize, UCHAR_MAX, maxKeySize); // max byte value is 0xFF.
394      if (status != EOK) {
395          LOGE("memset error:%d", status);
396          return -E_SECUREC_ERROR;
397      }
398  
399      if (!keyPrefix.empty()) {
400          status = memcpy_s(end, maxKeySize, keyPrefix.data(), keyPrefix.size());
401          if (status != EOK) {
402              LOGE("memcpy error:%d", status);
403              return -E_SECUREC_ERROR;
404          }
405      }
406  
407      // index wouldn't be too large, just add one to the first index.
408      errCode = sqlite3_bind_blob(statement, index + 1, end, maxKeySize, SQLITE_TRANSIENT);
409      if (errCode != SQLITE_OK) {
410          LOGE("Bind the prefix second error:%d", errCode);
411          return SQLiteUtils::MapSQLiteErrno(errCode);
412      }
413      return E_OK;
414  }
415  
BeginTransaction(sqlite3 * db,TransactType type)416  int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type)
417  {
418      if (type == TransactType::IMMEDIATE) {
419          return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL);
420      }
421  
422      return ExecuteRawSQL(db, BEGIN_SQL);
423  }
424  
CommitTransaction(sqlite3 * db)425  int SQLiteUtils::CommitTransaction(sqlite3 *db)
426  {
427      return ExecuteRawSQL(db, COMMIT_SQL);
428  }
429  
RollbackTransaction(sqlite3 * db)430  int SQLiteUtils::RollbackTransaction(sqlite3 *db)
431  {
432      return ExecuteRawSQL(db, ROLLBACK_SQL);
433  }
434  
ExecuteRawSQL(sqlite3 * db,const std::string & sql)435  int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql)
436  {
437      if (db == nullptr) {
438          return -E_INVALID_DB;
439      }
440  
441      sqlite3_stmt *stmt = nullptr;
442      int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
443      if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
444          LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno);
445          return errCode;
446      }
447  
448      do {
449          errCode = SQLiteUtils::StepWithRetry(stmt);
450          if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
451              errCode = E_OK;
452              break;
453          } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
454              LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno);
455              break;
456          }
457      } while (true);
458  
459      int ret = E_OK;
460      SQLiteUtils::ResetStatement(stmt, true, ret);
461      return errCode != E_OK ? errCode : ret;
462  }
463  
SetKey(sqlite3 * db,CipherType type,const CipherPassword & passwd,bool setWal,uint32_t iterTimes)464  int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes)
465  {
466      if (db == nullptr) {
467          return -E_INVALID_DB;
468      }
469  
470      if (passwd.GetSize() != 0) {
471  #ifndef OMIT_ENCRYPT
472          int errCode = SetKeyInner(db, type, passwd, iterTimes);
473          if (errCode != E_OK) {
474              LOGE("[SQLiteUtils][Setkey] set keyInner failed:%d", errCode);
475              return errCode;
476          }
477          errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL);
478          if (errCode != E_OK) {
479              LOGE("[SQLiteUtils][Setkey] set sha algo failed:%d", errCode);
480              return errCode;
481          }
482          errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL);
483          if (errCode != E_OK) {
484              LOGE("[SQLiteUtils][Setkey] set rekey sha algo failed:%d", errCode);
485              return errCode;
486          }
487  #else
488          return -E_NOT_SUPPORT;
489  #endif
490      }
491  
492      // verify key
493      int errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL);
494      if (errCode != E_OK) {
495          LOGE("[SQLiteUtils][Setkey] verify version failed:%d", errCode);
496          if (errno == EKEYREVOKED) {
497              return -E_EKEYREVOKED;
498          }
499          if (errCode == -E_BUSY) {
500              return errCode;
501          }
502  #ifndef OMIT_ENCRYPT
503          errCode = UpdateCipherShaAlgo(db, setWal, type, passwd, iterTimes);
504          if (errCode != E_OK) {
505              LOGE("[SQLiteUtils][Setkey] upgrade cipher sha algo failed:%d", errCode);
506          }
507  #endif
508      }
509      return errCode;
510  }
511  
GetColumnBlobValue(sqlite3_stmt * statement,int index,std::vector<uint8_t> & value)512  int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector<uint8_t> &value)
513  {
514      if (statement == nullptr) {
515          return -E_INVALID_ARGS;
516      }
517  
518      int keySize = sqlite3_column_bytes(statement, index);
519      if (keySize < 0) {
520          LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize);
521          value.resize(0);
522          return E_OK;
523      }
524      auto keyRead = static_cast<const uint8_t *>(sqlite3_column_blob(statement, index));
525      if (keySize == 0 || keyRead == nullptr) {
526          value.resize(0);
527      } else {
528          if (keySize > MAX_BLOB_READ_SIZE) {
529              LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize);
530              keySize = MAX_BLOB_READ_SIZE + 1;
531          }
532          value.resize(keySize);
533          value.assign(keyRead, keyRead + keySize);
534      }
535      return E_OK;
536  }
537  
GetColumnTextValue(sqlite3_stmt * statement,int index,std::string & value)538  int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value)
539  {
540      if (statement == nullptr) {
541          return -E_INVALID_ARGS;
542      }
543  
544      int valSize = sqlite3_column_bytes(statement, index);
545      if (valSize < 0) {
546          LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize);
547          value = {};
548          return E_OK;
549      }
550      const unsigned char *val = sqlite3_column_text(statement, index);
551      if (valSize == 0 || val == nullptr) {
552          value = {};
553          return E_OK;
554      }
555      value = std::string(reinterpret_cast<const char *>(val));
556      if (valSize > MAX_TEXT_READ_SIZE) {
557          LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize);
558          value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid
559      }
560      return E_OK;
561  }
562  
AttachNewDatabase(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)563  int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password,
564      const std::string &attachDbAbsPath, const std::string &attachAsName)
565  {
566  #ifndef OMIT_ENCRYPT
567      int errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
568      if (errCode != E_OK) {
569          LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
570          return errCode;
571      }
572  #endif
573      errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
574  #ifndef OMIT_ENCRYPT
575      if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) {
576          errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_ATTACH_SQL);
577          if (errCode != E_OK) {
578              LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha1 algo failed:%d", errCode);
579              return errCode;
580          }
581          errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
582          if (errCode != E_OK) {
583              LOGE("[SQLiteUtils][AttachNewDatabase] attach db failed:%d", errCode);
584              return errCode;
585          }
586          errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
587          if (errCode != E_OK) {
588              LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
589          }
590      }
591  #endif
592      return errCode;
593  }
594  
AttachNewDatabaseInner(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)595  int SQLiteUtils::AttachNewDatabaseInner(sqlite3 *db, CipherType type, const CipherPassword &password,
596      const std::string &attachDbAbsPath, const std::string &attachAsName)
597  {
598      // example: "ATTACH '../new.db' AS backup KEY XXXX;"
599      std::string attachSql = "ATTACH ? AS " + attachAsName + " KEY ?;"; // Internal interface not need verify alias name
600  
601      sqlite3_stmt* statement = nullptr;
602      int errCode = SQLiteUtils::GetStatement(db, attachSql, statement);
603      if (errCode != E_OK) {
604          return errCode;
605      }
606      // 1st is name.
607      errCode = sqlite3_bind_text(statement, 1, attachDbAbsPath.c_str(), attachDbAbsPath.length(), SQLITE_TRANSIENT);
608      if (errCode != SQLITE_OK) {
609          LOGE("Bind the attached db name failed:%d", errCode);
610          errCode = SQLiteUtils::MapSQLiteErrno(errCode);
611          goto END;
612      }
613      // Passwords do not allow vector operations, so we can not use function BindBlobToStatement here.
614      errCode = sqlite3_bind_blob(statement, 2, static_cast<const void *>(password.GetData()),  // 2 means password index.
615          password.GetSize(), SQLITE_TRANSIENT);
616      if (errCode != SQLITE_OK) {
617          LOGE("Bind the attached key failed:%d", errCode);
618          errCode = SQLiteUtils::MapSQLiteErrno(errCode);
619          goto END;
620      }
621  
622      errCode = SQLiteUtils::StepWithRetry(statement);
623      if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
624          LOGE("Execute the SQLite attach failed:%d", errCode);
625          goto END;
626      }
627      errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL);
628      if (errCode != E_OK) {
629          LOGE("Set journal mode failed: %d", errCode);
630      }
631  
632  END:
633      SQLiteUtils::ResetStatement(statement, true, errCode);
634      return errCode;
635  }
636  
CreateMetaDatabase(const std::string & metaDbPath)637  int SQLiteUtils::CreateMetaDatabase(const std::string &metaDbPath)
638  {
639      OpenDbProperties metaProperties {metaDbPath, true, false};
640      sqlite3 *db = nullptr;
641      int errCode = SQLiteUtils::OpenDatabase(metaProperties, db);
642      if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
643          LOGE("[CreateMetaDatabase] Failed to create the meta database[%d]", errCode);
644      }
645      if (db != nullptr) { // LCOV_EXCL_BR_LINE
646          (void)sqlite3_close_v2(db);
647          db = nullptr;
648      }
649      return errCode;
650  }
CheckIntegrity(sqlite3 * db,const std::string & sql)651  int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql)
652  {
653      sqlite3_stmt *statement = nullptr;
654      int errCode = SQLiteUtils::GetStatement(db, sql, statement);
655      if (errCode != E_OK) {
656          LOGE("Prepare the integrity check statement error:%d", errCode);
657          return errCode;
658      }
659      int resultCnt = 0;
660      bool checkResultOK = false;
661      do {
662          errCode = SQLiteUtils::StepWithRetry(statement);
663          if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
664              break;
665          } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
666              auto result = reinterpret_cast<const char *>(sqlite3_column_text(statement, 0));
667              if (result == nullptr) {
668                  continue;
669              }
670              resultCnt = (resultCnt > 1) ? resultCnt : (resultCnt + 1);
671              if (strcmp(result, "ok") == 0) {
672                  checkResultOK = true;
673              }
674          } else {
675              checkResultOK = false;
676              LOGW("Step for the integrity check failed:%d", errCode);
677              break;
678          }
679      } while (true);
680      if (resultCnt == 1 && checkResultOK) {
681          errCode = E_OK;
682      } else {
683          errCode = -E_INVALID_PASSWD_OR_CORRUPTED_DB;
684      }
685      SQLiteUtils::ResetStatement(statement, true, errCode);
686      return errCode;
687  }
688  #ifdef RELATIONAL_STORE
689  
690  namespace { // anonymous namespace for schema analysis
AnalysisSchemaSqlAndTrigger(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)691  int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
692  {
693      std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? ";
694      if (!caseSensitive) {
695          sql += "COLLATE NOCASE";
696      }
697      sqlite3_stmt *statement = nullptr;
698      int errCode = SQLiteUtils::GetStatement(db, sql, statement);
699      if (errCode != E_OK) {
700          LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode);
701          return errCode;
702      }
703      errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName);
704      if (errCode != E_OK) {
705          LOGE("[AnalysisSchema] Bind table name failed:%d", errCode);
706          SQLiteUtils::ResetStatement(statement, true, errCode);
707          return errCode;
708      }
709  
710      errCode = -E_NOT_FOUND;
711      do {
712          int err = SQLiteUtils::StepWithRetry(statement);
713          if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
714              break;
715          } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
716              errCode = E_OK;
717              std::string type;
718              (void) SQLiteUtils::GetColumnTextValue(statement, 0, type);
719              if (type == "table") {
720                  std::string createTableSql;
721                  (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql
722                  table.SetCreateTableSql(createTableSql);
723              }
724          } else {
725              LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err);
726              errCode = SQLiteUtils::MapSQLiteErrno(err);
727              break;
728          }
729      } while (true);
730      SQLiteUtils::ResetStatement(statement, true, errCode);
731      return errCode;
732  }
733  
GetSchemaIndexList(sqlite3 * db,const std::string & tableName,std::vector<std::string> & indexList,std::vector<std::string> & uniqueList)734  int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector<std::string> &indexList,
735      std::vector<std::string> &uniqueList)
736  {
737      std::string sql = "pragma index_list('" + tableName + "')";
738      sqlite3_stmt *statement = nullptr;
739      int errCode = SQLiteUtils::GetStatement(db, sql, statement);
740      if (errCode != E_OK) {
741          LOGE("[AnalysisSchema] Prepare the get schema index list statement error:%d", errCode);
742          return errCode;
743      }
744  
745      do {
746          errCode = SQLiteUtils::StepWithRetry(statement);
747          if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
748              errCode = E_OK;
749              break;
750          } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
751              std::string indexName;
752              (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName);  // 1 means index name
753              std::string origin;
754              (void) SQLiteUtils::GetColumnTextValue(statement, 3, origin);  // 3 means index type, whether unique
755              if (origin == "c") { // 'c' means index created by user declare
756                  indexList.push_back(indexName);
757              } else if (origin == "u") { // 'u' means an unique define
758                  uniqueList.push_back(indexName);
759              }
760          } else {
761              LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode);
762              break;
763          }
764      } while (true);
765      SQLiteUtils::ResetStatement(statement, true, errCode);
766      return errCode;
767  }
768  
AnalysisSchemaIndexDefine(sqlite3 * db,const std::string & indexName,CompositeFields & indexDefine)769  int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine)
770  {
771      auto sql = "pragma index_info('" + indexName + "')";
772      sqlite3_stmt *statement = nullptr;
773      int errCode = SQLiteUtils::GetStatement(db, sql, statement);
774      if (errCode != E_OK) {
775          LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode);
776          return errCode;
777      }
778  
779      do {
780          errCode = SQLiteUtils::StepWithRetry(statement);
781          if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
782              errCode = E_OK;
783              break;
784          } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
785              std::string indexField;
786              (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField);  // 2 means index's column name.
787              indexDefine.push_back(indexField);
788          } else {
789              LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode);
790              break;
791          }
792      } while (true);
793  
794      SQLiteUtils::ResetStatement(statement, true, errCode);
795      return errCode;
796  }
797  
AnalysisSchemaIndex(sqlite3 * db,const std::string & tableName,TableInfo & table)798  int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table)
799  {
800      std::vector<std::string> indexList;
801      std::vector<std::string> uniqueList;
802      int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList);
803      if (errCode != E_OK) {
804          LOGE("[AnalysisSchema] get schema index list failed.");
805          return errCode;
806      }
807  
808      for (const auto &indexName : indexList) {
809          CompositeFields indexDefine;
810          errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine);
811          if (errCode != E_OK) {
812              LOGE("[AnalysisSchema] analysis schema index columns failed.");
813              return errCode;
814          }
815          table.AddIndexDefine(indexName, indexDefine);
816      }
817  
818      std::vector<CompositeFields> uniques;
819      for (const auto &uniqueName : uniqueList) {
820          CompositeFields uniqueDefine;
821          errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine);
822          if (errCode != E_OK) {
823              LOGE("[AnalysisSchema] analysis schema unique columns failed.");
824              return errCode;
825          }
826          uniques.push_back(uniqueDefine);
827      }
828      table.SetUniqueDefine(uniques);
829      return E_OK;
830  }
831  
SetPrimaryKeyCollateType(const std::string & sql,FieldInfo & field)832  void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field)
833  {
834      std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName());
835      if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") ||
836          DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) {
837          field.SetCollateType(CollateType::COLLATE_NOCASE);
838      } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") ||
839          DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) {
840          field.SetCollateType(CollateType::COLLATE_RTRIM);
841      }
842  }
843  
SetFieldInfo(sqlite3_stmt * statement,TableInfo & table)844  int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table)
845  {
846      FieldInfo field;
847      field.SetColumnId(sqlite3_column_int(statement, 0));  // 0 means column id index
848  
849      std::string tmpString;
850      (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString);  // 1 means column name index
851      if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) {
852          LOGE("[AnalysisSchema] unsupported field name.");
853          return -E_NOT_SUPPORT;
854      }
855      field.SetFieldName(tmpString);
856  
857      (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString);  // 2 means datatype index
858      field.SetDataType(tmpString);
859  
860      field.SetNotNull(static_cast<bool>(sqlite3_column_int64(statement, 3)));  // 3 means whether null index
861  
862      (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString);  // 4 means default value index
863      if (!tmpString.empty()) {
864          field.SetDefaultValue(tmpString);
865      }
866  
867      int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index
868      if (keyIndex != 0) {  // not 0 means is a primary key
869          table.SetPrimaryKey(field.GetFieldName(), keyIndex);
870          SetPrimaryKeyCollateType(table.GetCreateTableSql(), field);
871      }
872      table.AddField(field);
873      return E_OK;
874  }
875  } // end of anonymous namespace for schema analysis
876  
AnalysisSchemaFieldDefine(sqlite3 * db,const std::string & tableName,TableInfo & table)877  int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table)
878  {
879      std::string sql = "pragma table_info('" + tableName + "')";
880      sqlite3_stmt *statement = nullptr;
881      int errCode = SQLiteUtils::GetStatement(db, sql, statement);
882      if (errCode != E_OK) {
883          LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode);
884          return errCode;
885      }
886  
887      do {
888          errCode = SQLiteUtils::StepWithRetry(statement);
889          if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
890              errCode = E_OK;
891              break;
892          } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
893              errCode = SetFieldInfo(statement, table);
894              if (errCode != E_OK) {
895                  break;
896              }
897          } else {
898              LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode);
899              break;
900          }
901      } while (true);
902  
903      if (table.GetPrimaryKey().empty()) {
904          table.SetPrimaryKey("rowid", 1);
905      }
906  
907      SQLiteUtils::ResetStatement(statement, true, errCode);
908      return errCode;
909  }
910  
AnalysisSchema(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)911  int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
912  {
913      if (db == nullptr) {
914          return -E_INVALID_DB;
915      }
916  
917      if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) {
918          LOGE("[AnalysisSchema] unsupported table name.");
919          return -E_NOT_SUPPORT;
920      }
921  
922      int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive);
923      if (errCode != E_OK) {
924          LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode);
925          return errCode;
926      }
927  
928      errCode = AnalysisSchemaIndex(db, tableName, table);
929      if (errCode != E_OK) {
930          LOGE("[AnalysisSchema] Analysis index failed.");
931          return errCode;
932      }
933  
934      errCode = AnalysisSchemaFieldDefine(db, tableName, table);
935      if (errCode != E_OK) {
936          LOGE("[AnalysisSchema] Analysis field failed.");
937          return errCode;
938      }
939  
940      table.SetTableName(tableName);
941      return E_OK;
942  }
943  #endif
944  #ifndef OMIT_ENCRYPT
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)945  int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
946      const std::string &newDbName)
947  {
948      if (db == nullptr) {
949          return -E_INVALID_DB;
950      }
951  
952      int errCode = AttachNewDatabase(db, type, passwd, newDbName);
953      if (errCode != E_OK) {
954          LOGE("Attach New Db fail!");
955          return errCode;
956      }
957      errCode = SQLiteUtils::ExecuteRawSQL(db, EXPORT_BACKUP_SQL);
958      if (errCode != E_OK) {
959          LOGE("Execute the SQLite export failed:%d", errCode);
960      }
961  
962      int detachError = SQLiteUtils::ExecuteRawSQL(db, DETACH_BACKUP_SQL);
963      if (errCode == E_OK) {
964          errCode = detachError;
965          if (detachError != E_OK) {
966              LOGE("Execute the SQLite detach failed:%d", errCode);
967          }
968      }
969      return errCode;
970  }
971  
Rekey(sqlite3 * db,const CipherPassword & passwd)972  int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
973  {
974      if (db == nullptr) {
975          return -E_INVALID_DB;
976      }
977  
978      int errCode = sqlite3_rekey(db, static_cast<const void *>(passwd.GetData()), static_cast<int>(passwd.GetSize()));
979      if (errCode != E_OK) {
980          LOGE("SQLite rekey failed:(%d)", errCode);
981          return SQLiteUtils::MapSQLiteErrno(errCode);
982      }
983  
984      return E_OK;
985  }
986  #else
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)987  int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
988      const std::string &newDbName)
989  {
990      (void)db;
991      (void)type;
992      (void)passwd;
993      (void)newDbName;
994      return -E_NOT_SUPPORT;
995  }
996  
Rekey(sqlite3 * db,const CipherPassword & passwd)997  int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
998  {
999      (void)db;
1000      (void)passwd;
1001      return -E_NOT_SUPPORT;
1002  }
1003  #endif
1004  
GetVersion(const OpenDbProperties & properties,int & version)1005  int SQLiteUtils::GetVersion(const OpenDbProperties &properties, int &version)
1006  {
1007      if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
1008          return -E_INVALID_ARGS;
1009      }
1010  
1011      sqlite3 *dbTemp = nullptr;
1012      // Please make sure the database file exists and is working properly
1013      std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
1014      int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, SQLITE_OPEN_URI | SQLITE_OPEN_READONLY, nullptr);
1015      if (errCode != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1016          errCode = SQLiteUtils::MapSQLiteErrno(errCode);
1017          LOGE("Open database failed: %d, sys:%d", errCode, errno);
1018          goto END;
1019      }
1020      // in memory mode no need cipher
1021      if (!properties.isMemDb) { // LCOV_EXCL_BR_LINE
1022          errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, false,
1023              properties.iterTimes);
1024          if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1025              LOGE("Set key failed: %d", errCode);
1026              goto END;
1027          }
1028      }
1029  
1030      errCode = GetVersion(dbTemp, version);
1031  
1032  END:
1033      if (dbTemp != nullptr) { // LCOV_EXCL_BR_LINE
1034          (void)sqlite3_close_v2(dbTemp);
1035          dbTemp = nullptr;
1036      }
1037      return errCode;
1038  }
1039  
GetVersion(sqlite3 * db,int & version)1040  int SQLiteUtils::GetVersion(sqlite3 *db, int &version)
1041  {
1042      if (db == nullptr) {
1043          return -E_INVALID_DB;
1044      }
1045  
1046      std::string strSql = "PRAGMA user_version;";
1047      sqlite3_stmt *statement = nullptr;
1048      int errCode = sqlite3_prepare(db, strSql.c_str(), -1, &statement, nullptr);
1049      if (errCode != SQLITE_OK || statement == nullptr) {
1050          LOGE("[SqlUtil][GetVer] sqlite3_prepare failed.");
1051          errCode = SQLiteUtils::MapSQLiteErrno(errCode);
1052          return errCode;
1053      }
1054  
1055      if (sqlite3_step(statement) == SQLITE_ROW) {
1056          // Get pragma user_version at first column
1057          version = sqlite3_column_int(statement, 0);
1058      } else {
1059          LOGE("[SqlUtil][GetVer] Get db user_version failed.");
1060          errCode = SQLiteUtils::MapSQLiteErrno(SQLITE_ERROR);
1061      }
1062  
1063      SQLiteUtils::ResetStatement(statement, true, errCode);
1064      return errCode;
1065  }
1066  
GetJournalMode(sqlite3 * db,std::string & mode)1067  int SQLiteUtils::GetJournalMode(sqlite3 *db, std::string &mode)
1068  {
1069      if (db == nullptr) {
1070          return -E_INVALID_DB;
1071      }
1072  
1073      std::string sql = "PRAGMA journal_mode;";
1074      sqlite3_stmt *statement = nullptr;
1075      int errCode = SQLiteUtils::GetStatement(db, sql, statement);
1076      if (errCode != E_OK || statement == nullptr) {
1077          return errCode;
1078      }
1079  
1080      errCode = SQLiteUtils::StepWithRetry(statement);
1081      if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1082          errCode = SQLiteUtils::GetColumnTextValue(statement, 0, mode);
1083      } else {
1084          LOGE("[SqlUtil][GetJournal] Get db journal_mode failed.");
1085      }
1086  
1087      SQLiteUtils::ResetStatement(statement, true, errCode);
1088      return errCode;
1089  }
1090  
SetUserVer(const OpenDbProperties & properties,int version)1091  int SQLiteUtils::SetUserVer(const OpenDbProperties &properties, int version)
1092  {
1093      if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
1094          return -E_INVALID_ARGS;
1095      }
1096  
1097      // Please make sure the database file exists and is working properly
1098      sqlite3 *db = nullptr;
1099      int errCode = SQLiteUtils::OpenDatabase(properties, db);
1100      if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1101          return errCode;
1102      }
1103  
1104      // Set user version
1105      errCode = SQLiteUtils::SetUserVer(db, version);
1106      if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1107          LOGE("Set user version fail: %d", errCode);
1108          goto END;
1109      }
1110  
1111  END:
1112      if (db != nullptr) { // LCOV_EXCL_BR_LINE
1113          (void)sqlite3_close_v2(db);
1114          db = nullptr;
1115      }
1116  
1117      return errCode;
1118  }
1119  
SetUserVer(sqlite3 * db,int version)1120  int SQLiteUtils::SetUserVer(sqlite3 *db, int version)
1121  {
1122      if (db == nullptr) {
1123          return -E_INVALID_DB;
1124      }
1125      std::string userVersionSql = "PRAGMA user_version=" + std::to_string(version) + ";";
1126      return SQLiteUtils::ExecuteRawSQL(db, userVersionSql);
1127  }
1128  
MapSQLiteErrno(int errCode)1129  int SQLiteUtils::MapSQLiteErrno(int errCode)
1130  {
1131      switch (errCode) {
1132          case SQLITE_OK:
1133              return E_OK;
1134          case SQLITE_IOERR:
1135              if (errno == EKEYREVOKED) {
1136                  return -E_EKEYREVOKED;
1137              }
1138              break;
1139          case SQLITE_CORRUPT:
1140          case SQLITE_NOTADB:
1141              return -E_INVALID_PASSWD_OR_CORRUPTED_DB;
1142          case SQLITE_LOCKED:
1143          case SQLITE_BUSY:
1144              return -E_BUSY;
1145          case SQLITE_ERROR:
1146              if (errno == EKEYREVOKED) {
1147                  return -E_EKEYREVOKED;
1148              }
1149              break;
1150          case SQLITE_AUTH:
1151              return -E_DENIED_SQL;
1152          case SQLITE_CONSTRAINT:
1153              return -E_CONSTRAINT;
1154          case SQLITE_CANTOPEN:
1155              return -E_SQLITE_CANT_OPEN;
1156          default:
1157              break;
1158      }
1159      return -errCode;
1160  }
1161  
SetBusyTimeout(sqlite3 * db,int timeout)1162  int SQLiteUtils::SetBusyTimeout(sqlite3 *db, int timeout)
1163  {
1164      if (db == nullptr) {
1165          return -E_INVALID_DB;
1166      }
1167  
1168      // Set the default busy handler to retry automatically before returning SQLITE_BUSY.
1169      int errCode = sqlite3_busy_timeout(db, timeout);
1170      if (errCode != SQLITE_OK) {
1171          LOGE("[SQLite] set busy timeout failed:%d", errCode);
1172      }
1173  
1174      return SQLiteUtils::MapSQLiteErrno(errCode);
1175  }
1176  
1177  #ifndef OMIT_ENCRYPT
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)1178  int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
1179      const std::string &targetFile, const CipherPassword &passwd)
1180  {
1181      std::vector<std::string> createTableSqls;
1182      OpenDbProperties option = {srcFile, true, false, createTableSqls, type, srcPasswd};
1183      sqlite3 *db = nullptr;
1184      int errCode = SQLiteUtils::OpenDatabase(option, db);
1185      if (errCode != E_OK) {
1186          LOGE("Open db error while exporting:%d", errCode);
1187          return errCode;
1188      }
1189  
1190      errCode = SQLiteUtils::ExportDatabase(db, type, passwd, targetFile);
1191      if (db != nullptr) {
1192          (void)sqlite3_close_v2(db);
1193          db = nullptr;
1194      }
1195      return errCode;
1196  }
1197  #else
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)1198  int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
1199      const std::string &targetFile, const CipherPassword &passwd)
1200  {
1201      (void)srcFile;
1202      (void)type;
1203      (void)srcPasswd;
1204      (void)targetFile;
1205      (void)passwd;
1206      return -E_NOT_SUPPORT;
1207  }
1208  #endif
1209  
SaveSchema(sqlite3 * db,const std::string & strSchema)1210  int SQLiteUtils::SaveSchema(sqlite3 *db, const std::string &strSchema)
1211  {
1212      if (db == nullptr) {
1213          return -E_INVALID_DB;
1214      }
1215  
1216      sqlite3_stmt *statement = nullptr;
1217      std::string sql = "INSERT OR REPLACE INTO meta_data VALUES(?,?);";
1218      int errCode = GetStatement(db, sql, statement);
1219      if (errCode != E_OK) {
1220          return errCode;
1221      }
1222  
1223      Key schemaKey;
1224      DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemaKey);
1225      errCode = BindBlobToStatement(statement, BIND_KEY_INDEX, schemaKey, false);
1226      if (errCode != E_OK) {
1227          ResetStatement(statement, true, errCode);
1228          return errCode;
1229      }
1230  
1231      Value schemaValue;
1232      DBCommon::StringToVector(strSchema, schemaValue);
1233      errCode = BindBlobToStatement(statement, BIND_VAL_INDEX, schemaValue, false);
1234      if (errCode != E_OK) {
1235          ResetStatement(statement, true, errCode);
1236          return errCode;
1237      }
1238  
1239      errCode = StepWithRetry(statement); // memory db does not support schema
1240      if (errCode != MapSQLiteErrno(SQLITE_DONE)) {
1241          LOGE("[SqlUtil][SetSchema] StepWithRetry fail, errCode=%d.", errCode);
1242          ResetStatement(statement, true, errCode);
1243          return errCode;
1244      }
1245      errCode = E_OK;
1246      ResetStatement(statement, true, errCode);
1247      return errCode;
1248  }
1249  
GetSchema(sqlite3 * db,std::string & strSchema)1250  int SQLiteUtils::GetSchema(sqlite3 *db, std::string &strSchema)
1251  {
1252      if (db == nullptr) {
1253          return -E_INVALID_DB;
1254      }
1255  
1256      bool isExists = false;
1257      int errCode = CheckTableExists(db, "meta_data", isExists);
1258      if (errCode != E_OK || !isExists) {
1259          LOGW("meta table may has not been created, err=%d, isExists=%d", errCode, isExists);
1260          return errCode;
1261      }
1262  
1263      sqlite3_stmt *statement = nullptr;
1264      std::string sql = "SELECT value FROM meta_data WHERE key=?;";
1265      errCode = GetStatement(db, sql, statement);
1266      if (errCode != E_OK) {
1267          return errCode;
1268      }
1269  
1270      Key schemakey;
1271      DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemakey);
1272      errCode = BindBlobToStatement(statement, 1, schemakey, false);
1273      if (errCode != E_OK) {
1274          ResetStatement(statement, true, errCode);
1275          return errCode;
1276      }
1277  
1278      errCode = StepWithRetry(statement); // memory db does not support schema
1279      if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1280          ResetStatement(statement, true, errCode);
1281          return -E_NOT_FOUND;
1282      } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1283          ResetStatement(statement, true, errCode);
1284          return errCode;
1285      }
1286  
1287      Value schemaValue;
1288      errCode = GetColumnBlobValue(statement, 0, schemaValue);
1289      if (errCode != E_OK) {
1290          ResetStatement(statement, true, errCode);
1291          return errCode;
1292      }
1293      DBCommon::VectorToString(schemaValue, strSchema);
1294      ResetStatement(statement, true, errCode);
1295      return errCode;
1296  }
1297  
IncreaseIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)1298  int SQLiteUtils::IncreaseIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
1299      uint32_t skipSize)
1300  {
1301      if (db == nullptr) {
1302          LOGE("[IncreaseIndex] Sqlite DB not exists.");
1303          return -E_INVALID_DB;
1304      }
1305      if (name.empty() || info.empty()) {
1306          LOGE("[IncreaseIndex] Name or info can not be empty.");
1307          return -E_NOT_PERMIT;
1308      }
1309      std::string indexName = SchemaUtils::FieldPathString(name);
1310      std::string sqlCommand = "CREATE INDEX IF NOT EXISTS '" + indexName + "' ON sync_data (";
1311      for (uint32_t i = 0; i < info.size(); i++) {
1312          if (i != 0) {
1313              sqlCommand += ", ";
1314          }
1315          std::string extractSql = SchemaObject::GenerateExtractSQL(type, info[i].first, info[i].second,
1316              skipSize);
1317          if (extractSql.empty()) { // Unlikely
1318              LOGE("[IncreaseIndex] GenerateExtractSQL fail at field=%u.", i);
1319              return -E_INTERNAL_ERROR;
1320          }
1321          sqlCommand += extractSql;
1322      }
1323      sqlCommand += ") WHERE (flag&0x01=0);";
1324      return SQLiteUtils::ExecuteRawSQL(db, sqlCommand);
1325  }
1326  
ChangeIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)1327  int SQLiteUtils::ChangeIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
1328      uint32_t skipSize)
1329  {
1330      // Currently we change index by drop it then create it, SQLite "REINDEX" may be used in the future
1331      int errCode = DecreaseIndex(db, name);
1332      if (errCode != E_OK) {
1333          LOGE("[ChangeIndex] Decrease fail=%d.", errCode);
1334          return errCode;
1335      }
1336      errCode = IncreaseIndex(db, name, info, type, skipSize);
1337      if (errCode != E_OK) {
1338          LOGE("[ChangeIndex] Increase fail=%d.", errCode);
1339          return errCode;
1340      }
1341      return E_OK;
1342  }
1343  
DecreaseIndex(sqlite3 * db,const IndexName & name)1344  int SQLiteUtils::DecreaseIndex(sqlite3 *db, const IndexName &name)
1345  {
1346      if (db == nullptr) {
1347          LOGE("[DecreaseIndex] Sqlite DB not exists.");
1348          return -E_INVALID_DB;
1349      }
1350      if (name.empty()) {
1351          LOGE("[DecreaseIndex] Name can not be empty.");
1352          return -E_NOT_PERMIT;
1353      }
1354      std::string indexName = SchemaUtils::FieldPathString(name);
1355      std::string sqlCommand = "DROP INDEX IF EXISTS '" + indexName + "';";
1356      return ExecuteRawSQL(db, sqlCommand);
1357  }
1358  
RegisterJsonFunctions(sqlite3 * db)1359  int SQLiteUtils::RegisterJsonFunctions(sqlite3 *db)
1360  {
1361      if (db == nullptr) {
1362          LOGE("Sqlite DB not exists.");
1363          return -E_INVALID_DB;
1364      }
1365      int errCode = sqlite3_create_function_v2(db, "calc_hash_key", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1366          nullptr, &CalcHashKey, nullptr, nullptr, nullptr);
1367      if (errCode != SQLITE_OK) {
1368          LOGE("sqlite3_create_function_v2 about calc_hash_key returned %d", errCode);
1369          return MapSQLiteErrno(errCode);
1370      }
1371  #ifdef USING_DB_JSON_EXTRACT_AUTOMATICALLY
1372      // Specify need 3 parameter in json_extract_by_path function
1373      errCode = sqlite3_create_function_v2(db, "json_extract_by_path", 3, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1374          nullptr, &JsonExtractByPath, nullptr, nullptr, nullptr);
1375      if (errCode != SQLITE_OK) {
1376          LOGE("sqlite3_create_function_v2 about json_extract_by_path returned %d", errCode);
1377          return MapSQLiteErrno(errCode);
1378      }
1379  #endif
1380      return E_OK;
1381  }
1382  
1383  namespace {
SchemaObjectDestructor(SchemaObject * inObject)1384  void SchemaObjectDestructor(SchemaObject *inObject)
1385  {
1386      delete inObject;
1387      inObject = nullptr;
1388  }
1389  }
1390  #ifdef RELATIONAL_STORE
RegisterCalcHash(sqlite3 * db)1391  int SQLiteUtils::RegisterCalcHash(sqlite3 *db)
1392  {
1393      TransactFunc func;
1394      func.xFunc = &CalcHash;
1395      return SQLiteUtils::RegisterFunction(db, "calc_hash", 2, nullptr, func); // 2 is params count
1396  }
1397  
GetSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1398  void SQLiteUtils::GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1399  {
1400      if (ctx == nullptr || argc != 1 || argv == nullptr) {
1401          LOGE("Parameter does not meet restrictions.");
1402          return;
1403      }
1404  
1405      sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
1406  }
1407  
GetRawSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1408  void SQLiteUtils::GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1409  {
1410      if (ctx == nullptr || argc != 0 || argv == nullptr) {
1411          LOGE("Parameter does not meet restrictions.");
1412          return;
1413      }
1414  
1415      uint64_t curTime = 0;
1416      int errCode = TimeHelper::GetSysCurrentRawTime(curTime);
1417      if (errCode != E_OK) {
1418          sqlite3_result_error(ctx, "get raw sys time failed in sqlite utils.", errCode);
1419          return;
1420      }
1421      sqlite3_result_int64(ctx, (sqlite3_int64)(curTime));
1422  }
1423  
GetLastTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1424  void SQLiteUtils::GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1425  {
1426      if (ctx == nullptr || argc != 0 || argv == nullptr) { // LCOV_EXCL_BR_LINE
1427          LOGE("Parameter does not meet restrictions.");
1428          return;
1429      }
1430      // Never used internally, just for sql prepare
1431      sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
1432  }
1433  
CloudDataChangedObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1434  void SQLiteUtils::CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1435  {
1436      if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts
1437          return;
1438      }
1439      sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
1440  }
1441  
CloudDataChangedServerObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1442  void SQLiteUtils::CloudDataChangedServerObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1443  {
1444      if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is param counts
1445          return;
1446      }
1447      sqlite3 *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1448      std::string fileName;
1449      if (!SQLiteRelationalUtils::GetDbFileName(db, fileName)) {
1450          return;
1451      }
1452      auto tableNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
1453      if (tableNameChar == nullptr) {
1454          return;
1455      }
1456      std::string tableName = static_cast<std::string>(tableNameChar);
1457  
1458      uint64_t isTrackerChange = static_cast<uint64_t>(sqlite3_value_int(argv[1])); // 1 is param index
1459      LOGD("Cloud data changed, server observer callback %u", isTrackerChange);
1460      {
1461          std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
1462          auto itTable = g_serverChangedDataMap[fileName].find(tableName);
1463          if (itTable != g_serverChangedDataMap[fileName].end()) {
1464              itTable->second.isTrackedDataChange =
1465                  (static_cast<uint8_t>(itTable->second.isTrackedDataChange) | isTrackerChange) > 0;
1466          } else {
1467              DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) };
1468              g_serverChangedDataMap[fileName].insert_or_assign(tableName, properties);
1469          }
1470      }
1471      sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
1472  }
1473  
GetAndResetServerObserverData(const std::string & dbName,const std::string & tableName,ChangeProperties & changeProperties)1474  void SQLiteUtils::GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName,
1475      ChangeProperties &changeProperties)
1476  {
1477      std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
1478      auto itDb = g_serverChangedDataMap.find(dbName);
1479      if (itDb != g_serverChangedDataMap.end() && !itDb->second.empty()) {
1480          auto itTable = itDb->second.find(tableName);
1481          if (itTable == itDb->second.end()) {
1482              return;
1483          }
1484          changeProperties = itTable->second;
1485          g_serverChangedDataMap[dbName].erase(itTable);
1486      }
1487  }
1488  
RegisterGetSysTime(sqlite3 * db)1489  int SQLiteUtils::RegisterGetSysTime(sqlite3 *db)
1490  {
1491      TransactFunc func;
1492      func.xFunc = &GetSysTime;
1493      return SQLiteUtils::RegisterFunction(db, "get_sys_time", 1, nullptr, func);
1494  }
1495  
RegisterGetLastTime(sqlite3 * db)1496  int SQLiteUtils::RegisterGetLastTime(sqlite3 *db)
1497  {
1498      TransactFunc func;
1499      func.xFunc = &GetLastTime;
1500      return SQLiteUtils::RegisterFunction(db, "get_last_time", 0, nullptr, func);
1501  }
1502  
RegisterGetRawSysTime(sqlite3 * db)1503  int SQLiteUtils::RegisterGetRawSysTime(sqlite3 *db)
1504  {
1505      TransactFunc func;
1506      func.xFunc = &GetRawSysTime;
1507      return SQLiteUtils::RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func);
1508  }
1509  
RegisterCloudDataChangeObserver(sqlite3 * db)1510  int SQLiteUtils::RegisterCloudDataChangeObserver(sqlite3 *db)
1511  {
1512      TransactFunc func;
1513      func.xFunc = &CloudDataChangedObserver;
1514      return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts
1515  }
1516  
RegisterCloudDataChangeServerObserver(sqlite3 * db)1517  int SQLiteUtils::RegisterCloudDataChangeServerObserver(sqlite3 *db)
1518  {
1519      TransactFunc func;
1520      func.xFunc = &CloudDataChangedServerObserver;
1521      return RegisterFunction(db, "server_observer", 2, db, func); // 2 is param counts
1522  }
1523  
CreateSameStuTable(sqlite3 * db,const TableInfo & baseTbl,const std::string & newTableName)1524  int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName)
1525  {
1526      std::string sql = "CREATE TABLE IF NOT EXISTS '" + newTableName + "' (";
1527      const FieldInfoMap &fields = baseTbl.GetFields();
1528      for (uint32_t cid = 0; cid < fields.size(); ++cid) {
1529          std::string fieldName = baseTbl.GetFieldName(cid);
1530          const auto &it = fields.find(fieldName);
1531          if (it == fields.end()) {
1532              return -E_INVALID_DB;
1533          }
1534          sql += "'" + fieldName + "' '" + it->second.GetDataType() + "'";
1535          if (it->second.IsNotNull()) {
1536              sql += " NOT NULL";
1537          }
1538          if (it->second.HasDefaultValue()) {
1539              sql += " DEFAULT " + it->second.GetDefaultValue();
1540          }
1541          sql += ",";
1542      }
1543      // base table has primary key
1544      if (!(baseTbl.GetPrimaryKey().size() == 1 && baseTbl.GetPrimaryKey().at(0) == "rowid")) {
1545          sql += " PRIMARY KEY (";
1546          for (const auto &it : baseTbl.GetPrimaryKey()) {
1547              sql += "'" + it.second + "',";
1548          }
1549          sql.pop_back();
1550          sql += "),";
1551      }
1552      sql.pop_back();
1553      sql += ");";
1554      int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
1555      if (errCode != E_OK) {
1556          LOGE("[SQLite] execute create table sql failed");
1557      }
1558      return errCode;
1559  }
1560  
CloneIndexes(sqlite3 * db,const std::string & oriTableName,const std::string & newTableName)1561  int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName)
1562  {
1563      std::string sql =
1564          "SELECT 'CREATE ' || CASE WHEN il.'unique' THEN 'UNIQUE ' ELSE '' END || 'INDEX IF NOT EXISTS ' || '" +
1565              newTableName + "_' || il.name || ' ON ' || '" + newTableName +
1566              "' || '(' || GROUP_CONCAT(ii.name) || ');' "
1567          "FROM sqlite_master AS m,"
1568              "pragma_index_list(m.name) AS il,"
1569              "pragma_index_info(il.name) AS ii "
1570          "WHERE m.type='table' AND m.name='" + oriTableName + "' AND il.origin='c' "
1571          "GROUP BY il.name;";
1572      sqlite3_stmt *stmt = nullptr;
1573      int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1574      if (errCode != E_OK) {
1575          LOGE("Prepare the clone sql failed:%d", errCode);
1576          return errCode;
1577      }
1578  
1579      std::vector<std::string> indexes;
1580      while (true) {
1581          errCode = SQLiteUtils::StepWithRetry(stmt, false);
1582          if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1583              std::string indexSql;
1584              (void)GetColumnTextValue(stmt, 0, indexSql);
1585              indexes.emplace_back(indexSql);
1586              continue;
1587          }
1588          if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1589              errCode = E_OK;
1590          }
1591          (void)ResetStatement(stmt, true, errCode);
1592          break;
1593      }
1594  
1595      if (errCode != E_OK) {
1596          return errCode;
1597      }
1598  
1599      for (const auto &it : indexes) {
1600          errCode = SQLiteUtils::ExecuteRawSQL(db, it);
1601          if (errCode != E_OK) {
1602              LOGE("[SQLite] execute clone index sql failed");
1603          }
1604      }
1605      return errCode;
1606  }
1607  
GetRelationalSchema(sqlite3 * db,std::string & schema,const std::string & key)1608  int SQLiteUtils::GetRelationalSchema(sqlite3 *db, std::string &schema, const std::string &key)
1609  {
1610      if (db == nullptr) {
1611          return -E_INVALID_DB;
1612      }
1613  
1614      sqlite3_stmt *statement = nullptr;
1615      std::string sql = "SELECT value FROM " + DBConstant::RELATIONAL_PREFIX + "metadata WHERE key=?;";
1616      int errCode = GetStatement(db, sql, statement);
1617      if (errCode != E_OK) {
1618          return errCode;
1619      }
1620  
1621      Key schemakey;
1622      DBCommon::StringToVector(key, schemakey);
1623      errCode = BindBlobToStatement(statement, 1, schemakey, false);
1624      if (errCode != E_OK) {
1625          ResetStatement(statement, true, errCode);
1626          return errCode;
1627      }
1628  
1629      errCode = StepWithRetry(statement);
1630      if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1631          ResetStatement(statement, true, errCode);
1632          return -E_NOT_FOUND;
1633      } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1634          ResetStatement(statement, true, errCode);
1635          return errCode;
1636      }
1637  
1638      Value schemaValue;
1639      errCode = GetColumnBlobValue(statement, 0, schemaValue);
1640      if (errCode != E_OK) {
1641          ResetStatement(statement, true, errCode);
1642          return errCode;
1643      }
1644      DBCommon::VectorToString(schemaValue, schema);
1645      ResetStatement(statement, true, errCode);
1646      return errCode;
1647  }
1648  
GetLogTableVersion(sqlite3 * db,std::string & version)1649  int SQLiteUtils::GetLogTableVersion(sqlite3 *db, std::string &version)
1650  {
1651      if (db == nullptr) {
1652          return -E_INVALID_DB;
1653      }
1654  
1655      sqlite3_stmt *statement = nullptr;
1656      std::string sql = "SELECT value FROM " + DBConstant::RELATIONAL_PREFIX + "metadata WHERE key=?;";
1657      int errCode = GetStatement(db, sql, statement);
1658      if (errCode != E_OK) {
1659          return errCode;
1660      }
1661  
1662      Key logTableKey;
1663      DBCommon::StringToVector(DBConstant::LOG_TABLE_VERSION_KEY, logTableKey);
1664      errCode = BindBlobToStatement(statement, 1, logTableKey, false);
1665      if (errCode != E_OK) {
1666          ResetStatement(statement, true, errCode);
1667          return errCode;
1668      }
1669  
1670      errCode = StepWithRetry(statement);
1671      if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1672          ResetStatement(statement, true, errCode);
1673          return -E_NOT_FOUND;
1674      } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1675          ResetStatement(statement, true, errCode);
1676          return errCode;
1677      }
1678  
1679      Value value;
1680      errCode = GetColumnBlobValue(statement, 0, value);
1681      if (errCode != E_OK) {
1682          ResetStatement(statement, true, errCode);
1683          return errCode;
1684      }
1685      DBCommon::VectorToString(value, version);
1686      ResetStatement(statement, true, errCode);
1687      return errCode;
1688  }
1689  
RegisterFunction(sqlite3 * db,const std::string & funcName,int nArg,void * uData,TransactFunc & func)1690  int SQLiteUtils::RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func)
1691  {
1692      if (db == nullptr) {
1693          LOGE("Sqlite DB not exists.");
1694          return -E_INVALID_DB;
1695      }
1696  
1697      int errCode = sqlite3_create_function_v2(db, funcName.c_str(), nArg, SQLITE_UTF8 | SQLITE_DETERMINISTIC, uData,
1698          func.xFunc, func.xStep, func.xFinal, func.xDestroy);
1699      if (errCode != SQLITE_OK) {
1700          LOGE("sqlite3_create_function_v2 about [%s] returned %d", funcName.c_str(), errCode);
1701          return MapSQLiteErrno(errCode);
1702      }
1703      return E_OK;
1704  }
1705  #endif
RegisterFlatBufferFunction(sqlite3 * db,const std::string & inSchema)1706  int SQLiteUtils::RegisterFlatBufferFunction(sqlite3 *db, const std::string &inSchema)
1707  {
1708      if (db == nullptr) {
1709          LOGE("Sqlite DB not exists.");
1710          return -E_INVALID_DB;
1711      }
1712      auto heapSchemaObj = new (std::nothrow) SchemaObject;
1713      if (heapSchemaObj == nullptr) {
1714          return -E_OUT_OF_MEMORY;
1715      }
1716      int errCode = heapSchemaObj->ParseFromSchemaString(inSchema);
1717      if (errCode != E_OK) { // Unlikely, it has been parsed before
1718          delete heapSchemaObj;
1719          heapSchemaObj = nullptr;
1720          return -E_INTERNAL_ERROR;
1721      }
1722      if (heapSchemaObj->GetSchemaType() != SchemaType::FLATBUFFER) { // Do not need to register FlatBufferExtract
1723          delete heapSchemaObj;
1724          heapSchemaObj = nullptr;
1725          return E_OK;
1726      }
1727      errCode = sqlite3_create_function_v2(db, SchemaObject::GetExtractFuncName(SchemaType::FLATBUFFER).c_str(),
1728          3, SQLITE_UTF8 | SQLITE_DETERMINISTIC, heapSchemaObj, &FlatBufferExtractByPath, nullptr, nullptr, // 3 args
1729          reinterpret_cast<void(*)(void*)>(SchemaObjectDestructor));
1730      // About the release of heapSchemaObj: SQLite guarantee that at following case, sqlite will invoke the destructor
1731      // (that is SchemaObjectDestructor) we passed to it. See sqlite.org for more information.
1732      // The destructor is invoked when the function is deleted, either by being overloaded or when the database
1733      // connection closes. The destructor is also invoked if the call to sqlite3_create_function_v2() fails
1734      if (errCode != SQLITE_OK) {
1735          LOGE("sqlite3_create_function_v2 about flatbuffer_extract_by_path return=%d.", errCode);
1736          // As mentioned above, SQLite had invoked the SchemaObjectDestructor to release the heapSchemaObj
1737          return MapSQLiteErrno(errCode);
1738      }
1739      return E_OK;
1740  }
1741  
UpdateMetaDataWithinTrigger(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1742  void SQLiteUtils::UpdateMetaDataWithinTrigger(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1743  {
1744      if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 : Number of parameters for sqlite register function
1745          LOGE("[UpdateMetaDataWithinTrigger] Invalid parameter, argc=%d.", argc);
1746          return;
1747      }
1748      auto *handle = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1749      if (handle == nullptr) {
1750          sqlite3_result_error(ctx, "Sqlite context is invalid.", USING_STR_LEN);
1751          LOGE("Sqlite context is invalid.");
1752          return;
1753      }
1754      auto *keyPtr = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0])); // 0 : first argv for key
1755      int keyLen = sqlite3_value_bytes(argv[0]); // 0 : first argv for key
1756      if (keyPtr == nullptr || keyLen <= 0 || keyLen > static_cast<int>(DBConstant::MAX_KEY_SIZE)) {
1757          sqlite3_result_error(ctx, "key is invalid.", USING_STR_LEN);
1758          LOGE("key is invalid.");
1759          return;
1760      }
1761      auto val = sqlite3_value_int64(argv[1]); // 1 : second argv for value
1762  
1763      sqlite3_stmt *stmt = nullptr;
1764      int errCode = SQLiteUtils::GetStatement(handle, UPDATE_META_SQL, stmt);
1765      if (errCode != E_OK) {
1766          sqlite3_result_error(ctx, "Get update meta_data statement failed.", USING_STR_LEN);
1767          LOGE("Get update meta_data statement failed. %d", errCode);
1768          return;
1769      }
1770  
1771      Key key(keyPtr, keyPtr + keyLen);
1772      errCode = SQLiteUtils::BindBlobToStatement(stmt, BIND_KEY_INDEX, key, false);
1773      if (errCode != E_OK) {
1774          sqlite3_result_error(ctx, "Bind key to statement failed.", USING_STR_LEN);
1775          LOGE("Bind key to statement failed. %d", errCode);
1776          goto END;
1777      }
1778  
1779      errCode = SQLiteUtils::BindInt64ToStatement(stmt, BIND_VAL_INDEX, val);
1780      if (errCode != E_OK) {
1781          sqlite3_result_error(ctx, "Bind value to statement failed.", USING_STR_LEN);
1782          LOGE("Bind value to statement failed. %d", errCode);
1783          goto END;
1784      }
1785  
1786      errCode = SQLiteUtils::StepWithRetry(stmt, false);
1787      if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1788          sqlite3_result_error(ctx, "Execute the update meta_data attach failed.", USING_STR_LEN);
1789          LOGE("Execute the update meta_data attach failed. %d", errCode);
1790      }
1791  END:
1792      SQLiteUtils::ResetStatement(stmt, true, errCode);
1793  }
1794  
RegisterMetaDataUpdateFunction(sqlite3 * db)1795  int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db)
1796  {
1797      int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC.c_str(),
1798          2, // 2: argc for register function
1799          SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::UpdateMetaDataWithinTrigger, nullptr, nullptr, nullptr);
1800      if (errCode != SQLITE_OK) {
1801          LOGE("sqlite3_create_function_v2 about %s returned %d", DBConstant::UPDATE_META_FUNC.c_str(), errCode);
1802      }
1803      return SQLiteUtils::MapSQLiteErrno(errCode);
1804  }
1805  
1806  struct ValueParseCache {
1807      ValueObject valueParsed;
1808      std::vector<uint8_t> valueOriginal;
1809  };
1810  
1811  namespace {
IsDeleteRecord(const uint8_t * valueBlob,int valueBlobLen)1812  inline bool IsDeleteRecord(const uint8_t *valueBlob, int valueBlobLen)
1813  {
1814      return (valueBlob == nullptr) || (valueBlobLen <= 0); // In fact, sqlite guarantee valueBlobLen not negative
1815  }
1816  
1817  // Use the same cache id as sqlite use for json_extract which is substituted by our json_extract_by_path
1818  // A negative cache-id enables sharing of cache between different operation during the same statement
1819  constexpr int VALUE_CACHE_ID = -429938;
1820  
ValueParseCacheFree(ValueParseCache * inCache)1821  void ValueParseCacheFree(ValueParseCache *inCache)
1822  {
1823      delete inCache;
1824      inCache = nullptr;
1825  }
1826  
1827  // We don't use cache array since we only cache value column of sqlite table, see sqlite implementation for compare.
ParseValueThenCacheOrGetFromCache(sqlite3_context * ctx,const uint8_t * valueBlob,uint32_t valueBlobLen,uint32_t offset)1828  const ValueObject *ParseValueThenCacheOrGetFromCache(sqlite3_context *ctx, const uint8_t *valueBlob,
1829      uint32_t valueBlobLen, uint32_t offset)
1830  {
1831      // Note: All parameter had already been check inside JsonExtractByPath, only called by JsonExtractByPath
1832      auto cached = static_cast<ValueParseCache *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID));
1833      if (cached != nullptr) { // A previous cache exist
1834          if (cached->valueOriginal.size() == valueBlobLen) {
1835              if (std::memcmp(cached->valueOriginal.data(), valueBlob, valueBlobLen) == 0) {
1836                  // Cache match
1837                  return &(cached->valueParsed);
1838              }
1839          }
1840      }
1841      // No cache or cache mismatch
1842      auto newCache = new (std::nothrow) ValueParseCache;
1843      if (newCache == nullptr) {
1844          sqlite3_result_error(ctx, "[ParseValueCache] OOM.", USING_STR_LEN);
1845          LOGE("[ParseValueCache] OOM.");
1846          return nullptr;
1847      }
1848      int errCode = newCache->valueParsed.Parse(valueBlob, valueBlob + valueBlobLen, offset);
1849      if (errCode != E_OK) {
1850          sqlite3_result_error(ctx, "[ParseValueCache] Parse fail.", USING_STR_LEN);
1851          LOGE("[ParseValueCache] Parse fail, errCode=%d.", errCode);
1852          delete newCache;
1853          newCache = nullptr;
1854          return nullptr;
1855      }
1856      newCache->valueOriginal.assign(valueBlob, valueBlob + valueBlobLen);
1857      sqlite3_set_auxdata(ctx, VALUE_CACHE_ID, newCache, reinterpret_cast<void(*)(void*)>(ValueParseCacheFree));
1858      // If sqlite3_set_auxdata fail, it will immediately call ValueParseCacheFree to delete newCache;
1859      // Next time sqlite3_set_auxdata will call ValueParseCacheFree to delete newCache of this time;
1860      // At the end, newCache will be eventually deleted when call sqlite3_reset or sqlite3_finalize;
1861      // Since sqlite3_set_auxdata may fail, we have to call sqlite3_get_auxdata other than return newCache directly.
1862      auto cacheInAuxdata = static_cast<ValueParseCache *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID));
1863      if (cacheInAuxdata == nullptr) {
1864          return nullptr;
1865      }
1866      return &(cacheInAuxdata->valueParsed);
1867  }
1868  }
1869  
JsonExtractByPath(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1870  void SQLiteUtils::JsonExtractByPath(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1871  {
1872      if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 parameters, which are value, path and offset
1873          LOGE("[JsonExtract] Invalid parameter, argc=%d.", argc);
1874          return;
1875      }
1876      auto valueBlob = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
1877      int valueBlobLen = sqlite3_value_bytes(argv[0]);
1878      if (IsDeleteRecord(valueBlob, valueBlobLen)) {
1879          // Currently delete records are filtered out of query and create-index sql, so not allowed here.
1880          sqlite3_result_error(ctx, "[JsonExtract] Delete record not allowed.", USING_STR_LEN);
1881          LOGE("[JsonExtract] Delete record not allowed.");
1882          return;
1883      }
1884      auto path = reinterpret_cast<const char *>(sqlite3_value_text(argv[1]));
1885      int offset = sqlite3_value_int(argv[2]); // index 2 is the third parameter
1886      if ((path == nullptr) || (offset < 0)) {
1887          sqlite3_result_error(ctx, "[JsonExtract] Path nullptr or offset invalid.", USING_STR_LEN);
1888          LOGE("[JsonExtract] Path nullptr or offset=%d invalid.", offset);
1889          return;
1890      }
1891      FieldPath outPath;
1892      int errCode = SchemaUtils::ParseAndCheckFieldPath(path, outPath);
1893      if (errCode != E_OK) {
1894          sqlite3_result_error(ctx, "[JsonExtract] Path illegal.", USING_STR_LEN);
1895          LOGE("[JsonExtract] Path illegal.");
1896          return;
1897      }
1898      // Parameter Check Done Here
1899      const ValueObject *valueObj = ParseValueThenCacheOrGetFromCache(ctx, valueBlob, static_cast<uint32_t>(valueBlobLen),
1900          static_cast<uint32_t>(offset));
1901      if (valueObj == nullptr) {
1902          return; // Necessary had been printed in ParseValueThenCacheOrGetFromCache
1903      }
1904      JsonExtractInnerFunc(ctx, *valueObj, outPath);
1905  }
1906  
1907  namespace {
IsExtractableType(FieldType inType)1908  inline bool IsExtractableType(FieldType inType)
1909  {
1910      return (inType != FieldType::LEAF_FIELD_NULL && inType != FieldType::LEAF_FIELD_ARRAY &&
1911          inType != FieldType::LEAF_FIELD_OBJECT && inType != FieldType::INTERNAL_FIELD_OBJECT);
1912  }
1913  }
1914  
JsonExtractInnerFunc(sqlite3_context * ctx,const ValueObject & inValue,const FieldPath & inPath)1915  void SQLiteUtils::JsonExtractInnerFunc(sqlite3_context *ctx, const ValueObject &inValue, const FieldPath &inPath)
1916  {
1917      FieldType outType = FieldType::LEAF_FIELD_NULL; // Default type null for invalid-path(path not exist)
1918      int errCode = inValue.GetFieldTypeByFieldPath(inPath, outType);
1919      if (errCode != E_OK && errCode != -E_INVALID_PATH) {
1920          sqlite3_result_error(ctx, "[JsonExtract] GetFieldType fail.", USING_STR_LEN);
1921          LOGE("[JsonExtract] GetFieldType fail, errCode=%d.", errCode);
1922          return;
1923      }
1924      FieldValue outValue;
1925      if (IsExtractableType(outType)) {
1926          errCode = inValue.GetFieldValueByFieldPath(inPath, outValue);
1927          if (errCode != E_OK) {
1928              sqlite3_result_error(ctx, "[JsonExtract] GetFieldValue fail.", USING_STR_LEN);
1929              LOGE("[JsonExtract] GetFieldValue fail, errCode=%d.", errCode);
1930              return;
1931          }
1932      }
1933      // FieldType null, array, object do not have value, all these FieldValue will be regarded as null in JsonReturn.
1934      ExtractReturn(ctx, outType, outValue);
1935  }
1936  
1937  // NOTE!!! This function is performance sensitive !!! Carefully not to allocate memory often!!!
FlatBufferExtractByPath(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1938  void SQLiteUtils::FlatBufferExtractByPath(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1939  {
1940      if (ctx == nullptr || argc != 3 || argv == nullptr) { // 3 parameters, which are value, path and offset
1941          LOGE("[FlatBufferExtract] Invalid parameter, argc=%d.", argc);
1942          return;
1943      }
1944      auto schema = static_cast<SchemaObject *>(sqlite3_user_data(ctx));
1945      if (schema == nullptr || !schema->IsSchemaValid() ||
1946          (schema->GetSchemaType() != SchemaType::FLATBUFFER)) { // LCOV_EXCL_BR_LINE
1947          sqlite3_result_error(ctx, "[FlatBufferExtract] No SchemaObject or invalid.", USING_STR_LEN);
1948          LOGE("[FlatBufferExtract] No SchemaObject or invalid.");
1949          return;
1950      }
1951      // Get information from argv
1952      auto valueBlob = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
1953      int valueBlobLen = sqlite3_value_bytes(argv[0]);
1954      if (IsDeleteRecord(valueBlob, valueBlobLen)) { // LCOV_EXCL_BR_LINE
1955          // Currently delete records are filtered out of query and create-index sql, so not allowed here.
1956          sqlite3_result_error(ctx, "[FlatBufferExtract] Delete record not allowed.", USING_STR_LEN);
1957          LOGE("[FlatBufferExtract] Delete record not allowed.");
1958          return;
1959      }
1960      auto path = reinterpret_cast<const char *>(sqlite3_value_text(argv[1]));
1961      int offset = sqlite3_value_int(argv[2]); // index 2 is the third parameter
1962      if ((path == nullptr) || (offset < 0) ||
1963          (static_cast<uint32_t>(offset) != schema->GetSkipSize())) { // LCOV_EXCL_BR_LINE
1964          sqlite3_result_error(ctx, "[FlatBufferExtract] Path null or offset invalid.", USING_STR_LEN);
1965          LOGE("[FlatBufferExtract] Path null or offset=%d(skipsize=%u) invalid.", offset, schema->GetSkipSize());
1966          return;
1967      }
1968      FlatBufferExtractInnerFunc(ctx, *schema, RawValue { valueBlob, valueBlobLen }, path);
1969  }
1970  
1971  namespace {
1972  constexpr uint32_t FLATBUFFER_MAX_CACHE_SIZE = 102400; // 100 KBytes
1973  
FlatBufferCacheFree(std::vector<uint8_t> * inCache)1974  void FlatBufferCacheFree(std::vector<uint8_t> *inCache)
1975  {
1976      delete inCache;
1977      inCache = nullptr;
1978  }
1979  }
1980  
FlatBufferExtractInnerFunc(sqlite3_context * ctx,const SchemaObject & schema,const RawValue & inValue,RawString inPath)1981  void SQLiteUtils::FlatBufferExtractInnerFunc(sqlite3_context *ctx, const SchemaObject &schema, const RawValue &inValue,
1982      RawString inPath)
1983  {
1984      // All parameter had already been check inside FlatBufferExtractByPath, only called by FlatBufferExtractByPath
1985      if (schema.GetSkipSize() % SchemaConstant::SECURE_BYTE_ALIGN == 0) { // LCOV_EXCL_BR_LINE
1986          TypeValue outExtract;
1987          int errCode = schema.ExtractValue(ValueSource::FROM_DBFILE, inPath, inValue, outExtract, nullptr);
1988          if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1989              sqlite3_result_error(ctx, "[FlatBufferExtract] ExtractValue fail.", USING_STR_LEN);
1990              LOGE("[FlatBufferExtract] ExtractValue fail, errCode=%d.", errCode);
1991              return;
1992          }
1993          ExtractReturn(ctx, outExtract.first, outExtract.second);
1994          return;
1995      }
1996      // Not byte-align secure, we have to make a cache for copy. Check whether cache had already exist.
1997      auto cached = static_cast<std::vector<uint8_t> *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID)); // Share the same id
1998      if (cached == nullptr) { // LCOV_EXCL_BR_LINE
1999          // Make the cache
2000          auto newCache = new (std::nothrow) std::vector<uint8_t>;
2001          if (newCache == nullptr) {
2002              sqlite3_result_error(ctx, "[FlatBufferExtract] OOM.", USING_STR_LEN);
2003              LOGE("[FlatBufferExtract] OOM.");
2004              return;
2005          }
2006          newCache->resize(FLATBUFFER_MAX_CACHE_SIZE);
2007          sqlite3_set_auxdata(ctx, VALUE_CACHE_ID, newCache, reinterpret_cast<void(*)(void*)>(FlatBufferCacheFree));
2008          // If sqlite3_set_auxdata fail, it will immediately call FlatBufferCacheFree to delete newCache;
2009          // Next time sqlite3_set_auxdata will call FlatBufferCacheFree to delete newCache of this time;
2010          // At the end, newCache will be eventually deleted when call sqlite3_reset or sqlite3_finalize;
2011          // Since sqlite3_set_auxdata may fail, we have to call sqlite3_get_auxdata other than return newCache directly.
2012          // See sqlite.org for more information.
2013          cached = static_cast<std::vector<uint8_t> *>(sqlite3_get_auxdata(ctx, VALUE_CACHE_ID));
2014      }
2015      if (cached == nullptr) { // LCOV_EXCL_BR_LINE
2016          LOGW("[FlatBufferExtract] Something wrong with Auxdata, but it is no matter without cache.");
2017      }
2018      TypeValue outExtract;
2019      int errCode = schema.ExtractValue(ValueSource::FROM_DBFILE, inPath, inValue, outExtract, cached);
2020      if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
2021          sqlite3_result_error(ctx, "[FlatBufferExtract] ExtractValue fail.", USING_STR_LEN);
2022          LOGE("[FlatBufferExtract] ExtractValue fail, errCode=%d.", errCode);
2023          return;
2024      }
2025      ExtractReturn(ctx, outExtract.first, outExtract.second);
2026  }
2027  
ExtractReturn(sqlite3_context * ctx,FieldType type,const FieldValue & value)2028  void SQLiteUtils::ExtractReturn(sqlite3_context *ctx, FieldType type, const FieldValue &value)
2029  {
2030      if (ctx == nullptr) {
2031          return;
2032      }
2033      switch (type) {
2034          case FieldType::LEAF_FIELD_BOOL:
2035              sqlite3_result_int(ctx, (value.boolValue ? 1 : 0));
2036              break;
2037          case FieldType::LEAF_FIELD_INTEGER:
2038              sqlite3_result_int(ctx, value.integerValue);
2039              break;
2040          case FieldType::LEAF_FIELD_LONG:
2041              sqlite3_result_int64(ctx, value.longValue);
2042              break;
2043          case FieldType::LEAF_FIELD_DOUBLE:
2044              sqlite3_result_double(ctx, value.doubleValue);
2045              break;
2046          case FieldType::LEAF_FIELD_STRING:
2047              // The SQLITE_TRANSIENT value means that the content will likely change in the near future and
2048              // that SQLite should make its own private copy of the content before returning.
2049              sqlite3_result_text(ctx, value.stringValue.c_str(), -1, SQLITE_TRANSIENT); // -1 mean use the string length
2050              break;
2051          default:
2052              // All other type regard as null
2053              sqlite3_result_null(ctx);
2054      }
2055      return;
2056  }
2057  
CalcHashFunc(sqlite3_context * ctx,sqlite3_value ** argv)2058  static void CalcHashFunc(sqlite3_context *ctx, sqlite3_value **argv)
2059  {
2060      auto keyBlob = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
2061      if (keyBlob == nullptr) {
2062          sqlite3_result_error(ctx, "Parameters is invalid.", USING_STR_LEN);
2063          LOGE("Parameters is invalid.");
2064          return;
2065      }
2066      int blobLen = sqlite3_value_bytes(argv[0]);
2067      std::vector<uint8_t> value(keyBlob, keyBlob + blobLen);
2068      std::vector<uint8_t> hashValue;
2069      int errCode = DBCommon::CalcValueHash(value, hashValue);
2070      if (errCode != E_OK) {
2071          sqlite3_result_error(ctx, "Get hash value error.", USING_STR_LEN);
2072          LOGE("Get hash value error.");
2073          return;
2074      }
2075      sqlite3_result_blob(ctx, hashValue.data(), hashValue.size(), SQLITE_TRANSIENT);
2076  }
2077  
CalcHashKey(sqlite3_context * ctx,int argc,sqlite3_value ** argv)2078  void SQLiteUtils::CalcHashKey(sqlite3_context *ctx, int argc, sqlite3_value **argv)
2079  {
2080      // 1 means that the function only needs one parameter, namely key
2081      if (ctx == nullptr || argc != 1 || argv == nullptr) {
2082          LOGE("Parameter does not meet restrictions.");
2083          return;
2084      }
2085      CalcHashFunc(ctx, argv);
2086  }
2087  
CalcHash(sqlite3_context * ctx,int argc,sqlite3_value ** argv)2088  void SQLiteUtils::CalcHash(sqlite3_context *ctx, int argc, sqlite3_value **argv)
2089  {
2090      if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is params count
2091          LOGE("Parameter does not meet restrictions.");
2092          return;
2093      }
2094      CalcHashFunc(ctx, argv);
2095  }
2096  
2097  
GetDbSize(const std::string & dir,const std::string & dbName,uint64_t & size)2098  int SQLiteUtils::GetDbSize(const std::string &dir, const std::string &dbName, uint64_t &size)
2099  {
2100      std::string dataDir = dir + "/" + dbName + DBConstant::DB_EXTENSION;
2101      uint64_t localDbSize = 0;
2102      int errCode = OS::CalFileSize(dataDir, localDbSize);
2103      if (errCode != E_OK) {
2104          LOGD("Failed to get the db file size, errCode:%d", errCode);
2105          return errCode;
2106      }
2107  
2108      std::string shmFileName = dataDir + "-shm";
2109      uint64_t localshmFileSize = 0;
2110      errCode = OS::CalFileSize(shmFileName, localshmFileSize);
2111      if (errCode != E_OK) {
2112          localshmFileSize = 0;
2113      }
2114  
2115      std::string walFileName = dataDir + "-wal";
2116      uint64_t localWalFileSize = 0;
2117      errCode = OS::CalFileSize(walFileName, localWalFileSize);
2118      if (errCode != E_OK) {
2119          localWalFileSize = 0;
2120      }
2121  
2122      // 64-bit system is Suffice. Computer storage is less than uint64_t max
2123      size += (localDbSize + localshmFileSize + localWalFileSize);
2124      return E_OK;
2125  }
2126  
SetDataBaseProperty(sqlite3 * db,const OpenDbProperties & properties,bool setWal,const std::vector<std::string> & sqls)2127  int SQLiteUtils::SetDataBaseProperty(sqlite3 *db, const OpenDbProperties &properties, bool setWal,
2128      const std::vector<std::string> &sqls)
2129  {
2130      // Set the default busy handler to retry automatically before returning SQLITE_BUSY.
2131      int errCode = SetBusyTimeout(db, BUSY_TIMEOUT_MS);
2132      if (errCode != E_OK) {
2133          return errCode;
2134      }
2135      if (!properties.isMemDb) {
2136          errCode = SQLiteUtils::SetKey(db, properties.cipherType, properties.passwd, setWal,
2137              properties.iterTimes);
2138          if (errCode != E_OK) {
2139              LOGD("SQLiteUtils::SetKey fail!!![%d]", errCode);
2140              return errCode;
2141          }
2142      }
2143  
2144      for (const auto &sql : sqls) {
2145          errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
2146          if (errCode != E_OK) {
2147              LOGE("[SQLite] execute sql failed: %d", errCode);
2148              return errCode;
2149          }
2150      }
2151      // Create table if not exist according the sqls.
2152      if (properties.createIfNecessary) {
2153          for (const auto &sql : properties.sqls) {
2154              errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
2155              if (errCode != E_OK) {
2156                  LOGE("[SQLite] execute preset sqls failed");
2157                  return errCode;
2158              }
2159          }
2160      }
2161      return E_OK;
2162  }
2163  
2164  #ifndef OMIT_ENCRYPT
SetCipherSettings(sqlite3 * db,CipherType type,uint32_t iterTimes)2165  int SQLiteUtils::SetCipherSettings(sqlite3 *db, CipherType type, uint32_t iterTimes)
2166  {
2167      if (db == nullptr) {
2168          return -E_INVALID_DB;
2169      }
2170      std::string cipherName = GetCipherName(type);
2171      if (cipherName.empty()) {
2172          return -E_INVALID_ARGS;
2173      }
2174      std::string cipherConfig = CIPHER_CONFIG_SQL + cipherName + ";";
2175      int errCode = SQLiteUtils::ExecuteRawSQL(db, cipherConfig);
2176      if (errCode != E_OK) {
2177          LOGE("[SQLiteUtils][SetCipherSettings] config cipher failed:%d", errCode);
2178          return errCode;
2179      }
2180      errCode = SQLiteUtils::ExecuteRawSQL(db, KDF_ITER_CONFIG_SQL + std::to_string(iterTimes));
2181      if (errCode != E_OK) {
2182          LOGE("[SQLiteUtils][SetCipherSettings] config iter failed:%d", errCode);
2183      }
2184      return errCode;
2185  }
2186  
GetCipherName(CipherType type)2187  std::string SQLiteUtils::GetCipherName(CipherType type)
2188  {
2189      if (type == CipherType::AES_256_GCM || type == CipherType::DEFAULT) {
2190          return "'aes-256-gcm'";
2191      }
2192      return "";
2193  }
2194  #endif
2195  
DropTriggerByName(sqlite3 * db,const std::string & name)2196  int SQLiteUtils::DropTriggerByName(sqlite3 *db, const std::string &name)
2197  {
2198      const std::string dropTriggerSql = "DROP TRIGGER " + name + ";";
2199      int errCode = SQLiteUtils::ExecuteRawSQL(db, dropTriggerSql);
2200      if (errCode != E_OK) {
2201          LOGE("Remove trigger failed. %d", errCode);
2202      }
2203      return errCode;
2204  }
2205  
ExpandedSql(sqlite3_stmt * stmt,std::string & basicString)2206  int SQLiteUtils::ExpandedSql(sqlite3_stmt *stmt, std::string &basicString)
2207  {
2208      if (stmt == nullptr) {
2209          return -E_INVALID_ARGS;
2210      }
2211      char *eSql = sqlite3_expanded_sql(stmt);
2212      if (eSql == nullptr) {
2213          LOGE("expand statement to sql failed.");
2214          return -E_INVALID_DATA;
2215      }
2216      basicString = std::string(eSql);
2217      sqlite3_free(eSql);
2218      return E_OK;
2219  }
2220  
ExecuteCheckPoint(sqlite3 * db)2221  void SQLiteUtils::ExecuteCheckPoint(sqlite3 *db)
2222  {
2223      if (db == nullptr) {
2224          return;
2225      }
2226  
2227      int chkResult = sqlite3_wal_checkpoint_v2(db, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr);
2228      LOGI("SQLite checkpoint result:%d", chkResult);
2229  }
2230  
CheckTableEmpty(sqlite3 * db,const std::string & tableName,bool & isEmpty)2231  int SQLiteUtils::CheckTableEmpty(sqlite3 *db, const std::string &tableName, bool &isEmpty)
2232  {
2233      if (db == nullptr) {
2234          return -E_INVALID_ARGS;
2235      }
2236  
2237      std::string cntSql = "SELECT min(rowid) FROM '" + tableName + "';";
2238      sqlite3_stmt *stmt = nullptr;
2239      int errCode = SQLiteUtils::GetStatement(db, cntSql, stmt);
2240      if (errCode != E_OK) {
2241          return errCode;
2242      }
2243  
2244      errCode = SQLiteUtils::StepWithRetry(stmt, false);
2245      if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
2246          isEmpty = (sqlite3_column_type(stmt, 0) == SQLITE_NULL);
2247          errCode = E_OK;
2248      }
2249  
2250      SQLiteUtils::ResetStatement(stmt, true, errCode);
2251      return SQLiteUtils::MapSQLiteErrno(errCode);
2252  }
2253  
SetPersistWalMode(sqlite3 * db)2254  int SQLiteUtils::SetPersistWalMode(sqlite3 *db)
2255  {
2256      if (db == nullptr) {
2257          return -E_INVALID_ARGS;
2258      }
2259      int opCode = 1;
2260      int errCode = sqlite3_file_control(db, "main", SQLITE_FCNTL_PERSIST_WAL, &opCode);
2261      if (errCode != SQLITE_OK) {
2262          LOGE("Set persist wal mode failed. %d", errCode);
2263      }
2264      return SQLiteUtils::MapSQLiteErrno(errCode);
2265  }
2266  
GetLastRowId(sqlite3 * db)2267  int64_t SQLiteUtils::GetLastRowId(sqlite3 *db)
2268  {
2269      if (db == nullptr) {
2270          return -1;
2271      }
2272      return sqlite3_last_insert_rowid(db);
2273  }
2274  
GetLastErrorMsg()2275  std::string SQLiteUtils::GetLastErrorMsg()
2276  {
2277      std::lock_guard<std::mutex> autoLock(logMutex_);
2278      return lastErrorMsg_;
2279  }
2280  
SetAuthorizer(sqlite3 * db,int (* xAuth)(void *,int,const char *,const char *,const char *,const char *))2281  int SQLiteUtils::SetAuthorizer(sqlite3 *db,
2282      int (*xAuth)(void*, int, const char*, const char*, const char*, const char*))
2283  {
2284      return SQLiteUtils::MapSQLiteErrno(sqlite3_set_authorizer(db, xAuth, nullptr));
2285  }
2286  
GetSelectCols(sqlite3_stmt * stmt,std::vector<std::string> & colNames)2287  void SQLiteUtils::GetSelectCols(sqlite3_stmt *stmt, std::vector<std::string> &colNames)
2288  {
2289      colNames.clear();
2290      for (int i = 0; i < sqlite3_column_count(stmt); ++i) {
2291          const char *name = sqlite3_column_name(stmt, i);
2292          colNames.emplace_back(name == nullptr ? std::string() : std::string(name));
2293      }
2294  }
2295  
SetKeyInner(sqlite3 * db,CipherType type,const CipherPassword & passwd,uint32_t iterTimes)2296  int SQLiteUtils::SetKeyInner(sqlite3 *db, CipherType type, const CipherPassword &passwd, uint32_t iterTimes)
2297  {
2298  #ifndef OMIT_ENCRYPT
2299      int errCode = sqlite3_key(db, static_cast<const void *>(passwd.GetData()), static_cast<int>(passwd.GetSize()));
2300      if (errCode != SQLITE_OK) {
2301          LOGE("[SQLiteUtils][SetKeyInner] config key failed:(%d)", errCode);
2302          return SQLiteUtils::MapSQLiteErrno(errCode);
2303      }
2304  
2305      errCode = SQLiteUtils::SetCipherSettings(db, type, iterTimes);
2306      if (errCode != E_OK) {
2307          LOGE("[SQLiteUtils][SetKeyInner] set cipher settings failed:%d", errCode);
2308      }
2309      return errCode;
2310  #else
2311      return -E_NOT_SUPPORT;
2312  #endif
2313  }
2314  
BindDataValueByType(sqlite3_stmt * statement,const std::optional<DataValue> & data,int cid)2315  int SQLiteUtils::BindDataValueByType(sqlite3_stmt *statement, const std::optional<DataValue> &data, int cid)
2316  {
2317      int errCode = E_OK;
2318      StorageType type = data.value_or(DataValue()).GetType();
2319      switch (type) {
2320          case StorageType::STORAGE_TYPE_INTEGER: {
2321              int64_t intData = 0;
2322              (void)data.value().GetInt64(intData);
2323              errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_int64(statement, cid, intData));
2324              break;
2325          }
2326  
2327          case StorageType::STORAGE_TYPE_REAL: {
2328              double doubleData = 0;
2329              (void)data.value().GetDouble(doubleData);
2330              errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_double(statement, cid, doubleData));
2331              break;
2332          }
2333  
2334          case StorageType::STORAGE_TYPE_TEXT: {
2335              std::string strData;
2336              (void)data.value().GetText(strData);
2337              errCode = SQLiteUtils::BindTextToStatement(statement, cid, strData);
2338              break;
2339          }
2340  
2341          case StorageType::STORAGE_TYPE_BLOB: {
2342              Blob blob;
2343              (void)data.value().GetBlob(blob);
2344              std::vector<uint8_t> blobData(blob.GetData(), blob.GetData() + blob.GetSize());
2345              errCode = SQLiteUtils::BindBlobToStatement(statement, cid, blobData, true);
2346              break;
2347          }
2348  
2349          case StorageType::STORAGE_TYPE_NULL: {
2350              errCode = SQLiteUtils::MapSQLiteErrno(sqlite3_bind_null(statement, cid));
2351              break;
2352          }
2353  
2354          default:
2355              break;
2356      }
2357      return errCode;
2358  }
2359  
UpdateCipherShaAlgo(sqlite3 * db,bool setWal,CipherType type,const CipherPassword & passwd,uint32_t iterTimes)2360  int SQLiteUtils::UpdateCipherShaAlgo(sqlite3 *db, bool setWal, CipherType type, const CipherPassword &passwd,
2361      uint32_t iterTimes)
2362  {
2363      if (passwd.GetSize() != 0) {
2364          int errCode = SetKeyInner(db, type, passwd, iterTimes);
2365          if (errCode != E_OK) {
2366              return errCode;
2367          }
2368          // set sha1 algo for old version
2369          errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_SQL);
2370          if (errCode != E_OK) {
2371              LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set sha algo failed:%d", errCode);
2372              return errCode;
2373          }
2374          // try to get user version
2375          errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL);
2376          if (errCode != E_OK) {
2377              LOGE("[SQLiteUtils][UpdateCipherShaAlgo] verify version failed:%d", errCode);
2378              if (errno == EKEYREVOKED) {
2379                  return -E_EKEYREVOKED;
2380              }
2381              if (errCode == -E_BUSY) {
2382                  return errCode;
2383              }
2384              return -E_INVALID_PASSWD_OR_CORRUPTED_DB;
2385          }
2386          // try to update rekey sha algo by rekey operation
2387          errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL);
2388          if (errCode != E_OK) {
2389              LOGE("[SQLiteUtils][UpdateCipherShaAlgo] set rekey sha algo failed:%d", errCode);
2390              return errCode;
2391          }
2392          if (setWal) {
2393              errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL);
2394              if (errCode != E_OK) {
2395                  LOGE("[SQLite][UpdateCipherShaAlgo] execute wal sql failed: %d", errCode);
2396                  return errCode;
2397              }
2398          }
2399          return Rekey(db, passwd);
2400      }
2401      return -E_INVALID_PASSWD_OR_CORRUPTED_DB;
2402  }
2403  
CheckTableExists(sqlite3 * db,const std::string & tableName,bool & isCreated,bool isCheckMeta)2404  int SQLiteUtils::CheckTableExists(sqlite3 *db, const std::string &tableName, bool &isCreated, bool isCheckMeta)
2405  {
2406      if (db == nullptr) {
2407          return -1;
2408      }
2409  
2410      sqlite3_stmt *stmt = nullptr;
2411      int errCode = SQLiteUtils::GetStatement(db, isCheckMeta ? CHECK_META_DB_TABLE_CREATED : CHECK_TABLE_CREATED, stmt);
2412      if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
2413          LOGE("Get check table statement failed. err=%d", errCode);
2414          return errCode;
2415      }
2416  
2417      errCode = SQLiteUtils::BindTextToStatement(stmt, 1, tableName);
2418      if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
2419          LOGE("Bind table name to statement failed. err=%d", errCode);
2420          goto END;
2421      }
2422  
2423      errCode = SQLiteUtils::StepWithRetry(stmt);
2424      if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
2425          LOGE("Check table exists failed. err=%d", errCode); // should always return a row data
2426          goto END;
2427      }
2428      errCode = E_OK;
2429      isCreated = (sqlite3_column_int(stmt, 0) == 1);
2430  END:
2431      SQLiteUtils::ResetStatement(stmt, true, errCode);
2432      return errCode;
2433  }
2434  
StepNext(sqlite3_stmt * stmt,bool isMemDb)2435  int SQLiteUtils::StepNext(sqlite3_stmt *stmt, bool isMemDb)
2436  {
2437      if (stmt == nullptr) {
2438          return -E_INVALID_ARGS;
2439      }
2440      int errCode = SQLiteUtils::StepWithRetry(stmt, isMemDb);
2441      if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
2442          errCode = -E_FINISHED;
2443      } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
2444          errCode = E_OK;
2445      }
2446      return errCode;
2447  }
2448  } // namespace DistributedDB
2449