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