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