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 #define LOG_TAG "SqliteConnection"
17 #include "sqlite_connection.h"
18
19 #include <cerrno>
20 #include <memory>
21 #include <sqlite3sym.h>
22 #include <sstream>
23 #include <string>
24 #include <sys/stat.h>
25
26 #include "sqlite3.h"
27 #include "value_object.h"
28
29 #ifdef RDB_SUPPORT_ICU
30 #include <unicode/ucol.h>
31 #endif
32
33 #include <unistd.h>
34
35 #include "logger.h"
36 #include "raw_data_parser.h"
37 #include "rdb_errno.h"
38 #include "rdb_security_manager.h"
39 #include "rdb_sql_statistic.h"
40 #include "rdb_store_config.h"
41 #include "relational_store_client.h"
42 #include "sqlite_errno.h"
43 #include "sqlite_global_config.h"
44 #include "sqlite_utils.h"
45 #include "rdb_fault_hiview_reporter.h"
46 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
47 #include "relational/relational_store_sqlite_ext.h"
48 #include "rdb_manager_impl.h"
49 #endif
50 #include "task_executor.h"
51
52 namespace OHOS {
53 namespace NativeRdb {
54 using namespace OHOS::Rdb;
55 using namespace std::chrono;
56 using RdbKeyFile = RdbSecurityManager::KeyFileType;
57 using Reportor = RdbFaultHiViewReporter;
58 constexpr const char *INTEGRITIES[] = {nullptr, "PRAGMA quick_check", "PRAGMA integrity_check"};
59 constexpr SqliteConnection::Suffix SqliteConnection::FILE_SUFFIXES[];
60 constexpr const char *SqliteConnection::MERGE_ASSETS_FUNC;
61 constexpr const char *SqliteConnection::MERGE_ASSET_FUNC;
62 constexpr int SqliteConnection::DEFAULT_BUSY_TIMEOUT_MS;
63 constexpr int SqliteConnection::BACKUP_PAGES_PRE_STEP; // 1024 * 4 * 12800 == 50m
64 constexpr int SqliteConnection::BACKUP_PRE_WAIT_TIME;
65 constexpr ssize_t SqliteConnection::SLAVE_WAL_SIZE_LIMIT;
66 constexpr uint32_t SqliteConnection::NO_ITER;
67 constexpr uint32_t SqliteConnection::WAL_INDEX;
68 __attribute__((used))
69 const int32_t SqliteConnection::regCreator_ = Connection::RegisterCreator(DB_SQLITE, SqliteConnection::Create);
70 __attribute__((used))
71 const int32_t SqliteConnection::regRepairer_ = Connection::RegisterRepairer(DB_SQLITE, SqliteConnection::Repair);
72 __attribute__((used))
73 const int32_t SqliteConnection::regDeleter_ = Connection::RegisterDeleter(DB_SQLITE, SqliteConnection::Delete);
74 __attribute__((used))
75 const int32_t SqliteConnection::regCollector_ = Connection::RegisterCollector(DB_SQLITE, SqliteConnection::Collect);
76
Create(const RdbStoreConfig & config,bool isWrite)77 std::pair<int32_t, std::shared_ptr<Connection>> SqliteConnection::Create(const RdbStoreConfig &config, bool isWrite)
78 {
79 std::pair<int32_t, std::shared_ptr<Connection>> result = { E_ERROR, nullptr };
80 auto &[errCode, conn] = result;
81 std::tie(errCode, conn) = InnerCreate(config, isWrite);
82 return result;
83 }
84
Delete(const RdbStoreConfig & config)85 int32_t SqliteConnection::Delete(const RdbStoreConfig &config)
86 {
87 std::string path = config.GetPath();
88 std::string slavePath = SqliteUtils::GetSlavePath(path);
89 Delete(path);
90 Delete(slavePath);
91 return E_OK;
92 }
93
Delete(const std::string & path)94 int32_t SqliteConnection::Delete(const std::string &path)
95 {
96 for (const auto &suffix : FILE_SUFFIXES) {
97 SqliteUtils::DeleteFile(path + suffix.suffix_);
98 }
99 return E_OK;
100 }
101
Collect(const RdbStoreConfig & config)102 std::map<std::string, Connection::Info> SqliteConnection::Collect(const RdbStoreConfig &config)
103 {
104 std::map<std::string, Connection::Info> collection;
105 std::string path;
106 Info info;
107 SqliteGlobalConfig::GetDbPath(config, path);
108 for (auto &suffix : FILE_SUFFIXES) {
109 if (suffix.debug_ == nullptr) {
110 continue;
111 }
112 auto file = path + suffix.suffix_;
113 struct stat fileStat;
114 if (stat(file.c_str(), &fileStat) != 0) {
115 continue;
116 }
117 info.inode_ = fileStat.st_ino;
118 info.oldInode_ = 0;
119 info.atime_.sec_ = fileStat.st_atime;
120 info.mtime_.sec_ = fileStat.st_mtime;
121 info.ctime_.sec_ = fileStat.st_ctime;
122 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
123 info.atime_.nsec_ = fileStat.st_atim.tv_nsec;
124 info.mtime_.nsec_ = fileStat.st_mtim.tv_nsec;
125 info.ctime_.nsec_ = fileStat.st_ctim.tv_nsec;
126 #endif
127 info.size_ = fileStat.st_size;
128 info.dev_ = fileStat.st_dev;
129 info.mode_ = fileStat.st_mode;
130 info.uid_ = fileStat.st_uid;
131 info.gid_ = fileStat.st_gid;
132 collection.insert(std::pair{ suffix.debug_, info });
133 }
134 return collection;
135 }
136
SqliteConnection(const RdbStoreConfig & config,bool isWriteConnection)137 SqliteConnection::SqliteConnection(const RdbStoreConfig &config, bool isWriteConnection)
138 : dbHandle_(nullptr), isWriter_(isWriteConnection), isReadOnly_(false), maxVariableNumber_(0), filePath(""),
139 config_(config)
140 {
141 backupId_ = TaskExecutor::INVALID_TASK_ID;
142 }
143
CreateSlaveConnection(const RdbStoreConfig & config,bool checkSlaveExist)144 int SqliteConnection::CreateSlaveConnection(const RdbStoreConfig &config, bool checkSlaveExist)
145 {
146 if (config.GetHaMode() != HAMode::MAIN_REPLICA && config.GetHaMode() != HAMode::MANUAL_TRIGGER) {
147 return E_OK;
148 }
149 std::map<std::string, DebugInfo> bugInfo = Connection::Collect(config);
150 bool isSlaveExist = access(config.GetPath().c_str(), F_OK) == 0;
151 bool isSlaveLockExist = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false);
152 bool hasFailure = SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true);
153 bool walOverLimit = bugInfo.find(FILE_SUFFIXES[WAL_INDEX].debug_) != bugInfo.end() &&
154 bugInfo[FILE_SUFFIXES[WAL_INDEX].debug_].size_ > SLAVE_WAL_SIZE_LIMIT;
155 LOG_INFO("slave cfg:[%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d,%{public}d]%{public}s "
156 "%{public}s,[%{public}d,%{public}d,%{public}d,%{public}d]",
157 config.GetDBType(), config.GetHaMode(), config.IsEncrypt(), config.GetArea(), config.GetSecurityLevel(),
158 config.GetRoleType(), config.IsReadOnly(),
159 Reportor::FormatBrief(bugInfo, SqliteUtils::Anonymous(config.GetName())).c_str(),
160 Reportor::FormatBrief(Connection::Collect(config_), "master").c_str(), isSlaveExist, isSlaveLockExist,
161 hasFailure, walOverLimit);
162 if (config.GetHaMode() == HAMode::MANUAL_TRIGGER &&
163 (checkSlaveExist && (!isSlaveExist || isSlaveLockExist || hasFailure || walOverLimit))) {
164 if (walOverLimit) {
165 SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
166 }
167 return E_OK;
168 }
169
170 std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, true);
171 int errCode = connection->InnerOpen(config);
172 if (errCode != E_OK) {
173 SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
174 if (errCode == E_SQLITE_CORRUPT) {
175 LOG_WARN("slave corrupt, rebuild:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
176 (void)Delete(config.GetPath());
177 errCode = connection->InnerOpen(config);
178 if (errCode != E_OK) {
179 LOG_ERROR("reopen slave failed:%{public}d", errCode);
180 return errCode;
181 }
182 } else {
183 LOG_WARN("open slave failed:%{public}d, %{public}s", errCode,
184 SqliteUtils::Anonymous(config.GetPath()).c_str());
185 return errCode;
186 }
187 }
188 slaveConnection_ = connection;
189 return errCode;
190 }
191
GetSlaveRdbStoreConfig(const RdbStoreConfig & rdbConfig)192 RdbStoreConfig SqliteConnection::GetSlaveRdbStoreConfig(const RdbStoreConfig &rdbConfig)
193 {
194 RdbStoreConfig rdbStoreConfig(SqliteUtils::GetSlavePath(rdbConfig.GetPath()));
195 rdbStoreConfig.SetEncryptStatus(rdbConfig.IsEncrypt());
196 rdbStoreConfig.SetSearchable(rdbConfig.IsSearchable());
197 rdbStoreConfig.SetIsVector(rdbConfig.IsVector());
198 rdbStoreConfig.SetAutoClean(rdbConfig.GetAutoClean());
199 rdbStoreConfig.SetSecurityLevel(rdbConfig.GetSecurityLevel());
200 rdbStoreConfig.SetDataGroupId(rdbConfig.GetDataGroupId());
201 rdbStoreConfig.SetName(SqliteUtils::GetSlavePath(rdbConfig.GetName()));
202 rdbStoreConfig.SetCustomDir(rdbConfig.GetCustomDir());
203 rdbStoreConfig.SetAllowRebuild(rdbConfig.GetAllowRebuild());
204 rdbStoreConfig.SetReadOnly(rdbConfig.IsReadOnly());
205 rdbStoreConfig.SetAutoCheck(rdbConfig.IsAutoCheck());
206 rdbStoreConfig.SetCreateNecessary(rdbConfig.IsCreateNecessary());
207 rdbStoreConfig.SetJournalSize(rdbConfig.GetJournalSize());
208 rdbStoreConfig.SetPageSize(rdbConfig.GetPageSize());
209 rdbStoreConfig.SetReadConSize(rdbConfig.GetReadConSize());
210 rdbStoreConfig.SetReadTime(rdbConfig.GetReadTime());
211 rdbStoreConfig.SetDBType(rdbConfig.GetDBType());
212 rdbStoreConfig.SetVisitorDir(rdbConfig.GetVisitorDir());
213 rdbStoreConfig.SetScalarFunctions(rdbConfig.GetScalarFunctions());
214 rdbStoreConfig.SetJournalMode(rdbConfig.GetJournalMode());
215
216 rdbStoreConfig.SetModuleName(rdbConfig.GetModuleName());
217 rdbStoreConfig.SetPluginLibs(rdbConfig.GetPluginLibs());
218 rdbStoreConfig.SetHaMode(rdbConfig.GetHaMode());
219
220 rdbStoreConfig.SetCryptoParam(rdbConfig.GetCryptoParam());
221 return rdbStoreConfig;
222 }
223
InnerOpen(const RdbStoreConfig & config)224 int SqliteConnection::InnerOpen(const RdbStoreConfig &config)
225 {
226 std::string dbPath;
227 auto errCode = SqliteGlobalConfig::GetDbPath(config, dbPath);
228 if (errCode != E_OK) {
229 return errCode;
230 }
231
232 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
233 bool isDbFileExist = access(dbPath.c_str(), F_OK) == 0;
234 if (!isDbFileExist && (!config.IsCreateNecessary())) {
235 LOG_ERROR("db not exist errno is %{public}d", errno);
236 return E_DB_NOT_EXIST;
237 }
238 #endif
239 isReadOnly_ = !isWriter_ || config.IsReadOnly();
240 int openFileFlags = config.IsReadOnly() ? (SQLITE_OPEN_READONLY | SQLITE_OPEN_FULLMUTEX)
241 : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX);
242 errCode = OpenDatabase(dbPath, openFileFlags);
243 if (errCode != E_OK) {
244 return errCode;
245 }
246
247 maxVariableNumber_ = sqlite3_limit(dbHandle_, SQLITE_LIMIT_VARIABLE_NUMBER, -1);
248 errCode = Configure(config, dbPath);
249 isConfigured_ = true;
250 if (errCode != E_OK) {
251 return errCode;
252 }
253
254 if (isWriter_) {
255 ValueObject checkResult{"ok"};
256 auto index = static_cast<uint32_t>(config.GetIntegrityCheck());
257 if (index < static_cast<uint32_t>(sizeof(INTEGRITIES) / sizeof(INTEGRITIES[0]))) {
258 auto sql = INTEGRITIES[index];
259 if (sql != nullptr) {
260 LOG_INFO("%{public}s : %{public}s, ", sql, SqliteUtils::Anonymous(config.GetName()).c_str());
261 std::tie(errCode, checkResult) = ExecuteForValue(sql);
262 }
263 if (errCode == E_OK && static_cast<std::string>(checkResult) != "ok") {
264 LOG_ERROR("%{public}s integrity check result is %{public}s, sql:%{public}s",
265 SqliteUtils::Anonymous(config.GetName()).c_str(),
266 static_cast<std::string>(checkResult).c_str(), sql);
267 Reportor::ReportFault(Reportor::Create(config, errCode, static_cast<std::string>(checkResult)));
268 }
269 }
270 }
271
272 filePath = dbPath;
273 return E_OK;
274 }
275
OpenDatabase(const std::string & dbPath,int openFileFlags)276 int32_t SqliteConnection::OpenDatabase(const std::string &dbPath, int openFileFlags)
277 {
278 int errCode = sqlite3_open_v2(dbPath.c_str(), &dbHandle_, openFileFlags, nullptr);
279 if (errCode != SQLITE_OK) {
280 LOG_ERROR("fail to open database errCode=%{public}d, dbPath=%{public}s, flags=%{public}d, errno=%{public}d",
281 errCode, SqliteUtils::Anonymous(dbPath).c_str(), openFileFlags, errno);
282 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
283 auto const pos = dbPath.find_last_of("\\/");
284 if (pos != std::string::npos) {
285 std::string filepath = dbPath.substr(0, pos);
286 if (access(filepath.c_str(), F_OK | W_OK) != 0) {
287 LOG_ERROR("The path to the database file to be created is not valid, err = %{public}d", errno);
288 return E_INVALID_FILE_PATH;
289 }
290 }
291 #endif
292 return SQLiteError::ErrNo(errCode);
293 }
294 return E_OK;
295 }
296
SetCustomFunctions(const RdbStoreConfig & config)297 int SqliteConnection::SetCustomFunctions(const RdbStoreConfig &config)
298 {
299 customScalarFunctions_ = config.GetScalarFunctions();
300 for (auto &it : customScalarFunctions_) {
301 int errCode = SetCustomScalarFunction(it.first, it.second.argc_, &it.second.function_);
302 if (errCode != E_OK) {
303 return errCode;
304 }
305 }
306 return E_OK;
307 }
308
CustomScalarFunctionCallback(sqlite3_context * ctx,int argc,sqlite3_value ** argv)309 static void CustomScalarFunctionCallback(sqlite3_context *ctx, int argc, sqlite3_value **argv)
310 {
311 if (ctx == nullptr || argv == nullptr) {
312 LOG_ERROR("ctx or argv is nullptr.");
313 return;
314 }
315 auto function = static_cast<ScalarFunction *>(sqlite3_user_data(ctx));
316 if (function == nullptr) {
317 LOG_ERROR("function is nullptr.");
318 return;
319 }
320
321 std::vector<std::string> argsVector;
322 for (int i = 0; i < argc; ++i) {
323 auto arg = reinterpret_cast<const char *>(sqlite3_value_text(argv[i]));
324 if (arg == nullptr) {
325 LOG_ERROR("arg is nullptr, index is %{public}d, errno is %{public}d", i, errno);
326 sqlite3_result_null(ctx);
327 return;
328 }
329 argsVector.emplace_back(std::string(arg));
330 }
331
332 std::string result = (*function)(argsVector);
333 if (result.empty()) {
334 sqlite3_result_null(ctx);
335 return;
336 }
337 sqlite3_result_text(ctx, result.c_str(), -1, SQLITE_TRANSIENT);
338 }
339
SetCustomScalarFunction(const std::string & functionName,int argc,ScalarFunction * function)340 int SqliteConnection::SetCustomScalarFunction(const std::string &functionName, int argc, ScalarFunction *function)
341 {
342 int err = sqlite3_create_function_v2(dbHandle_, functionName.c_str(), argc, SQLITE_UTF8, function,
343 &CustomScalarFunctionCallback, nullptr, nullptr, nullptr);
344 if (err != SQLITE_OK) {
345 LOG_ERROR("SetCustomScalarFunction errCode is %{public}d, errno is %{public}d.", err, errno);
346 }
347 return err;
348 }
349
Configure(const RdbStoreConfig & config,std::string & dbPath)350 int SqliteConnection::Configure(const RdbStoreConfig &config, std::string &dbPath)
351 {
352 if (config.GetStorageMode() == StorageMode::MODE_MEMORY) {
353 return E_OK;
354 }
355
356 if (config.GetRoleType() == VISITOR) {
357 return E_OK;
358 }
359
360 auto errCode = RegDefaultFunctions(dbHandle_);
361 if (errCode != E_OK) {
362 return errCode;
363 }
364
365 SetBusyTimeout(DEFAULT_BUSY_TIMEOUT_MS);
366
367 LimitPermission(dbPath);
368
369 errCode = SetPersistWal();
370 if (errCode != E_OK) {
371 return errCode;
372 }
373
374 errCode = SetPageSize(config);
375 if (errCode != E_OK) {
376 return errCode;
377 }
378
379 errCode = SetEncrypt(config);
380 if (errCode != E_OK) {
381 return errCode;
382 }
383
384 errCode = SetJournalMode(config);
385 if (errCode != E_OK) {
386 return errCode;
387 }
388
389 // set the user version to the wal file;
390 SetWalFile(config);
391
392 errCode = SetJournalSizeLimit(config);
393 if (errCode != E_OK) {
394 return errCode;
395 }
396
397 errCode = SetAutoCheckpoint(config);
398 if (errCode != E_OK) {
399 return errCode;
400 }
401
402 errCode = SetCustomFunctions(config);
403 if (errCode != E_OK) {
404 return errCode;
405 }
406 return LoadExtension(config, dbHandle_);
407 }
408
~SqliteConnection()409 SqliteConnection::~SqliteConnection()
410 {
411 if (backupId_ != TaskExecutor::INVALID_TASK_ID) {
412 auto pool = TaskExecutor::GetInstance().GetExecutor();
413 if (pool != nullptr) {
414 pool->Remove(backupId_, true);
415 }
416 }
417 if (dbHandle_ != nullptr) {
418 if (hasClientObserver_) {
419 UnRegisterClientObserver(dbHandle_);
420 }
421 if (isWriter_) {
422 UnregisterStoreObserver(dbHandle_);
423 }
424
425 int errCode = sqlite3_close_v2(dbHandle_);
426 if (errCode != SQLITE_OK) {
427 LOG_ERROR("could not close database err = %{public}d, errno = %{public}d", errCode, errno);
428 }
429 }
430 }
431
OnInitialize()432 int32_t SqliteConnection::OnInitialize()
433 {
434 return 0;
435 }
436
CreateStatement(const std::string & sql,std::shared_ptr<Connection> conn)437 std::pair<int, std::shared_ptr<Statement>> SqliteConnection::CreateStatement(
438 const std::string &sql, std::shared_ptr<Connection> conn)
439 {
440 std::shared_ptr<SqliteStatement> statement = std::make_shared<SqliteStatement>();
441 statement->config_ = &config_;
442 int errCode = statement->Prepare(dbHandle_, sql);
443 if (errCode != E_OK) {
444 return { errCode, nullptr };
445 }
446 statement->conn_ = conn;
447 if (slaveConnection_ && IsWriter()) {
448 auto slaveStmt = std::make_shared<SqliteStatement>();
449 slaveStmt->config_ = &slaveConnection_->config_;
450 errCode = slaveStmt->Prepare(slaveConnection_->dbHandle_, sql);
451 if (errCode != E_OK) {
452 LOG_WARN("prepare slave stmt failed:%{public}d, sql:%{public}s", errCode, sql.c_str());
453 SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true, true);
454 return { E_OK, statement };
455 }
456 statement->slave_ = slaveStmt;
457 }
458 return { E_OK, statement };
459 }
460
IsWriter() const461 bool SqliteConnection::IsWriter() const
462 {
463 return isWriter_;
464 }
465
SubscribeTableChanges(const Connection::Notifier & notifier)466 int SqliteConnection::SubscribeTableChanges(const Connection::Notifier ¬ifier)
467 {
468 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
469 if (!isWriter_ || notifier == nullptr) {
470 return E_OK;
471 }
472 hasClientObserver_ = true;
473 int32_t status = RegisterClientObserver(dbHandle_, [notifier](const ClientChangedData &clientData) {
474 std::set<std::string> tables;
475 for (auto &[key, val] : clientData.tableData) {
476 if (val.isTrackedDataChange) {
477 tables.insert(key);
478 }
479 }
480 notifier(tables);
481 });
482 if (status != E_OK) {
483 LOG_ERROR("RegisterClientObserver error, status:%{public}d", status);
484 }
485 return status;
486 #endif
487 return E_OK;
488 }
489
GetMaxVariable() const490 int SqliteConnection::GetMaxVariable() const
491 {
492 return maxVariableNumber_;
493 }
494
GetJournalMode()495 int32_t SqliteConnection::GetJournalMode()
496 {
497 return (int32_t)mode_;
498 }
499
GetDBType() const500 int32_t SqliteConnection::GetDBType() const
501 {
502 return DB_SQLITE;
503 }
504
SetPageSize(const RdbStoreConfig & config)505 int SqliteConnection::SetPageSize(const RdbStoreConfig &config)
506 {
507 if (isReadOnly_ || config.GetPageSize() == GlobalExpr::DB_PAGE_SIZE) {
508 return E_OK;
509 }
510
511 int targetValue = config.GetPageSize();
512 auto [errCode, object] = ExecuteForValue("PRAGMA page_size");
513 if (errCode != E_OK) {
514 LOG_ERROR("SetPageSize fail to get page size : %{public}d", errCode);
515 return errCode;
516 }
517
518 if (static_cast<int64_t>(object) == targetValue) {
519 return E_OK;
520 }
521
522 errCode = ExecuteSql("PRAGMA page_size=" + std::to_string(targetValue));
523 if (errCode != E_OK) {
524 LOG_ERROR("SetPageSize fail to set page size : %{public}d", errCode);
525 }
526 return errCode;
527 }
528
SetEncryptAgo(const RdbStoreConfig & config)529 int SqliteConnection::SetEncryptAgo(const RdbStoreConfig &config)
530 {
531 if (!config.GetCryptoParam().IsValid()) {
532 LOG_ERROR("Invalid crypto param: %{public}s, %{public}d, %{public}d, %{public}d, %{public}d, %{public}u",
533 SqliteUtils::Anonymous(config.GetName()).c_str(), config.GetCryptoParam().iterNum,
534 config.GetCryptoParam().encryptAlgo, config.GetCryptoParam().hmacAlgo, config.GetCryptoParam().kdfAlgo,
535 config.GetCryptoParam().cryptoPageSize);
536 return E_INVALID_ARGS;
537 }
538
539 if (config.GetIter() != NO_ITER) {
540 auto errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_ALGO_PREFIX) +
541 SqliteUtils::EncryptAlgoDescription(config.GetEncryptAlgo()) +
542 std::string(GlobalExpr::ALGO_SUFFIX));
543 if (errCode != E_OK) {
544 LOG_ERROR("set cipher algo failed, err = %{public}d", errCode);
545 return errCode;
546 }
547
548 errCode = ExecuteSql(std::string(GlobalExpr::CIPHER_KDF_ITER) + std::to_string(config.GetIter()));
549 if (errCode != E_OK) {
550 LOG_ERROR("set kdf iter number V1 failed, err = %{public}d", errCode);
551 return errCode;
552 }
553 }
554
555 auto errCode = ExecuteSql(std::string(GlobalExpr::CODEC_HMAC_ALGO_PREFIX) +
556 SqliteUtils::HmacAlgoDescription(config.GetCryptoParam().hmacAlgo) +
557 std::string(GlobalExpr::ALGO_SUFFIX));
558 if (errCode != E_OK) {
559 LOG_ERROR("set codec hmac algo failed, err = %{public}d", errCode);
560 return errCode;
561 }
562
563 errCode = ExecuteSql(std::string(GlobalExpr::CODEC_KDF_ALGO_PREFIX) +
564 SqliteUtils::KdfAlgoDescription(config.GetCryptoParam().kdfAlgo) +
565 std::string(GlobalExpr::ALGO_SUFFIX));
566 if (errCode != E_OK) {
567 LOG_ERROR("set codec kdf algo failed, err = %{public}d", errCode);
568 return errCode;
569 }
570
571 errCode = ExecuteSql(
572 std::string(GlobalExpr::CODEC_PAGE_SIZE_PREFIX) + std::to_string(config.GetCryptoParam().cryptoPageSize));
573 if (errCode != E_OK) {
574 LOG_ERROR("set codec page size failed, err = %{public}d", errCode);
575 return errCode;
576 }
577
578 errCode = ExecuteSql(GlobalExpr::CODEC_REKEY_HMAC_ALGO);
579 if (errCode != E_OK) {
580 LOG_ERROR("set rekey sha algo failed, err = %{public}d", errCode);
581 return errCode;
582 }
583 return E_OK;
584 }
585
ReSetKey(const RdbStoreConfig & config)586 int SqliteConnection::ReSetKey(const RdbStoreConfig &config)
587 {
588 if (!IsWriter()) {
589 return E_OK;
590 }
591 LOG_INFO("name = %{public}s, iter = %{public}d", SqliteUtils::Anonymous(config.GetName()).c_str(),
592 config.GetIter());
593 std::vector<uint8_t> newKey = config.GetNewEncryptKey();
594 int errCode = sqlite3_rekey(dbHandle_, static_cast<const void *>(newKey.data()), static_cast<int>(newKey.size()));
595 newKey.assign(newKey.size(), 0);
596 if (errCode != SQLITE_OK) {
597 LOG_ERROR("ReKey failed, err = %{public}d, errno = %{public}d", errCode, errno);
598 RdbSecurityManager::GetInstance().DelKeyFile(config.GetPath(), RdbKeyFile::PUB_KEY_FILE_NEW_KEY);
599 return E_OK;
600 }
601 config.ChangeEncryptKey();
602 return E_OK;
603 }
604
GetSecManagerName(const RdbStoreConfig & config)605 std::string SqliteConnection::GetSecManagerName(const RdbStoreConfig &config)
606 {
607 auto name = config.GetBundleName();
608 if (name.empty()) {
609 LOG_WARN("Bundle name is empty, using path instead.");
610 return std::string(config.GetPath()).substr(0, config.GetPath().rfind("/") + 1);
611 }
612 return name;
613 }
614
SetEncrypt(const RdbStoreConfig & config)615 int SqliteConnection::SetEncrypt(const RdbStoreConfig &config)
616 {
617 if (!config.IsEncrypt()) {
618 return E_OK;
619 }
620
621 std::vector<uint8_t> key = config.GetEncryptKey();
622 std::vector<uint8_t> newKey = config.GetNewEncryptKey();
623 auto errCode = SetEncryptKey(key, config);
624 key.assign(key.size(), 0);
625 if (errCode != E_OK) {
626 if (!newKey.empty()) {
627 LOG_INFO("use new key, iter=%{public}d err=%{public}d errno=%{public}d name=%{public}s", config.GetIter(),
628 errCode, errno, SqliteUtils::Anonymous(config.GetName()).c_str());
629 errCode = SetEncryptKey(newKey, config);
630 }
631 newKey.assign(newKey.size(), 0);
632 if (errCode != E_OK) {
633 errCode = SetServiceKey(config, errCode);
634 LOG_ERROR("fail, iter=%{public}d err=%{public}d errno=%{public}d name=%{public}s", config.GetIter(),
635 errCode, errno, SqliteUtils::Anonymous(config.GetName()).c_str());
636 return errCode;
637 }
638 config.ChangeEncryptKey();
639 newKey = {};
640 }
641
642 if (!newKey.empty()) {
643 ReSetKey(config);
644 }
645 newKey.assign(newKey.size(), 0);
646 return E_OK;
647 }
648
SetEncryptKey(const std::vector<uint8_t> & key,const RdbStoreConfig & config)649 int SqliteConnection::SetEncryptKey(const std::vector<uint8_t> &key, const RdbStoreConfig &config)
650 {
651 if (key.empty()) {
652 return E_INVALID_SECRET_KEY;
653 }
654
655 auto errCode = sqlite3_key(dbHandle_, static_cast<const void *>(key.data()), static_cast<int>(key.size()));
656 if (errCode != SQLITE_OK) {
657 return SQLiteError::ErrNo(errCode);
658 }
659
660 errCode = SetEncryptAgo(config);
661 if (errCode != E_OK) {
662 return errCode;
663 }
664
665 if (IsWriter()) {
666 ValueObject version;
667 std::tie(errCode, version) = ExecuteForValue(GlobalExpr::PRAGMA_VERSION);
668 if (errCode != E_OK || version.GetType() == ValueObject::TYPE_NULL) {
669 return errCode;
670 }
671 return E_OK;
672 }
673 return errCode;
674 }
675
SetPersistWal()676 int SqliteConnection::SetPersistWal()
677 {
678 int opcode = 1;
679 int errCode = sqlite3_file_control(dbHandle_, "main", SQLITE_FCNTL_PERSIST_WAL, &opcode);
680 if (errCode != SQLITE_OK) {
681 LOG_ERROR("failed.");
682 return E_SET_PERSIST_WAL;
683 }
684 return E_OK;
685 }
686
SetBusyTimeout(int timeout)687 int SqliteConnection::SetBusyTimeout(int timeout)
688 {
689 auto errCode = sqlite3_busy_timeout(dbHandle_, timeout);
690 if (errCode != SQLITE_OK) {
691 LOG_ERROR("set buys timeout failed, errCode=%{public}d, errno=%{public}d", errCode, errno);
692 return errCode;
693 }
694 return E_OK;
695 }
696
RegDefaultFunctions(sqlite3 * dbHandle)697 int SqliteConnection::RegDefaultFunctions(sqlite3 *dbHandle)
698 {
699 if (dbHandle == nullptr) {
700 return SQLITE_OK;
701 }
702 // The number of parameters is 2
703 int errCode = sqlite3_create_function_v2(dbHandle, MERGE_ASSETS_FUNC, 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC,
704 nullptr, &MergeAssets, nullptr, nullptr, nullptr);
705 if (errCode != SQLITE_OK) {
706 LOG_ERROR("register function mergeAssets failed, errCode=%{public}d, errno=%{public}d", errCode, errno);
707 return errCode;
708 }
709 // The number of parameters is 2
710 errCode = sqlite3_create_function_v2(dbHandle, MERGE_ASSET_FUNC, 2, SQLITE_UTF8 | SQLITE_DETERMINISTIC, nullptr,
711 &MergeAsset, nullptr, nullptr, nullptr);
712 if (errCode != SQLITE_OK) {
713 LOG_ERROR("register function mergeAsset failed, errCode=%{public}d, errno=%{public}d", errCode, errno);
714 return errCode;
715 }
716 return SQLITE_OK;
717 }
718
SetJournalMode(const RdbStoreConfig & config)719 int SqliteConnection::SetJournalMode(const RdbStoreConfig &config)
720 {
721 if (isReadOnly_) {
722 return E_OK;
723 }
724
725 auto [errCode, object] = ExecuteForValue("PRAGMA journal_mode");
726 if (errCode != E_OK) {
727 LOG_ERROR("SqliteConnection SetJournalMode fail to get journal mode : %{public}d", errCode);
728 return errCode;
729 }
730
731 if (config.GetJournalMode().compare(static_cast<std::string>(object)) == 0) {
732 return E_OK;
733 }
734
735 std::string currentMode = SqliteUtils::StrToUpper(static_cast<std::string>(object));
736 if (currentMode != config.GetJournalMode()) {
737 auto [errorCode, journalMode] = ExecuteForValue("PRAGMA journal_mode=" + config.GetJournalMode());
738 if (errorCode != E_OK) {
739 LOG_ERROR("SqliteConnection SetJournalMode: fail to set journal mode err=%{public}d", errorCode);
740 return errorCode;
741 }
742
743 if (SqliteUtils::StrToUpper(static_cast<std::string>(journalMode)) != config.GetJournalMode()) {
744 LOG_ERROR("SqliteConnection SetJournalMode: result incorrect.");
745 return E_EXECUTE_RESULT_INCORRECT;
746 }
747 }
748
749 if (config.GetJournalMode() == "WAL") {
750 errCode = SetWalSyncMode(config.GetSyncMode());
751 }
752 if (config.GetJournalMode() == "TRUNCATE") {
753 mode_ = JournalMode::MODE_TRUNCATE;
754 }
755 return errCode;
756 }
757
SetJournalSizeLimit(const RdbStoreConfig & config)758 int SqliteConnection::SetJournalSizeLimit(const RdbStoreConfig &config)
759 {
760 if (isReadOnly_ || config.GetJournalSize() == GlobalExpr::DB_JOURNAL_SIZE) {
761 return E_OK;
762 }
763
764 int targetValue = SqliteGlobalConfig::GetJournalFileSize();
765 auto [errCode, currentValue] = ExecuteForValue("PRAGMA journal_size_limit");
766 if (errCode != E_OK) {
767 LOG_ERROR("SqliteConnection SetJournalSizeLimit fail to get journal_size_limit : %{public}d", errCode);
768 return errCode;
769 }
770
771 if (static_cast<int64_t>(currentValue) == targetValue) {
772 return E_OK;
773 }
774
775 std::tie(errCode, currentValue) = ExecuteForValue("PRAGMA journal_size_limit=" + std::to_string(targetValue));
776 if (errCode != E_OK) {
777 LOG_ERROR("SqliteConnection SetJournalSizeLimit fail to set journal_size_limit : %{public}d", errCode);
778 }
779 return errCode;
780 }
781
SetAutoCheckpoint(const RdbStoreConfig & config)782 int SqliteConnection::SetAutoCheckpoint(const RdbStoreConfig &config)
783 {
784 if (isReadOnly_ || !config.IsAutoCheck()) {
785 return E_OK;
786 }
787
788 int targetValue = SqliteGlobalConfig::GetWalAutoCheckpoint();
789 auto [errCode, value] = ExecuteForValue("PRAGMA wal_autocheckpoint");
790 if (errCode != E_OK) {
791 LOG_ERROR("SqliteConnection SetAutoCheckpoint fail to get wal_autocheckpoint : %{public}d", errCode);
792 return errCode;
793 }
794
795 if (static_cast<int64_t>(value) == targetValue) {
796 return E_OK;
797 }
798
799 std::tie(errCode, value) = ExecuteForValue("PRAGMA wal_autocheckpoint=" + std::to_string(targetValue));
800 if (errCode != E_OK) {
801 LOG_ERROR("SqliteConnection SetAutoCheckpoint fail to set wal_autocheckpoint : %{public}d", errCode);
802 }
803 return errCode;
804 }
805
SetWalFile(const RdbStoreConfig & config)806 int SqliteConnection::SetWalFile(const RdbStoreConfig &config)
807 {
808 if (!IsWriter()) {
809 return E_OK;
810 }
811 auto [errCode, version] = ExecuteForValue(GlobalExpr::PRAGMA_VERSION);
812 if (errCode != E_OK) {
813 return errCode;
814 }
815 return ExecuteSql(std::string(GlobalExpr::PRAGMA_VERSION) + "=?", { std::move(version) });
816 }
817
SetWalSyncMode(const std::string & syncMode)818 int SqliteConnection::SetWalSyncMode(const std::string &syncMode)
819 {
820 std::string targetValue = SqliteGlobalConfig::GetSyncMode();
821 if (syncMode.length() != 0) {
822 targetValue = syncMode;
823 }
824
825 auto [errCode, object] = ExecuteForValue("PRAGMA synchronous");
826 if (errCode != E_OK) {
827 LOG_ERROR("get wal sync mode fail, errCode:%{public}d", errCode);
828 return errCode;
829 }
830
831 std::string walSyncMode = SqliteUtils::StrToUpper(static_cast<std::string>(object));
832 if (walSyncMode == targetValue) {
833 return E_OK;
834 }
835
836 errCode = ExecuteSql("PRAGMA synchronous=" + targetValue);
837 if (errCode != E_OK) {
838 LOG_ERROR("set wal sync mode fail, errCode:%{public}d", errCode);
839 }
840 return errCode;
841 }
842
ExecuteSql(const std::string & sql,const std::vector<ValueObject> & bindArgs)843 int SqliteConnection::ExecuteSql(const std::string &sql, const std::vector<ValueObject> &bindArgs)
844 {
845 auto [errCode, statement] = CreateStatement(sql, nullptr);
846 if (statement == nullptr || errCode != E_OK) {
847 return errCode;
848 }
849 return statement->Execute(bindArgs);
850 }
851
ExecuteForValue(const std::string & sql,const std::vector<ValueObject> & bindArgs)852 std::pair<int32_t, ValueObject> SqliteConnection::ExecuteForValue(const std::string &sql,
853 const std::vector<ValueObject> &bindArgs)
854 {
855 auto [errCode, statement] = CreateStatement(sql, nullptr);
856 if (statement == nullptr || errCode != E_OK) {
857 return { static_cast<int32_t>(errCode), ValueObject() };
858 }
859
860 ValueObject object;
861 std::tie(errCode, object) = statement->ExecuteForValue(bindArgs);
862 if (errCode != E_OK) {
863 LOG_ERROR("execute sql failed, errCode:%{public}d, sql:%{public}s, args size:%{public}zu",
864 SQLiteError::ErrNo(errCode), sql.c_str(), bindArgs.size());
865 }
866 return { errCode, object };
867 }
868
ClearCache()869 int SqliteConnection::ClearCache()
870 {
871 if (dbHandle_ != nullptr && mode_ == JournalMode::MODE_WAL) {
872 sqlite3_db_release_memory(dbHandle_);
873 }
874 if (slaveConnection_) {
875 int errCode = slaveConnection_->ClearCache();
876 if (errCode != E_OK) {
877 LOG_ERROR("slaveConnection clearCache failed:%{public}d", errCode);
878 }
879 }
880 return E_OK;
881 }
882
LimitPermission(const std::string & dbPath) const883 void SqliteConnection::LimitPermission(const std::string &dbPath) const
884 {
885 struct stat st = { 0 };
886 if (stat(dbPath.c_str(), &st) == 0) {
887 if ((st.st_mode & (S_IXUSR | S_IXGRP | S_IRWXO)) != 0) {
888 int ret = chmod(dbPath.c_str(), st.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
889 if (ret != 0) {
890 LOG_DEBUG("SqliteConnection LimitPermission chmod fail, err = %{public}d", errno);
891 }
892 }
893 } else {
894 LOG_ERROR("SqliteConnection LimitPermission stat fail, err = %{public}d", errno);
895 }
896 }
897
898 #ifdef RDB_SUPPORT_ICU
Collate8Compare(void * p,int n1,const void * v1,int n2,const void * v2)899 int Collate8Compare(void *p, int n1, const void *v1, int n2, const void *v2)
900 {
901 UCollator *coll = reinterpret_cast<UCollator *>(p);
902 UCharIterator i1;
903 UCharIterator i2;
904 UErrorCode status = U_ZERO_ERROR;
905
906 uiter_setUTF8(&i1, (const char *)v1, n1);
907 uiter_setUTF8(&i2, (const char *)v2, n2);
908
909 UCollationResult result = ucol_strcollIter(coll, &i1, &i2, &status);
910
911 if (U_FAILURE(status)) {
912 LOG_ERROR("Ucol strcoll error.");
913 }
914
915 if (result == UCOL_LESS) {
916 return -1;
917 } else if (result == UCOL_GREATER) {
918 return 1;
919 }
920 return 0;
921 }
922
LocalizedCollatorDestroy(UCollator * collator)923 void LocalizedCollatorDestroy(UCollator *collator)
924 {
925 ucol_close(collator);
926 }
927 #endif
928
929 /**
930 * The database locale.
931 */
ConfigLocale(const std::string & localeStr)932 int SqliteConnection::ConfigLocale(const std::string &localeStr)
933 {
934 #ifdef RDB_SUPPORT_ICU
935 std::unique_lock<std::mutex> lock(mutex_);
936 UErrorCode status = U_ZERO_ERROR;
937 UCollator *collator = ucol_open(localeStr.c_str(), &status);
938 if (U_FAILURE(status)) {
939 LOG_ERROR("Can not open collator.");
940 return E_ERROR;
941 }
942 ucol_setAttribute(collator, UCOL_STRENGTH, UCOL_PRIMARY, &status);
943 if (U_FAILURE(status)) {
944 LOG_ERROR("Set attribute of collator failed.");
945 return E_ERROR;
946 }
947
948 int err = sqlite3_create_collation_v2(dbHandle_, "LOCALES", SQLITE_UTF8, collator, Collate8Compare,
949 (void (*)(void *))LocalizedCollatorDestroy);
950 if (err != SQLITE_OK) {
951 LOG_ERROR("SCreate collator in sqlite3 failed.");
952 return err;
953 }
954 #endif
955 return E_OK;
956 }
957
CleanDirtyData(const std::string & table,uint64_t cursor)958 int SqliteConnection::CleanDirtyData(const std::string &table, uint64_t cursor)
959 {
960 if (table.empty()) {
961 LOG_ERROR("table is empty");
962 return E_INVALID_ARGS;
963 }
964 uint64_t tmpCursor = cursor == UINT64_MAX ? 0 : cursor;
965 auto status = DropLogicDeletedData(dbHandle_, table, tmpCursor);
966 LOG_INFO("status:%{public}d, table:%{public}s, cursor:%{public}" PRIu64 "", status,
967 SqliteUtils::Anonymous(table).c_str(), cursor);
968 return status == DistributedDB::DBStatus::OK ? E_OK : E_ERROR;
969 }
970
TryCheckPoint(bool timeout)971 int SqliteConnection::TryCheckPoint(bool timeout)
972 {
973 if (!isWriter_) {
974 return E_NOT_SUPPORT;
975 }
976
977 std::shared_ptr<Connection> autoCheck(slaveConnection_.get(), [this, timeout](Connection *conn) {
978 if (conn != nullptr && backupId_ == TaskExecutor::INVALID_TASK_ID) {
979 conn->TryCheckPoint(timeout);
980 }
981 });
982 std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle_, "main"));
983 ssize_t size = SqliteUtils::GetFileSize(walName);
984 if (size < 0) {
985 LOG_ERROR("Invalid size for WAL:%{public}s size:%{public}zd", SqliteUtils::Anonymous(walName).c_str(), size);
986 return E_ERROR;
987 }
988
989 if (size <= config_.GetStartCheckpointSize()) {
990 return E_OK;
991 }
992
993 if (!timeout && size < config_.GetCheckpointSize()) {
994 return E_INNER_WARNING;
995 }
996
997 (void)sqlite3_busy_timeout(dbHandle_, CHECKPOINT_TIME);
998 int errCode = sqlite3_wal_checkpoint_v2(dbHandle_, nullptr, SQLITE_CHECKPOINT_TRUNCATE, nullptr, nullptr);
999 (void)sqlite3_busy_timeout(dbHandle_, DEFAULT_BUSY_TIMEOUT_MS);
1000 if (errCode != SQLITE_OK) {
1001 LOG_WARN("sqlite3_wal_checkpoint_v2 failed err:%{public}d,size:%{public}zd,wal:%{public}s.", errCode, size,
1002 SqliteUtils::Anonymous(walName).c_str());
1003 return SQLiteError::ErrNo(errCode);
1004 }
1005 return E_OK;
1006 }
1007
LimitWalSize()1008 int SqliteConnection::LimitWalSize()
1009 {
1010 if (!isConfigured_ || !isWriter_) {
1011 return E_OK;
1012 }
1013
1014 std::string walName = sqlite3_filename_wal(sqlite3_db_filename(dbHandle_, "main"));
1015 ssize_t fileSize = SqliteUtils::GetFileSize(walName);
1016 if (fileSize < 0 || fileSize > config_.GetWalLimitSize()) {
1017 LOG_ERROR("The WAL file size exceeds the limit, %{public}s size is %{public}zd",
1018 SqliteUtils::Anonymous(walName).c_str(), fileSize);
1019 return E_WAL_SIZE_OVER_LIMIT;
1020 }
1021 return E_OK;
1022 }
1023
MergeAssets(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1024 void SqliteConnection::MergeAssets(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1025 {
1026 // 2 is the number of parameters
1027 if (ctx == nullptr || argc != 2 || argv == nullptr) {
1028 LOG_ERROR("Parameter does not meet restrictions.");
1029 return;
1030 }
1031 std::map<std::string, ValueObject::Asset> assets;
1032 auto data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
1033 if (data != nullptr) {
1034 int len = sqlite3_value_bytes(argv[0]);
1035 RawDataParser::ParserRawData(data, len, assets);
1036 }
1037 std::map<std::string, ValueObject::Asset> newAssets;
1038 data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[1]));
1039 if (data != nullptr) {
1040 int len = sqlite3_value_bytes(argv[1]);
1041 RawDataParser::ParserRawData(data, len, newAssets);
1042 }
1043 CompAssets(assets, newAssets);
1044 auto blob = RawDataParser::PackageRawData(assets);
1045 sqlite3_result_blob(ctx, blob.data(), blob.size(), SQLITE_TRANSIENT);
1046 }
1047
MergeAsset(sqlite3_context * ctx,int argc,sqlite3_value ** argv)1048 void SqliteConnection::MergeAsset(sqlite3_context *ctx, int argc, sqlite3_value **argv)
1049 {
1050 // 2 is the number of parameters
1051 if (ctx == nullptr || argc != 2 || argv == nullptr) {
1052 LOG_ERROR("Parameter does not meet restrictions.");
1053 return;
1054 }
1055 ValueObject::Asset asset;
1056 size_t size = 0;
1057 auto data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[0]));
1058 if (data != nullptr) {
1059 int len = sqlite3_value_bytes(argv[0]);
1060 size = RawDataParser::ParserRawData(data, len, asset);
1061 }
1062 ValueObject::Asset newAsset;
1063 data = static_cast<const uint8_t *>(sqlite3_value_blob(argv[1]));
1064 if (data != nullptr) {
1065 int len = sqlite3_value_bytes(argv[1]);
1066 RawDataParser::ParserRawData(data, len, newAsset);
1067 }
1068
1069 if (size == 0) {
1070 asset = std::move(newAsset);
1071 if (asset.status != AssetValue::Status::STATUS_DELETE) {
1072 asset.status = AssetValue::Status::STATUS_INSERT;
1073 }
1074 } else if (asset.name == newAsset.name) {
1075 MergeAsset(asset, newAsset);
1076 } else {
1077 LOG_WARN("name change! old:%{public}s, new:%{public}s", SqliteUtils::Anonymous(asset.name).c_str(),
1078 SqliteUtils::Anonymous(newAsset.name).c_str());
1079 }
1080 auto blob = RawDataParser::PackageRawData(asset);
1081 sqlite3_result_blob(ctx, blob.data(), blob.size(), SQLITE_TRANSIENT);
1082 }
1083
CompAssets(std::map<std::string,ValueObject::Asset> & assets,std::map<std::string,ValueObject::Asset> & newAssets)1084 void SqliteConnection::CompAssets(std::map<std::string, ValueObject::Asset> &assets,
1085 std::map<std::string, ValueObject::Asset> &newAssets)
1086 {
1087 auto oldIt = assets.begin();
1088 auto newIt = newAssets.begin();
1089 for (; oldIt != assets.end() && newIt != newAssets.end();) {
1090 if (oldIt->first == newIt->first) {
1091 MergeAsset(oldIt->second, newIt->second);
1092 oldIt++;
1093 newIt = newAssets.erase(newIt);
1094 continue;
1095 }
1096 if (oldIt->first < newIt->first) {
1097 ++oldIt;
1098 continue;
1099 }
1100 newIt++;
1101 }
1102 for (auto &[key, value] : newAssets) {
1103 value.status = ValueObject::Asset::Status::STATUS_INSERT;
1104 assets.insert(std::pair{ key, std::move(value) });
1105 }
1106 }
1107
MergeAsset(ValueObject::Asset & oldAsset,ValueObject::Asset & newAsset)1108 void SqliteConnection::MergeAsset(ValueObject::Asset &oldAsset, ValueObject::Asset &newAsset)
1109 {
1110 using Status = ValueObject::Asset::Status;
1111 if (newAsset.status == Status::STATUS_DELETE) {
1112 oldAsset.status = Status::STATUS_DELETE;
1113 oldAsset.hash = "";
1114 oldAsset.modifyTime = "";
1115 oldAsset.size = "";
1116 return;
1117 }
1118 auto status = static_cast<int32_t>(oldAsset.status);
1119 switch (status) {
1120 case Status::STATUS_UNKNOWN: // fallthrough
1121 case Status::STATUS_NORMAL: // fallthrough
1122 case Status::STATUS_ABNORMAL: // fallthrough
1123 case Status::STATUS_INSERT: // fallthrough
1124 case Status::STATUS_UPDATE: // fallthrough
1125 if (oldAsset.modifyTime != newAsset.modifyTime || oldAsset.size != newAsset.size ||
1126 oldAsset.uri != newAsset.uri || oldAsset.path != newAsset.path) {
1127 if (oldAsset.modifyTime != newAsset.modifyTime || oldAsset.size != newAsset.size ||
1128 oldAsset.uri == newAsset.uri || oldAsset.path == newAsset.path) {
1129 oldAsset.expiresTime = newAsset.expiresTime;
1130 oldAsset.hash = newAsset.hash;
1131 oldAsset.status = Status::STATUS_UPDATE;
1132 }
1133 oldAsset.version = newAsset.version;
1134 oldAsset.uri = newAsset.uri;
1135 oldAsset.createTime = newAsset.createTime;
1136 oldAsset.modifyTime = newAsset.modifyTime;
1137 oldAsset.size = newAsset.size;
1138 oldAsset.path = newAsset.path;
1139 }
1140 return;
1141 default:
1142 return;
1143 }
1144 }
1145
Subscribe(const std::string & event,const std::shared_ptr<RdbStoreObserver> & observer)1146 int32_t SqliteConnection::Subscribe(const std::string &event, const std::shared_ptr<RdbStoreObserver> &observer)
1147 {
1148 if (!isWriter_ || observer == nullptr) {
1149 return E_OK;
1150 }
1151 std::lock_guard<std::mutex> lock(mutex_);
1152 observers_.try_emplace(event);
1153 auto &list = observers_.find(event)->second;
1154 for (auto it = list.begin(); it != list.end(); it++) {
1155 if ((*it)->GetObserver() == observer) {
1156 LOG_ERROR("duplicate subscribe.");
1157 return E_OK;
1158 }
1159 }
1160 auto localStoreObserver = std::make_shared<RdbStoreLocalDbObserver>(observer);
1161 int32_t errCode = RegisterStoreObserver(dbHandle_, localStoreObserver);
1162 if (errCode != E_OK) {
1163 LOG_ERROR("subscribe failed.");
1164 return errCode;
1165 }
1166 observers_[event].push_back(std::move(localStoreObserver));
1167 return E_OK;
1168 }
1169
Unsubscribe(const std::string & event,const std::shared_ptr<RdbStoreObserver> & observer)1170 int32_t SqliteConnection::Unsubscribe(const std::string &event, const std::shared_ptr<RdbStoreObserver> &observer)
1171 {
1172 if (!isWriter_) {
1173 return E_OK;
1174 }
1175 if (observer) {
1176 return UnsubscribeLocalDetail(event, observer);
1177 }
1178 return UnsubscribeLocalDetailAll(event);
1179 }
1180
UnsubscribeLocalDetail(const std::string & event,const std::shared_ptr<RdbStoreObserver> & observer)1181 int32_t SqliteConnection::UnsubscribeLocalDetail(const std::string &event,
1182 const std::shared_ptr<RdbStoreObserver> &observer)
1183 {
1184 std::lock_guard<std::mutex> lock(mutex_);
1185 auto observers = observers_.find(event);
1186 if (observers == observers_.end()) {
1187 return E_OK;
1188 }
1189
1190 auto &list = observers->second;
1191 for (auto it = list.begin(); it != list.end(); it++) {
1192 if ((*it)->GetObserver() == observer) {
1193 int32_t err = UnregisterStoreObserver(dbHandle_, *it);
1194 if (err != 0) {
1195 LOG_ERROR("unsubscribeLocalShared failed.");
1196 return err;
1197 }
1198 list.erase(it);
1199 break;
1200 }
1201 }
1202 if (list.empty()) {
1203 observers_.erase(event);
1204 }
1205 return E_OK;
1206 }
1207
UnsubscribeLocalDetailAll(const std::string & event)1208 int32_t SqliteConnection::UnsubscribeLocalDetailAll(const std::string &event)
1209 {
1210 std::lock_guard<std::mutex> lock(mutex_);
1211 auto observers = observers_.find(event);
1212 if (observers == observers_.end()) {
1213 return E_OK;
1214 }
1215
1216 auto &list = observers->second;
1217 auto it = list.begin();
1218 while (it != list.end()) {
1219 int32_t err = UnregisterStoreObserver(dbHandle_, *it);
1220 if (err != 0) {
1221 LOG_ERROR("unsubscribe failed.");
1222 return err;
1223 }
1224 it = list.erase(it);
1225 }
1226
1227 observers_.erase(event);
1228 return E_OK;
1229 }
1230
Backup(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,bool isAsync,SlaveStatus & slaveStatus)1231 int32_t SqliteConnection::Backup(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
1232 bool isAsync, SlaveStatus &slaveStatus)
1233 {
1234 if (slaveStatus == SlaveStatus::BACKING_UP) {
1235 LOG_INFO("backing up, return:%{public}s", config_.GetName().c_str());
1236 return E_OK;
1237 }
1238 LOG_INFO("begin backup to slave:%{public}s, isAsync:%{public}d",
1239 SqliteUtils::Anonymous(databasePath).c_str(), isAsync);
1240 if (!isAsync) {
1241 if (slaveConnection_ == nullptr) {
1242 RdbStoreConfig rdbSlaveStoreConfig = GetSlaveRdbStoreConfig(config_);
1243 int errCode = CreateSlaveConnection(rdbSlaveStoreConfig, false);
1244 if (errCode != E_OK) {
1245 LOG_ERROR("manual slave conn failed:%{public}d", errCode);
1246 return errCode;
1247 }
1248 }
1249 return ExchangeSlaverToMaster(false, slaveStatus);
1250 }
1251
1252 if (backupId_ == TaskExecutor::INVALID_TASK_ID) {
1253 auto pool = TaskExecutor::GetInstance().GetExecutor();
1254 if (pool == nullptr) {
1255 LOG_WARN("task pool err when restore");
1256 return E_OK;
1257 }
1258 backupId_ = pool->Execute([this, &slaveStatus]() {
1259 auto [err, conn] = InnerCreate(config_, true);
1260 if (err != E_OK) {
1261 return;
1262 }
1263 err = conn->ExchangeSlaverToMaster(false, slaveStatus);
1264 if (err != E_OK) {
1265 LOG_WARN("master backup to slave failed:%{public}d", err);
1266 }
1267 backupId_ = TaskExecutor::INVALID_TASK_ID;
1268 });
1269 }
1270 return E_OK;
1271 }
1272
Restore(const std::string & databasePath,const std::vector<uint8_t> & destEncryptKey,SlaveStatus & slaveStatus)1273 int32_t SqliteConnection::Restore(const std::string &databasePath, const std::vector<uint8_t> &destEncryptKey,
1274 SlaveStatus &slaveStatus)
1275 {
1276 LOG_INFO("begin to restore from slave:%{public}s", SqliteUtils::Anonymous(databasePath).c_str());
1277 return ExchangeSlaverToMaster(true, slaveStatus);
1278 };
1279
LoadExtension(const RdbStoreConfig & config,sqlite3 * dbHandle)1280 int SqliteConnection::LoadExtension(const RdbStoreConfig &config, sqlite3 *dbHandle)
1281 {
1282 if (config.GetPluginLibs().empty() || dbHandle == nullptr) {
1283 return E_OK;
1284 }
1285 if (config.GetPluginLibs().size() > SqliteUtils::MAX_LOAD_EXTENSION_COUNT) {
1286 LOG_ERROR("failed, size %{public}zu is too large", config.GetPluginLibs().size());
1287 return E_INVALID_ARGS;
1288 }
1289 int err = sqlite3_db_config(dbHandle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SqliteUtils::ENABLE_LOAD_EXTENSION,
1290 nullptr);
1291 if (err != SQLITE_OK) {
1292 LOG_ERROR("enable failed, err=%{public}d, errno=%{public}d", err, errno);
1293 return SQLiteError::ErrNo(err);
1294 }
1295 for (auto &path : config.GetPluginLibs()) {
1296 if (path.empty()) {
1297 continue;
1298 }
1299 if (access(path.c_str(), F_OK) != 0) {
1300 LOG_ERROR("no file, errno:%{public}d %{public}s", errno, SqliteUtils::Anonymous(path).c_str());
1301 return E_INVALID_FILE_PATH;
1302 }
1303 err = sqlite3_load_extension(dbHandle, path.c_str(), nullptr, nullptr);
1304 if (err != SQLITE_OK) {
1305 LOG_ERROR("load error. err=%{public}d, errno=%{public}d, errmsg:%{public}s, lib=%{public}s", err, errno,
1306 sqlite3_errmsg(dbHandle), SqliteUtils::Anonymous(path).c_str());
1307 break;
1308 }
1309 }
1310 int ret = sqlite3_db_config(dbHandle, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SqliteUtils::DISABLE_LOAD_EXTENSION,
1311 nullptr);
1312 if (ret != SQLITE_OK) {
1313 LOG_ERROR("disable failed, err=%{public}d, errno=%{public}d", err, errno);
1314 }
1315 return SQLiteError::ErrNo(err == SQLITE_OK ? ret : err);
1316 }
1317
SetServiceKey(const RdbStoreConfig & config,int32_t errCode)1318 int SqliteConnection::SetServiceKey(const RdbStoreConfig &config, int32_t errCode)
1319 {
1320 DistributedRdb::RdbSyncerParam param;
1321 param.bundleName_ = config.GetBundleName();
1322 param.hapName_ = config.GetModuleName();
1323 param.storeName_ = config.GetName();
1324 param.customDir_ = config.GetCustomDir();
1325 param.area_ = config.GetArea();
1326 param.level_ = static_cast<int32_t>(config.GetSecurityLevel());
1327 param.type_ = config.GetDistributedType();
1328 param.isEncrypt_ = config.IsEncrypt();
1329 param.isAutoClean_ = config.GetAutoClean();
1330 param.isSearchable_ = config.IsSearchable();
1331 param.haMode_ = config.GetHaMode();
1332 param.password_ = {};
1333 std::vector<uint8_t> key;
1334 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
1335 auto [svcErr, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param);
1336 if (svcErr != E_OK) {
1337 return errCode;
1338 }
1339 svcErr = service->GetPassword(param, key);
1340 if (svcErr != RDB_OK) {
1341 return errCode;
1342 }
1343 #endif
1344
1345 errCode = SetEncryptKey(key, config);
1346 if (errCode == E_OK) {
1347 config.RestoreEncryptKey(key);
1348 }
1349 key.assign(key.size(), 0);
1350 return errCode;
1351 }
1352
ExchangeSlaverToMaster(bool isRestore,SlaveStatus & curStatus)1353 int SqliteConnection::ExchangeSlaverToMaster(bool isRestore, SlaveStatus &curStatus)
1354 {
1355 curStatus = SlaveStatus::BACKING_UP;
1356 auto err = ExchangeVerify(isRestore);
1357 if (err != E_OK) {
1358 curStatus = SlaveStatus::UNDEFINED;
1359 return err;
1360 }
1361
1362 sqlite3 *dbFrom = isRestore ? dbHandle_ : slaveConnection_->dbHandle_;
1363 sqlite3 *dbTo = isRestore ? slaveConnection_->dbHandle_ : dbHandle_;
1364 sqlite3_backup *pBackup = sqlite3_backup_init(dbFrom, "main", dbTo, "main");
1365 if (pBackup == nullptr) {
1366 LOG_WARN("slave backup init failed");
1367 curStatus = SlaveStatus::UNDEFINED;
1368 return E_OK;
1369 }
1370 int rc = SQLITE_OK;
1371 do {
1372 if (!isRestore && curStatus == SlaveStatus::BACKUP_INTERRUPT) {
1373 LOG_INFO("backup slave was interrupt!");
1374 rc = E_BACKUP_INTERRUPT;
1375 break;
1376 }
1377 rc = sqlite3_backup_step(pBackup, BACKUP_PAGES_PRE_STEP);
1378 LOG_INFO("backup slave process cur/total:%{public}d/%{public}d, rs:%{public}d, isRestore:%{public}d",
1379 sqlite3_backup_pagecount(pBackup) - sqlite3_backup_remaining(pBackup), sqlite3_backup_pagecount(pBackup),
1380 rc, isRestore);
1381 if (!isRestore) {
1382 sqlite3_sleep(BACKUP_PRE_WAIT_TIME);
1383 }
1384 } while (sqlite3_backup_pagecount(pBackup) != 0 && (rc == SQLITE_OK || rc == SQLITE_BUSY || rc == SQLITE_LOCKED));
1385 (void)sqlite3_backup_finish(pBackup);
1386 if (rc != SQLITE_DONE) {
1387 LOG_ERROR("backup slave err:%{public}d, isRestore:%{public}d", rc, isRestore);
1388 if (!isRestore) {
1389 RdbStoreConfig slaveConfig(slaveConnection_->config_.GetPath());
1390 if (rc != SQLITE_BUSY && rc != SQLITE_LOCKED) {
1391 slaveConnection_ = nullptr;
1392 (void)SqliteConnection::Delete(slaveConfig.GetPath());
1393 }
1394 curStatus = SlaveStatus::BACKUP_INTERRUPT;
1395 }
1396 return rc == E_BACKUP_INTERRUPT ? E_BACKUP_INTERRUPT : SQLiteError::ErrNo(rc);
1397 }
1398 rc = isRestore ? TryCheckPoint(true) : slaveConnection_->TryCheckPoint(true);
1399 if (rc != E_OK && config_.GetHaMode() == HAMode::MANUAL_TRIGGER) {
1400 if (!isRestore) {
1401 curStatus = SlaveStatus::BACKUP_INTERRUPT;
1402 }
1403 LOG_WARN("CheckPoint failed err:%{public}d, isRestore:%{public}d", rc, isRestore);
1404 return E_OK;
1405 }
1406 curStatus = SlaveStatus::BACKUP_FINISHED;
1407 SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false);
1408 SqliteUtils::TryAccessSlaveLock(config_.GetPath(), true, false, true);
1409 LOG_INFO("backup slave success, isRestore:%{public}d", isRestore);
1410 return E_OK;
1411 }
1412
GenerateExchangeStrategy(const SlaveStatus & status)1413 ExchangeStrategy SqliteConnection::GenerateExchangeStrategy(const SlaveStatus &status)
1414 {
1415 if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr ||
1416 config_.GetHaMode() == HAMode::SINGLE || status == SlaveStatus::BACKING_UP) {
1417 return ExchangeStrategy::NOT_HANDLE;
1418 }
1419 static const std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
1420 auto [mRet, mObj] = ExecuteForValue(querySql);
1421 if (mRet != E_OK) {
1422 LOG_WARN("main abnormal, err:%{public}d", mRet);
1423 return ExchangeStrategy::RESTORE;
1424 }
1425 int64_t mCount = static_cast<int64_t>(mObj);
1426 // trigger mode only does restore, not backup
1427 if (config_.GetHaMode() == HAMode::MANUAL_TRIGGER) {
1428 return mCount == 0 ? ExchangeStrategy::RESTORE : ExchangeStrategy::NOT_HANDLE;
1429 }
1430 auto [sRet, sObj] = slaveConnection_->ExecuteForValue(querySql);
1431 if (sRet != E_OK) {
1432 LOG_WARN("slave db abnormal, need backup, err:%{public}d", sRet);
1433 return ExchangeStrategy::BACKUP;
1434 }
1435 if (status == SlaveStatus::DB_NOT_EXITS || status == SlaveStatus::BACKUP_INTERRUPT) {
1436 return ExchangeStrategy::BACKUP;
1437 }
1438 int64_t sCount = static_cast<int64_t>(sObj);
1439 std::string failureFlagFile = config_.GetPath() + "-slaveFailure";
1440 if (mCount == sCount && access(failureFlagFile.c_str(), F_OK) != 0) {
1441 LOG_INFO("equal, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
1442 return ExchangeStrategy::NOT_HANDLE;
1443 }
1444 if (mCount == 0) {
1445 LOG_INFO("main empty, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
1446 return ExchangeStrategy::RESTORE;
1447 }
1448 LOG_INFO("backup, main:%{public}" PRId64 ",slave:%{public}" PRId64, mCount, sCount);
1449 return ExchangeStrategy::BACKUP;
1450 }
1451
Repair(const RdbStoreConfig & config)1452 int32_t SqliteConnection::Repair(const RdbStoreConfig &config)
1453 {
1454 if (config.GetHaMode() != MAIN_REPLICA && config.GetHaMode() != MANUAL_TRIGGER) {
1455 return E_NOT_SUPPORT;
1456 }
1457 std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, true);
1458 if (connection == nullptr) {
1459 return E_NOT_SUPPORT;
1460 }
1461 RdbStoreConfig rdbSlaveStoreConfig = connection->GetSlaveRdbStoreConfig(config);
1462 int ret = connection->CreateSlaveConnection(rdbSlaveStoreConfig);
1463 if (ret != E_OK) {
1464 return ret;
1465 }
1466 ret = connection->IsRepairable();
1467 if (ret != E_OK) {
1468 return ret;
1469 }
1470 LOG_WARN("begin repair main:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
1471 (void)SqliteConnection::Delete(config.GetPath());
1472 ret = connection->InnerOpen(config);
1473 if (ret != E_OK) {
1474 LOG_ERROR("reopen db failed, err:%{public}d", ret);
1475 return ret;
1476 }
1477 connection->TryCheckPoint(true);
1478 SlaveStatus curStatus;
1479 ret = connection->ExchangeSlaverToMaster(true, curStatus);
1480 if (ret != E_OK) {
1481 LOG_ERROR("repair failed, [%{public}s]->[%{public}s], err:%{public}d", rdbSlaveStoreConfig.GetName().c_str(),
1482 SqliteUtils::Anonymous(config.GetName()).c_str(), ret);
1483 } else {
1484 LOG_INFO("repair main success:%{public}s", SqliteUtils::Anonymous(config.GetPath()).c_str());
1485 }
1486 connection->slaveConnection_ = nullptr;
1487 connection = nullptr;
1488 return ret;
1489 }
1490
IsRepairable()1491 int SqliteConnection::IsRepairable()
1492 {
1493 if (slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) {
1494 return E_STORE_CLOSED;
1495 }
1496 if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, false)) {
1497 LOG_ERROR("unavailable slave, %{public}s", config_.GetName().c_str());
1498 return E_DB_RESTORE_NOT_ALLOWED;
1499 }
1500 std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
1501 auto [qRet, qObj] = slaveConnection_->ExecuteForValue(querySql);
1502 if (qRet != E_OK || (static_cast<int64_t>(qObj) == 0L)) {
1503 LOG_INFO("cancel repair, ret:%{public}d", qRet);
1504 return E_DB_RESTORE_NOT_ALLOWED;
1505 }
1506 return E_OK;
1507 }
1508
ExchangeVerify(bool isRestore)1509 int SqliteConnection::ExchangeVerify(bool isRestore)
1510 {
1511 if (dbHandle_ == nullptr || slaveConnection_ == nullptr || slaveConnection_->dbHandle_ == nullptr) {
1512 LOG_WARN("slave conn invalid");
1513 return E_STORE_CLOSED;
1514 }
1515 if (access(config_.GetPath().c_str(), F_OK) != 0) {
1516 LOG_WARN("main no exist, isR:%{public}d, %{public}s", isRestore, config_.GetName().c_str());
1517 return E_DB_NOT_EXIST;
1518 }
1519 if (isRestore) {
1520 int err = IsRepairable();
1521 if (err != E_OK) {
1522 return err;
1523 }
1524 auto [cRet, cObj] = slaveConnection_->ExecuteForValue(INTEGRITIES[2]); // 2 is integrity_check
1525 if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
1526 LOG_ERROR("slave may corrupt, cancel, ret:%{public}s, cRet:%{public}d",
1527 static_cast<std::string>(cObj).c_str(), cRet);
1528 return E_SQLITE_CORRUPT;
1529 }
1530 std::string querySql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table';";
1531 std::tie(cRet, cObj) = ExecuteForValue(querySql);
1532 if (cRet == E_OK && (static_cast<int64_t>(cObj) == 0L)) {
1533 LOG_INFO("main empty, need restore, %{public}s", config_.GetName().c_str());
1534 return E_OK;
1535 }
1536 if (SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, false, true)) {
1537 LOG_ERROR("incomplete slave, %{public}s", config_.GetName().c_str());
1538 return E_DB_RESTORE_NOT_ALLOWED;
1539 }
1540 } else {
1541 auto [cRet, cObj] = ExecuteForValue(INTEGRITIES[1]); // 1 is quick_check
1542 if (cRet != E_OK || (static_cast<std::string>(cObj) != "ok")) {
1543 LOG_ERROR("main corrupt, cancel, ret:%{public}s, qRet:%{public}d",
1544 static_cast<std::string>(cObj).c_str(), cRet);
1545 return E_SQLITE_CORRUPT;
1546 }
1547 if (!SqliteUtils::TryAccessSlaveLock(config_.GetPath(), false, true)) {
1548 LOG_WARN("try create slave lock failed! isRestore:%{public}d", isRestore);
1549 }
1550 }
1551 return E_OK;
1552 }
1553
InnerCreate(const RdbStoreConfig & config,bool isWrite)1554 std::pair<int32_t, std::shared_ptr<SqliteConnection>> SqliteConnection::InnerCreate(const RdbStoreConfig &config,
1555 bool isWrite)
1556 {
1557 std::pair<int32_t, std::shared_ptr<SqliteConnection>> result = { E_ERROR, nullptr };
1558 auto &[errCode, conn] = result;
1559 std::shared_ptr<SqliteConnection> connection = std::make_shared<SqliteConnection>(config, isWrite);
1560 if (connection == nullptr) {
1561 LOG_ERROR("connection is nullptr.");
1562 return result;
1563 }
1564
1565 RdbStoreConfig slaveCfg = connection->GetSlaveRdbStoreConfig(config);
1566 errCode = connection->InnerOpen(config);
1567 if (errCode != E_OK) {
1568 return result;
1569 }
1570 conn = connection;
1571 if (isWrite) {
1572 (void)connection->CreateSlaveConnection(slaveCfg, isWrite);
1573 }
1574 return result;
1575 }
1576 } // namespace NativeRdb
1577 } // namespace OHOS