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