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