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