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