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