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