• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &notifier)
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