1 /*
2 * Copyright (c) 2022 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_connection.h"
17
18 #include <sqlite3sym.h>
19 #include <sys/stat.h>
20
21 #include <cerrno>
22 #include <memory>
23 #include <new>
24
25 #ifdef RDB_SUPPORT_ICU
26 #include <unicode/ucol.h>
27 #endif
28
29 #include <unistd.h>
30
31 #include "file_ex.h"
32 #include "logger.h"
33 #include "raw_data_parser.h"
34 #include "rdb_errno.h"
35 #include "sqlite_errno.h"
36 #include "sqlite_global_config.h"
37 #include "sqlite_utils.h"
38 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
39 #include "directory_ex.h"
40 #include "rdb_security_manager.h"
41 #include "relational/relational_store_sqlite_ext.h"
42 #include "relational_store_client.h"
43 #include "share_block.h"
44 #include "shared_block_serializer_info.h"
45 #endif
46
47 namespace OHOS {
48 namespace NativeRdb {
49 using namespace OHOS::Rdb;
50
51 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
52 // error status
53 const int ERROR_STATUS = -1;
54 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
55 using RdbKeyFile = RdbSecurityManager::KeyFileType;
56 #endif
57 #endif
58
Open(const RdbStoreConfig & config,bool isWriteConnection,int & errCode)59 std::shared_ptr<SqliteConnection> SqliteConnection::Open(
60 const RdbStoreConfig &config, bool isWriteConnection, int &errCode)
61 {
62 for (size_t i = 0; i < ITERS_COUNT; i++) {
63 std::shared_ptr<SqliteConnection> connection(new (std::nothrow) SqliteConnection(isWriteConnection));
64 if (connection == nullptr) {
65 LOG_ERROR("SqliteConnection::Open new failed, connection is nullptr");
66 return nullptr;
67 }
68 errCode = connection->InnerOpen(config, i);
69 if (errCode == E_OK) {
70 return connection;
71 }
72 }
73 return nullptr;
74 }
75
SqliteConnection(bool isWriteConnection)76 SqliteConnection::SqliteConnection(bool isWriteConnection)
77 : dbHandle(nullptr),
78 isWriteConnection(isWriteConnection),
79 isReadOnly(false),
80 statement(),
81 stepStatement(nullptr),
82 filePath(""),
83 openFlags(0),
84 inTransaction_(false)
85 {
86 }
87
GetDbPath(const RdbStoreConfig & config,std::string & dbPath)88 int SqliteConnection::GetDbPath(const RdbStoreConfig &config, std::string &dbPath)
89 {
90 if (config.GetStorageMode() == StorageMode::MODE_MEMORY) {
91 dbPath = SqliteGlobalConfig::GetMemoryDbPath();
92 } else if (config.GetPath().empty()) {
93 LOG_ERROR("SqliteConnection GetDbPath input empty database path");
94 return E_EMPTY_FILE_NAME;
95 } else if (config.GetPath().front() != '/' && config.GetPath().at(1) != ':') {
96 LOG_ERROR("SqliteConnection GetDbPath input relative path");
97 return E_RELATIVE_PATH;
98 } else {
99 dbPath = config.GetPath();
100 }
101 return E_OK;
102 }
103
InnerOpen(const RdbStoreConfig & config,uint32_t retry)104 int SqliteConnection::InnerOpen(const RdbStoreConfig &config, uint32_t retry)
105 {
106 std::string dbPath;
107 auto ret = GetDbPath(config, dbPath);
108 if (ret != E_OK) {
109 return ret;
110 }
111
112 stepStatement = std::make_shared<SqliteStatement>();
113 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
114 bool isDbFileExist = access(dbPath.c_str(), F_OK) == 0;
115 if (!isDbFileExist && (!config.IsCreateNecessary())) {
116 LOG_ERROR("SqliteConnection InnerOpen db not exist");
117 return E_DB_NOT_EXIST;
118 }
119 #endif
120 isReadOnly = !isWriteConnection || config.IsReadOnly();
121 int openFileFlags = config.IsReadOnly() ?
122 (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX) :
123 (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
124 int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle, openFileFlags, nullptr);
125 if (errCode != SQLITE_OK) {
126 LOG_ERROR("SqliteConnection InnerOpen fail to open database err = %{public}d", errCode);
127 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
128 auto const pos = dbPath.find_last_of("\\/");
129 if (pos != std::string::npos) {
130 std::string filepath = dbPath.substr(0, pos);
131 if (access(filepath.c_str(), F_OK | W_OK) != 0) {
132 LOG_ERROR("The path to the database file to be created is not valid, err = %{public}d", errno);
133 return E_INVALID_FILE_PATH;
134 }
135 }
136 #endif
137 return SQLiteError::ErrNo(errCode);
138 }
139 maxVariableNumber_ = sqlite3_limit(dbHandle, SQLITE_LIMIT_VARIABLE_NUMBER, -1);
140 errCode = Configure(config, retry, dbPath);
141 isConfigured_ = true;
142 if (errCode != E_OK) {
143 return errCode;
144 }
145
146 if (isWriteConnection) {
147 errCode = sqlite3_wal_checkpoint_v2(dbHandle, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr);
148 if (errCode != SQLITE_OK) {
149 LOG_WARN("sqlite checkpoint errCode is %{public}d", errCode);
150 }
151 }
152
153 filePath = dbPath;
154 openFlags = openFileFlags;
155
156 return E_OK;
157 }
158
SetCustomFunctions(const RdbStoreConfig & config)159 int SqliteConnection::SetCustomFunctions(const RdbStoreConfig &config)
160 {
161 customScalarFunctions_ = config.GetScalarFunctions();
162 for (auto &it : customScalarFunctions_) {
163 int errCode = SetCustomScalarFunction(it.first, it.second.argc_, &it.second.function_);
164 if (errCode != E_OK) {
165 return errCode;
166 }
167 }
168 return E_OK;
169 }
170
CustomScalarFunctionCallback(sqlite3_context * ctx,int argc,sqlite3_value ** argv)171 static void CustomScalarFunctionCallback(sqlite3_context *ctx, int argc, sqlite3_value **argv)
172 {
173 if (ctx == nullptr || argv == nullptr) {
174 LOG_ERROR("ctx or argv is nullptr");
175 return;
176 }
177 auto function = static_cast<ScalarFunction *>(sqlite3_user_data(ctx));
178 if (function == nullptr) {
179 LOG_ERROR("function is nullptr");
180 return;
181 }
182
183 std::vector<std::string> argsVector;
184 for (int i = 0; i < argc; ++i) {
185 auto arg = reinterpret_cast<const char*>(sqlite3_value_text(argv[i]));
186 if (arg == nullptr) {
187 LOG_ERROR("arg is nullptr, index is %{public}d", i);
188 sqlite3_result_null(ctx);
189 return;
190 }
191 argsVector.emplace_back(std::string(arg));
192 }
193
194 std::string result = (*function)(argsVector);
195 if (result.empty()) {
196 sqlite3_result_null(ctx);
197 return;
198 }
199 sqlite3_result_text(ctx, result.c_str(), -1, SQLITE_TRANSIENT);
200 }
201
SetCustomScalarFunction(const std::string & functionName,int argc,ScalarFunction * function)202 int SqliteConnection::SetCustomScalarFunction(const std::string &functionName, int argc, ScalarFunction *function)
203 {
204 int err = sqlite3_create_function_v2(dbHandle,
205 functionName.c_str(),
206 argc,
207 SQLITE_UTF8,
208 function,
209 &CustomScalarFunctionCallback,
210 nullptr,
211 nullptr,
212 nullptr);
213 if (err != SQLITE_OK) {
214 LOG_ERROR("SetCustomScalarFunction errCode is %{public}d", err);
215 }
216 return err;
217 }
218
Configure(const RdbStoreConfig & config,uint32_t retry,std::string & dbPath)219 int SqliteConnection::Configure(const RdbStoreConfig &config, uint32_t retry, std::string &dbPath)
220 {
221 if (retry >= ITERS_COUNT) {
222 return E_INVALID_ARGS;
223 }
224
225 if (config.GetStorageMode() == StorageMode::MODE_MEMORY) {
226 return E_OK;
227 }
228
229 auto errCode = RegDefaultFunctions(dbHandle);
230 if (errCode != E_OK) {
231 return errCode;
232 }
233
234 SetBusyTimeout(DEFAULT_BUSY_TIMEOUT_MS);
235 if (errCode != E_OK) {
236 return errCode;
237 }
238 LimitPermission(dbPath);
239
240 errCode = SetPersistWal();
241 if (errCode != E_OK) {
242 return errCode;
243 }
244
245 errCode = SetPageSize(config);
246 if (errCode != E_OK) {
247 return errCode;
248 }
249
250 errCode = SetEncryptKey(config, ITERS[retry]);
251 if (errCode != E_OK) {
252 return errCode;
253 }
254
255 errCode = SetJournalMode(config);
256 if (errCode != E_OK) {
257 return errCode;
258 }
259
260 errCode = SetJournalSizeLimit(config);
261 if (errCode != E_OK) {
262 return errCode;
263 }
264
265 errCode = SetAutoCheckpoint(config);
266 if (errCode != E_OK) {
267 return errCode;
268 }
269
270 errCode = SetCustomFunctions(config);
271 if (errCode != E_OK) {
272 return errCode;
273 }
274
275 return E_OK;
276 }
277
~SqliteConnection()278 SqliteConnection::~SqliteConnection()
279 {
280 if (dbHandle != nullptr) {
281 statement.Finalize();
282 if (stepStatement != nullptr) {
283 stepStatement->Finalize();
284 }
285 int errCode = sqlite3_close_v2(dbHandle);
286 if (errCode != SQLITE_OK) {
287 LOG_ERROR("SqliteConnection ~SqliteConnection: could not close database err = %{public}d", errCode);
288 }
289 }
290 }
291
SetPageSize(const RdbStoreConfig & config)292 int SqliteConnection::SetPageSize(const RdbStoreConfig &config)
293 {
294 if (isReadOnly || config.GetPageSize() == GlobalExpr::DB_PAGE_SIZE) {
295 return E_OK;
296 }
297
298 int targetValue = config.GetPageSize();
299 int64_t value = 0;
300 int errCode = ExecuteGetLong(value, "PRAGMA page_size");
301 if (errCode != E_OK) {
302 LOG_ERROR("SqliteConnection SetPageSize fail to get page size : %{public}d", errCode);
303 return errCode;
304 }
305
306 if (value == targetValue) {
307 return E_OK;
308 }
309
310 errCode = ExecuteSql("PRAGMA page_size=" + std::to_string(targetValue));
311 if (errCode != E_OK) {
312 LOG_ERROR("SqliteConnection SetPageSize fail to set page size : %{public}d", errCode);
313 }
314 return errCode;
315 }
316
317 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
ExecuteEncryptSql(const RdbStoreConfig & config,uint32_t iter)318 int SqliteConnection::ExecuteEncryptSql(const RdbStoreConfig &config, uint32_t iter)
319 {
320 int errCode = E_ERROR;
321 if (iter != NO_ITER) {
322 errCode = ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ALGO);
323 if (errCode != E_OK) {
324 LOG_ERROR("set cipher algo failed, err = %{public}d", errCode);
325 return errCode;
326 }
327 errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(iter));
328 if (errCode != E_OK) {
329 LOG_ERROR("set kdf iter number V1 failed, err = %{public}d", errCode);
330 return errCode;
331 }
332 }
333
334 errCode = ExecuteSql(GlobalExpr::CODEC_HMAC_ALGO);
335 if (errCode != E_OK) {
336 LOG_ERROR("set codec hmac algo failed, err = %{public}d", errCode);
337 return errCode;
338 }
339
340 errCode = ExecuteSql(GlobalExpr::CODEC_REKEY_HMAC_ALGO);
341 if (errCode != E_OK) {
342 LOG_ERROR("set rekey sha algo failed, err = %{public}d", errCode);
343 return errCode;
344 }
345
346 std::string version;
347 errCode = ExecuteGetString(version, GlobalExpr::PRAGMA_VERSION);
348 if (errCode != E_OK || version.empty()) {
349 LOG_ERROR("test failed, iter = %{public}d, err = %{public}d, name = %{public}s", iter, errCode,
350 config.GetName().c_str());
351 return errCode;
352 }
353
354 return errCode;
355 }
356
ReSetKey(const RdbStoreConfig & config)357 int SqliteConnection::ReSetKey(const RdbStoreConfig &config)
358 {
359 auto rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword(config.GetPath(), RdbKeyFile::PUB_KEY_FILE_NEW_KEY);
360 if (!rdbPwd.IsValid()) {
361 RdbSecurityManager::GetInstance().DelRdbSecretDataFile(config.GetPath(), RdbKeyFile::PUB_KEY_FILE_NEW_KEY);
362 LOG_ERROR("new key is not valid.");
363 return E_OK;
364 }
365
366 auto key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
367 int errCode = sqlite3_rekey(dbHandle, static_cast<const void *>(key.data()), static_cast<int>(key.size()));
368 key.assign(key.size(), 0);
369 if (errCode != SQLITE_OK) {
370 LOG_ERROR("ReKey failed, err = %{public}d", errCode);
371 RdbSecurityManager::GetInstance().DelRdbSecretDataFile(config.GetPath(), RdbKeyFile::PUB_KEY_FILE_NEW_KEY);
372 return E_OK;
373 }
374
375 RdbSecurityManager::GetInstance().UpdateKeyFile(config.GetPath());
376 return E_OK;
377 }
378 #endif
379
SetEncryptKey(const RdbStoreConfig & config,uint32_t iter)380 int SqliteConnection::SetEncryptKey(const RdbStoreConfig &config, uint32_t iter)
381 {
382 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
383 std::vector<uint8_t> key = config.GetEncryptKey();
384 bool isKeyExpired = false;
385 int32_t errCode = E_OK;
386 if (config.IsEncrypt()) {
387 errCode = RdbSecurityManager::GetInstance().Init(config.GetBundleName());
388 if (errCode != E_OK) {
389 key.assign(key.size(), 0);
390 return errCode;
391 }
392 auto rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword(config.GetPath(), RdbKeyFile::PUB_KEY_FILE);
393 key.assign(key.size(), 0);
394 key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
395 isKeyExpired = rdbPwd.isKeyExpired;
396 } else if (key.empty()) {
397 return E_OK;
398 }
399
400 errCode = sqlite3_key(dbHandle, static_cast<const void *>(key.data()), static_cast<int>(key.size()));
401 key.assign(key.size(), 0);
402 if (errCode != SQLITE_OK) {
403 if (RdbSecurityManager::GetInstance().IsKeyFileExists(config.GetPath(), RdbKeyFile::PUB_KEY_FILE_NEW_KEY)) {
404 auto rdbPwd =
405 RdbSecurityManager::GetInstance().GetRdbPassword(config.GetPath(), RdbKeyFile::PUB_KEY_FILE_NEW_KEY);
406 key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
407 errCode = sqlite3_key(dbHandle, static_cast<const void *>(key.data()), static_cast<int>(key.size()));
408 key.assign(key.size(), 0);
409 if (errCode != SQLITE_OK) {
410 LOG_ERROR("SqliteConnection SetEncryptKey fail with new key, err = %{public}d", errCode);
411 return SQLiteError::ErrNo(errCode);
412 }
413 RdbSecurityManager::GetInstance().UpdateKeyFile(config.GetPath());
414 }
415 if (errCode != SQLITE_OK) {
416 LOG_ERROR("SqliteConnection SetEncryptKey fail, err = %{public}d", errCode);
417 return SQLiteError::ErrNo(errCode);
418 }
419 }
420
421 errCode = ExecuteEncryptSql(config, iter);
422 if (errCode != E_OK) {
423 LOG_ERROR("execute encrypt sql failed, err = %{public}d", errCode);
424 return errCode;
425 }
426
427 if (isKeyExpired) {
428 ReSetKey(config);
429 }
430 #endif
431 return E_OK;
432 }
433
SetPersistWal()434 int SqliteConnection::SetPersistWal()
435 {
436 int opcode = 1;
437 int errCode = sqlite3_file_control(dbHandle, "main", SQLITE_FCNTL_PERSIST_WAL, &opcode);
438 if (errCode != SQLITE_OK) {
439 LOG_ERROR("failed");
440 return E_SET_PERSIST_WAL;
441 }
442 return E_OK;
443 }
444
SetBusyTimeout(int timeout)445 int SqliteConnection::SetBusyTimeout(int timeout)
446 {
447 auto errCode = sqlite3_busy_timeout(dbHandle, timeout);
448 if (errCode != SQLITE_OK) {
449 LOG_ERROR("set buys timeout failed, errCode=%{public}d", errCode);
450 return errCode;
451 }
452 return E_OK;
453 }
454
RegDefaultFunctions(sqlite3 * dbHandle)455 int SqliteConnection::RegDefaultFunctions(sqlite3 *dbHandle)
456 {
457 if (dbHandle == nullptr) {
458 return SQLITE_OK;
459 }
460 // The number of parameters is 2
461 return sqlite3_create_function_v2(dbHandle, "merge_assets", 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
462 &MergeAssets, nullptr, nullptr, nullptr);
463 }
464
SetJournalMode(const RdbStoreConfig & config)465 int SqliteConnection::SetJournalMode(const RdbStoreConfig &config)
466 {
467 if (isReadOnly || config.GetJournalMode().compare(GlobalExpr::DB_DEFAULT_JOURNAL_MODE) == 0) {
468 return E_OK;
469 }
470
471 std::string currentMode;
472 int errCode = ExecuteGetString(currentMode, "PRAGMA journal_mode");
473 if (errCode != E_OK) {
474 LOG_ERROR("SqliteConnection SetJournalMode fail to get journal mode : %{public}d", errCode);
475 return errCode;
476 }
477
478 currentMode = SqliteUtils::StrToUpper(currentMode);
479 if (currentMode != config.GetJournalMode()) {
480 std::string result;
481 int errorCode = ExecuteGetString(result, "PRAGMA journal_mode=" + config.GetJournalMode());
482 if (errorCode != E_OK) {
483 LOG_ERROR("SqliteConnection SetJournalMode: fail to set journal mode err=%{public}d", errorCode);
484 return errorCode;
485 }
486
487 if (SqliteUtils::StrToUpper(result) != config.GetJournalMode()) {
488 LOG_ERROR("SqliteConnection SetJournalMode: result incorrect");
489 return E_EXECUTE_RESULT_INCORRECT;
490 }
491 }
492
493 if (config.GetJournalMode() == "WAL") {
494 errCode = SetWalSyncMode(config.GetSyncMode());
495 }
496
497 return errCode;
498 }
499
SetJournalSizeLimit(const RdbStoreConfig & config)500 int SqliteConnection::SetJournalSizeLimit(const RdbStoreConfig &config)
501 {
502 if (isReadOnly || config.GetJournalSize() == GlobalExpr::DB_JOURNAL_SIZE) {
503 return E_OK;
504 }
505
506 int targetValue = SqliteGlobalConfig::GetJournalFileSize();
507 int64_t currentValue = 0;
508 int errCode = ExecuteGetLong(currentValue, "PRAGMA journal_size_limit");
509 if (errCode != E_OK) {
510 LOG_ERROR("SqliteConnection SetJournalSizeLimit fail to get journal_size_limit : %{public}d", errCode);
511 return errCode;
512 }
513
514 if (currentValue == targetValue) {
515 return E_OK;
516 }
517
518 int64_t result;
519 errCode = ExecuteGetLong(result, "PRAGMA journal_size_limit=" + std::to_string(targetValue));
520 if (errCode != E_OK) {
521 LOG_ERROR("SqliteConnection SetJournalSizeLimit fail to set journal_size_limit : %{public}d", errCode);
522 }
523 return errCode;
524 }
525
SetAutoCheckpoint(const RdbStoreConfig & config)526 int SqliteConnection::SetAutoCheckpoint(const RdbStoreConfig &config)
527 {
528 if (isReadOnly || config.IsAutoCheck() == GlobalExpr::DB_AUTO_CHECK) {
529 return E_OK;
530 }
531
532 int targetValue = SqliteGlobalConfig::GetWalAutoCheckpoint();
533 int64_t value = 0;
534 int errCode = ExecuteGetLong(value, "PRAGMA wal_autocheckpoint");
535 if (errCode != E_OK) {
536 LOG_ERROR("SqliteConnection SetAutoCheckpoint fail to get wal_autocheckpoint : %{public}d", errCode);
537 return errCode;
538 }
539
540 if (value == targetValue) {
541 return E_OK;
542 }
543
544 int64_t result;
545 errCode = ExecuteGetLong(result, "PRAGMA wal_autocheckpoint=" + std::to_string(targetValue));
546 if (errCode != E_OK) {
547 LOG_ERROR("SqliteConnection SetAutoCheckpoint fail to set wal_autocheckpoint : %{public}d", errCode);
548 }
549 return errCode;
550 }
551
SetWalSyncMode(const std::string & syncMode)552 int SqliteConnection::SetWalSyncMode(const std::string &syncMode)
553 {
554 std::string targetValue = SqliteGlobalConfig::GetWalSyncMode();
555 if (syncMode.length() != 0) {
556 targetValue = syncMode;
557 }
558
559 std::string value;
560 int errCode = ExecuteGetString(value, "PRAGMA synchronous");
561 if (errCode != E_OK) {
562 LOG_ERROR("SqliteConnection setWalSyncMode fail to get synchronous mode : %{public}d", errCode);
563 return errCode;
564 }
565
566 value = SqliteUtils::StrToUpper(value);
567 if (value == targetValue) {
568 return E_OK;
569 }
570
571 errCode = ExecuteSql("PRAGMA synchronous=" + targetValue);
572 if (errCode != E_OK) {
573 LOG_ERROR("SqliteConnection setWalSyncMode fail to set synchronous mode : %{public}d", errCode);
574 }
575 return errCode;
576 }
577
IsWriteConnection() const578 bool SqliteConnection::IsWriteConnection() const
579 {
580 return isWriteConnection;
581 }
582
Prepare(const std::string & sql,bool & outIsReadOnly)583 int SqliteConnection::Prepare(const std::string &sql, bool &outIsReadOnly)
584 {
585 int errCode = statement.Prepare(dbHandle, sql);
586 if (errCode != E_OK) {
587 return errCode;
588 }
589 outIsReadOnly = statement.IsReadOnly();
590 return E_OK;
591 }
592
PrepareAndBind(const std::string & sql,const std::vector<ValueObject> & bindArgs)593 int SqliteConnection::PrepareAndBind(const std::string &sql, const std::vector<ValueObject> &bindArgs)
594 {
595 if (dbHandle == nullptr) {
596 LOG_ERROR("SqliteConnection dbHandle is nullptr");
597 return E_INVALID_STATEMENT;
598 }
599
600 int errCode = LimitWalSize();
601 if (errCode != E_OK) {
602 return errCode;
603 }
604
605 errCode = statement.Prepare(dbHandle, sql);
606 if (errCode != E_OK) {
607 return errCode;
608 }
609
610 if (!isWriteConnection && !statement.IsReadOnly()) {
611 return E_EXECUTE_WRITE_IN_READ_CONNECTION;
612 }
613
614 errCode = statement.BindArguments(bindArgs);
615 return errCode;
616 }
617
ExecuteSql(const std::string & sql,const std::vector<ValueObject> & bindArgs)618 int SqliteConnection::ExecuteSql(const std::string &sql, const std::vector<ValueObject> &bindArgs)
619 {
620 int errCode = PrepareAndBind(sql, bindArgs);
621 if (errCode != E_OK) {
622 return errCode;
623 }
624
625 errCode = statement.Step();
626 if (errCode == SQLITE_ROW) {
627 LOG_ERROR("SqliteConnection Execute : Queries can be performed using query or QuerySql methods only");
628 statement.ResetStatementAndClearBindings();
629 return E_QUERY_IN_EXECUTE;
630 } else if (errCode != SQLITE_DONE) {
631 LOG_ERROR("SqliteConnection Execute : err %{public}d", errCode);
632 statement.ResetStatementAndClearBindings();
633 return SQLiteError::ErrNo(errCode);
634 }
635
636 errCode = statement.ResetStatementAndClearBindings();
637 return errCode;
638 }
639
ExecuteForChangedRowCount(int & changedRows,const std::string & sql,const std::vector<ValueObject> & bindArgs)640 int SqliteConnection::ExecuteForChangedRowCount(
641 int &changedRows, const std::string &sql, const std::vector<ValueObject> &bindArgs)
642 {
643 int errCode = PrepareAndBind(sql, bindArgs);
644 if (errCode != E_OK) {
645 return errCode;
646 }
647
648 errCode = statement.Step();
649 if (errCode == SQLITE_ROW) {
650 LOG_ERROR("SqliteConnection ExecuteForChangedRowCount : Queries can be performed using query or QuerySql "
651 "methods only");
652 statement.ResetStatementAndClearBindings();
653 return E_QUERY_IN_EXECUTE;
654 } else if (errCode != SQLITE_DONE) {
655 LOG_ERROR("SqliteConnection ExecuteForChangedRowCount : failed %{public}d", errCode);
656 statement.ResetStatementAndClearBindings();
657 return SQLiteError::ErrNo(errCode);
658 }
659
660 changedRows = sqlite3_changes(dbHandle);
661 errCode = statement.ResetStatementAndClearBindings();
662 return errCode;
663 }
664
ExecuteForLastInsertedRowId(int64_t & outRowId,const std::string & sql,const std::vector<ValueObject> & bindArgs)665 int SqliteConnection::ExecuteForLastInsertedRowId(
666 int64_t &outRowId, const std::string &sql, const std::vector<ValueObject> &bindArgs)
667 {
668 int errCode = PrepareAndBind(sql, bindArgs);
669 if (errCode != E_OK) {
670 return errCode;
671 }
672
673 errCode = statement.Step();
674 if (errCode == SQLITE_ROW) {
675 LOG_ERROR("SqliteConnection ExecuteForLastInsertedRowId : Queries can be performed using query or QuerySql "
676 "methods only");
677 statement.ResetStatementAndClearBindings();
678 return E_QUERY_IN_EXECUTE;
679 } else if (errCode != SQLITE_DONE) {
680 LOG_ERROR("SqliteConnection ExecuteForLastInsertedRowId : failed %{public}d", errCode);
681 statement.ResetStatementAndClearBindings();
682 return SQLiteError::ErrNo(errCode);
683 }
684
685 outRowId = (sqlite3_changes(dbHandle) > 0) ? sqlite3_last_insert_rowid(dbHandle) : -1;
686 errCode = statement.ResetStatementAndClearBindings();
687 return errCode;
688 }
689
ExecuteGetLong(int64_t & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)690 int SqliteConnection::ExecuteGetLong(
691 int64_t &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs)
692 {
693 int errCode = PrepareAndBind(sql, bindArgs);
694 if (errCode != E_OK) {
695 return errCode;
696 }
697
698 errCode = statement.Step();
699 if (errCode != SQLITE_ROW) {
700 statement.ResetStatementAndClearBindings();
701 LOG_ERROR("Maybe sql is not available here ERROR is %{public}d.", errCode);
702 return errCode;
703 }
704
705 errCode = statement.GetColumnLong(0, outValue);
706 if (errCode != E_OK) {
707 statement.ResetStatementAndClearBindings();
708 return errCode;
709 }
710
711 errCode = statement.ResetStatementAndClearBindings();
712 return errCode;
713 }
714
ExecuteGetString(std::string & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)715 int SqliteConnection::ExecuteGetString(
716 std::string &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs)
717 {
718 int errCode = PrepareAndBind(sql, bindArgs);
719 if (errCode != E_OK) {
720 return errCode;
721 }
722
723 errCode = statement.Step();
724 if (errCode != SQLITE_ROW) {
725 statement.ResetStatementAndClearBindings();
726 return E_NO_ROW_IN_QUERY;
727 }
728
729 errCode = statement.GetColumnString(0, outValue);
730 if (errCode != E_OK) {
731 statement.ResetStatementAndClearBindings();
732 return errCode;
733 }
734
735 errCode = statement.ResetStatementAndClearBindings();
736 return errCode;
737 }
738
BeginStepQuery(int & errCode,const std::string & sql,const std::vector<ValueObject> & args) const739 std::shared_ptr<SqliteStatement> SqliteConnection::BeginStepQuery(int &errCode, const std::string &sql,
740 const std::vector<ValueObject> &args) const
741 {
742 errCode = stepStatement->Prepare(dbHandle, sql);
743 if (errCode != E_OK) {
744 return nullptr;
745 }
746 errCode = stepStatement->BindArguments(args);
747 if (errCode != E_OK) {
748 return nullptr;
749 }
750 return stepStatement;
751 }
752
DesFinalize()753 int SqliteConnection::DesFinalize()
754 {
755 int errCode = 0;
756 errCode = statement.Finalize();
757 if (errCode != SQLITE_OK) {
758 return errCode;
759 }
760
761 errCode = stepStatement->Finalize();
762 if (errCode != SQLITE_OK) {
763 return errCode;
764 }
765
766 if (dbHandle != nullptr) {
767 sqlite3_db_release_memory(dbHandle);
768 }
769 return errCode;
770 }
771
EndStepQuery()772 int SqliteConnection::EndStepQuery()
773 {
774 return stepStatement->ResetStatementAndClearBindings();
775 }
776
LimitPermission(const std::string & dbPath) const777 void SqliteConnection::LimitPermission(const std::string &dbPath) const
778 {
779 struct stat st = { 0 };
780 if (stat(dbPath.c_str(), &st) == 0) {
781 if ((st.st_mode & (S_IXUSR | S_IXGRP | S_IRWXO)) != 0) {
782 int ret = chmod(dbPath.c_str(), st.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
783 if (ret != 0) {
784 LOG_DEBUG("SqliteConnection LimitPermission chmod fail, err = %{public}d", errno);
785 }
786 }
787 } else {
788 LOG_ERROR("SqliteConnection LimitPermission stat fail, err = %{public}d", errno);
789 }
790 }
791
792 #ifdef RDB_SUPPORT_ICU
Collate8Compare(void * p,int n1,const void * v1,int n2,const void * v2)793 int Collate8Compare(void *p, int n1, const void *v1, int n2, const void *v2)
794 {
795 UCollator *coll = reinterpret_cast<UCollator *>(p);
796 UCharIterator i1;
797 UCharIterator i2;
798 UErrorCode status = U_ZERO_ERROR;
799
800 uiter_setUTF8(&i1, (const char *)v1, n1);
801 uiter_setUTF8(&i2, (const char *)v2, n2);
802
803 UCollationResult result = ucol_strcollIter(coll, &i1, &i2, &status);
804
805 if (U_FAILURE(status)) {
806 LOG_ERROR("Ucol strcoll error.");
807 }
808
809 if (result == UCOL_LESS) {
810 return -1;
811 } else if (result == UCOL_GREATER) {
812 return 1;
813 }
814 return 0;
815 }
816
LocalizedCollatorDestroy(UCollator * collator)817 void LocalizedCollatorDestroy(UCollator *collator)
818 {
819 ucol_close(collator);
820 }
821
822 /**
823 * The database locale.
824 */
ConfigLocale(const std::string localeStr)825 int SqliteConnection::ConfigLocale(const std::string localeStr)
826 {
827 std::unique_lock<std::mutex> lock(rdbMutex);
828 UErrorCode status = U_ZERO_ERROR;
829 UCollator *collator = ucol_open(localeStr.c_str(), &status);
830 if (U_FAILURE(status)) {
831 LOG_ERROR("Can not open collator.");
832 return E_ERROR;
833 }
834 ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status);
835 if (U_FAILURE(status)) {
836 LOG_ERROR("Set attribute of collator failed.");
837 return E_ERROR;
838 }
839
840 int err = sqlite3_create_collation_v2(dbHandle, "LOCALES", SQLITE_UTF8, collator, Collate8Compare,
841 (void (*)(void *))LocalizedCollatorDestroy);
842 if (err != SQLITE_OK) {
843 LOG_ERROR("SCreate collator in sqlite3 failed.");
844 return err;
845 }
846
847 return E_OK;
848 }
849 #endif
850
851 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
852 /**
853 * Executes a statement and populates the specified with a range of results.
854 */
ExecuteForSharedBlock(int & rowNum,std::string sql,const std::vector<ValueObject> & bindArgs,AppDataFwk::SharedBlock * sharedBlock,int startPos,int requiredPos,bool isCountAllRows)855 int SqliteConnection::ExecuteForSharedBlock(int &rowNum, std::string sql, const std::vector<ValueObject> &bindArgs,
856 AppDataFwk::SharedBlock *sharedBlock, int startPos, int requiredPos, bool isCountAllRows)
857 {
858 if (sharedBlock == nullptr) {
859 LOG_ERROR("ExecuteForSharedBlock:sharedBlock is null.");
860 return E_ERROR;
861 }
862 SqliteConnectionS connection(this->dbHandle, this->openFlags, this->filePath);
863 int errCode = PrepareAndBind(sql, bindArgs);
864 if (errCode != E_OK) {
865 LOG_ERROR("PrepareAndBind sql and bindArgs error = %{public}d ", errCode);
866 return errCode;
867 }
868 if (ClearSharedBlock(sharedBlock) == ERROR_STATUS) {
869 LOG_ERROR("ExecuteForSharedBlock:sharedBlock is null.");
870 return E_ERROR;
871 }
872 sqlite3_stmt *tempSqlite3St = statement.GetSql3Stmt();
873 int columnNum = sqlite3_column_count(tempSqlite3St);
874 if (SharedBlockSetColumnNum(sharedBlock, columnNum) == ERROR_STATUS) {
875 LOG_ERROR("ExecuteForSharedBlock:sharedBlock is null.");
876 return E_ERROR;
877 }
878
879 SharedBlockInfo sharedBlockInfo(&connection, sharedBlock, tempSqlite3St);
880 sharedBlockInfo.requiredPos = requiredPos;
881 sharedBlockInfo.columnNum = columnNum;
882 sharedBlockInfo.isCountAllRows = isCountAllRows;
883 sharedBlockInfo.startPos = startPos;
884
885 int rc = sqlite3_db_config(connection.db, SQLITE_DBCONFIG_USE_SHAREDBLOCK);
886 if (rc == SQLITE_OK) {
887 FillSharedBlockOpt(&sharedBlockInfo);
888 } else {
889 FillSharedBlock(&sharedBlockInfo);
890 }
891
892 if (!ResetStatement(&sharedBlockInfo)) {
893 LOG_ERROR("ExecuteForSharedBlock:ResetStatement Failed.");
894 return E_ERROR;
895 }
896 sharedBlock->SetStartPos(sharedBlockInfo.startPos);
897 sharedBlock->SetBlockPos(requiredPos - sharedBlockInfo.startPos);
898 sharedBlock->SetLastPos(sharedBlockInfo.startPos + sharedBlock->GetRowNum());
899 rowNum = static_cast<int>(GetCombinedData(sharedBlockInfo.startPos, sharedBlockInfo.totalRows));
900 return statement.ResetStatementAndClearBindings();
901 }
902
CleanDirtyData(const std::string & table,uint64_t cursor)903 int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor)
904 {
905 if (table.empty()) {
906 return E_ERROR;
907 }
908 uint64_t tmpCursor = cursor == UINT64_MAX ? 0 : cursor;
909 auto status = DropLogicDeletedData(dbHandle, table, tmpCursor);
910 return status == DistributedDB::DBStatus::OK ? E_OK : E_ERROR;
911 }
912
RegisterCallBackObserver(const DataChangeCallback & clientChangedData)913 int SqliteConnection::RegisterCallBackObserver(const DataChangeCallback &clientChangedData)
914 {
915 if (isWriteConnection && clientChangedData != nullptr) {
916 int32_t status = RegisterClientObserver(dbHandle, clientChangedData);
917 if (status != E_OK) {
918 LOG_ERROR("RegisterClientObserver error, status:%{public}d", status);
919 }
920 return status;
921 }
922 return E_OK;
923 }
924 #endif
925
SetInTransaction(bool transaction)926 void SqliteConnection::SetInTransaction(bool transaction)
927 {
928 inTransaction_ = transaction;
929 }
930
IsInTransaction()931 bool SqliteConnection::IsInTransaction()
932 {
933 return inTransaction_;
934 }
935
TryCheckPoint()936 int SqliteConnection::TryCheckPoint()
937 {
938 std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle, "main"));
939 int fileSize = SqliteUtils::GetFileSize(walName);
940 if (fileSize <= GlobalExpr::DB_WAL_SIZE_LIMIT_MIN) {
941 return E_OK;
942 }
943 int errCode = sqlite3_wal_checkpoint_v2(dbHandle, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr);
944 if (errCode != SQLITE_OK) {
945 LOG_WARN("sqlite3_wal_checkpoint_v2 failed err %{public}d.", errCode);
946 return E_ERROR;
947 }
948 return E_OK;
949 }
950
LimitWalSize()951 int SqliteConnection::LimitWalSize()
952 {
953 if (!isConfigured_ || !isWriteConnection) {
954 return E_OK;
955 }
956
957 std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle, "main"));
958 int fileSize = SqliteUtils::GetFileSize(walName);
959 if (fileSize > GlobalExpr::DB_WAL_SIZE_LIMIT_MAX) {
960 LOG_ERROR("the WAL file size over default limit, %{public}s size is %{public}d",
961 SqliteUtils::Anonymous(walName).c_str(), fileSize);
962 return E_WAL_SIZE_OVER_LIMIT;
963 }
964 return E_OK;
965 }
966
MergeAssets(sqlite3_context * ctx,int argc,sqlite3_value ** argv)967 void SqliteConnection::MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value **argv)
968 {
969 // 2 is the number of parameters
970 if (ctx == nullptr || argc != 2 || argv == nullptr) {
971 LOG_ERROR("Parameter does not meet restrictions.");
972 return;
973 }
974 std::map<std::string, ValueObject::Asset> assets;
975 auto data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
976 if (data != nullptr) {
977 int len = sqlite3_value_bytes(argv[0]);
978 RawDataParser::ParserRawData(data, len, assets);
979 }
980 std::map<std::string, ValueObject::Asset> newAssets;
981 data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[1]));
982 if (data != nullptr) {
983 int len = sqlite3_value_bytes(argv[1]);
984 RawDataParser::ParserRawData(data, len, newAssets);
985 }
986 CompAssets(assets, newAssets);
987 auto blob = RawDataParser::PackageRawData(assets);
988 sqlite3_result_blob(ctx, blob.data(), blob.size(), SQLITE_TRANSIENT);
989 }
990
CompAssets(std::map<std::string,ValueObject::Asset> & assets,std::map<std::string,ValueObject::Asset> & newAssets)991 void SqliteConnection::CompAssets(std::map<std::string, ValueObject::Asset> &assets, std::map<std::string,
992 ValueObject::Asset> &newAssets)
993 {
994 using Status = ValueObject::Asset::Status;
995 auto oldIt = assets.begin();
996 auto newIt = newAssets.begin();
997 for (; oldIt != assets.end() && newIt != newAssets.end();) {
998 if (oldIt->first == newIt->first) {
999 if (newIt->second.status == Status::STATUS_DELETE) {
1000 oldIt->second.status = Status::STATUS_DELETE;
1001 oldIt->second.hash = "";
1002 oldIt->second.modifyTime = "";
1003 oldIt->second.size = "";
1004 } else {
1005 MergeAsset(oldIt->second, newIt->second);
1006 }
1007 oldIt++;
1008 newIt = newAssets.erase(newIt);
1009 continue;
1010 }
1011 if (oldIt->first < newIt->first) {
1012 ++oldIt;
1013 continue;
1014 }
1015 newIt++;
1016 }
1017 for (auto &[key, value] : newAssets) {
1018 value.status = ValueObject::Asset::Status::STATUS_INSERT;
1019 assets.insert(std::pair{key, std::move(value)});
1020 }
1021 }
1022
MergeAsset(ValueObject::Asset & oldAsset,ValueObject::Asset & newAsset)1023 void SqliteConnection::MergeAsset(ValueObject::Asset &oldAsset, ValueObject::Asset &newAsset)
1024 {
1025 using Status = ValueObject::Asset::Status;
1026 auto status = static_cast<int32_t>(oldAsset.status);
1027 switch (status) {
1028 case Status::STATUS_UNKNOWN: // fallthrough
1029 case Status::STATUS_NORMAL: // fallthrough
1030 case Status::STATUS_ABNORMAL: // fallthrough
1031 case Status::STATUS_INSERT: // fallthrough
1032 case Status::STATUS_UPDATE: // fallthrough
1033 if (oldAsset.modifyTime != newAsset.modifyTime || oldAsset.size != newAsset.size ||
1034 oldAsset.uri != newAsset.uri || oldAsset.path != newAsset.path) {
1035 oldAsset.version = newAsset.version;
1036 oldAsset.expiresTime = newAsset.expiresTime;
1037 oldAsset.uri = newAsset.uri;
1038 oldAsset.createTime = newAsset.createTime;
1039 oldAsset.modifyTime = newAsset.modifyTime;
1040 oldAsset.size = newAsset.size;
1041 oldAsset.hash = newAsset.hash;
1042 oldAsset.path = newAsset.path;
1043 oldAsset.status = Status ::STATUS_UPDATE;
1044 }
1045 return;
1046 default:
1047 return;
1048 }
1049 }
1050
GetMaxVariableNumber()1051 int SqliteConnection::GetMaxVariableNumber()
1052 {
1053 return maxVariableNumber_;
1054 }
1055 } // namespace NativeRdb
1056 } // namespace OHOS
1057