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