• 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 #include <sys/stat.h>
26 
27 #include "sqlite_import.h"
28 #include "securec.h"
29 #include "db_constant.h"
30 #include "db_common.h"
31 #include "db_errno.h"
32 #include "log_print.h"
33 #include "value_object.h"
34 #include "schema_utils.h"
35 #include "schema_constant.h"
36 #include "sqlite_single_ver_storage_executor_sql.h"
37 #include "time_helper.h"
38 #include "platform_specific.h"
39 #include "sqlite_relational_utils.h"
40 
41 namespace DistributedDB {
42     std::mutex SQLiteUtils::logMutex_;
43     std::string SQLiteUtils::lastErrorMsg_;
44 namespace {
45     const int BUSY_SLEEP_TIME = 50; // sleep for 50us
46     const int NO_SIZE_LIMIT = -1;
47     const int MAX_STEP_TIMES = 8000;
48     const int BIND_KEY_INDEX = 1;
49     const int BIND_VAL_INDEX = 2;
50     const int USING_STR_LEN = -1;
51     const int MAX_BLOB_READ_SIZE = 64 * 1024 * 1024; // 64M limit
52     const int MAX_TEXT_READ_SIZE = 5 * 1024 * 1024; // 5M limit
53     const int HEAD_SIZE = 3;
54     const int END_SIZE = 3;
55     constexpr int MIN_SIZE = HEAD_SIZE + END_SIZE + 3;
56     const std::string REPLACE_CHAIN = "***";
57     const std::string DEFAULT_ANONYMOUS = "******";
58     const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;";
59     const std::string SYNC_MODE_FULL_SQL = "PRAGMA synchronous=FULL;";
60     const std::string USER_VERSION_SQL = "PRAGMA user_version;";
61     const std::string BEGIN_SQL = "BEGIN TRANSACTION";
62     const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION";
63     const std::string COMMIT_SQL = "COMMIT TRANSACTION";
64     const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION";
65     const std::string DEFAULT_ATTACH_CIPHER = "PRAGMA cipher_default_attach_cipher=";
66     const std::string DEFAULT_ATTACH_KDF_ITER = "PRAGMA cipher_default_attach_kdf_iter=5000";
67     const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;";
68     const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;";
69     const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;";
70     const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;";
71     const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');";
72     const std::string BACK_CIPHER_CONFIG_SQL = "PRAGMA backup.codec_cipher=";
73     const std::string BACK_KDF_ITER_CONFIG_SQL = "PRAGMA backup.codec_kdf_iter=5000;";
74     const std::string META_CIPHER_CONFIG_SQL = "PRAGMA meta.codec_cipher=";
75     const std::string META_KDF_ITER_CONFIG_SQL = "PRAGMA meta.codec_kdf_iter=5000;";
76 
77     const constexpr char *DETACH_BACKUP_SQL = "DETACH 'backup'";
78     const constexpr char *UPDATE_META_SQL = "INSERT OR REPLACE INTO meta_data VALUES (?, ?);";
79 
80     bool g_configLog = false;
81     std::mutex g_serverChangedDataMutex;
82     std::map<std::string, std::map<std::string, DistributedDB::ChangeProperties>> g_serverChangedDataMap;
83 }
84 
85 namespace TriggerMode {
86 const std::map<TriggerModeEnum, std::string> TRIGGER_MODE_MAP = {
87     {TriggerModeEnum::NONE,   ""},
88     {TriggerModeEnum::INSERT, "INSERT"},
89     {TriggerModeEnum::UPDATE, "UPDATE"},
90     {TriggerModeEnum::DELETE, "DELETE"},
91 };
92 
GetTriggerModeString(TriggerModeEnum mode)93 std::string GetTriggerModeString(TriggerModeEnum mode)
94 {
95     auto it = TRIGGER_MODE_MAP.find(mode);
96     return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second;
97 }
98 }
99 
Anonymous(const std::string & name)100 std::string SQLiteUtils::Anonymous(const std::string &name)
101 {
102     if (name.length() <= HEAD_SIZE) {
103         return DEFAULT_ANONYMOUS;
104     }
105 
106     if (name.length() < MIN_SIZE) {
107         return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN);
108     }
109 
110     return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE));
111 }
112 
IsNeedSkipLog(const unsigned int errType,const char * msg)113 bool IsNeedSkipLog(const unsigned int errType, const char *msg)
114 {
115     return errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr;
116 }
117 
SqliteLogCallback(void * data,int err,const char * msg)118 void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg)
119 {
120     bool verboseLog = (data != nullptr);
121     auto errType = static_cast<unsigned int>(err);
122     std::string logMsg = msg == nullptr ? "NULL" : msg;
123     errType &= 0xFF;
124     if (IsNeedSkipLog(errType, logMsg.c_str())) {
125         return;
126     }
127     if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA ||
128         errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) {
129         if (verboseLog) {
130             LOGD("[SQLite] Error[%d] sys[%d] %s ", err, errno, sqlite3_errstr(err));
131         }
132     } else if (errType == SQLITE_WARNING || errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) {
133         LOGI("[SQLite] Error[%d], sys[%d], %s, msg: %s ", err, errno,
134             sqlite3_errstr(err), SQLiteUtils::Anonymous(logMsg).c_str());
135     } else {
136         LOGE("[SQLite] Error[%d], sys[%d], msg: %s ", err, errno, logMsg.c_str());
137         return;
138     }
139 
140     const char *errMsg = sqlite3_errstr(err);
141     std::lock_guard<std::mutex> autoLock(logMutex_);
142     if (errMsg != nullptr) {
143         lastErrorMsg_ = std::string(errMsg);
144     }
145 }
146 
CreateDataBase(const OpenDbProperties & properties,sqlite3 * & dbTemp,bool setWal)147 int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal)
148 {
149     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
150     if (properties.createIfNecessary) {
151         flag |= SQLITE_OPEN_CREATE;
152     }
153     std::string cipherName = GetCipherName(properties.cipherType);
154     if (cipherName.empty()) {
155         LOGE("[SQLite] GetCipherName failed");
156         return -E_INVALID_ARGS;
157     }
158     std::string defaultAttachCipher = DEFAULT_ATTACH_CIPHER + cipherName + ";";
159     std::vector<std::string> sqls {defaultAttachCipher, DEFAULT_ATTACH_KDF_ITER};
160     if (setWal) {
161         sqls.push_back(WAL_MODE_SQL);
162     }
163     std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
164     int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, flag, nullptr);
165     if (errCode != SQLITE_OK) {
166         LOGE("[SQLite] open database failed: %d - sys err(%d)", errCode, errno);
167         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
168         goto END;
169     }
170 
171     errCode = SetDataBaseProperty(dbTemp, properties, setWal, sqls);
172     if (errCode != SQLITE_OK) {
173         LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode);
174         goto END;
175     }
176 
177 END:
178     if (errCode != E_OK && dbTemp != nullptr) {
179         (void)sqlite3_close_v2(dbTemp);
180         dbTemp = nullptr;
181     }
182     struct stat curStat;
183     stat(fileUrl.c_str(), &curStat);
184     LOGI("[SQLite] open database result: %d, inode: %llu", errCode, curStat.st_ino);
185 
186     return errCode;
187 }
188 
OpenDatabase(const OpenDbProperties & properties,sqlite3 * & db,bool setWal)189 int SQLiteUtils::OpenDatabase(const OpenDbProperties &properties, sqlite3 *&db, bool setWal)
190 {
191     {
192         // Only for register the sqlite3 log callback
193         std::lock_guard<std::mutex> lock(logMutex_);
194         if (!g_configLog) {
195             sqlite3_config(SQLITE_CONFIG_LOG, &SqliteLogCallback, &properties.createIfNecessary);
196             sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
197             g_configLog = true;
198         }
199     }
200     sqlite3 *dbTemp = nullptr;
201     int errCode = CreateDataBase(properties, dbTemp, setWal);
202     if (errCode != E_OK) {
203         goto END;
204     }
205     errCode = RegisterJsonFunctions(dbTemp);
206     if (errCode != E_OK) {
207         goto END;
208     }
209     // Set the synchroized mode, default for full mode.
210     errCode = ExecuteRawSQL(dbTemp, SYNC_MODE_FULL_SQL);
211     if (errCode != E_OK) {
212         LOGE("SQLite sync mode failed: %d", errCode);
213         goto END;
214     }
215 
216     if (!properties.isMemDb) {
217         errCode = SQLiteUtils::SetPersistWalMode(dbTemp);
218         if (errCode != E_OK) {
219             LOGE("SQLite set persist wall mode failed: %d", errCode);
220         }
221     }
222 
223 END:
224     if (errCode != E_OK && dbTemp != nullptr) {
225         (void)sqlite3_close_v2(dbTemp);
226         dbTemp = nullptr;
227     }
228     if (errCode != E_OK && errno == EKEYREVOKED) {
229         errCode = -E_EKEYREVOKED;
230     }
231     db = dbTemp;
232     return errCode;
233 }
234 
GetStatement(sqlite3 * db,const std::string & sql,sqlite3_stmt * & statement)235 int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement)
236 {
237     if (db == nullptr) {
238         LOGE("Invalid db for statement");
239         return -E_INVALID_DB;
240     }
241     // Prepare the new statement only when the input parameter is not null
242     if (statement != nullptr) {
243         return E_OK;
244     }
245     int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr);
246     if (errCode != SQLITE_OK) {
247         LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno);
248         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
249         SQLiteUtils::ResetStatement(statement, true, errCode);
250         return errCode;
251     }
252 
253     if (statement == nullptr) {
254         return -E_INVALID_DB;
255     }
256 
257     return E_OK;
258 }
259 
BindTextToStatement(sqlite3_stmt * statement,int index,const std::string & str)260 int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str)
261 {
262     if (statement == nullptr) {
263         return -E_INVALID_ARGS;
264     }
265 
266     int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
267     if (errCode != SQLITE_OK) {
268         LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode);
269         return SQLiteUtils::MapSQLiteErrno(errCode);
270     }
271 
272     return E_OK;
273 }
274 
BindInt64ToStatement(sqlite3_stmt * statement,int index,int64_t value)275 int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value)
276 {
277     // statement check outSide
278     int errCode = sqlite3_bind_int64(statement, index, value);
279     if (errCode != SQLITE_OK) {
280         LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode);
281         return SQLiteUtils::MapSQLiteErrno(errCode);
282     }
283 
284     return E_OK;
285 }
286 
BindBlobToStatement(sqlite3_stmt * statement,int index,const std::vector<uint8_t> & value,bool permEmpty)287 int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector<uint8_t> &value,
288     bool permEmpty)
289 {
290     if (statement == nullptr) {
291         return -E_INVALID_ARGS;
292     }
293 
294     // Check empty value.
295     if (value.empty() && !permEmpty) {
296         LOGI("[SQLiteUtil][Bind blob]Invalid value");
297         return -E_INVALID_ARGS;
298     }
299 
300     int errCode;
301     if (value.empty()) {
302         errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob.
303     } else {
304         errCode = sqlite3_bind_blob(statement, index, static_cast<const void *>(value.data()),
305             value.size(), SQLITE_TRANSIENT);
306     }
307 
308     if (errCode != SQLITE_OK) {
309         LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode);
310         return SQLiteUtils::MapSQLiteErrno(errCode);
311     }
312 
313     return E_OK;
314 }
315 
ResetStatement(sqlite3_stmt * & statement,bool isNeedFinalize,int & errCode)316 void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode)
317 {
318     ResetStatement(statement, isNeedFinalize, false, errCode);
319 }
320 
ResetStatement(sqlite3_stmt * & statement,bool isNeedFinalize,bool isIgnoreResetRet,int & errCode)321 void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, bool isIgnoreResetRet, int &errCode)
322 {
323     if (statement == nullptr) {
324         return;
325     }
326 
327     int innerCode = SQLITE_OK;
328     // if need finalize the statement, just goto finalize.
329     if (!isNeedFinalize) {
330         // reset the statement firstly.
331         innerCode = sqlite3_reset(statement);
332         if (innerCode != SQLITE_OK && !isIgnoreResetRet) {
333             LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno);
334             isNeedFinalize = true;
335         } else {
336             sqlite3_clear_bindings(statement);
337         }
338     }
339 
340     if (isNeedFinalize) {
341         int finalizeResult = sqlite3_finalize(statement);
342         if (finalizeResult != SQLITE_OK) {
343             LOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno);
344             innerCode = finalizeResult;
345         }
346         statement = nullptr;
347     }
348 
349     if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority.
350         errCode = SQLiteUtils::MapSQLiteErrno(innerCode);
351     }
352 }
353 
StepWithRetry(sqlite3_stmt * statement,bool isMemDb)354 int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb)
355 {
356     if (statement == nullptr) {
357         return -E_INVALID_ARGS;
358     }
359 
360     int errCode = E_OK;
361     int retryCount = 0;
362     do {
363         errCode = sqlite3_step(statement);
364         if ((errCode == SQLITE_LOCKED) && isMemDb) {
365             std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME));
366             retryCount++;
367         } else {
368             break;
369         }
370     } while (retryCount <= MAX_STEP_TIMES);
371 
372     if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) {
373         LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno);
374     }
375 
376     return SQLiteUtils::MapSQLiteErrno(errCode);
377 }
378 
BindPrefixKey(sqlite3_stmt * statement,int index,const Key & keyPrefix)379 int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &keyPrefix)
380 {
381     if (statement == nullptr) {
382         return -E_INVALID_ARGS;
383     }
384 
385     const size_t maxKeySize = DBConstant::MAX_KEY_SIZE;
386     // bind the first prefix key
387     int errCode = BindBlobToStatement(statement, index, keyPrefix, true);
388     if (errCode != SQLITE_OK) {
389         LOGE("Bind the prefix first error:%d", errCode);
390         return SQLiteUtils::MapSQLiteErrno(errCode);
391     }
392 
393     // bind the second prefix key
394     uint8_t end[maxKeySize];
395     errno_t status = memset_s(end, maxKeySize, UCHAR_MAX, maxKeySize); // max byte value is 0xFF.
396     if (status != EOK) {
397         LOGE("memset error:%d", status);
398         return -E_SECUREC_ERROR;
399     }
400 
401     if (!keyPrefix.empty()) {
402         status = memcpy_s(end, maxKeySize, keyPrefix.data(), keyPrefix.size());
403         if (status != EOK) {
404             LOGE("memcpy error:%d", status);
405             return -E_SECUREC_ERROR;
406         }
407     }
408 
409     // index wouldn't be too large, just add one to the first index.
410     errCode = sqlite3_bind_blob(statement, index + 1, end, maxKeySize, SQLITE_TRANSIENT);
411     if (errCode != SQLITE_OK) {
412         LOGE("Bind the prefix second error:%d", errCode);
413         return SQLiteUtils::MapSQLiteErrno(errCode);
414     }
415     return E_OK;
416 }
417 
BeginTransaction(sqlite3 * db,TransactType type)418 int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type)
419 {
420     if (type == TransactType::IMMEDIATE) {
421         return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL, true);
422     }
423 
424     return ExecuteRawSQL(db, BEGIN_SQL, true);
425 }
426 
CommitTransaction(sqlite3 * db)427 int SQLiteUtils::CommitTransaction(sqlite3 *db)
428 {
429     return ExecuteRawSQL(db, COMMIT_SQL, true);
430 }
431 
RollbackTransaction(sqlite3 * db)432 int SQLiteUtils::RollbackTransaction(sqlite3 *db)
433 {
434     return ExecuteRawSQL(db, ROLLBACK_SQL, true);
435 }
436 
ExecuteRawSQL(sqlite3 * db,const std::string & sql,bool ignoreResetFail)437 int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql, bool ignoreResetFail)
438 {
439     if (db == nullptr) {
440         return -E_INVALID_DB;
441     }
442 
443     sqlite3_stmt *stmt = nullptr;
444     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
445     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
446         LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno);
447         return errCode;
448     }
449 
450     do {
451         errCode = SQLiteUtils::StepWithRetry(stmt);
452         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
453             errCode = E_OK;
454             break;
455         } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
456             LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno);
457             break;
458         }
459     } while (true);
460 
461     int ret = E_OK;
462     SQLiteUtils::ResetStatement(stmt, true, ret);
463     if (!ignoreResetFail && ret != E_OK) {
464         return errCode != E_OK ? errCode : ret;
465     }
466     return errCode;
467 }
468 
SetKey(sqlite3 * db,CipherType type,const CipherPassword & passwd,bool setWal,uint32_t iterTimes)469 int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes)
470 {
471     if (db == nullptr) {
472         return -E_INVALID_DB;
473     }
474 
475     if (passwd.GetSize() != 0) {
476 #ifndef OMIT_ENCRYPT
477         int errCode = SetKeyInner(db, type, passwd, iterTimes);
478         if (errCode != E_OK) {
479             LOGE("[SQLiteUtils][Setkey] set keyInner failed:%d", errCode);
480             return errCode;
481         }
482         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL);
483         if (errCode != E_OK) {
484             LOGE("[SQLiteUtils][Setkey] set sha algo failed:%d", errCode);
485             return errCode;
486         }
487         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL);
488         if (errCode != E_OK) {
489             LOGE("[SQLiteUtils][Setkey] set rekey sha algo failed:%d", errCode);
490             return errCode;
491         }
492 #else
493         return -E_NOT_SUPPORT;
494 #endif
495     }
496 
497     // verify key
498     int errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL);
499     if (errCode != E_OK) {
500         LOGE("[SQLiteUtils][Setkey] verify version failed:%d", errCode);
501         if (errno == EKEYREVOKED) {
502             return -E_EKEYREVOKED;
503         }
504         if (errCode == -E_BUSY) {
505             return errCode;
506         }
507 #ifndef OMIT_ENCRYPT
508         if (passwd.GetSize() != 0) {
509             errCode = UpdateCipherShaAlgo(db, setWal, type, passwd, iterTimes);
510             if (errCode != E_OK) {
511                 LOGE("[SQLiteUtils][Setkey] upgrade cipher sha algo failed:%d", errCode);
512             }
513         }
514 #endif
515     }
516     return errCode;
517 }
518 
GetColumnBlobValue(sqlite3_stmt * statement,int index,std::vector<uint8_t> & value)519 int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector<uint8_t> &value)
520 {
521     if (statement == nullptr) {
522         return -E_INVALID_ARGS;
523     }
524 
525     int keySize = sqlite3_column_bytes(statement, index);
526     if (keySize < 0) {
527         LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize);
528         value.resize(0);
529         return E_OK;
530     }
531     auto keyRead = static_cast<const uint8_t *>(sqlite3_column_blob(statement, index));
532     if (keySize == 0 || keyRead == nullptr) {
533         value.resize(0);
534     } else {
535         if (keySize > MAX_BLOB_READ_SIZE) {
536             LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize);
537             keySize = MAX_BLOB_READ_SIZE + 1;
538         }
539         value.resize(keySize);
540         value.assign(keyRead, keyRead + keySize);
541     }
542     return E_OK;
543 }
544 
GetColumnTextValue(sqlite3_stmt * statement,int index,std::string & value)545 int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value)
546 {
547     if (statement == nullptr) {
548         return -E_INVALID_ARGS;
549     }
550 
551     int valSize = sqlite3_column_bytes(statement, index);
552     if (valSize < 0) {
553         LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize);
554         value = {};
555         return E_OK;
556     }
557     const unsigned char *val = sqlite3_column_text(statement, index);
558     if (valSize == 0 || val == nullptr) {
559         value = {};
560         return E_OK;
561     }
562     value = std::string(reinterpret_cast<const char *>(val));
563     if (valSize > MAX_TEXT_READ_SIZE) {
564         LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize);
565         value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid
566     }
567     return E_OK;
568 }
569 
AttachNewDatabase(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)570 int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password,
571     const std::string &attachDbAbsPath, const std::string &attachAsName)
572 {
573 #ifndef OMIT_ENCRYPT
574     int errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
575     if (errCode != E_OK) {
576         LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
577         return errCode;
578     }
579 #endif
580     errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
581 #ifndef OMIT_ENCRYPT
582     if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) {
583         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_ATTACH_SQL);
584         if (errCode != E_OK) {
585             LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha1 algo failed:%d", errCode);
586             return errCode;
587         }
588         errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
589         if (errCode != E_OK) {
590             LOGE("[SQLiteUtils][AttachNewDatabase] attach db failed:%d", errCode);
591             return errCode;
592         }
593         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
594         if (errCode != E_OK) {
595             LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
596         }
597     }
598 #endif
599     return errCode;
600 }
601 
AttachNewDatabaseInner(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)602 int SQLiteUtils::AttachNewDatabaseInner(sqlite3 *db, CipherType type, const CipherPassword &password,
603     const std::string &attachDbAbsPath, const std::string &attachAsName)
604 {
605     // example: "ATTACH '../new.db' AS backup KEY XXXX;"
606     std::string attachSql = "ATTACH ? AS " + attachAsName + " KEY ?;"; // Internal interface not need verify alias name
607 
608     sqlite3_stmt* statement = nullptr;
609     int errCode = SQLiteUtils::GetStatement(db, attachSql, statement);
610     if (errCode != E_OK) {
611         return errCode;
612     }
613     // 1st is name.
614     errCode = sqlite3_bind_text(statement, 1, attachDbAbsPath.c_str(), attachDbAbsPath.length(), SQLITE_TRANSIENT);
615     if (errCode != SQLITE_OK) {
616         LOGE("Bind the attached db name failed:%d", errCode);
617         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
618         goto END;
619     }
620     // Passwords do not allow vector operations, so we can not use function BindBlobToStatement here.
621     errCode = sqlite3_bind_blob(statement, 2, static_cast<const void *>(password.GetData()),  // 2 means password index.
622         password.GetSize(), SQLITE_TRANSIENT);
623     if (errCode != SQLITE_OK) {
624         LOGE("Bind the attached key failed:%d", errCode);
625         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
626         goto END;
627     }
628 
629     errCode = SQLiteUtils::StepWithRetry(statement);
630     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
631         LOGE("Execute the SQLite attach failed:%d", errCode);
632         goto END;
633     }
634     errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL);
635     if (errCode != E_OK) {
636         LOGE("Set journal mode failed: %d", errCode);
637     }
638 
639 END:
640     SQLiteUtils::ResetStatement(statement, true, errCode);
641     return errCode;
642 }
643 
CreateMetaDatabase(const std::string & metaDbPath)644 int SQLiteUtils::CreateMetaDatabase(const std::string &metaDbPath)
645 {
646     OpenDbProperties metaProperties {metaDbPath, true, false};
647     sqlite3 *db = nullptr;
648     int errCode = SQLiteUtils::OpenDatabase(metaProperties, db);
649     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
650         LOGE("[CreateMetaDatabase] Failed to create the meta database[%d]", errCode);
651     }
652     if (db != nullptr) { // LCOV_EXCL_BR_LINE
653         (void)sqlite3_close_v2(db);
654         db = nullptr;
655     }
656     return errCode;
657 }
658 
CheckIntegrity(const std::string & dbFile,CipherType type,const CipherPassword & passwd)659 int SQLiteUtils::CheckIntegrity(const std::string &dbFile, CipherType type, const CipherPassword &passwd)
660 {
661     std::vector<std::string> createTableSqls;
662     OpenDbProperties option = {dbFile, true, false, createTableSqls, type, passwd};
663     sqlite3 *db = nullptr;
664     int errCode = SQLiteUtils::OpenDatabase(option, db);
665     if (errCode != E_OK) {
666         LOGE("CheckIntegrity, open db error:%d", errCode);
667         return errCode;
668     }
669     errCode = CheckIntegrity(db, CHECK_DB_INTEGRITY_SQL);
670     if (db != nullptr) {
671         (void)sqlite3_close_v2(db);
672         db = nullptr;
673     }
674     return errCode;
675 }
676 
CheckIntegrity(sqlite3 * db,const std::string & sql)677 int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql)
678 {
679     sqlite3_stmt *statement = nullptr;
680     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
681     if (errCode != E_OK) {
682         LOGE("Prepare the integrity check statement error:%d", errCode);
683         return errCode;
684     }
685     int resultCnt = 0;
686     bool checkResultOK = false;
687     do {
688         errCode = SQLiteUtils::StepWithRetry(statement);
689         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
690             break;
691         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
692             auto result = reinterpret_cast<const char *>(sqlite3_column_text(statement, 0));
693             if (result == nullptr) {
694                 continue;
695             }
696             resultCnt = (resultCnt > 1) ? resultCnt : (resultCnt + 1);
697             if (strcmp(result, "ok") == 0) {
698                 checkResultOK = true;
699             }
700         } else {
701             checkResultOK = false;
702             LOGW("Step for the integrity check failed:%d", errCode);
703             break;
704         }
705     } while (true);
706     if (resultCnt == 1 && checkResultOK) {
707         errCode = E_OK;
708     } else {
709         errCode = -E_INVALID_PASSWD_OR_CORRUPTED_DB;
710     }
711     SQLiteUtils::ResetStatement(statement, true, errCode);
712     return errCode;
713 }
714 #ifdef RELATIONAL_STORE
715 
716 namespace { // anonymous namespace for schema analysis
AnalysisSchemaSqlAndTrigger(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)717 int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
718 {
719     std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? ";
720     if (!caseSensitive) {
721         sql += "COLLATE NOCASE";
722     }
723     sqlite3_stmt *statement = nullptr;
724     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
725     if (errCode != E_OK) {
726         LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode);
727         return errCode;
728     }
729     errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName);
730     if (errCode != E_OK) {
731         LOGE("[AnalysisSchema] Bind table name failed:%d", errCode);
732         SQLiteUtils::ResetStatement(statement, true, errCode);
733         return errCode;
734     }
735 
736     errCode = -E_NOT_FOUND;
737     do {
738         int err = SQLiteUtils::StepWithRetry(statement);
739         if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
740             break;
741         } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
742             errCode = E_OK;
743             std::string type;
744             (void) SQLiteUtils::GetColumnTextValue(statement, 0, type);
745             if (type == "table") {
746                 std::string createTableSql;
747                 (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql
748                 table.SetCreateTableSql(createTableSql);
749             }
750         } else {
751             LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err);
752             errCode = SQLiteUtils::MapSQLiteErrno(err);
753             break;
754         }
755     } while (true);
756     SQLiteUtils::ResetStatement(statement, true, errCode);
757     return errCode;
758 }
759 
GetSchemaIndexList(sqlite3 * db,const std::string & tableName,std::vector<std::string> & indexList,std::vector<std::string> & uniqueList)760 int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector<std::string> &indexList,
761     std::vector<std::string> &uniqueList)
762 {
763     std::string sql = "pragma index_list('" + tableName + "')";
764     sqlite3_stmt *statement = nullptr;
765     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
766     if (errCode != E_OK) {
767         LOGE("[AnalysisSchema] Prepare the get schema index list 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             std::string indexName;
778             (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName);  // 1 means index name
779             int unique = sqlite3_column_int64(statement, 2);  // 2 means index type, whether unique
780             if (unique == 0) { // 0 means index created by user declare
781                 indexList.push_back(indexName);
782             } else if (unique == 1) { // 1 means an unique define
783                 uniqueList.push_back(indexName);
784             }
785         } else {
786             LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode);
787             break;
788         }
789     } while (true);
790     SQLiteUtils::ResetStatement(statement, true, errCode);
791     return errCode;
792 }
793 
AnalysisSchemaIndexDefine(sqlite3 * db,const std::string & indexName,CompositeFields & indexDefine)794 int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine)
795 {
796     auto sql = "pragma index_info('" + indexName + "')";
797     sqlite3_stmt *statement = nullptr;
798     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
799     if (errCode != E_OK) {
800         LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode);
801         return errCode;
802     }
803 
804     do {
805         errCode = SQLiteUtils::StepWithRetry(statement);
806         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
807             errCode = E_OK;
808             break;
809         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
810             std::string indexField;
811             (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField);  // 2 means index's column name.
812             indexDefine.push_back(indexField);
813         } else {
814             LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode);
815             break;
816         }
817     } while (true);
818 
819     SQLiteUtils::ResetStatement(statement, true, errCode);
820     return errCode;
821 }
822 
AnalysisSchemaIndex(sqlite3 * db,const std::string & tableName,TableInfo & table)823 int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table)
824 {
825     std::vector<std::string> indexList;
826     std::vector<std::string> uniqueList;
827     int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList);
828     if (errCode != E_OK) {
829         LOGE("[AnalysisSchema] get schema index list failed.");
830         return errCode;
831     }
832 
833     for (const auto &indexName : indexList) {
834         CompositeFields indexDefine;
835         errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine);
836         if (errCode != E_OK) {
837             LOGE("[AnalysisSchema] analysis schema index columns failed.");
838             return errCode;
839         }
840         table.AddIndexDefine(indexName, indexDefine);
841     }
842 
843     std::vector<CompositeFields> uniques;
844     for (const auto &uniqueName : uniqueList) {
845         CompositeFields uniqueDefine;
846         errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine);
847         if (errCode != E_OK) {
848             LOGE("[AnalysisSchema] analysis schema unique columns failed.");
849             return errCode;
850         }
851         uniques.push_back(uniqueDefine);
852     }
853     table.SetUniqueDefine(uniques);
854     return E_OK;
855 }
856 
SetPrimaryKeyCollateType(const std::string & sql,FieldInfo & field)857 void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field)
858 {
859     std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName());
860     if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") ||
861         DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) {
862         field.SetCollateType(CollateType::COLLATE_NOCASE);
863     } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") ||
864         DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) {
865         field.SetCollateType(CollateType::COLLATE_RTRIM);
866     }
867 }
868 
SetFieldInfo(sqlite3_stmt * statement,TableInfo & table)869 int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table)
870 {
871     FieldInfo field;
872     field.SetColumnId(sqlite3_column_int(statement, 0));  // 0 means column id index
873 
874     std::string tmpString;
875     (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString);  // 1 means column name index
876     if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) {
877         LOGE("[AnalysisSchema] unsupported field name.");
878         return -E_NOT_SUPPORT;
879     }
880     field.SetFieldName(tmpString);
881 
882     (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString);  // 2 means datatype index
883     field.SetDataType(tmpString);
884 
885     field.SetNotNull(static_cast<bool>(sqlite3_column_int64(statement, 3)));  // 3 means whether null index
886 
887     (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString);  // 4 means default value index
888     if (!tmpString.empty()) {
889         field.SetDefaultValue(tmpString);
890     }
891 
892     int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index
893     if (keyIndex != 0) {  // not 0 means is a primary key
894         table.SetPrimaryKey(field.GetFieldName(), keyIndex);
895         SetPrimaryKeyCollateType(table.GetCreateTableSql(), field);
896     }
897     table.AddField(field);
898     return E_OK;
899 }
900 } // end of anonymous namespace for schema analysis
901 
AnalysisSchemaFieldDefine(sqlite3 * db,const std::string & tableName,TableInfo & table)902 int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table)
903 {
904     std::string sql = "pragma table_info('" + tableName + "')";
905     sqlite3_stmt *statement = nullptr;
906     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
907     if (errCode != E_OK) {
908         LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode);
909         return errCode;
910     }
911 
912     do {
913         errCode = SQLiteUtils::StepWithRetry(statement);
914         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
915             errCode = E_OK;
916             break;
917         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
918             errCode = SetFieldInfo(statement, table);
919             if (errCode != E_OK) {
920                 break;
921             }
922         } else {
923             LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode);
924             break;
925         }
926     } while (true);
927 
928     if (table.GetPrimaryKey().empty()) {
929         table.SetPrimaryKey("rowid", 1);
930     }
931 
932     SQLiteUtils::ResetStatement(statement, true, errCode);
933     return errCode;
934 }
935 
AnalysisSchema(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)936 int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
937 {
938     if (db == nullptr) {
939         return -E_INVALID_DB;
940     }
941 
942     if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) {
943         LOGE("[AnalysisSchema] unsupported table name.");
944         return -E_NOT_SUPPORT;
945     }
946 
947     int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive);
948     if (errCode != E_OK) {
949         LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode);
950         return errCode;
951     }
952 
953     errCode = AnalysisSchemaIndex(db, tableName, table);
954     if (errCode != E_OK) {
955         LOGE("[AnalysisSchema] Analysis index failed.");
956         return errCode;
957     }
958 
959     errCode = AnalysisSchemaFieldDefine(db, tableName, table);
960     if (errCode != E_OK) {
961         LOGE("[AnalysisSchema] Analysis field failed.");
962         return errCode;
963     }
964 
965     table.SetTableName(tableName);
966     return E_OK;
967 }
968 #endif
969 #ifndef OMIT_ENCRYPT
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)970 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
971     const std::string &newDbName)
972 {
973     if (db == nullptr) {
974         return -E_INVALID_DB;
975     }
976 
977     int errCode = AttachNewDatabase(db, type, passwd, newDbName);
978     if (errCode != E_OK) {
979         LOGE("Attach New Db fail!");
980         return errCode;
981     }
982     errCode = SQLiteUtils::ExecuteRawSQL(db, EXPORT_BACKUP_SQL);
983     if (errCode != E_OK) {
984         LOGE("Execute the SQLite export failed:%d", errCode);
985     }
986 
987     int detachError = SQLiteUtils::ExecuteRawSQL(db, DETACH_BACKUP_SQL);
988     if (errCode == E_OK) {
989         errCode = detachError;
990         if (detachError != E_OK) {
991             LOGE("Execute the SQLite detach failed:%d", errCode);
992         }
993     }
994     return errCode;
995 }
996 
Rekey(sqlite3 * db,const CipherPassword & passwd)997 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
998 {
999     if (db == nullptr) {
1000         return -E_INVALID_DB;
1001     }
1002 
1003     int errCode = sqlite3_rekey(db, static_cast<const void *>(passwd.GetData()), static_cast<int>(passwd.GetSize()));
1004     if (errCode != E_OK) {
1005         LOGE("SQLite rekey failed:(%d)", errCode);
1006         return SQLiteUtils::MapSQLiteErrno(errCode);
1007     }
1008 
1009     return E_OK;
1010 }
1011 #else
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)1012 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
1013     const std::string &newDbName)
1014 {
1015     (void)db;
1016     (void)type;
1017     (void)passwd;
1018     (void)newDbName;
1019     return -E_NOT_SUPPORT;
1020 }
1021 
Rekey(sqlite3 * db,const CipherPassword & passwd)1022 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
1023 {
1024     (void)db;
1025     (void)passwd;
1026     return -E_NOT_SUPPORT;
1027 }
1028 #endif
1029 
GetVersion(const OpenDbProperties & properties,int & version)1030 int SQLiteUtils::GetVersion(const OpenDbProperties &properties, int &version)
1031 {
1032     if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
1033         return -E_INVALID_ARGS;
1034     }
1035 
1036     sqlite3 *dbTemp = nullptr;
1037     // Please make sure the database file exists and is working properly
1038     std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
1039     int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, SQLITE_OPEN_URI | SQLITE_OPEN_READONLY, nullptr);
1040     if (errCode != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1041         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
1042         LOGE("Open database failed: %d, sys:%d", errCode, errno);
1043         goto END;
1044     }
1045     // in memory mode no need cipher
1046     if (!properties.isMemDb) { // LCOV_EXCL_BR_LINE
1047         errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, false,
1048             properties.iterTimes);
1049         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1050             LOGE("Set key failed: %d", errCode);
1051             goto END;
1052         }
1053     }
1054 
1055     errCode = GetVersion(dbTemp, version);
1056 
1057 END:
1058     if (dbTemp != nullptr) { // LCOV_EXCL_BR_LINE
1059         (void)sqlite3_close_v2(dbTemp);
1060         dbTemp = nullptr;
1061     }
1062     return errCode;
1063 }
1064 
GetVersion(sqlite3 * db,int & version)1065 int SQLiteUtils::GetVersion(sqlite3 *db, int &version)
1066 {
1067     if (db == nullptr) {
1068         return -E_INVALID_DB;
1069     }
1070 
1071     std::string strSql = "PRAGMA user_version;";
1072     sqlite3_stmt *statement = nullptr;
1073     int errCode = sqlite3_prepare(db, strSql.c_str(), -1, &statement, nullptr);
1074     if (errCode != SQLITE_OK || statement == nullptr) {
1075         LOGE("[SqlUtil][GetVer] sqlite3_prepare failed.");
1076         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
1077         return errCode;
1078     }
1079     int ret = E_OK;
1080     errCode = sqlite3_step(statement);
1081     if (errCode == SQLITE_ROW) {
1082         // Get pragma user_version at first column
1083         version = sqlite3_column_int(statement, 0);
1084     } else {
1085         LOGE("[SqlUtil][GetVer] Get db user_version failed.");
1086         ret = SQLiteUtils::MapSQLiteErrno(errCode);
1087     }
1088     errCode = E_OK;
1089     SQLiteUtils::ResetStatement(statement, true, errCode);
1090     return ret != E_OK ? ret : errCode;
1091 }
1092 
GetJournalMode(sqlite3 * db,std::string & mode)1093 int SQLiteUtils::GetJournalMode(sqlite3 *db, std::string &mode)
1094 {
1095     if (db == nullptr) {
1096         return -E_INVALID_DB;
1097     }
1098 
1099     std::string sql = "PRAGMA journal_mode;";
1100     sqlite3_stmt *statement = nullptr;
1101     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
1102     if (errCode != E_OK || statement == nullptr) {
1103         return errCode;
1104     }
1105 
1106     errCode = SQLiteUtils::StepWithRetry(statement);
1107     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1108         errCode = SQLiteUtils::GetColumnTextValue(statement, 0, mode);
1109     } else {
1110         LOGE("[SqlUtil][GetJournal] Get db journal_mode failed.");
1111     }
1112 
1113     SQLiteUtils::ResetStatement(statement, true, errCode);
1114     return errCode;
1115 }
1116 
SetUserVer(const OpenDbProperties & properties,int version)1117 int SQLiteUtils::SetUserVer(const OpenDbProperties &properties, int version)
1118 {
1119     if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
1120         return -E_INVALID_ARGS;
1121     }
1122 
1123     // Please make sure the database file exists and is working properly
1124     sqlite3 *db = nullptr;
1125     int errCode = SQLiteUtils::OpenDatabase(properties, db);
1126     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1127         return errCode;
1128     }
1129 
1130     // Set user version
1131     errCode = SQLiteUtils::SetUserVer(db, version);
1132     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1133         LOGE("Set user version fail: %d", errCode);
1134         goto END;
1135     }
1136 
1137 END:
1138     if (db != nullptr) { // LCOV_EXCL_BR_LINE
1139         (void)sqlite3_close_v2(db);
1140         db = nullptr;
1141     }
1142 
1143     return errCode;
1144 }
1145 
SetUserVer(sqlite3 * db,int version)1146 int SQLiteUtils::SetUserVer(sqlite3 *db, int version)
1147 {
1148     if (db == nullptr) {
1149         return -E_INVALID_DB;
1150     }
1151     std::string userVersionSql = "PRAGMA user_version=" + std::to_string(version) + ";";
1152     return SQLiteUtils::ExecuteRawSQL(db, userVersionSql);
1153 }
1154 
MapSQLiteErrno(int errCode)1155 int SQLiteUtils::MapSQLiteErrno(int errCode)
1156 {
1157     switch (errCode) {
1158         case SQLITE_OK:
1159             return E_OK;
1160         case SQLITE_IOERR:
1161             if (errno == EKEYREVOKED) {
1162                 return -E_EKEYREVOKED;
1163             }
1164             break;
1165         case SQLITE_CORRUPT:
1166         case SQLITE_NOTADB:
1167             return -E_INVALID_PASSWD_OR_CORRUPTED_DB;
1168         case SQLITE_LOCKED:
1169         case SQLITE_BUSY:
1170             return -E_BUSY;
1171         case SQLITE_ERROR:
1172             if (errno == EKEYREVOKED) {
1173                 return -E_EKEYREVOKED;
1174             }
1175             break;
1176         case SQLITE_AUTH:
1177             return -E_DENIED_SQL;
1178         case SQLITE_CONSTRAINT:
1179             return -E_CONSTRAINT;
1180         case SQLITE_CANTOPEN:
1181             return -E_SQLITE_CANT_OPEN;
1182         default:
1183             break;
1184     }
1185     return -errCode;
1186 }
1187 
SetBusyTimeout(sqlite3 * db,int timeout)1188 int SQLiteUtils::SetBusyTimeout(sqlite3 *db, int timeout)
1189 {
1190     if (db == nullptr) {
1191         return -E_INVALID_DB;
1192     }
1193 
1194     // Set the default busy handler to retry automatically before returning SQLITE_BUSY.
1195     int errCode = sqlite3_busy_timeout(db, timeout);
1196     if (errCode != SQLITE_OK) {
1197         LOGE("[SQLite] set busy timeout failed:%d", errCode);
1198     }
1199 
1200     return SQLiteUtils::MapSQLiteErrno(errCode);
1201 }
1202 
1203 #ifndef OMIT_ENCRYPT
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)1204 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
1205     const std::string &targetFile, const CipherPassword &passwd)
1206 {
1207     std::vector<std::string> createTableSqls;
1208     OpenDbProperties option = {srcFile, true, false, createTableSqls, type, srcPasswd};
1209     sqlite3 *db = nullptr;
1210     int errCode = SQLiteUtils::OpenDatabase(option, db);
1211     if (errCode != E_OK) {
1212         LOGE("Open db error while exporting:%d", errCode);
1213         return errCode;
1214     }
1215 
1216     errCode = SQLiteUtils::ExportDatabase(db, type, passwd, targetFile);
1217     if (db != nullptr) {
1218         (void)sqlite3_close_v2(db);
1219         db = nullptr;
1220     }
1221     return errCode;
1222 }
1223 #else
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)1224 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
1225     const std::string &targetFile, const CipherPassword &passwd)
1226 {
1227     (void)srcFile;
1228     (void)type;
1229     (void)srcPasswd;
1230     (void)targetFile;
1231     (void)passwd;
1232     return -E_NOT_SUPPORT;
1233 }
1234 #endif
1235 
SaveSchema(sqlite3 * db,const std::string & strSchema)1236 int SQLiteUtils::SaveSchema(sqlite3 *db, const std::string &strSchema)
1237 {
1238     if (db == nullptr) {
1239         return -E_INVALID_DB;
1240     }
1241 
1242     sqlite3_stmt *statement = nullptr;
1243     std::string sql = "INSERT OR REPLACE INTO meta_data VALUES(?,?);";
1244     int errCode = GetStatement(db, sql, statement);
1245     if (errCode != E_OK) {
1246         return errCode;
1247     }
1248 
1249     Key schemaKey;
1250     DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemaKey);
1251     errCode = BindBlobToStatement(statement, BIND_KEY_INDEX, schemaKey, false);
1252     if (errCode != E_OK) {
1253         ResetStatement(statement, true, errCode);
1254         return errCode;
1255     }
1256 
1257     Value schemaValue;
1258     DBCommon::StringToVector(strSchema, schemaValue);
1259     errCode = BindBlobToStatement(statement, BIND_VAL_INDEX, schemaValue, false);
1260     if (errCode != E_OK) {
1261         ResetStatement(statement, true, errCode);
1262         return errCode;
1263     }
1264 
1265     errCode = StepWithRetry(statement); // memory db does not support schema
1266     if (errCode != MapSQLiteErrno(SQLITE_DONE)) {
1267         LOGE("[SqlUtil][SetSchema] StepWithRetry fail, errCode=%d.", errCode);
1268         ResetStatement(statement, true, errCode);
1269         return errCode;
1270     }
1271     errCode = E_OK;
1272     ResetStatement(statement, true, errCode);
1273     return errCode;
1274 }
1275 
GetSchema(sqlite3 * db,std::string & strSchema)1276 int SQLiteUtils::GetSchema(sqlite3 *db, std::string &strSchema)
1277 {
1278     if (db == nullptr) {
1279         return -E_INVALID_DB;
1280     }
1281 
1282     bool isExists = false;
1283     int errCode = CheckTableExists(db, "meta_data", isExists);
1284     if (errCode != E_OK || !isExists) {
1285         LOGW("meta table may has not been created, err=%d, isExists=%d", errCode, isExists);
1286         return errCode;
1287     }
1288 
1289     sqlite3_stmt *statement = nullptr;
1290     std::string sql = "SELECT value FROM meta_data WHERE key=?;";
1291     errCode = GetStatement(db, sql, statement);
1292     if (errCode != E_OK) {
1293         return errCode;
1294     }
1295 
1296     Key schemakey;
1297     DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemakey);
1298     errCode = BindBlobToStatement(statement, 1, schemakey, false);
1299     if (errCode != E_OK) {
1300         ResetStatement(statement, true, errCode);
1301         return errCode;
1302     }
1303 
1304     errCode = StepWithRetry(statement); // memory db does not support schema
1305     if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1306         ResetStatement(statement, true, errCode);
1307         return -E_NOT_FOUND;
1308     } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1309         ResetStatement(statement, true, errCode);
1310         return errCode;
1311     }
1312 
1313     Value schemaValue;
1314     errCode = GetColumnBlobValue(statement, 0, schemaValue);
1315     if (errCode != E_OK) {
1316         ResetStatement(statement, true, errCode);
1317         return errCode;
1318     }
1319     DBCommon::VectorToString(schemaValue, strSchema);
1320     ResetStatement(statement, true, errCode);
1321     return errCode;
1322 }
1323 
IncreaseIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)1324 int SQLiteUtils::IncreaseIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
1325     uint32_t skipSize)
1326 {
1327     if (db == nullptr) {
1328         LOGE("[IncreaseIndex] Sqlite DB not exists.");
1329         return -E_INVALID_DB;
1330     }
1331     if (name.empty() || info.empty()) {
1332         LOGE("[IncreaseIndex] Name or info can not be empty.");
1333         return -E_NOT_PERMIT;
1334     }
1335     std::string indexName = SchemaUtils::FieldPathString(name);
1336     std::string sqlCommand = "CREATE INDEX IF NOT EXISTS '" + indexName + "' ON sync_data (";
1337     for (uint32_t i = 0; i < info.size(); i++) {
1338         if (i != 0) {
1339             sqlCommand += ", ";
1340         }
1341         std::string extractSql = SchemaObject::GenerateExtractSQL(type, info[i].first, info[i].second,
1342             skipSize);
1343         if (extractSql.empty()) { // Unlikely
1344             LOGE("[IncreaseIndex] GenerateExtractSQL fail at field=%u.", i);
1345             return -E_INTERNAL_ERROR;
1346         }
1347         sqlCommand += extractSql;
1348     }
1349     sqlCommand += ") WHERE (flag&0x01=0);";
1350     return SQLiteUtils::ExecuteRawSQL(db, sqlCommand);
1351 }
1352 
ChangeIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)1353 int SQLiteUtils::ChangeIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
1354     uint32_t skipSize)
1355 {
1356     // Currently we change index by drop it then create it, SQLite "REINDEX" may be used in the future
1357     int errCode = DecreaseIndex(db, name);
1358     if (errCode != E_OK) {
1359         LOGE("[ChangeIndex] Decrease fail=%d.", errCode);
1360         return errCode;
1361     }
1362     errCode = IncreaseIndex(db, name, info, type, skipSize);
1363     if (errCode != E_OK) {
1364         LOGE("[ChangeIndex] Increase fail=%d.", errCode);
1365         return errCode;
1366     }
1367     return E_OK;
1368 }
1369 
DecreaseIndex(sqlite3 * db,const IndexName & name)1370 int SQLiteUtils::DecreaseIndex(sqlite3 *db, const IndexName &name)
1371 {
1372     if (db == nullptr) {
1373         LOGE("[DecreaseIndex] Sqlite DB not exists.");
1374         return -E_INVALID_DB;
1375     }
1376     if (name.empty()) {
1377         LOGE("[DecreaseIndex] Name can not be empty.");
1378         return -E_NOT_PERMIT;
1379     }
1380     std::string indexName = SchemaUtils::FieldPathString(name);
1381     std::string sqlCommand = "DROP INDEX IF EXISTS '" + indexName + "';";
1382     return ExecuteRawSQL(db, sqlCommand);
1383 }
1384 
RegisterJsonFunctions(sqlite3 * db)1385 int SQLiteUtils::RegisterJsonFunctions(sqlite3 *db)
1386 {
1387     if (db == nullptr) {
1388         LOGE("Sqlite DB not exists.");
1389         return -E_INVALID_DB;
1390     }
1391     int errCode = sqlite3_create_function_v2(db, "calc_hash_key", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1392         nullptr, &CalcHashKey, nullptr, nullptr, nullptr);
1393     if (errCode != SQLITE_OK) {
1394         LOGE("sqlite3_create_function_v2 about calc_hash_key returned %d", errCode);
1395         return MapSQLiteErrno(errCode);
1396     }
1397 #ifdef USING_DB_JSON_EXTRACT_AUTOMATICALLY
1398     // Specify need 3 parameter in json_extract_by_path function
1399     errCode = sqlite3_create_function_v2(db, "json_extract_by_path", 3, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1400         nullptr, &JsonExtractByPath, nullptr, nullptr, nullptr);
1401     if (errCode != SQLITE_OK) {
1402         LOGE("sqlite3_create_function_v2 about json_extract_by_path returned %d", errCode);
1403         return MapSQLiteErrno(errCode);
1404     }
1405 #endif
1406     return E_OK;
1407 }
1408 
1409 namespace {
SchemaObjectDestructor(SchemaObject * inObject)1410 void SchemaObjectDestructor(SchemaObject *inObject)
1411 {
1412     delete inObject;
1413     inObject = nullptr;
1414 }
1415 }
1416 #ifdef RELATIONAL_STORE
RegisterCalcHash(sqlite3 * db)1417 int SQLiteUtils::RegisterCalcHash(sqlite3 *db)
1418 {
1419     TransactFunc func;
1420     func.xFunc = &CalcHash;
1421     return SQLiteUtils::RegisterFunction(db, "calc_hash", 2, nullptr, func); // 2 is params count
1422 }
1423 
GetSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1424 void SQLiteUtils::GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1425 {
1426     if (ctx == nullptr || argc != 1 || argv == nullptr) {
1427         LOGE("Parameter does not meet restrictions.");
1428         return;
1429     }
1430 
1431     sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
1432 }
1433 
GetRawSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1434 void SQLiteUtils::GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1435 {
1436     if (ctx == nullptr || argc != 0 || argv == nullptr) {
1437         LOGE("Parameter does not meet restrictions.");
1438         return;
1439     }
1440 
1441     uint64_t curTime = 0;
1442     int errCode = TimeHelper::GetSysCurrentRawTime(curTime);
1443     if (errCode != E_OK) {
1444         sqlite3_result_error(ctx, "get raw sys time failed in sqlite utils.", errCode);
1445         return;
1446     }
1447     sqlite3_result_int64(ctx, (sqlite3_int64)(curTime));
1448 }
1449 
GetLastTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1450 void SQLiteUtils::GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1451 {
1452     if (ctx == nullptr || argc != 0 || argv == nullptr) { // LCOV_EXCL_BR_LINE
1453         LOGE("Parameter does not meet restrictions.");
1454         return;
1455     }
1456     // Never used internally, just for sql prepare
1457     sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
1458 }
1459 
CloudDataChangedObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1460 void SQLiteUtils::CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1461 {
1462     if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts
1463         return;
1464     }
1465     sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
1466 }
1467 
CloudDataChangedServerObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1468 void SQLiteUtils::CloudDataChangedServerObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1469 {
1470     if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is param counts
1471         return;
1472     }
1473     sqlite3 *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1474     std::string fileName;
1475     if (!SQLiteRelationalUtils::GetDbFileName(db, fileName)) {
1476         return;
1477     }
1478     auto tableNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
1479     if (tableNameChar == nullptr) {
1480         return;
1481     }
1482     std::string tableName = static_cast<std::string>(tableNameChar);
1483 
1484     uint64_t isTrackerChange = static_cast<uint64_t>(sqlite3_value_int(argv[1])); // 1 is param index
1485     LOGD("Cloud data changed, server observer callback %u", isTrackerChange);
1486     {
1487         std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
1488         auto itTable = g_serverChangedDataMap[fileName].find(tableName);
1489         if (itTable != g_serverChangedDataMap[fileName].end()) {
1490             itTable->second.isTrackedDataChange =
1491                 (static_cast<uint8_t>(itTable->second.isTrackedDataChange) | isTrackerChange) > 0;
1492         } else {
1493             DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) };
1494             g_serverChangedDataMap[fileName].insert_or_assign(tableName, properties);
1495         }
1496     }
1497     sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
1498 }
1499 
GetAndResetServerObserverData(const std::string & dbName,const std::string & tableName,ChangeProperties & changeProperties)1500 void SQLiteUtils::GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName,
1501     ChangeProperties &changeProperties)
1502 {
1503     std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
1504     auto itDb = g_serverChangedDataMap.find(dbName);
1505     if (itDb != g_serverChangedDataMap.end() && !itDb->second.empty()) {
1506         auto itTable = itDb->second.find(tableName);
1507         if (itTable == itDb->second.end()) {
1508             return;
1509         }
1510         changeProperties = itTable->second;
1511         g_serverChangedDataMap[dbName].erase(itTable);
1512     }
1513 }
1514 
RegisterGetSysTime(sqlite3 * db)1515 int SQLiteUtils::RegisterGetSysTime(sqlite3 *db)
1516 {
1517     TransactFunc func;
1518     func.xFunc = &GetSysTime;
1519     return SQLiteUtils::RegisterFunction(db, "get_sys_time", 1, nullptr, func);
1520 }
1521 
RegisterGetLastTime(sqlite3 * db)1522 int SQLiteUtils::RegisterGetLastTime(sqlite3 *db)
1523 {
1524     TransactFunc func;
1525     func.xFunc = &GetLastTime;
1526     return SQLiteUtils::RegisterFunction(db, "get_last_time", 0, nullptr, func);
1527 }
1528 
RegisterGetRawSysTime(sqlite3 * db)1529 int SQLiteUtils::RegisterGetRawSysTime(sqlite3 *db)
1530 {
1531     TransactFunc func;
1532     func.xFunc = &GetRawSysTime;
1533     return SQLiteUtils::RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func);
1534 }
1535 
RegisterCloudDataChangeObserver(sqlite3 * db)1536 int SQLiteUtils::RegisterCloudDataChangeObserver(sqlite3 *db)
1537 {
1538     TransactFunc func;
1539     func.xFunc = &CloudDataChangedObserver;
1540     return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts
1541 }
1542 
RegisterCloudDataChangeServerObserver(sqlite3 * db)1543 int SQLiteUtils::RegisterCloudDataChangeServerObserver(sqlite3 *db)
1544 {
1545     TransactFunc func;
1546     func.xFunc = &CloudDataChangedServerObserver;
1547     return RegisterFunction(db, "server_observer", 2, db, func); // 2 is param counts
1548 }
1549 
CreateSameStuTable(sqlite3 * db,const TableInfo & baseTbl,const std::string & newTableName)1550 int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName)
1551 {
1552     std::string sql = "CREATE TABLE IF NOT EXISTS '" + newTableName + "' (";
1553     const FieldInfoMap &fields = baseTbl.GetFields();
1554     for (uint32_t cid = 0; cid < fields.size(); ++cid) {
1555         std::string fieldName = baseTbl.GetFieldName(cid);
1556         const auto &it = fields.find(fieldName);
1557         if (it == fields.end()) {
1558             return -E_INVALID_DB;
1559         }
1560         sql += "'" + fieldName + "' '" + it->second.GetDataType() + "'";
1561         if (it->second.IsNotNull()) {
1562             sql += " NOT NULL";
1563         }
1564         if (it->second.HasDefaultValue()) {
1565             sql += " DEFAULT " + it->second.GetDefaultValue();
1566         }
1567         sql += ",";
1568     }
1569     // base table has primary key
1570     if (!(baseTbl.GetPrimaryKey().size() == 1 && baseTbl.GetPrimaryKey().at(0) == "rowid")) {
1571         sql += " PRIMARY KEY (";
1572         for (const auto &it : baseTbl.GetPrimaryKey()) {
1573             sql += "'" + it.second + "',";
1574         }
1575         sql.pop_back();
1576         sql += "),";
1577     }
1578     sql.pop_back();
1579     sql += ");";
1580     int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
1581     if (errCode != E_OK) {
1582         LOGE("[SQLite] execute create table sql failed");
1583     }
1584     return errCode;
1585 }
1586 
CloneIndexes(sqlite3 * db,const std::string & oriTableName,const std::string & newTableName)1587 int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName)
1588 {
1589     std::string sql =
1590         "SELECT 'CREATE ' || CASE WHEN il.'unique' THEN 'UNIQUE ' ELSE '' END || 'INDEX IF NOT EXISTS ' || '" +
1591             newTableName + "_' || il.name || ' ON ' || '" + newTableName +
1592             "' || '(' || GROUP_CONCAT(ii.name) || ');' "
1593         "FROM sqlite_master AS m,"
1594             "pragma_index_list(m.name) AS il,"
1595             "pragma_index_info(il.name) AS ii "
1596         "WHERE m.type='table' AND m.name='" + oriTableName + "' AND il.origin='c' "
1597         "GROUP BY il.name;";
1598     sqlite3_stmt *stmt = nullptr;
1599     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1600     if (errCode != E_OK) {
1601         LOGE("Prepare the clone sql failed:%d", errCode);
1602         return errCode;
1603     }
1604 
1605     std::vector<std::string> indexes;
1606     while (true) {
1607         errCode = SQLiteUtils::StepWithRetry(stmt, false);
1608         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1609             std::string indexSql;
1610             (void)GetColumnTextValue(stmt, 0, indexSql);
1611             indexes.emplace_back(indexSql);
1612             continue;
1613         }
1614         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1615             errCode = E_OK;
1616         }
1617         (void)ResetStatement(stmt, true, errCode);
1618         break;
1619     }
1620 
1621     if (errCode != E_OK) {
1622         return errCode;
1623     }
1624 
1625     for (const auto &it : indexes) {
1626         errCode = SQLiteUtils::ExecuteRawSQL(db, it);
1627         if (errCode != E_OK) {
1628             LOGE("[SQLite] execute clone index sql failed");
1629         }
1630     }
1631     return errCode;
1632 }
1633 
GetRelationalSchema(sqlite3 * db,std::string & schema,const std::string & key)1634 int SQLiteUtils::GetRelationalSchema(sqlite3 *db, std::string &schema, const std::string &key)
1635 {
1636     if (db == nullptr) {
1637         return -E_INVALID_DB;
1638     }
1639 
1640     sqlite3_stmt *statement = nullptr;
1641     std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1642     int errCode = GetStatement(db, sql, statement);
1643     if (errCode != E_OK) {
1644         return errCode;
1645     }
1646 
1647     Key schemakey;
1648     DBCommon::StringToVector(key, schemakey);
1649     errCode = BindBlobToStatement(statement, 1, schemakey, false);
1650     if (errCode != E_OK) {
1651         ResetStatement(statement, true, errCode);
1652         return errCode;
1653     }
1654 
1655     errCode = StepWithRetry(statement);
1656     if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1657         ResetStatement(statement, true, errCode);
1658         return -E_NOT_FOUND;
1659     } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1660         ResetStatement(statement, true, errCode);
1661         return errCode;
1662     }
1663 
1664     Value schemaValue;
1665     errCode = GetColumnBlobValue(statement, 0, schemaValue);
1666     if (errCode != E_OK) {
1667         ResetStatement(statement, true, errCode);
1668         return errCode;
1669     }
1670     DBCommon::VectorToString(schemaValue, schema);
1671     ResetStatement(statement, true, errCode);
1672     return errCode;
1673 }
1674 
GetLogTableVersion(sqlite3 * db,std::string & version)1675 int SQLiteUtils::GetLogTableVersion(sqlite3 *db, std::string &version)
1676 {
1677     if (db == nullptr) {
1678         return -E_INVALID_DB;
1679     }
1680 
1681     sqlite3_stmt *statement = nullptr;
1682     std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1683     int errCode = GetStatement(db, sql, statement);
1684     if (errCode != E_OK) {
1685         return errCode;
1686     }
1687 
1688     Key logTableKey;
1689     DBCommon::StringToVector(DBConstant::LOG_TABLE_VERSION_KEY, logTableKey);
1690     errCode = BindBlobToStatement(statement, 1, logTableKey, false);
1691     if (errCode != E_OK) {
1692         ResetStatement(statement, true, errCode);
1693         return errCode;
1694     }
1695 
1696     errCode = StepWithRetry(statement);
1697     if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1698         ResetStatement(statement, true, errCode);
1699         return -E_NOT_FOUND;
1700     } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1701         ResetStatement(statement, true, errCode);
1702         return errCode;
1703     }
1704 
1705     Value value;
1706     errCode = GetColumnBlobValue(statement, 0, value);
1707     if (errCode != E_OK) {
1708         ResetStatement(statement, true, errCode);
1709         return errCode;
1710     }
1711     DBCommon::VectorToString(value, version);
1712     ResetStatement(statement, true, errCode);
1713     return errCode;
1714 }
1715 
RegisterFunction(sqlite3 * db,const std::string & funcName,int nArg,void * uData,TransactFunc & func)1716 int SQLiteUtils::RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func)
1717 {
1718     if (db == nullptr) {
1719         LOGE("Sqlite DB not exists.");
1720         return -E_INVALID_DB;
1721     }
1722 
1723     int errCode = sqlite3_create_function_v2(db, funcName.c_str(), nArg, SQLITE_UTF8 | SQLITE_DETERMINISTIC, uData,
1724         func.xFunc, func.xStep, func.xFinal, func.xDestroy);
1725     if (errCode != SQLITE_OK) {
1726         LOGE("sqlite3_create_function_v2 about [%s] returned %d", funcName.c_str(), errCode);
1727         return MapSQLiteErrno(errCode);
1728     }
1729     return E_OK;
1730 }
1731 #endif
RegisterFlatBufferFunction(sqlite3 * db,const std::string & inSchema)1732 int SQLiteUtils::RegisterFlatBufferFunction(sqlite3 *db, const std::string &inSchema)
1733 {
1734     if (db == nullptr) {
1735         LOGE("Sqlite DB not exists.");
1736         return -E_INVALID_DB;
1737     }
1738     auto heapSchemaObj = new (std::nothrow) SchemaObject;
1739     if (heapSchemaObj == nullptr) {
1740         return -E_OUT_OF_MEMORY;
1741     }
1742     int errCode = heapSchemaObj->ParseFromSchemaString(inSchema);
1743     if (errCode != E_OK) { // Unlikely, it has been parsed before
1744         delete heapSchemaObj;
1745         heapSchemaObj = nullptr;
1746         return -E_INTERNAL_ERROR;
1747     }
1748     if (heapSchemaObj->GetSchemaType() != SchemaType::FLATBUFFER) { // Do not need to register FlatBufferExtract
1749         delete heapSchemaObj;
1750         heapSchemaObj = nullptr;
1751         return E_OK;
1752     }
1753     errCode = sqlite3_create_function_v2(db, SchemaObject::GetExtractFuncName(SchemaType::FLATBUFFER).c_str(),
1754         3, SQLITE_UTF8 | SQLITE_DETERMINISTIC, heapSchemaObj, &FlatBufferExtractByPath, nullptr, nullptr, // 3 args
1755         reinterpret_cast<void(*)(void*)>(SchemaObjectDestructor));
1756     // About the release of heapSchemaObj: SQLite guarantee that at following case, sqlite will invoke the destructor
1757     // (that is SchemaObjectDestructor) we passed to it. See sqlite.org for more information.
1758     // The destructor is invoked when the function is deleted, either by being overloaded or when the database
1759     // connection closes. The destructor is also invoked if the call to sqlite3_create_function_v2() fails
1760     if (errCode != SQLITE_OK) {
1761         LOGE("sqlite3_create_function_v2 about flatbuffer_extract_by_path return=%d.", errCode);
1762         // As mentioned above, SQLite had invoked the SchemaObjectDestructor to release the heapSchemaObj
1763         return MapSQLiteErrno(errCode);
1764     }
1765     return E_OK;
1766 }
1767 
UpdateMetaDataWithinTrigger(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1768 void SQLiteUtils::UpdateMetaDataWithinTrigger(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1769 {
1770     if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 : Number of parameters for sqlite register function
1771         LOGE("[UpdateMetaDataWithinTrigger] Invalid parameter, argc=%d.", argc);
1772         return;
1773     }
1774     auto *handle = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1775     if (handle == nullptr) {
1776         sqlite3_result_error(ctx, "Sqlite context is invalid.", USING_STR_LEN);
1777         LOGE("Sqlite context is invalid.");
1778         return;
1779     }
1780     auto *keyPtr = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0])); // 0 : first argv for key
1781     int keyLen = sqlite3_value_bytes(argv[0]); // 0 : first argv for key
1782     if (keyPtr == nullptr || keyLen <= 0 || keyLen > static_cast<int>(DBConstant::MAX_KEY_SIZE)) {
1783         sqlite3_result_error(ctx, "key is invalid.", USING_STR_LEN);
1784         LOGE("key is invalid.");
1785         return;
1786     }
1787     auto val = sqlite3_value_int64(argv[1]); // 1 : second argv for value
1788 
1789     sqlite3_stmt *stmt = nullptr;
1790     int errCode = SQLiteUtils::GetStatement(handle, UPDATE_META_SQL, stmt);
1791     if (errCode != E_OK) {
1792         sqlite3_result_error(ctx, "Get update meta_data statement failed.", USING_STR_LEN);
1793         LOGE("Get update meta_data statement failed. %d", errCode);
1794         return;
1795     }
1796 
1797     Key key(keyPtr, keyPtr + keyLen);
1798     errCode = SQLiteUtils::BindBlobToStatement(stmt, BIND_KEY_INDEX, key, false);
1799     if (errCode != E_OK) {
1800         sqlite3_result_error(ctx, "Bind key to statement failed.", USING_STR_LEN);
1801         LOGE("Bind key to statement failed. %d", errCode);
1802         goto END;
1803     }
1804 
1805     errCode = SQLiteUtils::BindInt64ToStatement(stmt, BIND_VAL_INDEX, val);
1806     if (errCode != E_OK) {
1807         sqlite3_result_error(ctx, "Bind value to statement failed.", USING_STR_LEN);
1808         LOGE("Bind value to statement failed. %d", errCode);
1809         goto END;
1810     }
1811 
1812     errCode = SQLiteUtils::StepWithRetry(stmt, false);
1813     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1814         sqlite3_result_error(ctx, "Execute the update meta_data attach failed.", USING_STR_LEN);
1815         LOGE("Execute the update meta_data attach failed. %d", errCode);
1816     }
1817 END:
1818     SQLiteUtils::ResetStatement(stmt, true, errCode);
1819 }
1820 
RegisterMetaDataUpdateFunction(sqlite3 * db)1821 int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db)
1822 {
1823     int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC.c_str(),
1824         2, // 2: argc for register function
1825         SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::UpdateMetaDataWithinTrigger, nullptr, nullptr, nullptr);
1826     if (errCode != SQLITE_OK) {
1827         LOGE("sqlite3_create_function_v2 about %s returned %d", DBConstant::UPDATE_META_FUNC.c_str(), errCode);
1828     }
1829     return SQLiteUtils::MapSQLiteErrno(errCode);
1830 }
1831 } // namespace DistributedDB
1832