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 BIND_KEY_INDEX = 1;
46 const int BIND_VAL_INDEX = 2;
47 const int USING_STR_LEN = -1;
48 const int HEAD_SIZE = 3;
49 const int END_SIZE = 3;
50 constexpr int MIN_SIZE = HEAD_SIZE + END_SIZE + 3;
51 const std::string REPLACE_CHAIN = "***";
52 const std::string DEFAULT_ANONYMOUS = "******";
53 const std::string WAL_MODE_SQL = "PRAGMA journal_mode=WAL;";
54 const std::string SYNC_MODE_FULL_SQL = "PRAGMA synchronous=FULL;";
55 const std::string USER_VERSION_SQL = "PRAGMA user_version;";
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 SHA256_ALGO_SQL = "PRAGMA codec_hmac_algo=SHA256;";
59 const std::string SHA256_ALGO_REKEY_SQL = "PRAGMA codec_rekey_hmac_algo=SHA256;";
60 const std::string SHA1_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA1;";
61 const std::string SHA256_ALGO_ATTACH_SQL = "PRAGMA cipher_default_attach_hmac_algo=SHA256;";
62 const std::string EXPORT_BACKUP_SQL = "SELECT export_database('backup');";
63 const std::string BACK_CIPHER_CONFIG_SQL = "PRAGMA backup.codec_cipher=";
64 const std::string BACK_KDF_ITER_CONFIG_SQL = "PRAGMA backup.codec_kdf_iter=5000;";
65 const std::string META_CIPHER_CONFIG_SQL = "PRAGMA meta.codec_cipher=";
66 const std::string META_KDF_ITER_CONFIG_SQL = "PRAGMA meta.codec_kdf_iter=5000;";
67
68 const constexpr char *DETACH_BACKUP_SQL = "DETACH 'backup'";
69 const constexpr char *UPDATE_META_SQL = "INSERT OR REPLACE INTO meta_data VALUES (?, ?);";
70
71 bool g_configLog = false;
72 std::mutex g_serverChangedDataMutex;
73 std::map<std::string, std::map<std::string, DistributedDB::ChangeProperties>> g_serverChangedDataMap;
74 }
75
Anonymous(const std::string & name)76 std::string SQLiteUtils::Anonymous(const std::string &name)
77 {
78 if (name.length() <= HEAD_SIZE) {
79 return DEFAULT_ANONYMOUS;
80 }
81
82 if (name.length() < MIN_SIZE) {
83 return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN);
84 }
85
86 return (name.substr(0, HEAD_SIZE) + REPLACE_CHAIN + name.substr(name.length() - END_SIZE, END_SIZE));
87 }
88
IsNeedSkipLog(const unsigned int errType,const char * msg)89 bool IsNeedSkipLog(const unsigned int errType, const char *msg)
90 {
91 return errType == SQLITE_ERROR && strstr(msg, "\"?\": syntax error in \"PRAGMA user_ve") != nullptr;
92 }
93
SqliteLogCallback(void * data,int err,const char * msg)94 void SQLiteUtils::SqliteLogCallback(void *data, int err, const char *msg)
95 {
96 bool verboseLog = (data != nullptr);
97 auto errType = static_cast<unsigned int>(err);
98 bool isWarningDump = errType == (SQLITE_WARNING | (2 << 8)); // SQLITE_WARNING_DUMP
99 std::string logMsg = msg == nullptr ? "NULL" : msg;
100 errType &= 0xFF;
101 if (IsNeedSkipLog(errType, logMsg.c_str())) {
102 return;
103 }
104 if (errType == 0 || errType == SQLITE_CONSTRAINT || errType == SQLITE_SCHEMA ||
105 errType == SQLITE_NOTICE || err == SQLITE_WARNING_AUTOINDEX) {
106 if (verboseLog) {
107 LOGD("[SQLite] Error[%d] sys[%d] %s ", err, errno, sqlite3_errstr(err));
108 }
109 } else if ((errType == SQLITE_WARNING && !isWarningDump) ||
110 errType == SQLITE_IOERR || errType == SQLITE_CANTOPEN) {
111 LOGI("[SQLite] Error[%d], sys[%d], %s, msg: %s ", err, errno,
112 sqlite3_errstr(err), SQLiteUtils::Anonymous(logMsg).c_str());
113 } else {
114 LOGE("[SQLite] Error[%d], sys[%d], msg: %s ", err, errno, logMsg.c_str());
115 return;
116 }
117
118 const char *errMsg = sqlite3_errstr(err);
119 std::lock_guard<std::mutex> autoLock(logMutex_);
120 if (errMsg != nullptr) {
121 lastErrorMsg_ = std::string(errMsg);
122 }
123 }
124
CreateDataBase(const OpenDbProperties & properties,sqlite3 * & dbTemp,bool setWal)125 int SQLiteUtils::CreateDataBase(const OpenDbProperties &properties, sqlite3 *&dbTemp, bool setWal)
126 {
127 uint64_t flag = SQLITE_OPEN_URI | SQLITE_OPEN_READWRITE;
128 if (properties.createIfNecessary) {
129 flag |= SQLITE_OPEN_CREATE;
130 }
131 std::string cipherName = GetCipherName(properties.cipherType);
132 if (cipherName.empty()) {
133 LOGE("[SQLite] GetCipherName failed");
134 return -E_INVALID_ARGS;
135 }
136 std::string defaultAttachCipher = DEFAULT_ATTACH_CIPHER + cipherName + ";";
137 std::vector<std::string> sqls {defaultAttachCipher, DEFAULT_ATTACH_KDF_ITER};
138 if (setWal) {
139 sqls.push_back(WAL_MODE_SQL);
140 }
141 std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
142 int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, flag, nullptr);
143 if (errCode != SQLITE_OK) {
144 LOGE("[SQLite] open database failed: %d - sys err(%d)", errCode, errno);
145 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
146 goto END;
147 }
148
149 errCode = SetDataBaseProperty(dbTemp, properties, setWal, sqls);
150 if (errCode != SQLITE_OK) {
151 LOGE("[SQLite] SetDataBaseProperty failed: %d", errCode);
152 goto END;
153 }
154
155 END:
156 if (errCode != E_OK && dbTemp != nullptr) {
157 (void)sqlite3_close_v2(dbTemp);
158 dbTemp = nullptr;
159 }
160
161 return errCode;
162 }
163
OpenDatabase(const OpenDbProperties & properties,sqlite3 * & db,bool setWal)164 int SQLiteUtils::OpenDatabase(const OpenDbProperties &properties, sqlite3 *&db, bool setWal)
165 {
166 {
167 // Only for register the sqlite3 log callback
168 std::lock_guard<std::mutex> lock(logMutex_);
169 if (!g_configLog) {
170 sqlite3_config(SQLITE_CONFIG_LOG, &SqliteLogCallback, &properties.createIfNecessary);
171 sqlite3_config(SQLITE_CONFIG_LOOKASIDE, 0, 0);
172 g_configLog = true;
173 }
174 }
175 sqlite3 *dbTemp = nullptr;
176 int errCode = CreateDataBase(properties, dbTemp, setWal);
177 if (errCode != E_OK) {
178 goto END;
179 }
180 errCode = RegisterJsonFunctions(dbTemp);
181 if (errCode != E_OK) {
182 goto END;
183 }
184 // Set the synchroized mode, default for full mode.
185 errCode = ExecuteRawSQL(dbTemp, SYNC_MODE_FULL_SQL);
186 if (errCode != E_OK) {
187 LOGE("SQLite sync mode failed: %d", errCode);
188 goto END;
189 }
190
191 if (!properties.isMemDb) {
192 errCode = SQLiteUtils::SetPersistWalMode(dbTemp);
193 if (errCode != E_OK) {
194 LOGE("SQLite set persist wall mode failed: %d", errCode);
195 }
196 }
197
198 END:
199 if (errCode != E_OK && dbTemp != nullptr) {
200 (void)sqlite3_close_v2(dbTemp);
201 dbTemp = nullptr;
202 }
203 if (errCode != E_OK && errno == EKEYREVOKED) {
204 errCode = -E_EKEYREVOKED;
205 }
206 db = dbTemp;
207 return errCode;
208 }
209
BindPrefixKey(sqlite3_stmt * statement,int index,const Key & keyPrefix)210 int SQLiteUtils::BindPrefixKey(sqlite3_stmt *statement, int index, const Key &keyPrefix)
211 {
212 if (statement == nullptr) {
213 return -E_INVALID_ARGS;
214 }
215
216 const size_t maxKeySize = DBConstant::MAX_KEY_SIZE;
217 // bind the first prefix key
218 int errCode = BindBlobToStatement(statement, index, keyPrefix, true);
219 if (errCode != SQLITE_OK) {
220 LOGE("Bind the prefix first error:%d", errCode);
221 return SQLiteUtils::MapSQLiteErrno(errCode);
222 }
223
224 // bind the second prefix key
225 uint8_t end[maxKeySize];
226 errno_t status = memset_s(end, maxKeySize, UCHAR_MAX, maxKeySize); // max byte value is 0xFF.
227 if (status != EOK) {
228 LOGE("memset error:%d", status);
229 return -E_SECUREC_ERROR;
230 }
231
232 if (!keyPrefix.empty()) {
233 status = memcpy_s(end, maxKeySize, keyPrefix.data(), keyPrefix.size());
234 if (status != EOK) {
235 LOGE("memcpy error:%d", status);
236 return -E_SECUREC_ERROR;
237 }
238 }
239
240 // index wouldn't be too large, just add one to the first index.
241 errCode = sqlite3_bind_blob(statement, index + 1, end, maxKeySize, SQLITE_TRANSIENT);
242 if (errCode != SQLITE_OK) {
243 LOGE("Bind the prefix second error:%d", errCode);
244 return SQLiteUtils::MapSQLiteErrno(errCode);
245 }
246 return E_OK;
247 }
248
SetKey(sqlite3 * db,CipherType type,const CipherPassword & passwd,bool setWal,uint32_t iterTimes)249 int SQLiteUtils::SetKey(sqlite3 *db, CipherType type, const CipherPassword &passwd, bool setWal, uint32_t iterTimes)
250 {
251 if (db == nullptr) {
252 return -E_INVALID_DB;
253 }
254
255 if (passwd.GetSize() != 0) {
256 #ifndef OMIT_ENCRYPT
257 int errCode = SetKeyInner(db, type, passwd, iterTimes);
258 if (errCode != E_OK) {
259 LOGE("[SQLiteUtils][Setkey] set keyInner failed:%d", errCode);
260 return errCode;
261 }
262 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_SQL);
263 if (errCode != E_OK) {
264 LOGE("[SQLiteUtils][Setkey] set sha algo failed:%d", errCode);
265 return errCode;
266 }
267 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_REKEY_SQL);
268 if (errCode != E_OK) {
269 LOGE("[SQLiteUtils][Setkey] set rekey sha algo failed:%d", errCode);
270 return errCode;
271 }
272 #else
273 return -E_NOT_SUPPORT;
274 #endif
275 }
276
277 // verify key
278 int errCode = SQLiteUtils::ExecuteRawSQL(db, USER_VERSION_SQL);
279 if (errCode != E_OK) {
280 LOGE("[SQLiteUtils][Setkey] verify version failed:%d", errCode);
281 if (errno == EKEYREVOKED) {
282 return -E_EKEYREVOKED;
283 }
284 if (errCode == -E_BUSY) {
285 return errCode;
286 }
287 #ifndef OMIT_ENCRYPT
288 if (passwd.GetSize() != 0) {
289 errCode = UpdateCipherShaAlgo(db, setWal, type, passwd, iterTimes);
290 if (errCode != E_OK) {
291 LOGE("[SQLiteUtils][Setkey] upgrade cipher sha algo failed:%d", errCode);
292 }
293 }
294 #endif
295 }
296 return errCode;
297 }
298
AttachNewDatabase(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)299 int SQLiteUtils::AttachNewDatabase(sqlite3 *db, CipherType type, const CipherPassword &password,
300 const std::string &attachDbAbsPath, const std::string &attachAsName)
301 {
302 #ifndef OMIT_ENCRYPT
303 int errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
304 if (errCode != E_OK) {
305 LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
306 return errCode;
307 }
308 #endif
309 errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
310 #ifndef OMIT_ENCRYPT
311 if (errCode == -E_INVALID_PASSWD_OR_CORRUPTED_DB) {
312 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA1_ALGO_ATTACH_SQL);
313 if (errCode != E_OK) {
314 LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha1 algo failed:%d", errCode);
315 return errCode;
316 }
317 errCode = AttachNewDatabaseInner(db, type, password, attachDbAbsPath, attachAsName);
318 if (errCode != E_OK) {
319 LOGE("[SQLiteUtils][AttachNewDatabase] attach db failed:%d", errCode);
320 return errCode;
321 }
322 errCode = SQLiteUtils::ExecuteRawSQL(db, SHA256_ALGO_ATTACH_SQL);
323 if (errCode != E_OK) {
324 LOGE("[SQLiteUtils][AttachNewDatabase] set attach sha256 algo failed:%d", errCode);
325 }
326 }
327 #endif
328 return errCode;
329 }
330
AttachNewDatabaseInner(sqlite3 * db,CipherType type,const CipherPassword & password,const std::string & attachDbAbsPath,const std::string & attachAsName)331 int SQLiteUtils::AttachNewDatabaseInner(sqlite3 *db, CipherType type, const CipherPassword &password,
332 const std::string &attachDbAbsPath, const std::string &attachAsName)
333 {
334 // example: "ATTACH '../new.db' AS backup KEY XXXX;"
335 std::string attachSql = "ATTACH ? AS " + attachAsName + " KEY ?;"; // Internal interface not need verify alias name
336
337 sqlite3_stmt* statement = nullptr;
338 int errCode = SQLiteUtils::GetStatement(db, attachSql, statement);
339 if (errCode != E_OK) {
340 return errCode;
341 }
342 // 1st is name.
343 errCode = sqlite3_bind_text(statement, 1, attachDbAbsPath.c_str(), attachDbAbsPath.length(), SQLITE_TRANSIENT);
344 if (errCode != SQLITE_OK) {
345 LOGE("Bind the attached db name failed:%d", errCode);
346 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
347 goto END;
348 }
349 // Passwords do not allow vector operations, so we can not use function BindBlobToStatement here.
350 errCode = sqlite3_bind_blob(statement, 2, static_cast<const void *>(password.GetData()), // 2 means password index.
351 password.GetSize(), SQLITE_TRANSIENT);
352 if (errCode != SQLITE_OK) {
353 LOGE("Bind the attached key failed:%d", errCode);
354 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
355 goto END;
356 }
357
358 errCode = SQLiteUtils::StepWithRetry(statement);
359 if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
360 LOGE("Execute the SQLite attach failed:%d", errCode);
361 goto END;
362 }
363 errCode = SQLiteUtils::ExecuteRawSQL(db, WAL_MODE_SQL);
364 if (errCode != E_OK) {
365 LOGE("Set journal mode failed: %d", errCode);
366 }
367
368 END:
369 int ret = E_OK;
370 SQLiteUtils::ResetStatement(statement, true, ret);
371 return errCode != E_OK ? errCode : ret;
372 }
373
CreateMetaDatabase(const std::string & metaDbPath)374 int SQLiteUtils::CreateMetaDatabase(const std::string &metaDbPath)
375 {
376 OpenDbProperties metaProperties {metaDbPath, true, false};
377 sqlite3 *db = nullptr;
378 int errCode = SQLiteUtils::OpenDatabase(metaProperties, db);
379 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
380 LOGE("[CreateMetaDatabase] Failed to create the meta database[%d]", errCode);
381 }
382 if (db != nullptr) { // LCOV_EXCL_BR_LINE
383 (void)sqlite3_close_v2(db);
384 db = nullptr;
385 }
386 return errCode;
387 }
388
CheckIntegrity(const std::string & dbFile,CipherType type,const CipherPassword & passwd)389 int SQLiteUtils::CheckIntegrity(const std::string &dbFile, CipherType type, const CipherPassword &passwd)
390 {
391 std::vector<std::string> createTableSqls;
392 OpenDbProperties option = {dbFile, true, false, createTableSqls, type, passwd};
393 sqlite3 *db = nullptr;
394 int errCode = SQLiteUtils::OpenDatabase(option, db);
395 if (errCode != E_OK) {
396 LOGE("CheckIntegrity, open db error:%d", errCode);
397 return errCode;
398 }
399 errCode = CheckIntegrity(db, CHECK_DB_INTEGRITY_SQL);
400 if (db != nullptr) {
401 (void)sqlite3_close_v2(db);
402 db = nullptr;
403 }
404 return errCode;
405 }
406
CheckIntegrity(sqlite3 * db,const std::string & sql)407 int SQLiteUtils::CheckIntegrity(sqlite3 *db, const std::string &sql)
408 {
409 sqlite3_stmt *statement = nullptr;
410 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
411 if (errCode != E_OK) {
412 LOGE("Prepare the integrity check statement error:%d", errCode);
413 return errCode;
414 }
415 int resultCnt = 0;
416 bool checkResultOK = false;
417 do {
418 errCode = SQLiteUtils::StepWithRetry(statement);
419 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
420 break;
421 } else if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
422 auto result = reinterpret_cast<const char *>(sqlite3_column_text(statement, 0));
423 if (result == nullptr) {
424 continue;
425 }
426 resultCnt = (resultCnt > 1) ? resultCnt : (resultCnt + 1);
427 if (strcmp(result, "ok") == 0) {
428 checkResultOK = true;
429 }
430 } else {
431 checkResultOK = false;
432 LOGW("Step for the integrity check failed:%d", errCode);
433 break;
434 }
435 } while (true);
436 if (resultCnt == 1 && checkResultOK) {
437 errCode = E_OK;
438 } else {
439 errCode = -E_INVALID_PASSWD_OR_CORRUPTED_DB;
440 }
441 int ret = E_OK;
442 SQLiteUtils::ResetStatement(statement, true, ret);
443 return errCode != E_OK ? errCode : ret;
444 }
445
446 #ifndef OMIT_ENCRYPT
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)447 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
448 const std::string &newDbName)
449 {
450 if (db == nullptr) {
451 return -E_INVALID_DB;
452 }
453
454 int errCode = AttachNewDatabase(db, type, passwd, newDbName);
455 if (errCode != E_OK) {
456 LOGE("Attach New Db fail!");
457 return errCode;
458 }
459 errCode = SQLiteUtils::ExecuteRawSQL(db, EXPORT_BACKUP_SQL);
460 if (errCode != E_OK) {
461 LOGE("Execute the SQLite export failed:%d", errCode);
462 }
463
464 int detachError = SQLiteUtils::ExecuteRawSQL(db, DETACH_BACKUP_SQL);
465 if (errCode == E_OK) {
466 errCode = detachError;
467 if (detachError != E_OK) {
468 LOGE("Execute the SQLite detach failed:%d", errCode);
469 }
470 }
471 return errCode;
472 }
473
Rekey(sqlite3 * db,const CipherPassword & passwd)474 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
475 {
476 if (db == nullptr) {
477 return -E_INVALID_DB;
478 }
479
480 int errCode = sqlite3_rekey(db, static_cast<const void *>(passwd.GetData()), static_cast<int>(passwd.GetSize()));
481 if (errCode != E_OK) {
482 LOGE("SQLite rekey failed:(%d)", errCode);
483 return SQLiteUtils::MapSQLiteErrno(errCode);
484 }
485
486 return E_OK;
487 }
488 #else
ExportDatabase(sqlite3 * db,CipherType type,const CipherPassword & passwd,const std::string & newDbName)489 int SQLiteUtils::ExportDatabase(sqlite3 *db, CipherType type, const CipherPassword &passwd,
490 const std::string &newDbName)
491 {
492 (void)db;
493 (void)type;
494 (void)passwd;
495 (void)newDbName;
496 return -E_NOT_SUPPORT;
497 }
498
Rekey(sqlite3 * db,const CipherPassword & passwd)499 int SQLiteUtils::Rekey(sqlite3 *db, const CipherPassword &passwd)
500 {
501 (void)db;
502 (void)passwd;
503 return -E_NOT_SUPPORT;
504 }
505 #endif
506
GetVersion(const OpenDbProperties & properties,int & version)507 int SQLiteUtils::GetVersion(const OpenDbProperties &properties, int &version)
508 {
509 if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
510 return -E_INVALID_ARGS;
511 }
512
513 sqlite3 *dbTemp = nullptr;
514 // Please make sure the database file exists and is working properly
515 std::string fileUrl = DBConstant::SQLITE_URL_PRE + properties.uri;
516 int errCode = sqlite3_open_v2(fileUrl.c_str(), &dbTemp, SQLITE_OPEN_URI | SQLITE_OPEN_READONLY, nullptr);
517 if (errCode != SQLITE_OK) { // LCOV_EXCL_BR_LINE
518 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
519 LOGE("Open database failed: %d, sys:%d", errCode, errno);
520 goto END;
521 }
522 // in memory mode no need cipher
523 if (!properties.isMemDb) { // LCOV_EXCL_BR_LINE
524 errCode = SQLiteUtils::SetKey(dbTemp, properties.cipherType, properties.passwd, false,
525 properties.iterTimes);
526 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
527 LOGE("Set key failed: %d", errCode);
528 goto END;
529 }
530 }
531
532 errCode = GetVersion(dbTemp, version);
533
534 END:
535 if (dbTemp != nullptr) { // LCOV_EXCL_BR_LINE
536 (void)sqlite3_close_v2(dbTemp);
537 dbTemp = nullptr;
538 }
539 return errCode;
540 }
541
GetVersion(sqlite3 * db,int & version)542 int SQLiteUtils::GetVersion(sqlite3 *db, int &version)
543 {
544 if (db == nullptr) {
545 return -E_INVALID_DB;
546 }
547
548 std::string strSql = "PRAGMA user_version;";
549 sqlite3_stmt *statement = nullptr;
550 int errCode = sqlite3_prepare(db, strSql.c_str(), -1, &statement, nullptr);
551 if (errCode != SQLITE_OK || statement == nullptr) {
552 LOGE("[SqlUtil][GetVer] sqlite3_prepare failed.");
553 errCode = SQLiteUtils::MapSQLiteErrno(errCode);
554 return errCode;
555 }
556 int ret = E_OK;
557 errCode = sqlite3_step(statement);
558 if (errCode == SQLITE_ROW) {
559 // Get pragma user_version at first column
560 version = sqlite3_column_int(statement, 0);
561 } else {
562 LOGE("[SqlUtil][GetVer] Get db user_version failed.");
563 ret = SQLiteUtils::MapSQLiteErrno(errCode);
564 }
565 errCode = E_OK;
566 SQLiteUtils::ResetStatement(statement, true, errCode);
567 return ret != E_OK ? ret : errCode;
568 }
569
GetJournalMode(sqlite3 * db,std::string & mode)570 int SQLiteUtils::GetJournalMode(sqlite3 *db, std::string &mode)
571 {
572 if (db == nullptr) {
573 return -E_INVALID_DB;
574 }
575
576 std::string sql = "PRAGMA journal_mode;";
577 sqlite3_stmt *statement = nullptr;
578 int errCode = SQLiteUtils::GetStatement(db, sql, statement);
579 if (errCode != E_OK || statement == nullptr) {
580 return errCode;
581 }
582
583 errCode = SQLiteUtils::StepWithRetry(statement);
584 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
585 errCode = SQLiteUtils::GetColumnTextValue(statement, 0, mode);
586 } else {
587 LOGE("[SqlUtil][GetJournal] Get db journal_mode failed.");
588 }
589
590 int ret = E_OK;
591 SQLiteUtils::ResetStatement(statement, true, ret);
592 return errCode != E_OK ? errCode : ret;
593 }
594
SetUserVer(const OpenDbProperties & properties,int version)595 int SQLiteUtils::SetUserVer(const OpenDbProperties &properties, int version)
596 {
597 if (properties.uri.empty()) { // LCOV_EXCL_BR_LINE
598 return -E_INVALID_ARGS;
599 }
600
601 // Please make sure the database file exists and is working properly
602 sqlite3 *db = nullptr;
603 int errCode = SQLiteUtils::OpenDatabase(properties, db);
604 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
605 return errCode;
606 }
607
608 // Set user version
609 errCode = SQLiteUtils::SetUserVer(db, version);
610 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
611 LOGE("Set user version fail: %d", errCode);
612 goto END;
613 }
614
615 END:
616 if (db != nullptr) { // LCOV_EXCL_BR_LINE
617 (void)sqlite3_close_v2(db);
618 db = nullptr;
619 }
620
621 return errCode;
622 }
623
SetUserVer(sqlite3 * db,int version)624 int SQLiteUtils::SetUserVer(sqlite3 *db, int version)
625 {
626 if (db == nullptr) {
627 return -E_INVALID_DB;
628 }
629 std::string userVersionSql = "PRAGMA user_version=" + std::to_string(version) + ";";
630 return SQLiteUtils::ExecuteRawSQL(db, userVersionSql);
631 }
632
SetBusyTimeout(sqlite3 * db,int timeout)633 int SQLiteUtils::SetBusyTimeout(sqlite3 *db, int timeout)
634 {
635 if (db == nullptr) {
636 return -E_INVALID_DB;
637 }
638
639 // Set the default busy handler to retry automatically before returning SQLITE_BUSY.
640 int errCode = sqlite3_busy_timeout(db, timeout);
641 if (errCode != SQLITE_OK) {
642 LOGE("[SQLite] set busy timeout failed:%d", errCode);
643 }
644
645 return SQLiteUtils::MapSQLiteErrno(errCode);
646 }
647
648 #ifndef OMIT_ENCRYPT
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)649 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
650 const std::string &targetFile, const CipherPassword &passwd)
651 {
652 std::vector<std::string> createTableSqls;
653 OpenDbProperties option = {srcFile, true, false, createTableSqls, type, srcPasswd};
654 sqlite3 *db = nullptr;
655 int errCode = SQLiteUtils::OpenDatabase(option, db);
656 if (errCode != E_OK) {
657 LOGE("Open db error while exporting:%d", errCode);
658 return errCode;
659 }
660
661 errCode = SQLiteUtils::ExportDatabase(db, type, passwd, targetFile);
662 if (db != nullptr) {
663 (void)sqlite3_close_v2(db);
664 db = nullptr;
665 }
666 return errCode;
667 }
668 #else
ExportDatabase(const std::string & srcFile,CipherType type,const CipherPassword & srcPasswd,const std::string & targetFile,const CipherPassword & passwd)669 int SQLiteUtils::ExportDatabase(const std::string &srcFile, CipherType type, const CipherPassword &srcPasswd,
670 const std::string &targetFile, const CipherPassword &passwd)
671 {
672 (void)srcFile;
673 (void)type;
674 (void)srcPasswd;
675 (void)targetFile;
676 (void)passwd;
677 return -E_NOT_SUPPORT;
678 }
679 #endif
680
SaveSchema(sqlite3 * db,const std::string & strSchema)681 int SQLiteUtils::SaveSchema(sqlite3 *db, const std::string &strSchema)
682 {
683 if (db == nullptr) {
684 return -E_INVALID_DB;
685 }
686
687 sqlite3_stmt *statement = nullptr;
688 std::string sql = "INSERT OR REPLACE INTO meta_data VALUES(?,?);";
689 int errCode = GetStatement(db, sql, statement);
690 if (errCode != E_OK) {
691 return errCode;
692 }
693
694 Key schemaKey;
695 DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemaKey);
696 errCode = BindBlobToStatement(statement, BIND_KEY_INDEX, schemaKey, false);
697 if (errCode != E_OK) {
698 ResetStatement(statement, true, errCode);
699 return errCode;
700 }
701
702 Value schemaValue;
703 DBCommon::StringToVector(strSchema, schemaValue);
704 errCode = BindBlobToStatement(statement, BIND_VAL_INDEX, schemaValue, false);
705 if (errCode != E_OK) {
706 ResetStatement(statement, true, errCode);
707 return errCode;
708 }
709
710 errCode = StepWithRetry(statement); // memory db does not support schema
711 if (errCode != MapSQLiteErrno(SQLITE_DONE)) {
712 LOGE("[SqlUtil][SetSchema] StepWithRetry fail, errCode=%d.", errCode);
713 ResetStatement(statement, true, errCode);
714 return errCode;
715 }
716 errCode = E_OK;
717 ResetStatement(statement, true, errCode);
718 return errCode;
719 }
720
GetSchema(sqlite3 * db,std::string & strSchema)721 int SQLiteUtils::GetSchema(sqlite3 *db, std::string &strSchema)
722 {
723 if (db == nullptr) {
724 return -E_INVALID_DB;
725 }
726
727 bool isExists = false;
728 int errCode = CheckTableExists(db, "meta_data", isExists);
729 if (errCode != E_OK || !isExists) {
730 LOGW("[GetSchema] err=%d, meta=%d", errCode, isExists);
731 return errCode;
732 }
733
734 sqlite3_stmt *statement = nullptr;
735 std::string sql = "SELECT value FROM meta_data WHERE key=?;";
736 errCode = GetStatement(db, sql, statement);
737 if (errCode != E_OK) {
738 return errCode;
739 }
740
741 Key schemakey;
742 DBCommon::StringToVector(DBConstant::SCHEMA_KEY, schemakey);
743 errCode = BindBlobToStatement(statement, 1, schemakey, false);
744 if (errCode != E_OK) {
745 ResetStatement(statement, true, errCode);
746 return errCode;
747 }
748
749 errCode = StepWithRetry(statement); // memory db does not support schema
750 if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
751 ResetStatement(statement, true, errCode);
752 return -E_NOT_FOUND;
753 } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
754 ResetStatement(statement, true, errCode);
755 return errCode;
756 }
757
758 Value schemaValue;
759 errCode = GetColumnBlobValue(statement, 0, schemaValue);
760 if (errCode != E_OK) {
761 ResetStatement(statement, true, errCode);
762 return errCode;
763 }
764 DBCommon::VectorToString(schemaValue, strSchema);
765 ResetStatement(statement, true, errCode);
766 return errCode;
767 }
768
IncreaseIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)769 int SQLiteUtils::IncreaseIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
770 uint32_t skipSize)
771 {
772 if (db == nullptr) {
773 LOGE("[IncreaseIndex] Sqlite DB not exists.");
774 return -E_INVALID_DB;
775 }
776 if (name.empty() || info.empty()) {
777 LOGE("[IncreaseIndex] Name or info can not be empty.");
778 return -E_NOT_PERMIT;
779 }
780 std::string indexName = SchemaUtils::FieldPathString(name);
781 std::string sqlCommand = "CREATE INDEX IF NOT EXISTS '" + indexName + "' ON sync_data (";
782 for (uint32_t i = 0; i < info.size(); i++) {
783 if (i != 0) {
784 sqlCommand += ", ";
785 }
786 std::string extractSql = SchemaObject::GenerateExtractSQL(type, info[i].first, info[i].second,
787 skipSize);
788 if (extractSql.empty()) { // Unlikely
789 LOGE("[IncreaseIndex] GenerateExtractSQL fail at field=%u.", i);
790 return -E_INTERNAL_ERROR;
791 }
792 sqlCommand += extractSql;
793 }
794 sqlCommand += ") WHERE (flag&0x01=0);";
795 return SQLiteUtils::ExecuteRawSQL(db, sqlCommand);
796 }
797
ChangeIndex(sqlite3 * db,const IndexName & name,const IndexInfo & info,SchemaType type,uint32_t skipSize)798 int SQLiteUtils::ChangeIndex(sqlite3 *db, const IndexName &name, const IndexInfo &info, SchemaType type,
799 uint32_t skipSize)
800 {
801 // Currently we change index by drop it then create it, SQLite "REINDEX" may be used in the future
802 int errCode = DecreaseIndex(db, name);
803 if (errCode != E_OK) {
804 LOGE("[ChangeIndex] Decrease fail=%d.", errCode);
805 return errCode;
806 }
807 errCode = IncreaseIndex(db, name, info, type, skipSize);
808 if (errCode != E_OK) {
809 LOGE("[ChangeIndex] Increase fail=%d.", errCode);
810 return errCode;
811 }
812 return E_OK;
813 }
814
DecreaseIndex(sqlite3 * db,const IndexName & name)815 int SQLiteUtils::DecreaseIndex(sqlite3 *db, const IndexName &name)
816 {
817 if (db == nullptr) {
818 LOGE("[DecreaseIndex] Sqlite DB not exists.");
819 return -E_INVALID_DB;
820 }
821 if (name.empty()) {
822 LOGE("[DecreaseIndex] Name can not be empty.");
823 return -E_NOT_PERMIT;
824 }
825 std::string indexName = SchemaUtils::FieldPathString(name);
826 std::string sqlCommand = "DROP INDEX IF EXISTS '" + indexName + "';";
827 return ExecuteRawSQL(db, sqlCommand);
828 }
829
RegisterJsonFunctions(sqlite3 * db)830 int SQLiteUtils::RegisterJsonFunctions(sqlite3 *db)
831 {
832 if (db == nullptr) {
833 LOGE("Sqlite DB not exists.");
834 return -E_INVALID_DB;
835 }
836 int errCode = sqlite3_create_function_v2(db, "calc_hash_key", 1, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
837 nullptr, &CalcHashKey, nullptr, nullptr, nullptr);
838 if (errCode != SQLITE_OK) {
839 LOGE("sqlite3_create_function_v2 about calc_hash_key returned %d", errCode);
840 return MapSQLiteErrno(errCode);
841 }
842 #ifdef USING_DB_JSON_EXTRACT_AUTOMATICALLY
843 // Specify need 3 parameter in json_extract_by_path function
844 errCode = sqlite3_create_function_v2(db, "json_extract_by_path", 3, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
845 nullptr, &JsonExtractByPath, nullptr, nullptr, nullptr);
846 if (errCode != SQLITE_OK) {
847 LOGE("sqlite3_create_function_v2 about json_extract_by_path returned %d", errCode);
848 return MapSQLiteErrno(errCode);
849 }
850 #endif
851 return E_OK;
852 }
853
854 namespace {
SchemaObjectDestructor(SchemaObject * inObject)855 void SchemaObjectDestructor(SchemaObject *inObject)
856 {
857 delete inObject;
858 inObject = nullptr;
859 }
860 }
861 #ifdef RELATIONAL_STORE
RegisterCalcHash(sqlite3 * db)862 int SQLiteUtils::RegisterCalcHash(sqlite3 *db)
863 {
864 TransactFunc func;
865 func.xFunc = &CalcHash;
866 return SQLiteUtils::RegisterFunction(db, "calc_hash", 2, nullptr, func); // 2 is params count
867 }
868
GetSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)869 void SQLiteUtils::GetSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
870 {
871 if (ctx == nullptr || argc != 1 || argv == nullptr) {
872 LOGE("Parameter does not meet restrictions.");
873 return;
874 }
875
876 sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
877 }
878
GetRawSysTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)879 void SQLiteUtils::GetRawSysTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
880 {
881 if (ctx == nullptr || argc != 0 || argv == nullptr) {
882 LOGE("Parameter does not meet restrictions.");
883 return;
884 }
885
886 uint64_t curTime = 0;
887 int errCode = TimeHelper::GetSysCurrentRawTime(curTime);
888 if (errCode != E_OK) {
889 sqlite3_result_error(ctx, "get raw sys time failed in sqlite utils.", errCode);
890 return;
891 }
892 sqlite3_result_int64(ctx, (sqlite3_int64)(curTime));
893 }
894
GetLastTime(sqlite3_context * ctx,int argc,sqlite3_value ** argv)895 void SQLiteUtils::GetLastTime(sqlite3_context *ctx, int argc, sqlite3_value **argv)
896 {
897 if (ctx == nullptr || argc != 0 || argv == nullptr) { // LCOV_EXCL_BR_LINE
898 LOGE("Parameter does not meet restrictions.");
899 return;
900 }
901 // Never used internally, just for sql prepare
902 sqlite3_result_int64(ctx, (sqlite3_int64)TimeHelper::GetSysCurrentTime());
903 }
904
CloudDataChangedObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)905 void SQLiteUtils::CloudDataChangedObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
906 {
907 if (ctx == nullptr || argc != 4 || argv == nullptr) { // 4 is param counts
908 return;
909 }
910 sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
911 }
912
CloudDataChangedServerObserver(sqlite3_context * ctx,int argc,sqlite3_value ** argv)913 void SQLiteUtils::CloudDataChangedServerObserver(sqlite3_context *ctx, int argc, sqlite3_value **argv)
914 {
915 if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 is param counts
916 return;
917 }
918 sqlite3 *db = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
919 std::string fileName;
920 if (!SQLiteRelationalUtils::GetDbFileName(db, fileName)) {
921 return;
922 }
923 auto tableNameChar = reinterpret_cast<const char *>(sqlite3_value_text(argv[0]));
924 if (tableNameChar == nullptr) {
925 return;
926 }
927 std::string tableName = static_cast<std::string>(tableNameChar);
928
929 uint64_t isTrackerChange = static_cast<uint64_t>(sqlite3_value_int(argv[1])); // 1 is param index
930 LOGD("Cloud data changed, server observer callback %u", isTrackerChange);
931 {
932 std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
933 auto itTable = g_serverChangedDataMap[fileName].find(tableName);
934 if (itTable != g_serverChangedDataMap[fileName].end()) {
935 itTable->second.isTrackedDataChange =
936 (static_cast<uint8_t>(itTable->second.isTrackedDataChange) | isTrackerChange) > 0;
937 } else {
938 DistributedDB::ChangeProperties properties = { .isTrackedDataChange = (isTrackerChange > 0) };
939 g_serverChangedDataMap[fileName].insert_or_assign(tableName, properties);
940 }
941 }
942 sqlite3_result_int64(ctx, static_cast<sqlite3_int64>(1));
943 }
944
GetAndResetServerObserverData(const std::string & dbName,const std::string & tableName,ChangeProperties & changeProperties)945 void SQLiteUtils::GetAndResetServerObserverData(const std::string &dbName, const std::string &tableName,
946 ChangeProperties &changeProperties)
947 {
948 std::lock_guard<std::mutex> lock(g_serverChangedDataMutex);
949 auto itDb = g_serverChangedDataMap.find(dbName);
950 if (itDb != g_serverChangedDataMap.end() && !itDb->second.empty()) {
951 auto itTable = itDb->second.find(tableName);
952 if (itTable == itDb->second.end()) {
953 return;
954 }
955 changeProperties = itTable->second;
956 g_serverChangedDataMap[dbName].erase(itTable);
957 }
958 }
959
RegisterGetSysTime(sqlite3 * db)960 int SQLiteUtils::RegisterGetSysTime(sqlite3 *db)
961 {
962 TransactFunc func;
963 func.xFunc = &GetSysTime;
964 return SQLiteUtils::RegisterFunction(db, "get_sys_time", 1, nullptr, func);
965 }
966
RegisterGetLastTime(sqlite3 * db)967 int SQLiteUtils::RegisterGetLastTime(sqlite3 *db)
968 {
969 TransactFunc func;
970 func.xFunc = &GetLastTime;
971 return SQLiteUtils::RegisterFunction(db, "get_last_time", 0, nullptr, func);
972 }
973
RegisterGetRawSysTime(sqlite3 * db)974 int SQLiteUtils::RegisterGetRawSysTime(sqlite3 *db)
975 {
976 TransactFunc func;
977 func.xFunc = &GetRawSysTime;
978 return SQLiteUtils::RegisterFunction(db, "get_raw_sys_time", 0, nullptr, func);
979 }
980
RegisterCloudDataChangeObserver(sqlite3 * db)981 int SQLiteUtils::RegisterCloudDataChangeObserver(sqlite3 *db)
982 {
983 TransactFunc func;
984 func.xFunc = &CloudDataChangedObserver;
985 return RegisterFunction(db, "client_observer", 4, db, func); // 4 is param counts
986 }
987
RegisterCloudDataChangeServerObserver(sqlite3 * db)988 int SQLiteUtils::RegisterCloudDataChangeServerObserver(sqlite3 *db)
989 {
990 TransactFunc func;
991 func.xFunc = &CloudDataChangedServerObserver;
992 return RegisterFunction(db, "server_observer", 2, db, func); // 2 is param counts
993 }
994
CreateSameStuTable(sqlite3 * db,const TableInfo & baseTbl,const std::string & newTableName)995 int SQLiteUtils::CreateSameStuTable(sqlite3 *db, const TableInfo &baseTbl, const std::string &newTableName)
996 {
997 std::string sql = "CREATE TABLE IF NOT EXISTS '" + newTableName + "' (";
998 const FieldInfoMap &fields = baseTbl.GetFields();
999 for (uint32_t cid = 0; cid < fields.size(); ++cid) {
1000 std::string fieldName = baseTbl.GetFieldName(cid);
1001 const auto &it = fields.find(fieldName);
1002 if (it == fields.end()) {
1003 return -E_INVALID_DB;
1004 }
1005 sql += "'" + fieldName + "' '" + it->second.GetDataType() + "'";
1006 if (it->second.IsNotNull()) {
1007 sql += " NOT NULL";
1008 }
1009 if (it->second.HasDefaultValue()) {
1010 sql += " DEFAULT " + it->second.GetDefaultValue();
1011 }
1012 sql += ",";
1013 }
1014 // base table has primary key
1015 if (!(baseTbl.GetPrimaryKey().size() == 1 && baseTbl.GetPrimaryKey().at(0) == "rowid")) {
1016 sql += " PRIMARY KEY (";
1017 for (const auto &it : baseTbl.GetPrimaryKey()) {
1018 sql += "'" + it.second + "',";
1019 }
1020 sql.pop_back();
1021 sql += "),";
1022 }
1023 sql.pop_back();
1024 sql += ");";
1025 int errCode = SQLiteUtils::ExecuteRawSQL(db, sql);
1026 if (errCode != E_OK) {
1027 LOGE("[SQLite] execute create table sql failed");
1028 }
1029 return errCode;
1030 }
1031
CloneIndexes(sqlite3 * db,const std::string & oriTableName,const std::string & newTableName)1032 int SQLiteUtils::CloneIndexes(sqlite3 *db, const std::string &oriTableName, const std::string &newTableName)
1033 {
1034 std::string sql =
1035 "SELECT 'CREATE ' || CASE WHEN il.'unique' THEN 'UNIQUE ' ELSE '' END || 'INDEX IF NOT EXISTS ' || '" +
1036 newTableName + "_' || il.name || ' ON ' || '" + newTableName +
1037 "' || '(' || GROUP_CONCAT(ii.name) || ');' "
1038 "FROM sqlite_master AS m,"
1039 "pragma_index_list(m.name) AS il,"
1040 "pragma_index_info(il.name) AS ii "
1041 "WHERE m.type='table' AND m.name='" + oriTableName + "' AND il.origin='c' "
1042 "GROUP BY il.name;";
1043 sqlite3_stmt *stmt = nullptr;
1044 int errCode = SQLiteUtils::GetStatement(db, sql, stmt);
1045 if (errCode != E_OK) {
1046 LOGE("Prepare the clone sql failed:%d", errCode);
1047 return errCode;
1048 }
1049
1050 std::vector<std::string> indexes;
1051 while (true) {
1052 errCode = SQLiteUtils::StepWithRetry(stmt, false);
1053 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_ROW)) {
1054 std::string indexSql;
1055 (void)GetColumnTextValue(stmt, 0, indexSql);
1056 indexes.emplace_back(indexSql);
1057 continue;
1058 }
1059 if (errCode == SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1060 errCode = E_OK;
1061 }
1062 (void)ResetStatement(stmt, true, errCode);
1063 break;
1064 }
1065
1066 if (errCode != E_OK) {
1067 return errCode;
1068 }
1069
1070 for (const auto &it : indexes) {
1071 errCode = SQLiteUtils::ExecuteRawSQL(db, it);
1072 if (errCode != E_OK) {
1073 LOGE("[SQLite] execute clone index sql failed");
1074 }
1075 }
1076 return errCode;
1077 }
1078
GetRelationalSchema(sqlite3 * db,std::string & schema,const std::string & key)1079 int SQLiteUtils::GetRelationalSchema(sqlite3 *db, std::string &schema, const std::string &key)
1080 {
1081 if (db == nullptr) {
1082 return -E_INVALID_DB;
1083 }
1084
1085 sqlite3_stmt *statement = nullptr;
1086 std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1087 int errCode = GetStatement(db, sql, statement);
1088 if (errCode != E_OK) {
1089 return errCode;
1090 }
1091
1092 Key schemakey;
1093 DBCommon::StringToVector(key, schemakey);
1094 errCode = BindBlobToStatement(statement, 1, schemakey, false);
1095 if (errCode != E_OK) {
1096 ResetStatement(statement, true, errCode);
1097 return errCode;
1098 }
1099
1100 errCode = StepWithRetry(statement);
1101 if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1102 ResetStatement(statement, true, errCode);
1103 return -E_NOT_FOUND;
1104 } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1105 ResetStatement(statement, true, errCode);
1106 return errCode;
1107 }
1108
1109 Value schemaValue;
1110 errCode = GetColumnBlobValue(statement, 0, schemaValue);
1111 if (errCode != E_OK) {
1112 ResetStatement(statement, true, errCode);
1113 return errCode;
1114 }
1115 DBCommon::VectorToString(schemaValue, schema);
1116 ResetStatement(statement, true, errCode);
1117 return errCode;
1118 }
1119
GetLogTableVersion(sqlite3 * db,std::string & version)1120 int SQLiteUtils::GetLogTableVersion(sqlite3 *db, std::string &version)
1121 {
1122 if (db == nullptr) {
1123 return -E_INVALID_DB;
1124 }
1125
1126 sqlite3_stmt *statement = nullptr;
1127 std::string sql = "SELECT value FROM " + std::string(DBConstant::RELATIONAL_PREFIX) + "metadata WHERE key=?;";
1128 int errCode = GetStatement(db, sql, statement);
1129 if (errCode != E_OK) {
1130 return errCode;
1131 }
1132
1133 Key logTableKey;
1134 DBCommon::StringToVector(DBConstant::LOG_TABLE_VERSION_KEY, logTableKey);
1135 errCode = BindBlobToStatement(statement, 1, logTableKey, false);
1136 if (errCode != E_OK) {
1137 ResetStatement(statement, true, errCode);
1138 return errCode;
1139 }
1140
1141 errCode = StepWithRetry(statement);
1142 if (errCode == MapSQLiteErrno(SQLITE_DONE)) {
1143 ResetStatement(statement, true, errCode);
1144 return -E_NOT_FOUND;
1145 } else if (errCode != MapSQLiteErrno(SQLITE_ROW)) {
1146 ResetStatement(statement, true, errCode);
1147 return errCode;
1148 }
1149
1150 Value value;
1151 errCode = GetColumnBlobValue(statement, 0, value);
1152 if (errCode != E_OK) {
1153 ResetStatement(statement, true, errCode);
1154 return errCode;
1155 }
1156 DBCommon::VectorToString(value, version);
1157 ResetStatement(statement, true, errCode);
1158 return errCode;
1159 }
1160
RegisterFunction(sqlite3 * db,const std::string & funcName,int nArg,void * uData,TransactFunc & func)1161 int SQLiteUtils::RegisterFunction(sqlite3 *db, const std::string &funcName, int nArg, void *uData, TransactFunc &func)
1162 {
1163 if (db == nullptr) {
1164 LOGE("Sqlite DB not exists.");
1165 return -E_INVALID_DB;
1166 }
1167
1168 int errCode = sqlite3_create_function_v2(db, funcName.c_str(), nArg, SQLITE_UTF8 | SQLITE_DETERMINISTIC, uData,
1169 func.xFunc, func.xStep, func.xFinal, func.xDestroy);
1170 if (errCode != SQLITE_OK) {
1171 LOGE("sqlite3_create_function_v2 about [%s] returned %d", funcName.c_str(), errCode);
1172 return MapSQLiteErrno(errCode);
1173 }
1174 return E_OK;
1175 }
1176 #endif
RegisterFlatBufferFunction(sqlite3 * db,const std::string & inSchema)1177 int SQLiteUtils::RegisterFlatBufferFunction(sqlite3 *db, const std::string &inSchema)
1178 {
1179 if (db == nullptr) {
1180 LOGE("Sqlite DB not exists.");
1181 return -E_INVALID_DB;
1182 }
1183 auto heapSchemaObj = new (std::nothrow) SchemaObject;
1184 if (heapSchemaObj == nullptr) {
1185 return -E_OUT_OF_MEMORY;
1186 }
1187 int errCode = heapSchemaObj->ParseFromSchemaString(inSchema);
1188 if (errCode != E_OK) { // Unlikely, it has been parsed before
1189 delete heapSchemaObj;
1190 heapSchemaObj = nullptr;
1191 return -E_INTERNAL_ERROR;
1192 }
1193 if (heapSchemaObj->GetSchemaType() != SchemaType::FLATBUFFER) { // Do not need to register FlatBufferExtract
1194 delete heapSchemaObj;
1195 heapSchemaObj = nullptr;
1196 return E_OK;
1197 }
1198 errCode = sqlite3_create_function_v2(db, SchemaObject::GetExtractFuncName(SchemaType::FLATBUFFER).c_str(),
1199 3, SQLITE_UTF8 | SQLITE_DETERMINISTIC, heapSchemaObj, &FlatBufferExtractByPath, nullptr, nullptr, // 3 args
1200 reinterpret_cast<void(*)(void*)>(SchemaObjectDestructor));
1201 // About the release of heapSchemaObj: SQLite guarantee that at following case, sqlite will invoke the destructor
1202 // (that is SchemaObjectDestructor) we passed to it. See sqlite.org for more information.
1203 // The destructor is invoked when the function is deleted, either by being overloaded or when the database
1204 // connection closes. The destructor is also invoked if the call to sqlite3_create_function_v2() fails
1205 if (errCode != SQLITE_OK) {
1206 LOGE("sqlite3_create_function_v2 about flatbuffer_extract_by_path return=%d.", errCode);
1207 // As mentioned above, SQLite had invoked the SchemaObjectDestructor to release the heapSchemaObj
1208 return MapSQLiteErrno(errCode);
1209 }
1210 return E_OK;
1211 }
1212
UpdateMetaDataWithinTrigger(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1213 void SQLiteUtils::UpdateMetaDataWithinTrigger(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1214 {
1215 if (ctx == nullptr || argc != 2 || argv == nullptr) { // 2 : Number of parameters for sqlite register function
1216 LOGE("[UpdateMetaDataWithinTrigger] Invalid parameter, argc=%d.", argc);
1217 return;
1218 }
1219 auto *handle = static_cast<sqlite3 *>(sqlite3_user_data(ctx));
1220 if (handle == nullptr) {
1221 sqlite3_result_error(ctx, "Sqlite context is invalid.", USING_STR_LEN);
1222 LOGE("Sqlite context is invalid.");
1223 return;
1224 }
1225 auto *keyPtr = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0])); // 0 : first argv for key
1226 int keyLen = sqlite3_value_bytes(argv[0]); // 0 : first argv for key
1227 if (keyPtr == nullptr || keyLen <= 0 || keyLen > static_cast<int>(DBConstant::MAX_KEY_SIZE)) {
1228 sqlite3_result_error(ctx, "key is invalid.", USING_STR_LEN);
1229 LOGE("key is invalid.");
1230 return;
1231 }
1232 auto val = sqlite3_value_int64(argv[1]); // 1 : second argv for value
1233
1234 sqlite3_stmt *stmt = nullptr;
1235 int errCode = SQLiteUtils::GetStatement(handle, UPDATE_META_SQL, stmt);
1236 if (errCode != E_OK) {
1237 sqlite3_result_error(ctx, "Get update meta_data statement failed.", USING_STR_LEN);
1238 LOGE("Get update meta_data statement failed. %d", errCode);
1239 return;
1240 }
1241
1242 Key key(keyPtr, keyPtr + keyLen);
1243 errCode = SQLiteUtils::BindBlobToStatement(stmt, BIND_KEY_INDEX, key, false);
1244 if (errCode != E_OK) {
1245 sqlite3_result_error(ctx, "Bind key to statement failed.", USING_STR_LEN);
1246 LOGE("Bind key to statement failed. %d", errCode);
1247 goto END;
1248 }
1249
1250 errCode = SQLiteUtils::BindInt64ToStatement(stmt, BIND_VAL_INDEX, val);
1251 if (errCode != E_OK) {
1252 sqlite3_result_error(ctx, "Bind value to statement failed.", USING_STR_LEN);
1253 LOGE("Bind value to statement failed. %d", errCode);
1254 goto END;
1255 }
1256
1257 errCode = SQLiteUtils::StepWithRetry(stmt, false);
1258 if (errCode != SQLiteUtils::MapSQLiteErrno(SQLITE_DONE)) {
1259 sqlite3_result_error(ctx, "Execute the update meta_data attach failed.", USING_STR_LEN);
1260 LOGE("Execute the update meta_data attach failed. %d", errCode);
1261 }
1262 END:
1263 SQLiteUtils::ResetStatement(stmt, true, errCode);
1264 }
1265
RegisterMetaDataUpdateFunction(sqlite3 * db)1266 int SQLiteUtils::RegisterMetaDataUpdateFunction(sqlite3 *db)
1267 {
1268 int errCode = sqlite3_create_function_v2(db, DBConstant::UPDATE_META_FUNC,
1269 2, // 2: argc for register function
1270 SQLITE_UTF8 | SQLITE_DETERMINISTIC, db, &SQLiteUtils::UpdateMetaDataWithinTrigger, nullptr, nullptr, nullptr);
1271 if (errCode != SQLITE_OK) {
1272 LOGE("sqlite3_create_function_v2 about update_meta_within_trigger returned %d", errCode);
1273 }
1274 return SQLiteUtils::MapSQLiteErrno(errCode);
1275 }
1276 } // namespace DistributedDB
1277