• 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 BIND_KEY_INDEX = 1;
46     const int BIND_VAL_INDEX = 2;
47     const int USING_STR_LEN = -1;
48     const int HEAD_SIZE = 3;
49     const int END_SIZE = 3;
50     constexpr int MIN_SIZE = HEAD_SIZE + END_SIZE + 3;
51     const std::string REPLACE_CHAIN = "***";
52     const std::string DEFAULT_ANONYMOUS = "******";
53     const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;";
54     const std::string SYNC_MODE_FULL_SQL = "PRAGMA synchronous=FULL;";
55     const std::string USER_VERSION_SQL = "PRAGMA user_version;";
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 SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;";
59     const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;";
60     const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;";
61     const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;";
62     const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');";
63     const std::string BACK_CIPHER_CONFIG_SQL = "PRAGMA backup.codec_cipher=";
64     const std::string BACK_KDF_ITER_CONFIG_SQL = "PRAGMA backup.codec_kdf_iter=5000;";
65     const std::string META_CIPHER_CONFIG_SQL = "PRAGMA meta.codec_cipher=";
66     const std::string META_KDF_ITER_CONFIG_SQL = "PRAGMA meta.codec_kdf_iter=5000;";
67 
68     const constexpr char *DETACH_BACKUP_SQL = "DETACH 'backup'";
69     const constexpr char *UPDATE_META_SQL = "INSERT OR REPLACE INTO meta_data VALUES (?, ?);";
70 
71     bool g_configLog = false;
72     std::mutex g_serverChangedDataMutex;
73     std::map<std::string, std::map<std::string, DistributedDB::ChangeProperties>> g_serverChangedDataMap;
74 }
75 
Anonymous(const std::string & name)76 std::string SQLiteUtils::Anonymous(const std::string &name)
77 {
78     if (name.length() <= HEAD_SIZE) {
79         return DEFAULT_ANONYMOUS;
80     }
81 
82     if (name.length() < MIN_SIZE) {
83         return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN);
84     }
85 
86     return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE));
87 }
88 
IsNeedSkipLog(const unsigned int errType,const char * msg)89 bool IsNeedSkipLog(const unsigned int errType, const char *msg)
90 {
91     return errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr;
92 }
93 
SqliteLogCallback(void * data,int err,const char * msg)94 void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg)
95 {
96     bool verboseLog = (data != nullptr);
97     auto errType = static_cast<unsigned int>(err);
98     bool isWarningDump = errType == (SQLITE_WARNING | (2 << 8)); // SQLITE_WARNING_DUMP
99     std::string logMsg = msg == nullptr ? "NULL" : msg;
100     errType &= 0xFF;
101     if (IsNeedSkipLog(errType, logMsg.c_str())) {
102         return;
103     }
104     if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA ||
105         errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) {
106         if (verboseLog) {
107             LOGD("[SQLite] Error[%d] sys[%d] %s ", err, errno, sqlite3_errstr(err));
108         }
109     } else if ((errType == SQLITE_WARNING && !isWarningDump) ||
110         errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) {
111         LOGI("[SQLite] Error[%d], sys[%d], %s, msg: %s ", err, errno,
112             sqlite3_errstr(err), SQLiteUtils::Anonymous(logMsg).c_str());
113     } else {
114         LOGE("[SQLite] Error[%d], sys[%d], msg: %s ", err, errno, logMsg.c_str());
115         return;
116     }
117 
118     const char *errMsg = sqlite3_errstr(err);
119     std::lock_guard<std::mutex> autoLock(logMutex_);
120     if (errMsg != nullptr) {
121         lastErrorMsg_ = std::string(errMsg);
122     }
123 }
124 
CreateDataBase(const OpenDbProperties & properties,sqlite3 * & dbTemp,bool setWal)125 int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal)
126 {
127     uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
128     if (properties.createIfNecessary) {
129         flag |= SQLITE_OPEN_CREATE;
130     }
131     std::string cipherName = GetCipherName(properties.cipherType);
132     if (cipherName.empty()) {
133         LOGE("[SQLite] GetCipherName failed");
134         return -E_INVALID_ARGS;
135     }
136     std::string defaultAttachCipher = DEFAULT_ATTACH_CIPHER + cipherName + ";";
137     std::vector<std::string> sqls {defaultAttachCipher, DEFAULT_ATTACH_KDF_ITER};
138     if (setWal) {
139         sqls.push_back(WAL_MODE_SQL);
140     }
141     std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
142     int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, flag, nullptr);
143     if (errCode != SQLITE_OK) {
144         LOGE("[SQLite] open database failed: %d - sys err(%d)", errCode, errno);
145         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
146         goto END;
147     }
148 
149     errCode = SetDataBaseProperty(dbTemp, properties, setWal, sqls);
150     if (errCode != SQLITE_OK) {
151         LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode);
152         goto END;
153     }
154 
155 END:
156     if (errCode != E_OK && dbTemp != nullptr) {
157         (void)sqlite3_close_v2(dbTemp);
158         dbTemp = nullptr;
159     }
160 
161     return errCode;
162 }
163 
OpenDatabase(const OpenDbProperties & properties,sqlite3 * & db,bool setWal)164 int SQLiteUtils::OpenDatabase(const OpenDbProperties &properties, sqlite3 *&db, bool setWal)
165 {
166     {
167         // Only for register the sqlite3 log callback
168         std::lock_guard<std::mutex> lock(logMutex_);
169         if (!g_configLog) {
170             sqlite3_config(SQLITE_CONFIG_LOG, &SqliteLogCallback, &properties.createIfNecessary);
171             sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
172             g_configLog = true;
173         }
174     }
175     sqlite3 *dbTemp = nullptr;
176     int errCode = CreateDataBase(properties, dbTemp, setWal);
177     if (errCode != E_OK) {
178         goto END;
179     }
180     errCode = RegisterJsonFunctions(dbTemp);
181     if (errCode != E_OK) {
182         goto END;
183     }
184     // Set the synchroized mode, default for full mode.
185     errCode = ExecuteRawSQL(dbTemp, SYNC_MODE_FULL_SQL);
186     if (errCode != E_OK) {
187         LOGE("SQLite sync mode failed: %d", errCode);
188         goto END;
189     }
190 
191     if (!properties.isMemDb) {
192         errCode = SQLiteUtils::SetPersistWalMode(dbTemp);
193         if (errCode != E_OK) {
194             LOGE("SQLite set persist wall mode failed: %d", errCode);
195         }
196     }
197 
198 END:
199     if (errCode != E_OK && dbTemp != nullptr) {
200         (void)sqlite3_close_v2(dbTemp);
201         dbTemp = nullptr;
202     }
203     if (errCode != E_OK && errno == EKEYREVOKED) {
204         errCode = -E_EKEYREVOKED;
205     }
206     db = dbTemp;
207     return errCode;
208 }
209 
BindPrefixKey(sqlite3_stmt * statement,int index,const Key & keyPrefix)210 int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &keyPrefix)
211 {
212     if (statement == nullptr) {
213         return -E_INVALID_ARGS;
214     }
215 
216     const size_t maxKeySize = DBConstant::MAX_KEY_SIZE;
217     // bind the first prefix key
218     int errCode = BindBlobToStatement(statement, index, keyPrefix, true);
219     if (errCode != SQLITE_OK) {
220         LOGE("Bind the prefix first error:%d", errCode);
221         return SQLiteUtils::MapSQLiteErrno(errCode);
222     }
223 
224     // bind the second prefix key
225     uint8_t end[maxKeySize];
226     errno_t status = memset_s(end, maxKeySize, UCHAR_MAX, maxKeySize); // max byte value is 0xFF.
227     if (status != EOK) {
228         LOGE("memset error:%d", status);
229         return -E_SECUREC_ERROR;
230     }
231 
232     if (!keyPrefix.empty()) {
233         status = memcpy_s(end, maxKeySize, keyPrefix.data(), keyPrefix.size());
234         if (status != EOK) {
235             LOGE("memcpy error:%d", status);
236             return -E_SECUREC_ERROR;
237         }
238     }
239 
240     // index wouldn't be too large, just add one to the first index.
241     errCode = sqlite3_bind_blob(statement, index + 1, end, maxKeySize, SQLITE_TRANSIENT);
242     if (errCode != SQLITE_OK) {
243         LOGE("Bind the prefix second error:%d", errCode);
244         return SQLiteUtils::MapSQLiteErrno(errCode);
245     }
246     return E_OK;
247 }
248 
SetKey(sqlite3 * db,CipherType type,const CipherPassword & passwd,bool setWal,uint32_t iterTimes)249 int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes)
250 {
251     if (db == nullptr) {
252         return -E_INVALID_DB;
253     }
254 
255     if (passwd.GetSize() != 0) {
256 #ifndef OMIT_ENCRYPT
257         int errCode = SetKeyInner(db, type, passwd, iterTimes);
258         if (errCode != E_OK) {
259             LOGE("[SQLiteUtils][Setkey] set keyInner failed:%d", errCode);
260             return errCode;
261         }
262         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL);
263         if (errCode != E_OK) {
264             LOGE("[SQLiteUtils][Setkey] set sha algo failed:%d", errCode);
265             return errCode;
266         }
267         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL);
268         if (errCode != E_OK) {
269             LOGE("[SQLiteUtils][Setkey] set rekey sha algo failed:%d", errCode);
270             return errCode;
271         }
272 #else
273         return -E_NOT_SUPPORT;
274 #endif
275     }
276 
277     // verify key
278     int errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL);
279     if (errCode != E_OK) {
280         LOGE("[SQLiteUtils][Setkey] verify version failed:%d", errCode);
281         if (errno == EKEYREVOKED) {
282             return -E_EKEYREVOKED;
283         }
284         if (errCode == -E_BUSY) {
285             return errCode;
286         }
287 #ifndef OMIT_ENCRYPT
288         if (passwd.GetSize() != 0) {
289             errCode = UpdateCipherShaAlgo(db, setWal, type, passwd, iterTimes);
290             if (errCode != E_OK) {
291                 LOGE("[SQLiteUtils][Setkey] upgrade cipher sha algo failed:%d", errCode);
292             }
293         }
294 #endif
295     }
296     return errCode;
297 }
298 
AttachNewDatabase(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)299 int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password,
300     const std::string &attachDbAbsPath, const std::string &attachAsName)
301 {
302 #ifndef OMIT_ENCRYPT
303     int errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
304     if (errCode != E_OK) {
305         LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
306         return errCode;
307     }
308 #endif
309     errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
310 #ifndef OMIT_ENCRYPT
311     if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) {
312         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_ATTACH_SQL);
313         if (errCode != E_OK) {
314             LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha1 algo failed:%d", errCode);
315             return errCode;
316         }
317         errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
318         if (errCode != E_OK) {
319             LOGE("[SQLiteUtils][AttachNewDatabase] attach db failed:%d", errCode);
320             return errCode;
321         }
322         errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
323         if (errCode != E_OK) {
324             LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
325         }
326     }
327 #endif
328     return errCode;
329 }
330 
AttachNewDatabaseInner(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)331 int SQLiteUtils::AttachNewDatabaseInner(sqlite3 *db, CipherType type, const CipherPassword &password,
332     const std::string &attachDbAbsPath, const std::string &attachAsName)
333 {
334     // example: "ATTACH '../new.db' AS backup KEY XXXX;"
335     std::string attachSql = "ATTACH ? AS " + attachAsName + " KEY ?;"; // Internal interface not need verify alias name
336 
337     sqlite3_stmt* statement = nullptr;
338     int errCode = SQLiteUtils::GetStatement(db, attachSql, statement);
339     if (errCode != E_OK) {
340         return errCode;
341     }
342     // 1st is name.
343     errCode = sqlite3_bind_text(statement, 1, attachDbAbsPath.c_str(), attachDbAbsPath.length(), SQLITE_TRANSIENT);
344     if (errCode != SQLITE_OK) {
345         LOGE("Bind the attached db name failed:%d", errCode);
346         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
347         goto END;
348     }
349     // Passwords do not allow vector operations, so we can not use function BindBlobToStatement here.
350     errCode = sqlite3_bind_blob(statement, 2, static_cast<const void *>(password.GetData()),  // 2 means password index.
351         password.GetSize(), SQLITE_TRANSIENT);
352     if (errCode != SQLITE_OK) {
353         LOGE("Bind the attached key failed:%d", errCode);
354         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
355         goto END;
356     }
357 
358     errCode = SQLiteUtils::StepWithRetry(statement);
359     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
360         LOGE("Execute the SQLite attach failed:%d", errCode);
361         goto END;
362     }
363     errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL);
364     if (errCode != E_OK) {
365         LOGE("Set journal mode failed: %d", errCode);
366     }
367 
368 END:
369     int ret = E_OK;
370     SQLiteUtils::ResetStatement(statement, true, ret);
371     return errCode != E_OK ? errCode : ret;
372 }
373 
CreateMetaDatabase(const std::string & metaDbPath)374 int SQLiteUtils::CreateMetaDatabase(const std::string &metaDbPath)
375 {
376     OpenDbProperties metaProperties {metaDbPath, true, false};
377     sqlite3 *db = nullptr;
378     int errCode = SQLiteUtils::OpenDatabase(metaProperties, db);
379     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
380         LOGE("[CreateMetaDatabase] Failed to create the meta database[%d]", errCode);
381     }
382     if (db != nullptr) { // LCOV_EXCL_BR_LINE
383         (void)sqlite3_close_v2(db);
384         db = nullptr;
385     }
386     return errCode;
387 }
388 
CheckIntegrity(const std::string & dbFile,CipherType type,const CipherPassword & passwd)389 int SQLiteUtils::CheckIntegrity(const std::string &dbFile, CipherType type, const CipherPassword &passwd)
390 {
391     std::vector<std::string> createTableSqls;
392     OpenDbProperties option = {dbFile, true, false, createTableSqls, type, passwd};
393     sqlite3 *db = nullptr;
394     int errCode = SQLiteUtils::OpenDatabase(option, db);
395     if (errCode != E_OK) {
396         LOGE("CheckIntegrity, open db error:%d", errCode);
397         return errCode;
398     }
399     errCode = CheckIntegrity(db, CHECK_DB_INTEGRITY_SQL);
400     if (db != nullptr) {
401         (void)sqlite3_close_v2(db);
402         db = nullptr;
403     }
404     return errCode;
405 }
406 
CheckIntegrity(sqlite3 * db,const std::string & sql)407 int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql)
408 {
409     sqlite3_stmt *statement = nullptr;
410     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
411     if (errCode != E_OK) {
412         LOGE("Prepare the integrity check statement error:%d", errCode);
413         return errCode;
414     }
415     int resultCnt = 0;
416     bool checkResultOK = false;
417     do {
418         errCode = SQLiteUtils::StepWithRetry(statement);
419         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
420             break;
421         } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
422             auto result = reinterpret_cast<const char *>(sqlite3_column_text(statement, 0));
423             if (result == nullptr) {
424                 continue;
425             }
426             resultCnt = (resultCnt > 1) ? resultCnt : (resultCnt + 1);
427             if (strcmp(result, "ok") == 0) {
428                 checkResultOK = true;
429             }
430         } else {
431             checkResultOK = false;
432             LOGW("Step for the integrity check failed:%d", errCode);
433             break;
434         }
435     } while (true);
436     if (resultCnt == 1 && checkResultOK) {
437         errCode = E_OK;
438     } else {
439         errCode = -E_INVALID_PASSWD_OR_CORRUPTED_DB;
440     }
441     int ret = E_OK;
442     SQLiteUtils::ResetStatement(statement, true, ret);
443     return errCode != E_OK ? errCode : ret;
444 }
445 
446 #ifndef OMIT_ENCRYPT
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)447 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
448     const std::string &newDbName)
449 {
450     if (db == nullptr) {
451         return -E_INVALID_DB;
452     }
453 
454     int errCode = AttachNewDatabase(db, type, passwd, newDbName);
455     if (errCode != E_OK) {
456         LOGE("Attach New Db fail!");
457         return errCode;
458     }
459     errCode = SQLiteUtils::ExecuteRawSQL(db, EXPORT_BACKUP_SQL);
460     if (errCode != E_OK) {
461         LOGE("Execute the SQLite export failed:%d", errCode);
462     }
463 
464     int detachError = SQLiteUtils::ExecuteRawSQL(db, DETACH_BACKUP_SQL);
465     if (errCode == E_OK) {
466         errCode = detachError;
467         if (detachError != E_OK) {
468             LOGE("Execute the SQLite detach failed:%d", errCode);
469         }
470     }
471     return errCode;
472 }
473 
Rekey(sqlite3 * db,const CipherPassword & passwd)474 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
475 {
476     if (db == nullptr) {
477         return -E_INVALID_DB;
478     }
479 
480     int errCode = sqlite3_rekey(db, static_cast<const void *>(passwd.GetData()), static_cast<int>(passwd.GetSize()));
481     if (errCode != E_OK) {
482         LOGE("SQLite rekey failed:(%d)", errCode);
483         return SQLiteUtils::MapSQLiteErrno(errCode);
484     }
485 
486     return E_OK;
487 }
488 #else
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)489 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
490     const std::string &newDbName)
491 {
492     (void)db;
493     (void)type;
494     (void)passwd;
495     (void)newDbName;
496     return -E_NOT_SUPPORT;
497 }
498 
Rekey(sqlite3 * db,const CipherPassword & passwd)499 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
500 {
501     (void)db;
502     (void)passwd;
503     return -E_NOT_SUPPORT;
504 }
505 #endif
506 
GetVersion(const OpenDbProperties & properties,int & version)507 int SQLiteUtils::GetVersion(const OpenDbProperties &properties, int &version)
508 {
509     if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
510         return -E_INVALID_ARGS;
511     }
512 
513     sqlite3 *dbTemp = nullptr;
514     // Please make sure the database file exists and is working properly
515     std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
516     int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, SQLITE_OPEN_URI | SQLITE_OPEN_READONLY, nullptr);
517     if (errCode != SQLITE_OK) { // LCOV_EXCL_BR_LINE
518         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
519         LOGE("Open database failed: %d, sys:%d", errCode, errno);
520         goto END;
521     }
522     // in memory mode no need cipher
523     if (!properties.isMemDb) { // LCOV_EXCL_BR_LINE
524         errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, false,
525             properties.iterTimes);
526         if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
527             LOGE("Set key failed: %d", errCode);
528             goto END;
529         }
530     }
531 
532     errCode = GetVersion(dbTemp, version);
533 
534 END:
535     if (dbTemp != nullptr) { // LCOV_EXCL_BR_LINE
536         (void)sqlite3_close_v2(dbTemp);
537         dbTemp = nullptr;
538     }
539     return errCode;
540 }
541 
GetVersion(sqlite3 * db,int & version)542 int SQLiteUtils::GetVersion(sqlite3 *db, int &version)
543 {
544     if (db == nullptr) {
545         return -E_INVALID_DB;
546     }
547 
548     std::string strSql = "PRAGMA user_version;";
549     sqlite3_stmt *statement = nullptr;
550     int errCode = sqlite3_prepare(db, strSql.c_str(), -1, &statement, nullptr);
551     if (errCode != SQLITE_OK || statement == nullptr) {
552         LOGE("[SqlUtil][GetVer] sqlite3_prepare failed.");
553         errCode = SQLiteUtils::MapSQLiteErrno(errCode);
554         return errCode;
555     }
556     int ret = E_OK;
557     errCode = sqlite3_step(statement);
558     if (errCode == SQLITE_ROW) {
559         // Get pragma user_version at first column
560         version = sqlite3_column_int(statement, 0);
561     } else {
562         LOGE("[SqlUtil][GetVer] Get db user_version failed.");
563         ret = SQLiteUtils::MapSQLiteErrno(errCode);
564     }
565     errCode = E_OK;
566     SQLiteUtils::ResetStatement(statement, true, errCode);
567     return ret != E_OK ? ret : errCode;
568 }
569 
GetJournalMode(sqlite3 * db,std::string & mode)570 int SQLiteUtils::GetJournalMode(sqlite3 *db, std::string &mode)
571 {
572     if (db == nullptr) {
573         return -E_INVALID_DB;
574     }
575 
576     std::string sql = "PRAGMA journal_mode;";
577     sqlite3_stmt *statement = nullptr;
578     int errCode = SQLiteUtils::GetStatement(db, sql, statement);
579     if (errCode != E_OK || statement == nullptr) {
580         return errCode;
581     }
582 
583     errCode = SQLiteUtils::StepWithRetry(statement);
584     if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
585         errCode = SQLiteUtils::GetColumnTextValue(statement, 0, mode);
586     } else {
587         LOGE("[SqlUtil][GetJournal] Get db journal_mode failed.");
588     }
589 
590     int ret = E_OK;
591     SQLiteUtils::ResetStatement(statement, true, ret);
592     return errCode != E_OK ? errCode : ret;
593 }
594 
SetUserVer(const OpenDbProperties & properties,int version)595 int SQLiteUtils::SetUserVer(const OpenDbProperties &properties, int version)
596 {
597     if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
598         return -E_INVALID_ARGS;
599     }
600 
601     // Please make sure the database file exists and is working properly
602     sqlite3 *db = nullptr;
603     int errCode = SQLiteUtils::OpenDatabase(properties, db);
604     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
605         return errCode;
606     }
607 
608     // Set user version
609     errCode = SQLiteUtils::SetUserVer(db, version);
610     if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
611         LOGE("Set user version fail: %d", errCode);
612         goto END;
613     }
614 
615 END:
616     if (db != nullptr) { // LCOV_EXCL_BR_LINE
617         (void)sqlite3_close_v2(db);
618         db = nullptr;
619     }
620 
621     return errCode;
622 }
623 
SetUserVer(sqlite3 * db,int version)624 int SQLiteUtils::SetUserVer(sqlite3 *db, int version)
625 {
626     if (db == nullptr) {
627         return -E_INVALID_DB;
628     }
629     std::string userVersionSql = "PRAGMA user_version=" + std::to_string(version) + ";";
630     return SQLiteUtils::ExecuteRawSQL(db, userVersionSql);
631 }
632 
SetBusyTimeout(sqlite3 * db,int timeout)633 int SQLiteUtils::SetBusyTimeout(sqlite3 *db, int timeout)
634 {
635     if (db == nullptr) {
636         return -E_INVALID_DB;
637     }
638 
639     // Set the default busy handler to retry automatically before returning SQLITE_BUSY.
640     int errCode = sqlite3_busy_timeout(db, timeout);
641     if (errCode != SQLITE_OK) {
642         LOGE("[SQLite] set busy timeout failed:%d", errCode);
643     }
644 
645     return SQLiteUtils::MapSQLiteErrno(errCode);
646 }
647 
648 #ifndef OMIT_ENCRYPT
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)649 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
650     const std::string &targetFile, const CipherPassword &passwd)
651 {
652     std::vector<std::string> createTableSqls;
653     OpenDbProperties option = {srcFile, true, false, createTableSqls, type, srcPasswd};
654     sqlite3 *db = nullptr;
655     int errCode = SQLiteUtils::OpenDatabase(option, db);
656     if (errCode != E_OK) {
657         LOGE("Open db error while exporting:%d", errCode);
658         return errCode;
659     }
660 
661     errCode = SQLiteUtils::ExportDatabase(db, type, passwd, targetFile);
662     if (db != nullptr) {
663         (void)sqlite3_close_v2(db);
664         db = nullptr;
665     }
666     return errCode;
667 }
668 #else
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)669 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
670     const std::string &targetFile, const CipherPassword &passwd)
671 {
672     (void)srcFile;
673     (void)type;
674     (void)srcPasswd;
675     (void)targetFile;
676     (void)passwd;
677     return -E_NOT_SUPPORT;
678 }
679 #endif
680 
SaveSchema(sqlite3 * db,const std::string & strSchema)681 int SQLiteUtils::SaveSchema(sqlite3 *db, const std::string &strSchema)
682 {
683     if (db == nullptr) {
684         return -E_INVALID_DB;
685     }
686 
687     sqlite3_stmt *statement = nullptr;
688     std::string sql = "INSERT OR REPLACE INTO meta_data VALUES(?,?);";
689     int errCode = GetStatement(db, sql, statement);
690     if (errCode != E_OK) {
691         return errCode;
692     }
693 
694     Key schemaKey;
695     DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemaKey);
696     errCode = BindBlobToStatement(statement, BIND_KEY_INDEX, schemaKey, false);
697     if (errCode != E_OK) {
698         ResetStatement(statement, true, errCode);
699         return errCode;
700     }
701 
702     Value schemaValue;
703     DBCommon::StringToVector(strSchema, schemaValue);
704     errCode = BindBlobToStatement(statement, BIND_VAL_INDEX, schemaValue, false);
705     if (errCode != E_OK) {
706         ResetStatement(statement, true, errCode);
707         return errCode;
708     }
709 
710     errCode = StepWithRetry(statement); // memory db does not support schema
711     if (errCode != MapSQLiteErrno(SQLITE_DONE)) {
712         LOGE("[SqlUtil][SetSchema] StepWithRetry fail, errCode=%d.", errCode);
713         ResetStatement(statement, true, errCode);
714         return errCode;
715     }
716     errCode = E_OK;
717     ResetStatement(statement, true, errCode);
718     return errCode;
719 }
720 
GetSchema(sqlite3 * db,std::string & strSchema)721 int SQLiteUtils::GetSchema(sqlite3 *db, std::string &strSchema)
722 {
723     if (db == nullptr) {
724         return -E_INVALID_DB;
725     }
726 
727     bool isExists = false;
728     int errCode = CheckTableExists(db, "meta_data", isExists);
729     if (errCode != E_OK || !isExists) {
730         LOGW("[GetSchema] err=%d, meta=%d", errCode, isExists);
731         return errCode;
732     }
733 
734     sqlite3_stmt *statement = nullptr;
735     std::string sql = "SELECT value FROM meta_data WHERE key=?;";
736     errCode = GetStatement(db, sql, statement);
737     if (errCode != E_OK) {
738         return errCode;
739     }
740 
741     Key schemakey;
742     DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemakey);
743     errCode = BindBlobToStatement(statement, 1, schemakey, false);
744     if (errCode != E_OK) {
745         ResetStatement(statement, true, errCode);
746         return errCode;
747     }
748 
749     errCode = StepWithRetry(statement); // memory db does not support schema
750     if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
751         ResetStatement(statement, true, errCode);
752         return -E_NOT_FOUND;
753     } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
754         ResetStatement(statement, true, errCode);
755         return errCode;
756     }
757 
758     Value schemaValue;
759     errCode = GetColumnBlobValue(statement, 0, schemaValue);
760     if (errCode != E_OK) {
761         ResetStatement(statement, true, errCode);
762         return errCode;
763     }
764     DBCommon::VectorToString(schemaValue, strSchema);
765     ResetStatement(statement, true, errCode);
766     return errCode;
767 }
768 
IncreaseIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)769 int SQLiteUtils::IncreaseIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
770     uint32_t skipSize)
771 {
772     if (db == nullptr) {
773         LOGE("[IncreaseIndex] Sqlite DB not exists.");
774         return -E_INVALID_DB;
775     }
776     if (name.empty() || info.empty()) {
777         LOGE("[IncreaseIndex] Name or info can not be empty.");
778         return -E_NOT_PERMIT;
779     }
780     std::string indexName = SchemaUtils::FieldPathString(name);
781     std::string sqlCommand = "CREATE INDEX IF NOT EXISTS '" + indexName + "' ON sync_data (";
782     for (uint32_t i = 0; i < info.size(); i++) {
783         if (i != 0) {
784             sqlCommand += ", ";
785         }
786         std::string extractSql = SchemaObject::GenerateExtractSQL(type, info[i].first, info[i].second,
787             skipSize);
788         if (extractSql.empty()) { // Unlikely
789             LOGE("[IncreaseIndex] GenerateExtractSQL fail at field=%u.", i);
790             return -E_INTERNAL_ERROR;
791         }
792         sqlCommand += extractSql;
793     }
794     sqlCommand += ") WHERE (flag&0x01=0);";
795     return SQLiteUtils::ExecuteRawSQL(db, sqlCommand);
796 }
797 
ChangeIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)798 int SQLiteUtils::ChangeIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
799     uint32_t skipSize)
800 {
801     // Currently we change index by drop it then create it, SQLite "REINDEX" may be used in the future
802     int errCode = DecreaseIndex(db, name);
803     if (errCode != E_OK) {
804         LOGE("[ChangeIndex] Decrease fail=%d.", errCode);
805         return errCode;
806     }
807     errCode = IncreaseIndex(db, name, info, type, skipSize);
808     if (errCode != E_OK) {
809         LOGE("[ChangeIndex] Increase fail=%d.", errCode);
810         return errCode;
811     }
812     return E_OK;
813 }
814 
DecreaseIndex(sqlite3 * db,const IndexName & name)815 int SQLiteUtils::DecreaseIndex(sqlite3 *db, const IndexName &name)
816 {
817     if (db == nullptr) {
818         LOGE("[DecreaseIndex] Sqlite DB not exists.");
819         return -E_INVALID_DB;
820     }
821     if (name.empty()) {
822         LOGE("[DecreaseIndex] Name can not be empty.");
823         return -E_NOT_PERMIT;
824     }
825     std::string indexName = SchemaUtils::FieldPathString(name);
826     std::string sqlCommand = "DROP INDEX IF EXISTS '" + indexName + "';";
827     return ExecuteRawSQL(db, sqlCommand);
828 }
829 
RegisterJsonFunctions(sqlite3 * db)830 int SQLiteUtils::RegisterJsonFunctions(sqlite3 *db)
831 {
832     if (db == nullptr) {
833         LOGE("Sqlite DB not exists.");
834         return -E_INVALID_DB;
835     }
836     int errCode = sqlite3_create_function_v2(db, "calc_hash_key", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
837         nullptr, &CalcHashKey, nullptr, nullptr, nullptr);
838     if (errCode != SQLITE_OK) {
839         LOGE("sqlite3_create_function_v2 about calc_hash_key returned %d", errCode);
840         return MapSQLiteErrno(errCode);
841     }
842 #ifdef USING_DB_JSON_EXTRACT_AUTOMATICALLY
843     // Specify need 3 parameter in json_extract_by_path function
844     errCode = sqlite3_create_function_v2(db, "json_extract_by_path", 3, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
845         nullptr, &JsonExtractByPath, nullptr, nullptr, nullptr);
846     if (errCode != SQLITE_OK) {
847         LOGE("sqlite3_create_function_v2 about json_extract_by_path returned %d", errCode);
848         return MapSQLiteErrno(errCode);
849     }
850 #endif
851     return E_OK;
852 }
853 
854 namespace {
SchemaObjectDestructor(SchemaObject * inObject)855 void SchemaObjectDestructor(SchemaObject *inObject)
856 {
857     delete inObject;
858     inObject = nullptr;
859 }
860 }
861 #ifdef RELATIONAL_STORE
RegisterCalcHash(sqlite3 * db)862 int SQLiteUtils::RegisterCalcHash(sqlite3 *db)
863 {
864     TransactFunc func;
865     func.xFunc = &CalcHash;
866     return SQLiteUtils::RegisterFunction(db, "calc_hash", 2, nullptr, func); // 2 is params count
867 }
868 
GetSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)869 void SQLiteUtils::GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
870 {
871     if (ctx == nullptr || argc != 1 || argv == nullptr) {
872         LOGE("Parameter does not meet restrictions.");
873         return;
874     }
875 
876     sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
877 }
878 
GetRawSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)879 void SQLiteUtils::GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
880 {
881     if (ctx == nullptr || argc != 0 || argv == nullptr) {
882         LOGE("Parameter does not meet restrictions.");
883         return;
884     }
885 
886     uint64_t curTime = 0;
887     int errCode = TimeHelper::GetSysCurrentRawTime(curTime);
888     if (errCode != E_OK) {
889         sqlite3_result_error(ctx, "get raw sys time failed in sqlite utils.", errCode);
890         return;
891     }
892     sqlite3_result_int64(ctx, (sqlite3_int64)(curTime));
893 }
894 
GetLastTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)895 void SQLiteUtils::GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
896 {
897     if (ctx == nullptr || argc != 0 || argv == nullptr) { // LCOV_EXCL_BR_LINE
898         LOGE("Parameter does not meet restrictions.");
899         return;
900     }
901     // Never used internally, just for sql prepare
902     sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
903 }
904 
CloudDataChangedObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)905 void SQLiteUtils::CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
906 {
907     if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts
908         return;
909     }
910     sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
911 }
912 
CloudDataChangedServerObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)913 void SQLiteUtils::CloudDataChangedServerObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
914 {
915     if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is param counts
916         return;
917     }
918     sqlite3 *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
919     std::string fileName;
920     if (!SQLiteRelationalUtils::GetDbFileName(db, fileName)) {
921         return;
922     }
923     auto tableNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
924     if (tableNameChar == nullptr) {
925         return;
926     }
927     std::string tableName = static_cast<std::string>(tableNameChar);
928 
929     uint64_t isTrackerChange = static_cast<uint64_t>(sqlite3_value_int(argv[1])); // 1 is param index
930     LOGD("Cloud data changed, server observer callback %u", isTrackerChange);
931     {
932         std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
933         auto itTable = g_serverChangedDataMap[fileName].find(tableName);
934         if (itTable != g_serverChangedDataMap[fileName].end()) {
935             itTable->second.isTrackedDataChange =
936                 (static_cast<uint8_t>(itTable->second.isTrackedDataChange) | isTrackerChange) > 0;
937         } else {
938             DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) };
939             g_serverChangedDataMap[fileName].insert_or_assign(tableName, properties);
940         }
941     }
942     sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
943 }
944 
GetAndResetServerObserverData(const std::string & dbName,const std::string & tableName,ChangeProperties & changeProperties)945 void SQLiteUtils::GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName,
946     ChangeProperties &changeProperties)
947 {
948     std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
949     auto itDb = g_serverChangedDataMap.find(dbName);
950     if (itDb != g_serverChangedDataMap.end() && !itDb->second.empty()) {
951         auto itTable = itDb->second.find(tableName);
952         if (itTable == itDb->second.end()) {
953             return;
954         }
955         changeProperties = itTable->second;
956         g_serverChangedDataMap[dbName].erase(itTable);
957     }
958 }
959 
RegisterGetSysTime(sqlite3 * db)960 int SQLiteUtils::RegisterGetSysTime(sqlite3 *db)
961 {
962     TransactFunc func;
963     func.xFunc = &GetSysTime;
964     return SQLiteUtils::RegisterFunction(db, "get_sys_time", 1, nullptr, func);
965 }
966 
RegisterGetLastTime(sqlite3 * db)967 int SQLiteUtils::RegisterGetLastTime(sqlite3 *db)
968 {
969     TransactFunc func;
970     func.xFunc = &GetLastTime;
971     return SQLiteUtils::RegisterFunction(db, "get_last_time", 0, nullptr, func);
972 }
973 
RegisterGetRawSysTime(sqlite3 * db)974 int SQLiteUtils::RegisterGetRawSysTime(sqlite3 *db)
975 {
976     TransactFunc func;
977     func.xFunc = &GetRawSysTime;
978     return SQLiteUtils::RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func);
979 }
980 
RegisterCloudDataChangeObserver(sqlite3 * db)981 int SQLiteUtils::RegisterCloudDataChangeObserver(sqlite3 *db)
982 {
983     TransactFunc func;
984     func.xFunc = &CloudDataChangedObserver;
985     return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts
986 }
987 
RegisterCloudDataChangeServerObserver(sqlite3 * db)988 int SQLiteUtils::RegisterCloudDataChangeServerObserver(sqlite3 *db)
989 {
990     TransactFunc func;
991     func.xFunc = &CloudDataChangedServerObserver;
992     return RegisterFunction(db, "server_observer", 2, db, func); // 2 is param counts
993 }
994 
CreateSameStuTable(sqlite3 * db,const TableInfo & baseTbl,const std::string & newTableName)995 int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName)
996 {
997     std::string sql = "CREATE TABLE IF NOT EXISTS '" + newTableName + "' (";
998     const FieldInfoMap &fields = baseTbl.GetFields();
999     for (uint32_t cid = 0; cid < fields.size(); ++cid) {
1000         std::string fieldName = baseTbl.GetFieldName(cid);
1001         const auto &it = fields.find(fieldName);
1002         if (it == fields.end()) {
1003             return -E_INVALID_DB;
1004         }
1005         sql += "'" + fieldName + "' '" + it->second.GetDataType() + "'";
1006         if (it->second.IsNotNull()) {
1007             sql += " NOT NULL";
1008         }
1009         if (it->second.HasDefaultValue()) {
1010             sql += " DEFAULT " + it->second.GetDefaultValue();
1011         }
1012         sql += ",";
1013     }
1014     // base table has primary key
1015     if (!(baseTbl.GetPrimaryKey().size() == 1 && baseTbl.GetPrimaryKey().at(0) == "rowid")) {
1016         sql += " PRIMARY KEY (";
1017         for (const auto &it : baseTbl.GetPrimaryKey()) {
1018             sql += "'" + it.second + "',";
1019         }
1020         sql.pop_back();
1021         sql += "),";
1022     }
1023     sql.pop_back();
1024     sql += ");";
1025     int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
1026     if (errCode != E_OK) {
1027         LOGE("[SQLite] execute create table sql failed");
1028     }
1029     return errCode;
1030 }
1031 
CloneIndexes(sqlite3 * db,const std::string & oriTableName,const std::string & newTableName)1032 int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName)
1033 {
1034     std::string sql =
1035         "SELECT 'CREATE ' || CASE WHEN il.'unique' THEN 'UNIQUE ' ELSE '' END || 'INDEX IF NOT EXISTS ' || '" +
1036             newTableName + "_' || il.name || ' ON ' || '" + newTableName +
1037             "' || '(' || GROUP_CONCAT(ii.name) || ');' "
1038         "FROM sqlite_master AS m,"
1039             "pragma_index_list(m.name) AS il,"
1040             "pragma_index_info(il.name) AS ii "
1041         "WHERE m.type='table' AND m.name='" + oriTableName + "' AND il.origin='c' "
1042         "GROUP BY il.name;";
1043     sqlite3_stmt *stmt = nullptr;
1044     int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1045     if (errCode != E_OK) {
1046         LOGE("Prepare the clone sql failed:%d", errCode);
1047         return errCode;
1048     }
1049 
1050     std::vector<std::string> indexes;
1051     while (true) {
1052         errCode = SQLiteUtils::StepWithRetry(stmt, false);
1053         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1054             std::string indexSql;
1055             (void)GetColumnTextValue(stmt, 0, indexSql);
1056             indexes.emplace_back(indexSql);
1057             continue;
1058         }
1059         if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1060             errCode = E_OK;
1061         }
1062         (void)ResetStatement(stmt, true, errCode);
1063         break;
1064     }
1065 
1066     if (errCode != E_OK) {
1067         return errCode;
1068     }
1069 
1070     for (const auto &it : indexes) {
1071         errCode = SQLiteUtils::ExecuteRawSQL(db, it);
1072         if (errCode != E_OK) {
1073             LOGE("[SQLite] execute clone index sql failed");
1074         }
1075     }
1076     return errCode;
1077 }
1078 
GetRelationalSchema(sqlite3 * db,std::string & schema,const std::string & key)1079 int SQLiteUtils::GetRelationalSchema(sqlite3 *db, std::string &schema, const std::string &key)
1080 {
1081     if (db == nullptr) {
1082         return -E_INVALID_DB;
1083     }
1084 
1085     sqlite3_stmt *statement = nullptr;
1086     std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1087     int errCode = GetStatement(db, sql, statement);
1088     if (errCode != E_OK) {
1089         return errCode;
1090     }
1091 
1092     Key schemakey;
1093     DBCommon::StringToVector(key, schemakey);
1094     errCode = BindBlobToStatement(statement, 1, schemakey, false);
1095     if (errCode != E_OK) {
1096         ResetStatement(statement, true, errCode);
1097         return errCode;
1098     }
1099 
1100     errCode = StepWithRetry(statement);
1101     if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1102         ResetStatement(statement, true, errCode);
1103         return -E_NOT_FOUND;
1104     } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1105         ResetStatement(statement, true, errCode);
1106         return errCode;
1107     }
1108 
1109     Value schemaValue;
1110     errCode = GetColumnBlobValue(statement, 0, schemaValue);
1111     if (errCode != E_OK) {
1112         ResetStatement(statement, true, errCode);
1113         return errCode;
1114     }
1115     DBCommon::VectorToString(schemaValue, schema);
1116     ResetStatement(statement, true, errCode);
1117     return errCode;
1118 }
1119 
GetLogTableVersion(sqlite3 * db,std::string & version)1120 int SQLiteUtils::GetLogTableVersion(sqlite3 *db, std::string &version)
1121 {
1122     if (db == nullptr) {
1123         return -E_INVALID_DB;
1124     }
1125 
1126     sqlite3_stmt *statement = nullptr;
1127     std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1128     int errCode = GetStatement(db, sql, statement);
1129     if (errCode != E_OK) {
1130         return errCode;
1131     }
1132 
1133     Key logTableKey;
1134     DBCommon::StringToVector(DBConstant::LOG_TABLE_VERSION_KEY, logTableKey);
1135     errCode = BindBlobToStatement(statement, 1, logTableKey, false);
1136     if (errCode != E_OK) {
1137         ResetStatement(statement, true, errCode);
1138         return errCode;
1139     }
1140 
1141     errCode = StepWithRetry(statement);
1142     if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1143         ResetStatement(statement, true, errCode);
1144         return -E_NOT_FOUND;
1145     } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1146         ResetStatement(statement, true, errCode);
1147         return errCode;
1148     }
1149 
1150     Value value;
1151     errCode = GetColumnBlobValue(statement, 0, value);
1152     if (errCode != E_OK) {
1153         ResetStatement(statement, true, errCode);
1154         return errCode;
1155     }
1156     DBCommon::VectorToString(value, version);
1157     ResetStatement(statement, true, errCode);
1158     return errCode;
1159 }
1160 
RegisterFunction(sqlite3 * db,const std::string & funcName,int nArg,void * uData,TransactFunc & func)1161 int SQLiteUtils::RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func)
1162 {
1163     if (db == nullptr) {
1164         LOGE("Sqlite DB not exists.");
1165         return -E_INVALID_DB;
1166     }
1167 
1168     int errCode = sqlite3_create_function_v2(db, funcName.c_str(), nArg, SQLITE_UTF8 | SQLITE_DETERMINISTIC, uData,
1169         func.xFunc, func.xStep, func.xFinal, func.xDestroy);
1170     if (errCode != SQLITE_OK) {
1171         LOGE("sqlite3_create_function_v2 about [%s] returned %d", funcName.c_str(), errCode);
1172         return MapSQLiteErrno(errCode);
1173     }
1174     return E_OK;
1175 }
1176 #endif
RegisterFlatBufferFunction(sqlite3 * db,const std::string & inSchema)1177 int SQLiteUtils::RegisterFlatBufferFunction(sqlite3 *db, const std::string &inSchema)
1178 {
1179     if (db == nullptr) {
1180         LOGE("Sqlite DB not exists.");
1181         return -E_INVALID_DB;
1182     }
1183     auto heapSchemaObj = new (std::nothrow) SchemaObject;
1184     if (heapSchemaObj == nullptr) {
1185         return -E_OUT_OF_MEMORY;
1186     }
1187     int errCode = heapSchemaObj->ParseFromSchemaString(inSchema);
1188     if (errCode != E_OK) { // Unlikely, it has been parsed before
1189         delete heapSchemaObj;
1190         heapSchemaObj = nullptr;
1191         return -E_INTERNAL_ERROR;
1192     }
1193     if (heapSchemaObj->GetSchemaType() != SchemaType::FLATBUFFER) { // Do not need to register FlatBufferExtract
1194         delete heapSchemaObj;
1195         heapSchemaObj = nullptr;
1196         return E_OK;
1197     }
1198     errCode = sqlite3_create_function_v2(db, SchemaObject::GetExtractFuncName(SchemaType::FLATBUFFER).c_str(),
1199         3, SQLITE_UTF8 | SQLITE_DETERMINISTIC, heapSchemaObj, &FlatBufferExtractByPath, nullptr, nullptr, // 3 args
1200         reinterpret_cast<void(*)(void*)>(SchemaObjectDestructor));
1201     // About the release of heapSchemaObj: SQLite guarantee that at following case, sqlite will invoke the destructor
1202     // (that is SchemaObjectDestructor) we passed to it. See sqlite.org for more information.
1203     // The destructor is invoked when the function is deleted, either by being overloaded or when the database
1204     // connection closes. The destructor is also invoked if the call to sqlite3_create_function_v2() fails
1205     if (errCode != SQLITE_OK) {
1206         LOGE("sqlite3_create_function_v2 about flatbuffer_extract_by_path return=%d.", errCode);
1207         // As mentioned above, SQLite had invoked the SchemaObjectDestructor to release the heapSchemaObj
1208         return MapSQLiteErrno(errCode);
1209     }
1210     return E_OK;
1211 }
1212 
UpdateMetaDataWithinTrigger(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1213 void SQLiteUtils::UpdateMetaDataWithinTrigger(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1214 {
1215     if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 : Number of parameters for sqlite register function
1216         LOGE("[UpdateMetaDataWithinTrigger] Invalid parameter, argc=%d.", argc);
1217         return;
1218     }
1219     auto *handle = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1220     if (handle == nullptr) {
1221         sqlite3_result_error(ctx, "Sqlite context is invalid.", USING_STR_LEN);
1222         LOGE("Sqlite context is invalid.");
1223         return;
1224     }
1225     auto *keyPtr = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0])); // 0 : first argv for key
1226     int keyLen = sqlite3_value_bytes(argv[0]); // 0 : first argv for key
1227     if (keyPtr == nullptr || keyLen <= 0 || keyLen > static_cast<int>(DBConstant::MAX_KEY_SIZE)) {
1228         sqlite3_result_error(ctx, "key is invalid.", USING_STR_LEN);
1229         LOGE("key is invalid.");
1230         return;
1231     }
1232     auto val = sqlite3_value_int64(argv[1]); // 1 : second argv for value
1233 
1234     sqlite3_stmt *stmt = nullptr;
1235     int errCode = SQLiteUtils::GetStatement(handle, UPDATE_META_SQL, stmt);
1236     if (errCode != E_OK) {
1237         sqlite3_result_error(ctx, "Get update meta_data statement failed.", USING_STR_LEN);
1238         LOGE("Get update meta_data statement failed. %d", errCode);
1239         return;
1240     }
1241 
1242     Key key(keyPtr, keyPtr + keyLen);
1243     errCode = SQLiteUtils::BindBlobToStatement(stmt, BIND_KEY_INDEX, key, false);
1244     if (errCode != E_OK) {
1245         sqlite3_result_error(ctx, "Bind key to statement failed.", USING_STR_LEN);
1246         LOGE("Bind key to statement failed. %d", errCode);
1247         goto END;
1248     }
1249 
1250     errCode = SQLiteUtils::BindInt64ToStatement(stmt, BIND_VAL_INDEX, val);
1251     if (errCode != E_OK) {
1252         sqlite3_result_error(ctx, "Bind value to statement failed.", USING_STR_LEN);
1253         LOGE("Bind value to statement failed. %d", errCode);
1254         goto END;
1255     }
1256 
1257     errCode = SQLiteUtils::StepWithRetry(stmt, false);
1258     if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1259         sqlite3_result_error(ctx, "Execute the update meta_data attach failed.", USING_STR_LEN);
1260         LOGE("Execute the update meta_data attach failed. %d", errCode);
1261     }
1262 END:
1263     SQLiteUtils::ResetStatement(stmt, true, errCode);
1264 }
1265 
RegisterMetaDataUpdateFunction(sqlite3 * db)1266 int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db)
1267 {
1268     int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC,
1269         2, // 2: argc for register function
1270         SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::UpdateMetaDataWithinTrigger, nullptr, nullptr, nullptr);
1271     if (errCode != SQLITE_OK) {
1272         LOGE("sqlite3_create_function_v2 about update_meta_within_trigger returned %d", errCode);
1273     }
1274     return SQLiteUtils::MapSQLiteErrno(errCode);
1275 }
1276 } // namespace DistributedDB
1277