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