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