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