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 #include <sys/stat.h>
26
27 #include "sqlite_import.h"
28 #include "securec.h"
29 #include "db_constant.h"
30 #include "db_common.h"
31 #include "db_errno.h"
32 #include "log_print.h"
33 #include "value_object.h"
34 #include "schema_utils.h"
35 #include "schema_constant.h"
36 #include "sqlite_single_ver_storage_executor_sql.h"
37 #include "time_helper.h"
38 #include "platform_specific.h"
39 #include "sqlite_relational_utils.h"
40
41 namespace DistributedDB {
42 std::mutex SQLiteUtils::logMutex_;
43 std::string SQLiteUtils::lastErrorMsg_;
44 namespace {
45 const int BUSY_SLEEP_TIME = 50; // sleep for 50us
46 const int NO_SIZE_LIMIT = -1;
47 const int MAX_STEP_TIMES = 8000;
48 const int BIND_KEY_INDEX = 1;
49 const int BIND_VAL_INDEX = 2;
50 const int USING_STR_LEN = -1;
51 const int MAX_BLOB_READ_SIZE = 64 * 1024 * 1024; // 64M limit
52 const int MAX_TEXT_READ_SIZE = 5 * 1024 * 1024; // 5M limit
53 const int HEAD_SIZE = 3;
54 const int END_SIZE = 3;
55 constexpr int MIN_SIZE = HEAD_SIZE + END_SIZE + 3;
56 const std::string REPLACE_CHAIN = "***";
57 const std::string DEFAULT_ANONYMOUS = "******";
58 const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;";
59 const std::string SYNC_MODE_FULL_SQL = "PRAGMA synchronous=FULL;";
60 const std::string USER_VERSION_SQL = "PRAGMA user_version;";
61 const std::string BEGIN_SQL = "BEGIN TRANSACTION";
62 const std::string BEGIN_IMMEDIATE_SQL = "BEGIN IMMEDIATE TRANSACTION";
63 const std::string COMMIT_SQL = "COMMIT TRANSACTION";
64 const std::string ROLLBACK_SQL = "ROLLBACK TRANSACTION";
65 const std::string DEFAULT_ATTACH_CIPHER = "PRAGMA cipher_default_attach_cipher=";
66 const std::string DEFAULT_ATTACH_KDF_ITER = "PRAGMA cipher_default_attach_kdf_iter=5000";
67 const std::string SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;";
68 const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;";
69 const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;";
70 const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;";
71 const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');";
72 const std::string BACK_CIPHER_CONFIG_SQL = "PRAGMA backup.codec_cipher=";
73 const std::string BACK_KDF_ITER_CONFIG_SQL = "PRAGMA backup.codec_kdf_iter=5000;";
74 const std::string META_CIPHER_CONFIG_SQL = "PRAGMA meta.codec_cipher=";
75 const std::string META_KDF_ITER_CONFIG_SQL = "PRAGMA meta.codec_kdf_iter=5000;";
76
77 const constexpr char *DETACH_BACKUP_SQL = "DETACH 'backup'";
78 const constexpr char *UPDATE_META_SQL = "INSERT OR REPLACE INTO meta_data VALUES (?, ?);";
79
80 bool g_configLog = false;
81 std::mutex g_serverChangedDataMutex;
82 std::map<std::string, std::map<std::string, DistributedDB::ChangeProperties>> g_serverChangedDataMap;
83 }
84
85 namespace TriggerMode {
86 const std::map<TriggerModeEnum, std::string> TRIGGER_MODE_MAP = {
87 {TriggerModeEnum::NONE, ""},
88 {TriggerModeEnum::INSERT, "INSERT"},
89 {TriggerModeEnum::UPDATE, "UPDATE"},
90 {TriggerModeEnum::DELETE, "DELETE"},
91 };
92
GetTriggerModeString(TriggerModeEnum mode)93 std::string GetTriggerModeString(TriggerModeEnum mode)
94 {
95 auto it = TRIGGER_MODE_MAP.find(mode);
96 return (it == TRIGGER_MODE_MAP.end()) ? "" : it->second;
97 }
98 }
99
Anonymous(const std::string & name)100 std::string SQLiteUtils::Anonymous(const std::string &name)
101 {
102 if (name.length() <= HEAD_SIZE) {
103 return DEFAULT_ANONYMOUS;
104 }
105
106 if (name.length() < MIN_SIZE) {
107 return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN);
108 }
109
110 return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE));
111 }
112
IsNeedSkipLog(const unsigned int errType,const char * msg)113 bool IsNeedSkipLog(const unsigned int errType, const char *msg)
114 {
115 return errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr;
116 }
117
SqliteLogCallback(void * data,int err,const char * msg)118 void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg)
119 {
120 bool verboseLog = (data != nullptr);
121 auto errType = static_cast<unsigned int>(err);
122 std::string logMsg = msg == nullptr ? "NULL" : msg;
123 errType &= 0xFF;
124 if (IsNeedSkipLog(errType, logMsg.c_str())) {
125 return;
126 }
127 if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA ||
128 errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) {
129 if (verboseLog) {
130 LOGD("[SQLite] Error[%d] sys[%d] %s ", err, errno, sqlite3_errstr(err));
131 }
132 } else if (errType == SQLITE_WARNING || errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) {
133 LOGI("[SQLite] Error[%d], sys[%d], %s, msg: %s ", err, errno,
134 sqlite3_errstr(err), SQLiteUtils::Anonymous(logMsg).c_str());
135 } else {
136 LOGE("[SQLite] Error[%d], sys[%d], msg: %s ", err, errno, logMsg.c_str());
137 return;
138 }
139
140 const char *errMsg = sqlite3_errstr(err);
141 std::lock_guard<std::mutex> autoLock(logMutex_);
142 if (errMsg != nullptr) {
143 lastErrorMsg_ = std::string(errMsg);
144 }
145 }
146
CreateDataBase(const OpenDbProperties & properties,sqlite3 * & dbTemp,bool setWal)147 int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal)
148 {
149 uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
150 if (properties.createIfNecessary) {
151 flag |= SQLITE_OPEN_CREATE;
152 }
153 std::string cipherName = GetCipherName(properties.cipherType);
154 if (cipherName.empty()) {
155 LOGE("[SQLite] GetCipherName failed");
156 return -E_INVALID_ARGS;
157 }
158 std::string defaultAttachCipher = DEFAULT_ATTACH_CIPHER + cipherName + ";";
159 std::vector<std::string> sqls {defaultAttachCipher, DEFAULT_ATTACH_KDF_ITER};
160 if (setWal) {
161 sqls.push_back(WAL_MODE_SQL);
162 }
163 std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
164 int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, flag, nullptr);
165 if (errCode != SQLITE_OK) {
166 LOGE("[SQLite] open database failed: %d - sys err(%d)", errCode, errno);
167 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
168 goto END;
169 }
170
171 errCode = SetDataBaseProperty(dbTemp, properties, setWal, sqls);
172 if (errCode != SQLITE_OK) {
173 LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode);
174 goto END;
175 }
176
177 END:
178 if (errCode != E_OK && dbTemp != nullptr) {
179 (void)sqlite3_close_v2(dbTemp);
180 dbTemp = nullptr;
181 }
182 struct stat curStat;
183 stat(fileUrl.c_str(), &curStat);
184 LOGI("[SQLite] open database result: %d, inode: %llu", errCode, curStat.st_ino);
185
186 return errCode;
187 }
188
OpenDatabase(const OpenDbProperties & properties,sqlite3 * & db,bool setWal)189 int SQLiteUtils::OpenDatabase(const OpenDbProperties &properties, sqlite3 *&db, bool setWal)
190 {
191 {
192 // Only for register the sqlite3 log callback
193 std::lock_guard<std::mutex> lock(logMutex_);
194 if (!g_configLog) {
195 sqlite3_config(SQLITE_CONFIG_LOG, &SqliteLogCallback, &properties.createIfNecessary);
196 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
197 g_configLog = true;
198 }
199 }
200 sqlite3 *dbTemp = nullptr;
201 int errCode = CreateDataBase(properties, dbTemp, setWal);
202 if (errCode != E_OK) {
203 goto END;
204 }
205 errCode = RegisterJsonFunctions(dbTemp);
206 if (errCode != E_OK) {
207 goto END;
208 }
209 // Set the synchroized mode, default for full mode.
210 errCode = ExecuteRawSQL(dbTemp, SYNC_MODE_FULL_SQL);
211 if (errCode != E_OK) {
212 LOGE("SQLite sync mode failed: %d", errCode);
213 goto END;
214 }
215
216 if (!properties.isMemDb) {
217 errCode = SQLiteUtils::SetPersistWalMode(dbTemp);
218 if (errCode != E_OK) {
219 LOGE("SQLite set persist wall mode failed: %d", errCode);
220 }
221 }
222
223 END:
224 if (errCode != E_OK && dbTemp != nullptr) {
225 (void)sqlite3_close_v2(dbTemp);
226 dbTemp = nullptr;
227 }
228 if (errCode != E_OK && errno == EKEYREVOKED) {
229 errCode = -E_EKEYREVOKED;
230 }
231 db = dbTemp;
232 return errCode;
233 }
234
GetStatement(sqlite3 * db,const std::string & sql,sqlite3_stmt * & statement)235 int SQLiteUtils::GetStatement(sqlite3 *db, const std::string &sql, sqlite3_stmt *&statement)
236 {
237 if (db == nullptr) {
238 LOGE("Invalid db for statement");
239 return -E_INVALID_DB;
240 }
241 // Prepare the new statement only when the input parameter is not null
242 if (statement != nullptr) {
243 return E_OK;
244 }
245 int errCode = sqlite3_prepare_v2(db, sql.c_str(), NO_SIZE_LIMIT, &statement, nullptr);
246 if (errCode != SQLITE_OK) {
247 LOGE("Prepare SQLite statement failed:%d, sys:%d", errCode, errno);
248 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
249 SQLiteUtils::ResetStatement(statement, true, errCode);
250 return errCode;
251 }
252
253 if (statement == nullptr) {
254 return -E_INVALID_DB;
255 }
256
257 return E_OK;
258 }
259
BindTextToStatement(sqlite3_stmt * statement,int index,const std::string & str)260 int SQLiteUtils::BindTextToStatement(sqlite3_stmt *statement, int index, const std::string &str)
261 {
262 if (statement == nullptr) {
263 return -E_INVALID_ARGS;
264 }
265
266 int errCode = sqlite3_bind_text(statement, index, str.c_str(), str.length(), SQLITE_TRANSIENT);
267 if (errCode != SQLITE_OK) {
268 LOGE("[SQLiteUtil][Bind text]Failed to bind the value:%d", errCode);
269 return SQLiteUtils::MapSQLiteErrno(errCode);
270 }
271
272 return E_OK;
273 }
274
BindInt64ToStatement(sqlite3_stmt * statement,int index,int64_t value)275 int SQLiteUtils::BindInt64ToStatement(sqlite3_stmt *statement, int index, int64_t value)
276 {
277 // statement check outSide
278 int errCode = sqlite3_bind_int64(statement, index, value);
279 if (errCode != SQLITE_OK) {
280 LOGE("[SQLiteUtil][Bind int64]Failed to bind the value:%d", errCode);
281 return SQLiteUtils::MapSQLiteErrno(errCode);
282 }
283
284 return E_OK;
285 }
286
BindBlobToStatement(sqlite3_stmt * statement,int index,const std::vector<uint8_t> & value,bool permEmpty)287 int SQLiteUtils::BindBlobToStatement(sqlite3_stmt *statement, int index, const std::vector<uint8_t> &value,
288 bool permEmpty)
289 {
290 if (statement == nullptr) {
291 return -E_INVALID_ARGS;
292 }
293
294 // Check empty value.
295 if (value.empty() && !permEmpty) {
296 LOGI("[SQLiteUtil][Bind blob]Invalid value");
297 return -E_INVALID_ARGS;
298 }
299
300 int errCode;
301 if (value.empty()) {
302 errCode = sqlite3_bind_zeroblob(statement, index, -1); // -1 for zero-length blob.
303 } else {
304 errCode = sqlite3_bind_blob(statement, index, static_cast<const void *>(value.data()),
305 value.size(), SQLITE_TRANSIENT);
306 }
307
308 if (errCode != SQLITE_OK) {
309 LOGE("[SQLiteUtil][Bind blob]Failed to bind the value:%d", errCode);
310 return SQLiteUtils::MapSQLiteErrno(errCode);
311 }
312
313 return E_OK;
314 }
315
ResetStatement(sqlite3_stmt * & statement,bool isNeedFinalize,int & errCode)316 void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, int &errCode)
317 {
318 ResetStatement(statement, isNeedFinalize, false, errCode);
319 }
320
ResetStatement(sqlite3_stmt * & statement,bool isNeedFinalize,bool isIgnoreResetRet,int & errCode)321 void SQLiteUtils::ResetStatement(sqlite3_stmt *&statement, bool isNeedFinalize, bool isIgnoreResetRet, int &errCode)
322 {
323 if (statement == nullptr) {
324 return;
325 }
326
327 int innerCode = SQLITE_OK;
328 // if need finalize the statement, just goto finalize.
329 if (!isNeedFinalize) {
330 // reset the statement firstly.
331 innerCode = sqlite3_reset(statement);
332 if (innerCode != SQLITE_OK && !isIgnoreResetRet) {
333 LOGE("[SQLiteUtils] reset statement error:%d, sys:%d", innerCode, errno);
334 isNeedFinalize = true;
335 } else {
336 sqlite3_clear_bindings(statement);
337 }
338 }
339
340 if (isNeedFinalize) {
341 int finalizeResult = sqlite3_finalize(statement);
342 if (finalizeResult != SQLITE_OK) {
343 LOGE("[SQLiteUtils] finalize statement error:%d, sys:%d", finalizeResult, errno);
344 innerCode = finalizeResult;
345 }
346 statement = nullptr;
347 }
348
349 if (innerCode != SQLITE_OK) { // the sqlite error code has higher priority.
350 errCode = SQLiteUtils::MapSQLiteErrno(innerCode);
351 }
352 }
353
StepWithRetry(sqlite3_stmt * statement,bool isMemDb)354 int SQLiteUtils::StepWithRetry(sqlite3_stmt *statement, bool isMemDb)
355 {
356 if (statement == nullptr) {
357 return -E_INVALID_ARGS;
358 }
359
360 int errCode = E_OK;
361 int retryCount = 0;
362 do {
363 errCode = sqlite3_step(statement);
364 if ((errCode == SQLITE_LOCKED) && isMemDb) {
365 std::this_thread::sleep_for(std::chrono::microseconds(BUSY_SLEEP_TIME));
366 retryCount++;
367 } else {
368 break;
369 }
370 } while (retryCount <= MAX_STEP_TIMES);
371
372 if (errCode != SQLITE_DONE && errCode != SQLITE_ROW) {
373 LOGE("[SQLiteUtils] Step error:%d, sys:%d", errCode, errno);
374 }
375
376 return SQLiteUtils::MapSQLiteErrno(errCode);
377 }
378
BindPrefixKey(sqlite3_stmt * statement,int index,const Key & keyPrefix)379 int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &keyPrefix)
380 {
381 if (statement == nullptr) {
382 return -E_INVALID_ARGS;
383 }
384
385 const size_t maxKeySize = DBConstant::MAX_KEY_SIZE;
386 // bind the first prefix key
387 int errCode = BindBlobToStatement(statement, index, keyPrefix, true);
388 if (errCode != SQLITE_OK) {
389 LOGE("Bind the prefix first error:%d", errCode);
390 return SQLiteUtils::MapSQLiteErrno(errCode);
391 }
392
393 // bind the second prefix key
394 uint8_t end[maxKeySize];
395 errno_t status = memset_s(end, maxKeySize, UCHAR_MAX, maxKeySize); // max byte value is 0xFF.
396 if (status != EOK) {
397 LOGE("memset error:%d", status);
398 return -E_SECUREC_ERROR;
399 }
400
401 if (!keyPrefix.empty()) {
402 status = memcpy_s(end, maxKeySize, keyPrefix.data(), keyPrefix.size());
403 if (status != EOK) {
404 LOGE("memcpy error:%d", status);
405 return -E_SECUREC_ERROR;
406 }
407 }
408
409 // index wouldn't be too large, just add one to the first index.
410 errCode = sqlite3_bind_blob(statement, index + 1, end, maxKeySize, SQLITE_TRANSIENT);
411 if (errCode != SQLITE_OK) {
412 LOGE("Bind the prefix second error:%d", errCode);
413 return SQLiteUtils::MapSQLiteErrno(errCode);
414 }
415 return E_OK;
416 }
417
BeginTransaction(sqlite3 * db,TransactType type)418 int SQLiteUtils::BeginTransaction(sqlite3 *db, TransactType type)
419 {
420 if (type == TransactType::IMMEDIATE) {
421 return ExecuteRawSQL(db, BEGIN_IMMEDIATE_SQL, true);
422 }
423
424 return ExecuteRawSQL(db, BEGIN_SQL, true);
425 }
426
CommitTransaction(sqlite3 * db)427 int SQLiteUtils::CommitTransaction(sqlite3 *db)
428 {
429 return ExecuteRawSQL(db, COMMIT_SQL, true);
430 }
431
RollbackTransaction(sqlite3 * db)432 int SQLiteUtils::RollbackTransaction(sqlite3 *db)
433 {
434 return ExecuteRawSQL(db, ROLLBACK_SQL, true);
435 }
436
ExecuteRawSQL(sqlite3 * db,const std::string & sql,bool ignoreResetFail)437 int SQLiteUtils::ExecuteRawSQL(sqlite3 *db, const std::string &sql, bool ignoreResetFail)
438 {
439 if (db == nullptr) {
440 return -E_INVALID_DB;
441 }
442
443 sqlite3_stmt *stmt = nullptr;
444 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
445 if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_OK)) {
446 LOGE("[SQLiteUtils][ExecuteSQL] prepare statement failed(%d), sys(%d)", errCode, errno);
447 return errCode;
448 }
449
450 do {
451 errCode = SQLiteUtils::StepWithRetry(stmt);
452 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
453 errCode = E_OK;
454 break;
455 } else if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
456 LOGE("[SQLiteUtils][ExecuteSQL] execute statement failed(%d), sys(%d)", errCode, errno);
457 break;
458 }
459 } while (true);
460
461 int ret = E_OK;
462 SQLiteUtils::ResetStatement(stmt, true, ret);
463 if (!ignoreResetFail && ret != E_OK) {
464 return errCode != E_OK ? errCode : ret;
465 }
466 return errCode;
467 }
468
SetKey(sqlite3 * db,CipherType type,const CipherPassword & passwd,bool setWal,uint32_t iterTimes)469 int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes)
470 {
471 if (db == nullptr) {
472 return -E_INVALID_DB;
473 }
474
475 if (passwd.GetSize() != 0) {
476 #ifndef OMIT_ENCRYPT
477 int errCode = SetKeyInner(db, type, passwd, iterTimes);
478 if (errCode != E_OK) {
479 LOGE("[SQLiteUtils][Setkey] set keyInner failed:%d", errCode);
480 return errCode;
481 }
482 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL);
483 if (errCode != E_OK) {
484 LOGE("[SQLiteUtils][Setkey] set sha algo failed:%d", errCode);
485 return errCode;
486 }
487 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL);
488 if (errCode != E_OK) {
489 LOGE("[SQLiteUtils][Setkey] set rekey sha algo failed:%d", errCode);
490 return errCode;
491 }
492 #else
493 return -E_NOT_SUPPORT;
494 #endif
495 }
496
497 // verify key
498 int errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL);
499 if (errCode != E_OK) {
500 LOGE("[SQLiteUtils][Setkey] verify version failed:%d", errCode);
501 if (errno == EKEYREVOKED) {
502 return -E_EKEYREVOKED;
503 }
504 if (errCode == -E_BUSY) {
505 return errCode;
506 }
507 #ifndef OMIT_ENCRYPT
508 if (passwd.GetSize() != 0) {
509 errCode = UpdateCipherShaAlgo(db, setWal, type, passwd, iterTimes);
510 if (errCode != E_OK) {
511 LOGE("[SQLiteUtils][Setkey] upgrade cipher sha algo failed:%d", errCode);
512 }
513 }
514 #endif
515 }
516 return errCode;
517 }
518
GetColumnBlobValue(sqlite3_stmt * statement,int index,std::vector<uint8_t> & value)519 int SQLiteUtils::GetColumnBlobValue(sqlite3_stmt *statement, int index, std::vector<uint8_t> &value)
520 {
521 if (statement == nullptr) {
522 return -E_INVALID_ARGS;
523 }
524
525 int keySize = sqlite3_column_bytes(statement, index);
526 if (keySize < 0) {
527 LOGW("[SQLiteUtils][Column blob] size less than zero:%d", keySize);
528 value.resize(0);
529 return E_OK;
530 }
531 auto keyRead = static_cast<const uint8_t *>(sqlite3_column_blob(statement, index));
532 if (keySize == 0 || keyRead == nullptr) {
533 value.resize(0);
534 } else {
535 if (keySize > MAX_BLOB_READ_SIZE) {
536 LOGW("[SQLiteUtils][Column blob] size over limit:%d", keySize);
537 keySize = MAX_BLOB_READ_SIZE + 1;
538 }
539 value.resize(keySize);
540 value.assign(keyRead, keyRead + keySize);
541 }
542 return E_OK;
543 }
544
GetColumnTextValue(sqlite3_stmt * statement,int index,std::string & value)545 int SQLiteUtils::GetColumnTextValue(sqlite3_stmt *statement, int index, std::string &value)
546 {
547 if (statement == nullptr) {
548 return -E_INVALID_ARGS;
549 }
550
551 int valSize = sqlite3_column_bytes(statement, index);
552 if (valSize < 0) {
553 LOGW("[SQLiteUtils][Column Text] size less than zero:%d", valSize);
554 value = {};
555 return E_OK;
556 }
557 const unsigned char *val = sqlite3_column_text(statement, index);
558 if (valSize == 0 || val == nullptr) {
559 value = {};
560 return E_OK;
561 }
562 value = std::string(reinterpret_cast<const char *>(val));
563 if (valSize > MAX_TEXT_READ_SIZE) {
564 LOGW("[SQLiteUtils][Column text] size over limit:%d", valSize);
565 value.resize(MAX_TEXT_READ_SIZE + 1); // Reset value size to invalid
566 }
567 return E_OK;
568 }
569
AttachNewDatabase(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)570 int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password,
571 const std::string &attachDbAbsPath, const std::string &attachAsName)
572 {
573 #ifndef OMIT_ENCRYPT
574 int errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
575 if (errCode != E_OK) {
576 LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
577 return errCode;
578 }
579 #endif
580 errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
581 #ifndef OMIT_ENCRYPT
582 if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) {
583 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_ATTACH_SQL);
584 if (errCode != E_OK) {
585 LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha1 algo failed:%d", errCode);
586 return errCode;
587 }
588 errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
589 if (errCode != E_OK) {
590 LOGE("[SQLiteUtils][AttachNewDatabase] attach db failed:%d", errCode);
591 return errCode;
592 }
593 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
594 if (errCode != E_OK) {
595 LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
596 }
597 }
598 #endif
599 return errCode;
600 }
601
AttachNewDatabaseInner(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)602 int SQLiteUtils::AttachNewDatabaseInner(sqlite3 *db, CipherType type, const CipherPassword &password,
603 const std::string &attachDbAbsPath, const std::string &attachAsName)
604 {
605 // example: "ATTACH '../new.db' AS backup KEY XXXX;"
606 std::string attachSql = "ATTACH ? AS " + attachAsName + " KEY ?;"; // Internal interface not need verify alias name
607
608 sqlite3_stmt* statement = nullptr;
609 int errCode = SQLiteUtils::GetStatement(db, attachSql, statement);
610 if (errCode != E_OK) {
611 return errCode;
612 }
613 // 1st is name.
614 errCode = sqlite3_bind_text(statement, 1, attachDbAbsPath.c_str(), attachDbAbsPath.length(), SQLITE_TRANSIENT);
615 if (errCode != SQLITE_OK) {
616 LOGE("Bind the attached db name failed:%d", errCode);
617 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
618 goto END;
619 }
620 // Passwords do not allow vector operations, so we can not use function BindBlobToStatement here.
621 errCode = sqlite3_bind_blob(statement, 2, static_cast<const void *>(password.GetData()), // 2 means password index.
622 password.GetSize(), SQLITE_TRANSIENT);
623 if (errCode != SQLITE_OK) {
624 LOGE("Bind the attached key failed:%d", errCode);
625 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
626 goto END;
627 }
628
629 errCode = SQLiteUtils::StepWithRetry(statement);
630 if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
631 LOGE("Execute the SQLite attach failed:%d", errCode);
632 goto END;
633 }
634 errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL);
635 if (errCode != E_OK) {
636 LOGE("Set journal mode failed: %d", errCode);
637 }
638
639 END:
640 SQLiteUtils::ResetStatement(statement, true, errCode);
641 return errCode;
642 }
643
CreateMetaDatabase(const std::string & metaDbPath)644 int SQLiteUtils::CreateMetaDatabase(const std::string &metaDbPath)
645 {
646 OpenDbProperties metaProperties {metaDbPath, true, false};
647 sqlite3 *db = nullptr;
648 int errCode = SQLiteUtils::OpenDatabase(metaProperties, db);
649 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
650 LOGE("[CreateMetaDatabase] Failed to create the meta database[%d]", errCode);
651 }
652 if (db != nullptr) { // LCOV_EXCL_BR_LINE
653 (void)sqlite3_close_v2(db);
654 db = nullptr;
655 }
656 return errCode;
657 }
658
CheckIntegrity(const std::string & dbFile,CipherType type,const CipherPassword & passwd)659 int SQLiteUtils::CheckIntegrity(const std::string &dbFile, CipherType type, const CipherPassword &passwd)
660 {
661 std::vector<std::string> createTableSqls;
662 OpenDbProperties option = {dbFile, true, false, createTableSqls, type, passwd};
663 sqlite3 *db = nullptr;
664 int errCode = SQLiteUtils::OpenDatabase(option, db);
665 if (errCode != E_OK) {
666 LOGE("CheckIntegrity, open db error:%d", errCode);
667 return errCode;
668 }
669 errCode = CheckIntegrity(db, CHECK_DB_INTEGRITY_SQL);
670 if (db != nullptr) {
671 (void)sqlite3_close_v2(db);
672 db = nullptr;
673 }
674 return errCode;
675 }
676
CheckIntegrity(sqlite3 * db,const std::string & sql)677 int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql)
678 {
679 sqlite3_stmt *statement = nullptr;
680 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
681 if (errCode != E_OK) {
682 LOGE("Prepare the integrity check statement error:%d", errCode);
683 return errCode;
684 }
685 int resultCnt = 0;
686 bool checkResultOK = false;
687 do {
688 errCode = SQLiteUtils::StepWithRetry(statement);
689 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
690 break;
691 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
692 auto result = reinterpret_cast<const char *>(sqlite3_column_text(statement, 0));
693 if (result == nullptr) {
694 continue;
695 }
696 resultCnt = (resultCnt > 1) ? resultCnt : (resultCnt + 1);
697 if (strcmp(result, "ok") == 0) {
698 checkResultOK = true;
699 }
700 } else {
701 checkResultOK = false;
702 LOGW("Step for the integrity check failed:%d", errCode);
703 break;
704 }
705 } while (true);
706 if (resultCnt == 1 && checkResultOK) {
707 errCode = E_OK;
708 } else {
709 errCode = -E_INVALID_PASSWD_OR_CORRUPTED_DB;
710 }
711 SQLiteUtils::ResetStatement(statement, true, errCode);
712 return errCode;
713 }
714 #ifdef RELATIONAL_STORE
715
716 namespace { // anonymous namespace for schema analysis
AnalysisSchemaSqlAndTrigger(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)717 int AnalysisSchemaSqlAndTrigger(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
718 {
719 std::string sql = "SELECT type, sql FROM sqlite_master WHERE tbl_name = ? ";
720 if (!caseSensitive) {
721 sql += "COLLATE NOCASE";
722 }
723 sqlite3_stmt *statement = nullptr;
724 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
725 if (errCode != E_OK) {
726 LOGE("[AnalysisSchema] Prepare the analysis schema sql and trigger statement error:%d", errCode);
727 return errCode;
728 }
729 errCode = SQLiteUtils::BindTextToStatement(statement, 1, tableName);
730 if (errCode != E_OK) {
731 LOGE("[AnalysisSchema] Bind table name failed:%d", errCode);
732 SQLiteUtils::ResetStatement(statement, true, errCode);
733 return errCode;
734 }
735
736 errCode = -E_NOT_FOUND;
737 do {
738 int err = SQLiteUtils::StepWithRetry(statement);
739 if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
740 break;
741 } else if (err == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
742 errCode = E_OK;
743 std::string type;
744 (void) SQLiteUtils::GetColumnTextValue(statement, 0, type);
745 if (type == "table") {
746 std::string createTableSql;
747 (void) SQLiteUtils::GetColumnTextValue(statement, 1, createTableSql); // 1 means create table sql
748 table.SetCreateTableSql(createTableSql);
749 }
750 } else {
751 LOGE("[AnalysisSchema] Step for the analysis create table sql and trigger failed:%d", err);
752 errCode = SQLiteUtils::MapSQLiteErrno(err);
753 break;
754 }
755 } while (true);
756 SQLiteUtils::ResetStatement(statement, true, errCode);
757 return errCode;
758 }
759
GetSchemaIndexList(sqlite3 * db,const std::string & tableName,std::vector<std::string> & indexList,std::vector<std::string> & uniqueList)760 int GetSchemaIndexList(sqlite3 *db, const std::string &tableName, std::vector<std::string> &indexList,
761 std::vector<std::string> &uniqueList)
762 {
763 std::string sql = "pragma index_list('" + tableName + "')";
764 sqlite3_stmt *statement = nullptr;
765 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
766 if (errCode != E_OK) {
767 LOGE("[AnalysisSchema] Prepare the get schema index list 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 std::string indexName;
778 (void) SQLiteUtils::GetColumnTextValue(statement, 1, indexName); // 1 means index name
779 int unique = sqlite3_column_int64(statement, 2); // 2 means index type, whether unique
780 if (unique == 0) { // 0 means index created by user declare
781 indexList.push_back(indexName);
782 } else if (unique == 1) { // 1 means an unique define
783 uniqueList.push_back(indexName);
784 }
785 } else {
786 LOGW("[AnalysisSchema] Step for the get schema index list failed:%d", errCode);
787 break;
788 }
789 } while (true);
790 SQLiteUtils::ResetStatement(statement, true, errCode);
791 return errCode;
792 }
793
AnalysisSchemaIndexDefine(sqlite3 * db,const std::string & indexName,CompositeFields & indexDefine)794 int AnalysisSchemaIndexDefine(sqlite3 *db, const std::string &indexName, CompositeFields &indexDefine)
795 {
796 auto sql = "pragma index_info('" + indexName + "')";
797 sqlite3_stmt *statement = nullptr;
798 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
799 if (errCode != E_OK) {
800 LOGE("[AnalysisSchema] Prepare the analysis schema index statement error:%d", errCode);
801 return errCode;
802 }
803
804 do {
805 errCode = SQLiteUtils::StepWithRetry(statement);
806 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
807 errCode = E_OK;
808 break;
809 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
810 std::string indexField;
811 (void) SQLiteUtils::GetColumnTextValue(statement, 2, indexField); // 2 means index's column name.
812 indexDefine.push_back(indexField);
813 } else {
814 LOGW("[AnalysisSchema] Step for the analysis schema index failed:%d", errCode);
815 break;
816 }
817 } while (true);
818
819 SQLiteUtils::ResetStatement(statement, true, errCode);
820 return errCode;
821 }
822
AnalysisSchemaIndex(sqlite3 * db,const std::string & tableName,TableInfo & table)823 int AnalysisSchemaIndex(sqlite3 *db, const std::string &tableName, TableInfo &table)
824 {
825 std::vector<std::string> indexList;
826 std::vector<std::string> uniqueList;
827 int errCode = GetSchemaIndexList(db, tableName, indexList, uniqueList);
828 if (errCode != E_OK) {
829 LOGE("[AnalysisSchema] get schema index list failed.");
830 return errCode;
831 }
832
833 for (const auto &indexName : indexList) {
834 CompositeFields indexDefine;
835 errCode = AnalysisSchemaIndexDefine(db, indexName, indexDefine);
836 if (errCode != E_OK) {
837 LOGE("[AnalysisSchema] analysis schema index columns failed.");
838 return errCode;
839 }
840 table.AddIndexDefine(indexName, indexDefine);
841 }
842
843 std::vector<CompositeFields> uniques;
844 for (const auto &uniqueName : uniqueList) {
845 CompositeFields uniqueDefine;
846 errCode = AnalysisSchemaIndexDefine(db, uniqueName, uniqueDefine);
847 if (errCode != E_OK) {
848 LOGE("[AnalysisSchema] analysis schema unique columns failed.");
849 return errCode;
850 }
851 uniques.push_back(uniqueDefine);
852 }
853 table.SetUniqueDefine(uniques);
854 return E_OK;
855 }
856
SetPrimaryKeyCollateType(const std::string & sql,FieldInfo & field)857 void SetPrimaryKeyCollateType(const std::string &sql, FieldInfo &field)
858 {
859 std::string upperFieldName = DBCommon::ToUpperCase(field.GetFieldName());
860 if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE NOCASE", " ", " ,)") ||
861 DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE NOCASE", " (,", " ,")) {
862 field.SetCollateType(CollateType::COLLATE_NOCASE);
863 } else if (DBCommon::HasConstraint(sql, "PRIMARY KEY COLLATE RTRIM", " ", " ,)") ||
864 DBCommon::HasConstraint(sql, upperFieldName + " TEXT COLLATE RTRIM", " (,", " ,")) {
865 field.SetCollateType(CollateType::COLLATE_RTRIM);
866 }
867 }
868
SetFieldInfo(sqlite3_stmt * statement,TableInfo & table)869 int SetFieldInfo(sqlite3_stmt *statement, TableInfo &table)
870 {
871 FieldInfo field;
872 field.SetColumnId(sqlite3_column_int(statement, 0)); // 0 means column id index
873
874 std::string tmpString;
875 (void) SQLiteUtils::GetColumnTextValue(statement, 1, tmpString); // 1 means column name index
876 if (!DBCommon::CheckIsAlnumOrUnderscore(tmpString)) {
877 LOGE("[AnalysisSchema] unsupported field name.");
878 return -E_NOT_SUPPORT;
879 }
880 field.SetFieldName(tmpString);
881
882 (void) SQLiteUtils::GetColumnTextValue(statement, 2, tmpString); // 2 means datatype index
883 field.SetDataType(tmpString);
884
885 field.SetNotNull(static_cast<bool>(sqlite3_column_int64(statement, 3))); // 3 means whether null index
886
887 (void) SQLiteUtils::GetColumnTextValue(statement, 4, tmpString); // 4 means default value index
888 if (!tmpString.empty()) {
889 field.SetDefaultValue(tmpString);
890 }
891
892 int keyIndex = sqlite3_column_int(statement, 5); // 5 means primary key index
893 if (keyIndex != 0) { // not 0 means is a primary key
894 table.SetPrimaryKey(field.GetFieldName(), keyIndex);
895 SetPrimaryKeyCollateType(table.GetCreateTableSql(), field);
896 }
897 table.AddField(field);
898 return E_OK;
899 }
900 } // end of anonymous namespace for schema analysis
901
AnalysisSchemaFieldDefine(sqlite3 * db,const std::string & tableName,TableInfo & table)902 int SQLiteUtils::AnalysisSchemaFieldDefine(sqlite3 *db, const std::string &tableName, TableInfo &table)
903 {
904 std::string sql = "pragma table_info('" + tableName + "')";
905 sqlite3_stmt *statement = nullptr;
906 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
907 if (errCode != E_OK) {
908 LOGE("[AnalysisSchema] Prepare the analysis schema field statement error:%d", errCode);
909 return errCode;
910 }
911
912 do {
913 errCode = SQLiteUtils::StepWithRetry(statement);
914 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
915 errCode = E_OK;
916 break;
917 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
918 errCode = SetFieldInfo(statement, table);
919 if (errCode != E_OK) {
920 break;
921 }
922 } else {
923 LOGW("[AnalysisSchema] Step for the analysis schema field failed:%d", errCode);
924 break;
925 }
926 } while (true);
927
928 if (table.GetPrimaryKey().empty()) {
929 table.SetPrimaryKey("rowid", 1);
930 }
931
932 SQLiteUtils::ResetStatement(statement, true, errCode);
933 return errCode;
934 }
935
AnalysisSchema(sqlite3 * db,const std::string & tableName,TableInfo & table,bool caseSensitive)936 int SQLiteUtils::AnalysisSchema(sqlite3 *db, const std::string &tableName, TableInfo &table, bool caseSensitive)
937 {
938 if (db == nullptr) {
939 return -E_INVALID_DB;
940 }
941
942 if (!DBCommon::CheckIsAlnumOrUnderscore(tableName)) {
943 LOGE("[AnalysisSchema] unsupported table name.");
944 return -E_NOT_SUPPORT;
945 }
946
947 int errCode = AnalysisSchemaSqlAndTrigger(db, tableName, table, caseSensitive);
948 if (errCode != E_OK) {
949 LOGE("[AnalysisSchema] Analysis sql and trigger failed. errCode = [%d]", errCode);
950 return errCode;
951 }
952
953 errCode = AnalysisSchemaIndex(db, tableName, table);
954 if (errCode != E_OK) {
955 LOGE("[AnalysisSchema] Analysis index failed.");
956 return errCode;
957 }
958
959 errCode = AnalysisSchemaFieldDefine(db, tableName, table);
960 if (errCode != E_OK) {
961 LOGE("[AnalysisSchema] Analysis field failed.");
962 return errCode;
963 }
964
965 table.SetTableName(tableName);
966 return E_OK;
967 }
968 #endif
969 #ifndef OMIT_ENCRYPT
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)970 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
971 const std::string &newDbName)
972 {
973 if (db == nullptr) {
974 return -E_INVALID_DB;
975 }
976
977 int errCode = AttachNewDatabase(db, type, passwd, newDbName);
978 if (errCode != E_OK) {
979 LOGE("Attach New Db fail!");
980 return errCode;
981 }
982 errCode = SQLiteUtils::ExecuteRawSQL(db, EXPORT_BACKUP_SQL);
983 if (errCode != E_OK) {
984 LOGE("Execute the SQLite export failed:%d", errCode);
985 }
986
987 int detachError = SQLiteUtils::ExecuteRawSQL(db, DETACH_BACKUP_SQL);
988 if (errCode == E_OK) {
989 errCode = detachError;
990 if (detachError != E_OK) {
991 LOGE("Execute the SQLite detach failed:%d", errCode);
992 }
993 }
994 return errCode;
995 }
996
Rekey(sqlite3 * db,const CipherPassword & passwd)997 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
998 {
999 if (db == nullptr) {
1000 return -E_INVALID_DB;
1001 }
1002
1003 int errCode = sqlite3_rekey(db, static_cast<const void *>(passwd.GetData()), static_cast<int>(passwd.GetSize()));
1004 if (errCode != E_OK) {
1005 LOGE("SQLite rekey failed:(%d)", errCode);
1006 return SQLiteUtils::MapSQLiteErrno(errCode);
1007 }
1008
1009 return E_OK;
1010 }
1011 #else
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)1012 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
1013 const std::string &newDbName)
1014 {
1015 (void)db;
1016 (void)type;
1017 (void)passwd;
1018 (void)newDbName;
1019 return -E_NOT_SUPPORT;
1020 }
1021
Rekey(sqlite3 * db,const CipherPassword & passwd)1022 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
1023 {
1024 (void)db;
1025 (void)passwd;
1026 return -E_NOT_SUPPORT;
1027 }
1028 #endif
1029
GetVersion(const OpenDbProperties & properties,int & version)1030 int SQLiteUtils::GetVersion(const OpenDbProperties &properties, int &version)
1031 {
1032 if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
1033 return -E_INVALID_ARGS;
1034 }
1035
1036 sqlite3 *dbTemp = nullptr;
1037 // Please make sure the database file exists and is working properly
1038 std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
1039 int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, SQLITE_OPEN_URI | SQLITE_OPEN_READONLY, nullptr);
1040 if (errCode != SQLITE_OK) { // LCOV_EXCL_BR_LINE
1041 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
1042 LOGE("Open database failed: %d, sys:%d", errCode, errno);
1043 goto END;
1044 }
1045 // in memory mode no need cipher
1046 if (!properties.isMemDb) { // LCOV_EXCL_BR_LINE
1047 errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, false,
1048 properties.iterTimes);
1049 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1050 LOGE("Set key failed: %d", errCode);
1051 goto END;
1052 }
1053 }
1054
1055 errCode = GetVersion(dbTemp, version);
1056
1057 END:
1058 if (dbTemp != nullptr) { // LCOV_EXCL_BR_LINE
1059 (void)sqlite3_close_v2(dbTemp);
1060 dbTemp = nullptr;
1061 }
1062 return errCode;
1063 }
1064
GetVersion(sqlite3 * db,int & version)1065 int SQLiteUtils::GetVersion(sqlite3 *db, int &version)
1066 {
1067 if (db == nullptr) {
1068 return -E_INVALID_DB;
1069 }
1070
1071 std::string strSql = "PRAGMA user_version;";
1072 sqlite3_stmt *statement = nullptr;
1073 int errCode = sqlite3_prepare(db, strSql.c_str(), -1, &statement, nullptr);
1074 if (errCode != SQLITE_OK || statement == nullptr) {
1075 LOGE("[SqlUtil][GetVer] sqlite3_prepare failed.");
1076 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
1077 return errCode;
1078 }
1079 int ret = E_OK;
1080 errCode = sqlite3_step(statement);
1081 if (errCode == SQLITE_ROW) {
1082 // Get pragma user_version at first column
1083 version = sqlite3_column_int(statement, 0);
1084 } else {
1085 LOGE("[SqlUtil][GetVer] Get db user_version failed.");
1086 ret = SQLiteUtils::MapSQLiteErrno(errCode);
1087 }
1088 errCode = E_OK;
1089 SQLiteUtils::ResetStatement(statement, true, errCode);
1090 return ret != E_OK ? ret : errCode;
1091 }
1092
GetJournalMode(sqlite3 * db,std::string & mode)1093 int SQLiteUtils::GetJournalMode(sqlite3 *db, std::string &mode)
1094 {
1095 if (db == nullptr) {
1096 return -E_INVALID_DB;
1097 }
1098
1099 std::string sql = "PRAGMA journal_mode;";
1100 sqlite3_stmt *statement = nullptr;
1101 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
1102 if (errCode != E_OK || statement == nullptr) {
1103 return errCode;
1104 }
1105
1106 errCode = SQLiteUtils::StepWithRetry(statement);
1107 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1108 errCode = SQLiteUtils::GetColumnTextValue(statement, 0, mode);
1109 } else {
1110 LOGE("[SqlUtil][GetJournal] Get db journal_mode failed.");
1111 }
1112
1113 SQLiteUtils::ResetStatement(statement, true, errCode);
1114 return errCode;
1115 }
1116
SetUserVer(const OpenDbProperties & properties,int version)1117 int SQLiteUtils::SetUserVer(const OpenDbProperties &properties, int version)
1118 {
1119 if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
1120 return -E_INVALID_ARGS;
1121 }
1122
1123 // Please make sure the database file exists and is working properly
1124 sqlite3 *db = nullptr;
1125 int errCode = SQLiteUtils::OpenDatabase(properties, db);
1126 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1127 return errCode;
1128 }
1129
1130 // Set user version
1131 errCode = SQLiteUtils::SetUserVer(db, version);
1132 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
1133 LOGE("Set user version fail: %d", errCode);
1134 goto END;
1135 }
1136
1137 END:
1138 if (db != nullptr) { // LCOV_EXCL_BR_LINE
1139 (void)sqlite3_close_v2(db);
1140 db = nullptr;
1141 }
1142
1143 return errCode;
1144 }
1145
SetUserVer(sqlite3 * db,int version)1146 int SQLiteUtils::SetUserVer(sqlite3 *db, int version)
1147 {
1148 if (db == nullptr) {
1149 return -E_INVALID_DB;
1150 }
1151 std::string userVersionSql = "PRAGMA user_version=" + std::to_string(version) + ";";
1152 return SQLiteUtils::ExecuteRawSQL(db, userVersionSql);
1153 }
1154
MapSQLiteErrno(int errCode)1155 int SQLiteUtils::MapSQLiteErrno(int errCode)
1156 {
1157 switch (errCode) {
1158 case SQLITE_OK:
1159 return E_OK;
1160 case SQLITE_IOERR:
1161 if (errno == EKEYREVOKED) {
1162 return -E_EKEYREVOKED;
1163 }
1164 break;
1165 case SQLITE_CORRUPT:
1166 case SQLITE_NOTADB:
1167 return -E_INVALID_PASSWD_OR_CORRUPTED_DB;
1168 case SQLITE_LOCKED:
1169 case SQLITE_BUSY:
1170 return -E_BUSY;
1171 case SQLITE_ERROR:
1172 if (errno == EKEYREVOKED) {
1173 return -E_EKEYREVOKED;
1174 }
1175 break;
1176 case SQLITE_AUTH:
1177 return -E_DENIED_SQL;
1178 case SQLITE_CONSTRAINT:
1179 return -E_CONSTRAINT;
1180 case SQLITE_CANTOPEN:
1181 return -E_SQLITE_CANT_OPEN;
1182 default:
1183 break;
1184 }
1185 return -errCode;
1186 }
1187
SetBusyTimeout(sqlite3 * db,int timeout)1188 int SQLiteUtils::SetBusyTimeout(sqlite3 *db, int timeout)
1189 {
1190 if (db == nullptr) {
1191 return -E_INVALID_DB;
1192 }
1193
1194 // Set the default busy handler to retry automatically before returning SQLITE_BUSY.
1195 int errCode = sqlite3_busy_timeout(db, timeout);
1196 if (errCode != SQLITE_OK) {
1197 LOGE("[SQLite] set busy timeout failed:%d", errCode);
1198 }
1199
1200 return SQLiteUtils::MapSQLiteErrno(errCode);
1201 }
1202
1203 #ifndef OMIT_ENCRYPT
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)1204 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
1205 const std::string &targetFile, const CipherPassword &passwd)
1206 {
1207 std::vector<std::string> createTableSqls;
1208 OpenDbProperties option = {srcFile, true, false, createTableSqls, type, srcPasswd};
1209 sqlite3 *db = nullptr;
1210 int errCode = SQLiteUtils::OpenDatabase(option, db);
1211 if (errCode != E_OK) {
1212 LOGE("Open db error while exporting:%d", errCode);
1213 return errCode;
1214 }
1215
1216 errCode = SQLiteUtils::ExportDatabase(db, type, passwd, targetFile);
1217 if (db != nullptr) {
1218 (void)sqlite3_close_v2(db);
1219 db = nullptr;
1220 }
1221 return errCode;
1222 }
1223 #else
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)1224 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
1225 const std::string &targetFile, const CipherPassword &passwd)
1226 {
1227 (void)srcFile;
1228 (void)type;
1229 (void)srcPasswd;
1230 (void)targetFile;
1231 (void)passwd;
1232 return -E_NOT_SUPPORT;
1233 }
1234 #endif
1235
SaveSchema(sqlite3 * db,const std::string & strSchema)1236 int SQLiteUtils::SaveSchema(sqlite3 *db, const std::string &strSchema)
1237 {
1238 if (db == nullptr) {
1239 return -E_INVALID_DB;
1240 }
1241
1242 sqlite3_stmt *statement = nullptr;
1243 std::string sql = "INSERT OR REPLACE INTO meta_data VALUES(?,?);";
1244 int errCode = GetStatement(db, sql, statement);
1245 if (errCode != E_OK) {
1246 return errCode;
1247 }
1248
1249 Key schemaKey;
1250 DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemaKey);
1251 errCode = BindBlobToStatement(statement, BIND_KEY_INDEX, schemaKey, false);
1252 if (errCode != E_OK) {
1253 ResetStatement(statement, true, errCode);
1254 return errCode;
1255 }
1256
1257 Value schemaValue;
1258 DBCommon::StringToVector(strSchema, schemaValue);
1259 errCode = BindBlobToStatement(statement, BIND_VAL_INDEX, schemaValue, false);
1260 if (errCode != E_OK) {
1261 ResetStatement(statement, true, errCode);
1262 return errCode;
1263 }
1264
1265 errCode = StepWithRetry(statement); // memory db does not support schema
1266 if (errCode != MapSQLiteErrno(SQLITE_DONE)) {
1267 LOGE("[SqlUtil][SetSchema] StepWithRetry fail, errCode=%d.", errCode);
1268 ResetStatement(statement, true, errCode);
1269 return errCode;
1270 }
1271 errCode = E_OK;
1272 ResetStatement(statement, true, errCode);
1273 return errCode;
1274 }
1275
GetSchema(sqlite3 * db,std::string & strSchema)1276 int SQLiteUtils::GetSchema(sqlite3 *db, std::string &strSchema)
1277 {
1278 if (db == nullptr) {
1279 return -E_INVALID_DB;
1280 }
1281
1282 bool isExists = false;
1283 int errCode = CheckTableExists(db, "meta_data", isExists);
1284 if (errCode != E_OK || !isExists) {
1285 LOGW("meta table may has not been created, err=%d, isExists=%d", errCode, isExists);
1286 return errCode;
1287 }
1288
1289 sqlite3_stmt *statement = nullptr;
1290 std::string sql = "SELECT value FROM meta_data WHERE key=?;";
1291 errCode = GetStatement(db, sql, statement);
1292 if (errCode != E_OK) {
1293 return errCode;
1294 }
1295
1296 Key schemakey;
1297 DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemakey);
1298 errCode = BindBlobToStatement(statement, 1, schemakey, false);
1299 if (errCode != E_OK) {
1300 ResetStatement(statement, true, errCode);
1301 return errCode;
1302 }
1303
1304 errCode = StepWithRetry(statement); // memory db does not support schema
1305 if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1306 ResetStatement(statement, true, errCode);
1307 return -E_NOT_FOUND;
1308 } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1309 ResetStatement(statement, true, errCode);
1310 return errCode;
1311 }
1312
1313 Value schemaValue;
1314 errCode = GetColumnBlobValue(statement, 0, schemaValue);
1315 if (errCode != E_OK) {
1316 ResetStatement(statement, true, errCode);
1317 return errCode;
1318 }
1319 DBCommon::VectorToString(schemaValue, strSchema);
1320 ResetStatement(statement, true, errCode);
1321 return errCode;
1322 }
1323
IncreaseIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)1324 int SQLiteUtils::IncreaseIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
1325 uint32_t skipSize)
1326 {
1327 if (db == nullptr) {
1328 LOGE("[IncreaseIndex] Sqlite DB not exists.");
1329 return -E_INVALID_DB;
1330 }
1331 if (name.empty() || info.empty()) {
1332 LOGE("[IncreaseIndex] Name or info can not be empty.");
1333 return -E_NOT_PERMIT;
1334 }
1335 std::string indexName = SchemaUtils::FieldPathString(name);
1336 std::string sqlCommand = "CREATE INDEX IF NOT EXISTS '" + indexName + "' ON sync_data (";
1337 for (uint32_t i = 0; i < info.size(); i++) {
1338 if (i != 0) {
1339 sqlCommand += ", ";
1340 }
1341 std::string extractSql = SchemaObject::GenerateExtractSQL(type, info[i].first, info[i].second,
1342 skipSize);
1343 if (extractSql.empty()) { // Unlikely
1344 LOGE("[IncreaseIndex] GenerateExtractSQL fail at field=%u.", i);
1345 return -E_INTERNAL_ERROR;
1346 }
1347 sqlCommand += extractSql;
1348 }
1349 sqlCommand += ") WHERE (flag&0x01=0);";
1350 return SQLiteUtils::ExecuteRawSQL(db, sqlCommand);
1351 }
1352
ChangeIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)1353 int SQLiteUtils::ChangeIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
1354 uint32_t skipSize)
1355 {
1356 // Currently we change index by drop it then create it, SQLite "REINDEX" may be used in the future
1357 int errCode = DecreaseIndex(db, name);
1358 if (errCode != E_OK) {
1359 LOGE("[ChangeIndex] Decrease fail=%d.", errCode);
1360 return errCode;
1361 }
1362 errCode = IncreaseIndex(db, name, info, type, skipSize);
1363 if (errCode != E_OK) {
1364 LOGE("[ChangeIndex] Increase fail=%d.", errCode);
1365 return errCode;
1366 }
1367 return E_OK;
1368 }
1369
DecreaseIndex(sqlite3 * db,const IndexName & name)1370 int SQLiteUtils::DecreaseIndex(sqlite3 *db, const IndexName &name)
1371 {
1372 if (db == nullptr) {
1373 LOGE("[DecreaseIndex] Sqlite DB not exists.");
1374 return -E_INVALID_DB;
1375 }
1376 if (name.empty()) {
1377 LOGE("[DecreaseIndex] Name can not be empty.");
1378 return -E_NOT_PERMIT;
1379 }
1380 std::string indexName = SchemaUtils::FieldPathString(name);
1381 std::string sqlCommand = "DROP INDEX IF EXISTS '" + indexName + "';";
1382 return ExecuteRawSQL(db, sqlCommand);
1383 }
1384
RegisterJsonFunctions(sqlite3 * db)1385 int SQLiteUtils::RegisterJsonFunctions(sqlite3 *db)
1386 {
1387 if (db == nullptr) {
1388 LOGE("Sqlite DB not exists.");
1389 return -E_INVALID_DB;
1390 }
1391 int errCode = sqlite3_create_function_v2(db, "calc_hash_key", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1392 nullptr, &CalcHashKey, nullptr, nullptr, nullptr);
1393 if (errCode != SQLITE_OK) {
1394 LOGE("sqlite3_create_function_v2 about calc_hash_key returned %d", errCode);
1395 return MapSQLiteErrno(errCode);
1396 }
1397 #ifdef USING_DB_JSON_EXTRACT_AUTOMATICALLY
1398 // Specify need 3 parameter in json_extract_by_path function
1399 errCode = sqlite3_create_function_v2(db, "json_extract_by_path", 3, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
1400 nullptr, &JsonExtractByPath, nullptr, nullptr, nullptr);
1401 if (errCode != SQLITE_OK) {
1402 LOGE("sqlite3_create_function_v2 about json_extract_by_path returned %d", errCode);
1403 return MapSQLiteErrno(errCode);
1404 }
1405 #endif
1406 return E_OK;
1407 }
1408
1409 namespace {
SchemaObjectDestructor(SchemaObject * inObject)1410 void SchemaObjectDestructor(SchemaObject *inObject)
1411 {
1412 delete inObject;
1413 inObject = nullptr;
1414 }
1415 }
1416 #ifdef RELATIONAL_STORE
RegisterCalcHash(sqlite3 * db)1417 int SQLiteUtils::RegisterCalcHash(sqlite3 *db)
1418 {
1419 TransactFunc func;
1420 func.xFunc = &CalcHash;
1421 return SQLiteUtils::RegisterFunction(db, "calc_hash", 2, nullptr, func); // 2 is params count
1422 }
1423
GetSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1424 void SQLiteUtils::GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1425 {
1426 if (ctx == nullptr || argc != 1 || argv == nullptr) {
1427 LOGE("Parameter does not meet restrictions.");
1428 return;
1429 }
1430
1431 sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
1432 }
1433
GetRawSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1434 void SQLiteUtils::GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1435 {
1436 if (ctx == nullptr || argc != 0 || argv == nullptr) {
1437 LOGE("Parameter does not meet restrictions.");
1438 return;
1439 }
1440
1441 uint64_t curTime = 0;
1442 int errCode = TimeHelper::GetSysCurrentRawTime(curTime);
1443 if (errCode != E_OK) {
1444 sqlite3_result_error(ctx, "get raw sys time failed in sqlite utils.", errCode);
1445 return;
1446 }
1447 sqlite3_result_int64(ctx, (sqlite3_int64)(curTime));
1448 }
1449
GetLastTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1450 void SQLiteUtils::GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1451 {
1452 if (ctx == nullptr || argc != 0 || argv == nullptr) { // LCOV_EXCL_BR_LINE
1453 LOGE("Parameter does not meet restrictions.");
1454 return;
1455 }
1456 // Never used internally, just for sql prepare
1457 sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
1458 }
1459
CloudDataChangedObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1460 void SQLiteUtils::CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1461 {
1462 if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts
1463 return;
1464 }
1465 sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
1466 }
1467
CloudDataChangedServerObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1468 void SQLiteUtils::CloudDataChangedServerObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1469 {
1470 if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is param counts
1471 return;
1472 }
1473 sqlite3 *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1474 std::string fileName;
1475 if (!SQLiteRelationalUtils::GetDbFileName(db, fileName)) {
1476 return;
1477 }
1478 auto tableNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
1479 if (tableNameChar == nullptr) {
1480 return;
1481 }
1482 std::string tableName = static_cast<std::string>(tableNameChar);
1483
1484 uint64_t isTrackerChange = static_cast<uint64_t>(sqlite3_value_int(argv[1])); // 1 is param index
1485 LOGD("Cloud data changed, server observer callback %u", isTrackerChange);
1486 {
1487 std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
1488 auto itTable = g_serverChangedDataMap[fileName].find(tableName);
1489 if (itTable != g_serverChangedDataMap[fileName].end()) {
1490 itTable->second.isTrackedDataChange =
1491 (static_cast<uint8_t>(itTable->second.isTrackedDataChange) | isTrackerChange) > 0;
1492 } else {
1493 DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) };
1494 g_serverChangedDataMap[fileName].insert_or_assign(tableName, properties);
1495 }
1496 }
1497 sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
1498 }
1499
GetAndResetServerObserverData(const std::string & dbName,const std::string & tableName,ChangeProperties & changeProperties)1500 void SQLiteUtils::GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName,
1501 ChangeProperties &changeProperties)
1502 {
1503 std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
1504 auto itDb = g_serverChangedDataMap.find(dbName);
1505 if (itDb != g_serverChangedDataMap.end() && !itDb->second.empty()) {
1506 auto itTable = itDb->second.find(tableName);
1507 if (itTable == itDb->second.end()) {
1508 return;
1509 }
1510 changeProperties = itTable->second;
1511 g_serverChangedDataMap[dbName].erase(itTable);
1512 }
1513 }
1514
RegisterGetSysTime(sqlite3 * db)1515 int SQLiteUtils::RegisterGetSysTime(sqlite3 *db)
1516 {
1517 TransactFunc func;
1518 func.xFunc = &GetSysTime;
1519 return SQLiteUtils::RegisterFunction(db, "get_sys_time", 1, nullptr, func);
1520 }
1521
RegisterGetLastTime(sqlite3 * db)1522 int SQLiteUtils::RegisterGetLastTime(sqlite3 *db)
1523 {
1524 TransactFunc func;
1525 func.xFunc = &GetLastTime;
1526 return SQLiteUtils::RegisterFunction(db, "get_last_time", 0, nullptr, func);
1527 }
1528
RegisterGetRawSysTime(sqlite3 * db)1529 int SQLiteUtils::RegisterGetRawSysTime(sqlite3 *db)
1530 {
1531 TransactFunc func;
1532 func.xFunc = &GetRawSysTime;
1533 return SQLiteUtils::RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func);
1534 }
1535
RegisterCloudDataChangeObserver(sqlite3 * db)1536 int SQLiteUtils::RegisterCloudDataChangeObserver(sqlite3 *db)
1537 {
1538 TransactFunc func;
1539 func.xFunc = &CloudDataChangedObserver;
1540 return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts
1541 }
1542
RegisterCloudDataChangeServerObserver(sqlite3 * db)1543 int SQLiteUtils::RegisterCloudDataChangeServerObserver(sqlite3 *db)
1544 {
1545 TransactFunc func;
1546 func.xFunc = &CloudDataChangedServerObserver;
1547 return RegisterFunction(db, "server_observer", 2, db, func); // 2 is param counts
1548 }
1549
CreateSameStuTable(sqlite3 * db,const TableInfo & baseTbl,const std::string & newTableName)1550 int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName)
1551 {
1552 std::string sql = "CREATE TABLE IF NOT EXISTS '" + newTableName + "' (";
1553 const FieldInfoMap &fields = baseTbl.GetFields();
1554 for (uint32_t cid = 0; cid < fields.size(); ++cid) {
1555 std::string fieldName = baseTbl.GetFieldName(cid);
1556 const auto &it = fields.find(fieldName);
1557 if (it == fields.end()) {
1558 return -E_INVALID_DB;
1559 }
1560 sql += "'" + fieldName + "' '" + it->second.GetDataType() + "'";
1561 if (it->second.IsNotNull()) {
1562 sql += " NOT NULL";
1563 }
1564 if (it->second.HasDefaultValue()) {
1565 sql += " DEFAULT " + it->second.GetDefaultValue();
1566 }
1567 sql += ",";
1568 }
1569 // base table has primary key
1570 if (!(baseTbl.GetPrimaryKey().size() == 1 && baseTbl.GetPrimaryKey().at(0) == "rowid")) {
1571 sql += " PRIMARY KEY (";
1572 for (const auto &it : baseTbl.GetPrimaryKey()) {
1573 sql += "'" + it.second + "',";
1574 }
1575 sql.pop_back();
1576 sql += "),";
1577 }
1578 sql.pop_back();
1579 sql += ");";
1580 int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
1581 if (errCode != E_OK) {
1582 LOGE("[SQLite] execute create table sql failed");
1583 }
1584 return errCode;
1585 }
1586
CloneIndexes(sqlite3 * db,const std::string & oriTableName,const std::string & newTableName)1587 int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName)
1588 {
1589 std::string sql =
1590 "SELECT 'CREATE ' || CASE WHEN il.'unique' THEN 'UNIQUE ' ELSE '' END || 'INDEX IF NOT EXISTS ' || '" +
1591 newTableName + "_' || il.name || ' ON ' || '" + newTableName +
1592 "' || '(' || GROUP_CONCAT(ii.name) || ');' "
1593 "FROM sqlite_master AS m,"
1594 "pragma_index_list(m.name) AS il,"
1595 "pragma_index_info(il.name) AS ii "
1596 "WHERE m.type='table' AND m.name='" + oriTableName + "' AND il.origin='c' "
1597 "GROUP BY il.name;";
1598 sqlite3_stmt *stmt = nullptr;
1599 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1600 if (errCode != E_OK) {
1601 LOGE("Prepare the clone sql failed:%d", errCode);
1602 return errCode;
1603 }
1604
1605 std::vector<std::string> indexes;
1606 while (true) {
1607 errCode = SQLiteUtils::StepWithRetry(stmt, false);
1608 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1609 std::string indexSql;
1610 (void)GetColumnTextValue(stmt, 0, indexSql);
1611 indexes.emplace_back(indexSql);
1612 continue;
1613 }
1614 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1615 errCode = E_OK;
1616 }
1617 (void)ResetStatement(stmt, true, errCode);
1618 break;
1619 }
1620
1621 if (errCode != E_OK) {
1622 return errCode;
1623 }
1624
1625 for (const auto &it : indexes) {
1626 errCode = SQLiteUtils::ExecuteRawSQL(db, it);
1627 if (errCode != E_OK) {
1628 LOGE("[SQLite] execute clone index sql failed");
1629 }
1630 }
1631 return errCode;
1632 }
1633
GetRelationalSchema(sqlite3 * db,std::string & schema,const std::string & key)1634 int SQLiteUtils::GetRelationalSchema(sqlite3 *db, std::string &schema, const std::string &key)
1635 {
1636 if (db == nullptr) {
1637 return -E_INVALID_DB;
1638 }
1639
1640 sqlite3_stmt *statement = nullptr;
1641 std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1642 int errCode = GetStatement(db, sql, statement);
1643 if (errCode != E_OK) {
1644 return errCode;
1645 }
1646
1647 Key schemakey;
1648 DBCommon::StringToVector(key, schemakey);
1649 errCode = BindBlobToStatement(statement, 1, schemakey, false);
1650 if (errCode != E_OK) {
1651 ResetStatement(statement, true, errCode);
1652 return errCode;
1653 }
1654
1655 errCode = StepWithRetry(statement);
1656 if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1657 ResetStatement(statement, true, errCode);
1658 return -E_NOT_FOUND;
1659 } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1660 ResetStatement(statement, true, errCode);
1661 return errCode;
1662 }
1663
1664 Value schemaValue;
1665 errCode = GetColumnBlobValue(statement, 0, schemaValue);
1666 if (errCode != E_OK) {
1667 ResetStatement(statement, true, errCode);
1668 return errCode;
1669 }
1670 DBCommon::VectorToString(schemaValue, schema);
1671 ResetStatement(statement, true, errCode);
1672 return errCode;
1673 }
1674
GetLogTableVersion(sqlite3 * db,std::string & version)1675 int SQLiteUtils::GetLogTableVersion(sqlite3 *db, std::string &version)
1676 {
1677 if (db == nullptr) {
1678 return -E_INVALID_DB;
1679 }
1680
1681 sqlite3_stmt *statement = nullptr;
1682 std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1683 int errCode = GetStatement(db, sql, statement);
1684 if (errCode != E_OK) {
1685 return errCode;
1686 }
1687
1688 Key logTableKey;
1689 DBCommon::StringToVector(DBConstant::LOG_TABLE_VERSION_KEY, logTableKey);
1690 errCode = BindBlobToStatement(statement, 1, logTableKey, false);
1691 if (errCode != E_OK) {
1692 ResetStatement(statement, true, errCode);
1693 return errCode;
1694 }
1695
1696 errCode = StepWithRetry(statement);
1697 if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1698 ResetStatement(statement, true, errCode);
1699 return -E_NOT_FOUND;
1700 } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1701 ResetStatement(statement, true, errCode);
1702 return errCode;
1703 }
1704
1705 Value value;
1706 errCode = GetColumnBlobValue(statement, 0, value);
1707 if (errCode != E_OK) {
1708 ResetStatement(statement, true, errCode);
1709 return errCode;
1710 }
1711 DBCommon::VectorToString(value, version);
1712 ResetStatement(statement, true, errCode);
1713 return errCode;
1714 }
1715
RegisterFunction(sqlite3 * db,const std::string & funcName,int nArg,void * uData,TransactFunc & func)1716 int SQLiteUtils::RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func)
1717 {
1718 if (db == nullptr) {
1719 LOGE("Sqlite DB not exists.");
1720 return -E_INVALID_DB;
1721 }
1722
1723 int errCode = sqlite3_create_function_v2(db, funcName.c_str(), nArg, SQLITE_UTF8 | SQLITE_DETERMINISTIC, uData,
1724 func.xFunc, func.xStep, func.xFinal, func.xDestroy);
1725 if (errCode != SQLITE_OK) {
1726 LOGE("sqlite3_create_function_v2 about [%s] returned %d", funcName.c_str(), errCode);
1727 return MapSQLiteErrno(errCode);
1728 }
1729 return E_OK;
1730 }
1731 #endif
RegisterFlatBufferFunction(sqlite3 * db,const std::string & inSchema)1732 int SQLiteUtils::RegisterFlatBufferFunction(sqlite3 *db, const std::string &inSchema)
1733 {
1734 if (db == nullptr) {
1735 LOGE("Sqlite DB not exists.");
1736 return -E_INVALID_DB;
1737 }
1738 auto heapSchemaObj = new (std::nothrow) SchemaObject;
1739 if (heapSchemaObj == nullptr) {
1740 return -E_OUT_OF_MEMORY;
1741 }
1742 int errCode = heapSchemaObj->ParseFromSchemaString(inSchema);
1743 if (errCode != E_OK) { // Unlikely, it has been parsed before
1744 delete heapSchemaObj;
1745 heapSchemaObj = nullptr;
1746 return -E_INTERNAL_ERROR;
1747 }
1748 if (heapSchemaObj->GetSchemaType() != SchemaType::FLATBUFFER) { // Do not need to register FlatBufferExtract
1749 delete heapSchemaObj;
1750 heapSchemaObj = nullptr;
1751 return E_OK;
1752 }
1753 errCode = sqlite3_create_function_v2(db, SchemaObject::GetExtractFuncName(SchemaType::FLATBUFFER).c_str(),
1754 3, SQLITE_UTF8 | SQLITE_DETERMINISTIC, heapSchemaObj, &FlatBufferExtractByPath, nullptr, nullptr, // 3 args
1755 reinterpret_cast<void(*)(void*)>(SchemaObjectDestructor));
1756 // About the release of heapSchemaObj: SQLite guarantee that at following case, sqlite will invoke the destructor
1757 // (that is SchemaObjectDestructor) we passed to it. See sqlite.org for more information.
1758 // The destructor is invoked when the function is deleted, either by being overloaded or when the database
1759 // connection closes. The destructor is also invoked if the call to sqlite3_create_function_v2() fails
1760 if (errCode != SQLITE_OK) {
1761 LOGE("sqlite3_create_function_v2 about flatbuffer_extract_by_path return=%d.", errCode);
1762 // As mentioned above, SQLite had invoked the SchemaObjectDestructor to release the heapSchemaObj
1763 return MapSQLiteErrno(errCode);
1764 }
1765 return E_OK;
1766 }
1767
UpdateMetaDataWithinTrigger(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1768 void SQLiteUtils::UpdateMetaDataWithinTrigger(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1769 {
1770 if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 : Number of parameters for sqlite register function
1771 LOGE("[UpdateMetaDataWithinTrigger] Invalid parameter, argc=%d.", argc);
1772 return;
1773 }
1774 auto *handle = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1775 if (handle == nullptr) {
1776 sqlite3_result_error(ctx, "Sqlite context is invalid.", USING_STR_LEN);
1777 LOGE("Sqlite context is invalid.");
1778 return;
1779 }
1780 auto *keyPtr = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0])); // 0 : first argv for key
1781 int keyLen = sqlite3_value_bytes(argv[0]); // 0 : first argv for key
1782 if (keyPtr == nullptr || keyLen <= 0 || keyLen > static_cast<int>(DBConstant::MAX_KEY_SIZE)) {
1783 sqlite3_result_error(ctx, "key is invalid.", USING_STR_LEN);
1784 LOGE("key is invalid.");
1785 return;
1786 }
1787 auto val = sqlite3_value_int64(argv[1]); // 1 : second argv for value
1788
1789 sqlite3_stmt *stmt = nullptr;
1790 int errCode = SQLiteUtils::GetStatement(handle, UPDATE_META_SQL, stmt);
1791 if (errCode != E_OK) {
1792 sqlite3_result_error(ctx, "Get update meta_data statement failed.", USING_STR_LEN);
1793 LOGE("Get update meta_data statement failed. %d", errCode);
1794 return;
1795 }
1796
1797 Key key(keyPtr, keyPtr + keyLen);
1798 errCode = SQLiteUtils::BindBlobToStatement(stmt, BIND_KEY_INDEX, key, false);
1799 if (errCode != E_OK) {
1800 sqlite3_result_error(ctx, "Bind key to statement failed.", USING_STR_LEN);
1801 LOGE("Bind key to statement failed. %d", errCode);
1802 goto END;
1803 }
1804
1805 errCode = SQLiteUtils::BindInt64ToStatement(stmt, BIND_VAL_INDEX, val);
1806 if (errCode != E_OK) {
1807 sqlite3_result_error(ctx, "Bind value to statement failed.", USING_STR_LEN);
1808 LOGE("Bind value to statement failed. %d", errCode);
1809 goto END;
1810 }
1811
1812 errCode = SQLiteUtils::StepWithRetry(stmt, false);
1813 if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1814 sqlite3_result_error(ctx, "Execute the update meta_data attach failed.", USING_STR_LEN);
1815 LOGE("Execute the update meta_data attach failed. %d", errCode);
1816 }
1817 END:
1818 SQLiteUtils::ResetStatement(stmt, true, errCode);
1819 }
1820
RegisterMetaDataUpdateFunction(sqlite3 * db)1821 int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db)
1822 {
1823 int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC.c_str(),
1824 2, // 2: argc for register function
1825 SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::UpdateMetaDataWithinTrigger, nullptr, nullptr, nullptr);
1826 if (errCode != SQLITE_OK) {
1827 LOGE("sqlite3_create_function_v2 about %s returned %d", DBConstant::UPDATE_META_FUNC.c_str(), errCode);
1828 }
1829 return SQLiteUtils::MapSQLiteErrno(errCode);
1830 }
1831 } // namespace DistributedDB
1832