• 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 "RdbStoreImpl"
17 
18 #include "rdb_store_impl.h"
19 
20 #include <sstream>
21 #include <unistd.h>
22 
23 #include "logger.h"
24 #include "rdb_errno.h"
25 #include "rdb_trace.h"
26 #include "sqlite_sql_builder.h"
27 #include "sqlite_utils.h"
28 #include "step_result_set.h"
29 
30 #ifndef WINDOWS_PLATFORM
31 #include "directory_ex.h"
32 #endif
33 
34 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
35 #include "iresult_set.h"
36 #include "rdb_device_manager_adapter.h"
37 #include "rdb_manager.h"
38 #include "rdb_security_manager.h"
39 #include "relational_store_manager.h"
40 #include "result_set_proxy.h"
41 #include "runtime_config.h"
42 #include "sqlite_shared_result_set.h"
43 #endif
44 
45 #ifdef WINDOWS_PLATFORM
46 #define ISFILE(filePath) ((filePath.find("\\") == std::string::npos))
47 #else
48 #define ISFILE(filePath) ((filePath.find("/") == std::string::npos))
49 #endif
50 
51 namespace OHOS::NativeRdb {
Open(const RdbStoreConfig & config,int & errCode)52 std::shared_ptr<RdbStore> RdbStoreImpl::Open(const RdbStoreConfig &config, int &errCode)
53 {
54     std::shared_ptr<RdbStoreImpl> rdbStore = std::make_shared<RdbStoreImpl>();
55     errCode = rdbStore->InnerOpen(config);
56     if (errCode != E_OK) {
57         return nullptr;
58     }
59 
60     return rdbStore;
61 }
62 
InnerOpen(const RdbStoreConfig & config)63 int RdbStoreImpl::InnerOpen(const RdbStoreConfig &config)
64 {
65     int errCode = E_OK;
66     connectionPool = SqliteConnectionPool::Create(config, errCode);
67     if (connectionPool == nullptr) {
68         return errCode;
69     }
70     isOpen = true;
71     path = config.GetPath();
72     orgPath = path;
73     isReadOnly = config.IsReadOnly();
74     isMemoryRdb = config.IsMemoryRdb();
75     name = config.GetName();
76     fileType = config.GetDatabaseFileType();
77 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
78     syncerParam_.bundleName_ = config.GetBundleName();
79     syncerParam_.hapName_ = config.GetModuleName();
80     syncerParam_.storeName_ = config.GetName();
81     syncerParam_.area_ = config.GetArea();
82     syncerParam_.level_ = static_cast<int32_t>(config.GetSecurityLevel());
83     syncerParam_.type_ = config.GetDistributedType();
84     syncerParam_.isEncrypt_ = config.IsEncrypt();
85     syncerParam_.password_ = {};
86     isEncrypt_ = config.IsEncrypt();
87     // open uri share
88     if (!config.GetUri().empty()) {
89         std::shared_ptr<DistributedRdb::RdbService> service = nullptr;
90         errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service);
91         if (errCode != E_OK) {
92             LOG_ERROR("RdbStoreImpl::InnerOpen get service failed, err is %{public}d.", errCode);
93             return errCode;
94         }
95         errCode = service->CreateRDBTable(syncerParam_, config.GetWritePermission(), config.GetReadPermission());
96         if (errCode != E_OK) {
97             LOG_ERROR("RdbStoreImpl::InnerOpen service CreateRDBTable failed, err is %{public}d.", errCode);
98             return errCode;
99         }
100         isShared_ = true;
101     }
102 #endif
103     return E_OK;
104 }
105 
RdbStoreImpl()106 RdbStoreImpl::RdbStoreImpl()
107     : connectionPool(nullptr), isOpen(false), path(""), orgPath(""), isReadOnly(false), isMemoryRdb(false)
108 {
109 }
110 
~RdbStoreImpl()111 RdbStoreImpl::~RdbStoreImpl()
112 {
113     delete connectionPool;
114     threadMap.clear();
115     idleSessions.clear();
116 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
117     if (isShared_) {
118         std::shared_ptr<DistributedRdb::RdbService> service = nullptr;
119         int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service);
120         if (errCode != E_OK) {
121             LOG_ERROR("RdbStoreImpl::~RdbStoreImpl get service failed, err is %{public}d.", errCode);
122             return;
123         }
124         if (service->DestroyRDBTable(syncerParam_) != E_OK) {
125             LOG_ERROR("RdbStoreImpl::~RdbStoreImpl service DestroyRDBTable failed");
126         }
127     }
128 #endif
129 }
130 #ifdef WINDOWS_PLATFORM
Clear()131 void RdbStoreImpl::Clear()
132 {
133     delete connectionPool;
134     connectionPool = nullptr;
135 }
136 #endif
GetThreadSession()137 std::shared_ptr<StoreSession> RdbStoreImpl::GetThreadSession()
138 {
139     std::thread::id tid = std::this_thread::get_id();
140     std::lock_guard<std::mutex> lock(sessionMutex);
141 
142     auto iter = threadMap.find(tid);
143     if (iter != threadMap.end()) {
144         iter->second.second++; // useCount++
145         return iter->second.first;
146     }
147 
148     // get from idle stack
149     std::shared_ptr<StoreSession> session;
150     if (idleSessions.empty()) {
151         session = std::make_shared<StoreSession>(*connectionPool);
152     } else {
153         session = idleSessions.back();
154         idleSessions.pop_back();
155     }
156 
157     threadMap.insert(std::make_pair(tid, std::make_pair(session, 1))); // useCount is 1
158     return session;
159 }
160 
ReleaseThreadSession()161 void RdbStoreImpl::ReleaseThreadSession()
162 {
163     std::thread::id tid = std::this_thread::get_id();
164     std::lock_guard<std::mutex> lock(sessionMutex);
165 
166     auto iter = threadMap.find(tid);
167     if (iter == threadMap.end()) {
168         LOG_ERROR("RdbStoreImpl ReleaseThreadSession: no session found for the current thread");
169         return;
170     }
171     int &useCount = iter->second.second;
172     useCount--;
173     if (useCount > 0) {
174         return;
175     }
176 
177     if (idleSessions.size() < MAX_IDLE_SESSION_SIZE) {
178         idleSessions.push_back(iter->second.first);
179     }
180     threadMap.erase(iter);
181 }
182 
Insert(int64_t & outRowId,const std::string & table,const ValuesBucket & initialValues)183 int RdbStoreImpl::Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues)
184 {
185     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
186     return InsertWithConflictResolution(outRowId, table, initialValues, ConflictResolution::ON_CONFLICT_NONE);
187 }
188 
BatchInsert(int64_t & outInsertNum,const std::string & table,const std::vector<ValuesBucket> & initialBatchValues)189 int RdbStoreImpl::BatchInsert(int64_t &outInsertNum, const std::string &table,
190     const std::vector<ValuesBucket> &initialBatchValues)
191 {
192     int errCode = BeginTransaction();
193     if (errCode != E_OK) {
194         LOG_ERROR("Begin transaction with error code %{public}d.", errCode);
195         return errCode;
196     }
197     int64_t outRowId = 0;
198     for (auto const &value : initialBatchValues) {
199         ++outInsertNum;
200         if (RdbStoreImpl::Insert(outRowId, table, value) != E_OK) {
201             LOG_WARN("Roll back in batch insert.");
202             outRowId = -1;
203             outInsertNum = -1;
204             return RollBack();
205         }
206     }
207 
208     return Commit();
209 }
210 
Replace(int64_t & outRowId,const std::string & table,const ValuesBucket & initialValues)211 int RdbStoreImpl::Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues)
212 {
213     return InsertWithConflictResolution(outRowId, table, initialValues, ConflictResolution::ON_CONFLICT_REPLACE);
214 }
215 
InsertWithConflictResolution(int64_t & outRowId,const std::string & table,const ValuesBucket & initialValues,ConflictResolution conflictResolution)216 int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::string &table,
217     const ValuesBucket &initialValues, ConflictResolution conflictResolution)
218 {
219     if (table.empty()) {
220         return E_EMPTY_TABLE_NAME;
221     }
222 
223     if (initialValues.IsEmpty()) {
224         return E_EMPTY_VALUES_BUCKET;
225     }
226 
227     std::string conflictClause;
228     int errCode = SqliteUtils::GetConflictClause(static_cast<int>(conflictResolution), conflictClause);
229     if (errCode != E_OK) {
230         return errCode;
231     }
232 
233     std::stringstream sql;
234     sql << "INSERT" << conflictClause << " INTO " << table << '(';
235 
236     std::map<std::string, ValueObject> valuesMap;
237     initialValues.GetAll(valuesMap);
238     std::vector<ValueObject> bindArgs;
239     for (auto iter = valuesMap.begin(); iter != valuesMap.end(); iter++) {
240         sql << ((iter == valuesMap.begin()) ? "" : ",");
241         sql << iter->first;               // columnName
242         bindArgs.push_back(iter->second); // columnValue
243     }
244 
245     sql << ") VALUES (";
246     for (size_t i = 0; i < valuesMap.size(); i++) {
247         sql << ((i == 0) ? "?" : ",?");
248     }
249     sql << ')';
250 
251     std::shared_ptr<StoreSession> session = GetThreadSession();
252     errCode = session->ExecuteForLastInsertedRowId(outRowId, sql.str(), bindArgs);
253     ReleaseThreadSession();
254     return errCode;
255 }
256 
Update(int & changedRows,const std::string & table,const ValuesBucket & values,const std::string & whereClause,const std::vector<std::string> & whereArgs)257 int RdbStoreImpl::Update(int &changedRows, const std::string &table, const ValuesBucket &values,
258     const std::string &whereClause, const std::vector<std::string> &whereArgs)
259 {
260     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
261     return UpdateWithConflictResolution(
262         changedRows, table, values, whereClause, whereArgs, ConflictResolution::ON_CONFLICT_NONE);
263 }
264 
Update(int & changedRows,const ValuesBucket & values,const AbsRdbPredicates & predicates)265 int RdbStoreImpl::Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates)
266 {
267     return Update(
268         changedRows, predicates.GetTableName(), values, predicates.GetWhereClause(), predicates.GetWhereArgs());
269 }
270 
UpdateWithConflictResolution(int & changedRows,const std::string & table,const ValuesBucket & values,const std::string & whereClause,const std::vector<std::string> & whereArgs,ConflictResolution conflictResolution)271 int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
272     const std::string &whereClause, const std::vector<std::string> &whereArgs, ConflictResolution conflictResolution)
273 {
274     if (table.empty()) {
275         return E_EMPTY_TABLE_NAME;
276     }
277 
278     if (values.IsEmpty()) {
279         return E_EMPTY_VALUES_BUCKET;
280     }
281 
282     std::string conflictClause;
283     int errCode = SqliteUtils::GetConflictClause(static_cast<int>(conflictResolution), conflictClause);
284     if (errCode != E_OK) {
285         return errCode;
286     }
287 
288     std::stringstream sql;
289     sql << "UPDATE" << conflictClause << " " << table << " SET ";
290 
291     std::map<std::string, ValueObject> valuesMap;
292     values.GetAll(valuesMap);
293     std::vector<ValueObject> bindArgs;
294     for (auto iter = valuesMap.begin(); iter != valuesMap.end(); iter++) {
295         sql << ((iter == valuesMap.begin()) ? "" : ",");
296         sql << iter->first << "=?";       // columnName
297         bindArgs.push_back(iter->second); // columnValue
298     }
299 
300     if (whereClause.empty() == false) {
301         sql << " WHERE " << whereClause;
302     }
303 
304     for (auto &iter : whereArgs) {
305         bindArgs.push_back(ValueObject(iter));
306     }
307 
308     std::shared_ptr<StoreSession> session = GetThreadSession();
309     errCode = session->ExecuteForChangedRowCount(changedRows, sql.str(), bindArgs);
310     ReleaseThreadSession();
311     return errCode;
312 }
313 
Delete(int & deletedRows,const AbsRdbPredicates & predicates)314 int RdbStoreImpl::Delete(int &deletedRows, const AbsRdbPredicates &predicates)
315 {
316     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
317     return Delete(deletedRows, predicates.GetTableName(), predicates.GetWhereClause(), predicates.GetWhereArgs());
318 }
319 
Delete(int & deletedRows,const std::string & table,const std::string & whereClause,const std::vector<std::string> & whereArgs)320 int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
321     const std::vector<std::string> &whereArgs)
322 {
323     if (table.empty()) {
324         return E_EMPTY_TABLE_NAME;
325     }
326 
327     std::stringstream sql;
328     sql << "DELETE FROM " << table;
329     if (whereClause.empty() == false) {
330         sql << " WHERE " << whereClause;
331     }
332 
333     std::vector<ValueObject> bindArgs;
334     for (auto &iter : whereArgs) {
335         bindArgs.push_back(ValueObject(iter));
336     }
337 
338     std::shared_ptr<StoreSession> session = GetThreadSession();
339     int errCode = session->ExecuteForChangedRowCount(deletedRows, sql.str(), bindArgs);
340     ReleaseThreadSession();
341     return errCode;
342 }
343 
344 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
Query(const AbsRdbPredicates & predicates,const std::vector<std::string> columns)345 std::unique_ptr<AbsSharedResultSet> RdbStoreImpl::Query(
346     const AbsRdbPredicates &predicates, const std::vector<std::string> columns)
347 {
348     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
349     LOG_DEBUG("RdbStoreImpl::Query on called.");
350     std::vector<std::string> selectionArgs = predicates.GetWhereArgs();
351     std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
352     return QuerySql(sql, selectionArgs);
353 }
354 
QueryByStep(const AbsRdbPredicates & predicates,const std::vector<std::string> columns)355 std::unique_ptr<ResultSet> RdbStoreImpl::QueryByStep(
356     const AbsRdbPredicates &predicates, const std::vector<std::string> columns)
357 {
358     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
359     LOG_DEBUG("RdbStoreImpl::QueryByStep on called.");
360     std::vector<std::string> selectionArgs = predicates.GetWhereArgs();
361     std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
362     return QueryByStep(sql, selectionArgs);
363 }
364 
RemoteQuery(const std::string & device,const AbsRdbPredicates & predicates,const std::vector<std::string> & columns,int & errCode)365 std::shared_ptr<ResultSet> RdbStoreImpl::RemoteQuery(const std::string &device, const AbsRdbPredicates &predicates,
366     const std::vector<std::string> &columns, int &errCode)
367 {
368     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
369     LOG_DEBUG("RdbStoreImpl::RemoteQuery on called.");
370     std::vector<std::string> selectionArgs = predicates.GetWhereArgs();
371     std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
372     std::shared_ptr<DistributedRdb::RdbService> service = nullptr;
373     errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service);
374     if (errCode != E_OK) {
375         LOG_ERROR("RdbStoreImpl::RemoteQuery get service failed, err is %{public}d.", errCode);
376         return nullptr;
377     }
378     sptr<IRemoteObject> remoteResultSet;
379     if (service->RemoteQuery(syncerParam_, device, sql, selectionArgs, remoteResultSet) != E_OK) {
380         LOG_ERROR("RdbStoreImpl::RemoteQuery service RemoteQuery failed");
381         return nullptr;
382     }
383     return std::make_shared<ResultSetProxy>(remoteResultSet);
384 }
385 
Query(int & errCode,bool distinct,const std::string & table,const std::vector<std::string> & columns,const std::string & selection,const std::vector<std::string> & selectionArgs,const std::string & groupBy,const std::string & having,const std::string & orderBy,const std::string & limit)386 std::unique_ptr<AbsSharedResultSet> RdbStoreImpl::Query(int &errCode, bool distinct, const std::string &table,
387     const std::vector<std::string> &columns, const std::string &selection,
388     const std::vector<std::string> &selectionArgs, const std::string &groupBy, const std::string &having,
389     const std::string &orderBy, const std::string &limit)
390 {
391     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
392     std::string sql;
393     errCode = SqliteSqlBuilder::BuildQueryString(distinct, table, columns, selection, groupBy, having, orderBy, limit,
394         "", sql);
395     if (errCode != E_OK) {
396         return nullptr;
397     }
398 
399     auto resultSet = QuerySql(sql, selectionArgs);
400     return resultSet;
401 }
402 
QuerySql(const std::string & sql,const std::vector<std::string> & selectionArgs)403 std::unique_ptr<AbsSharedResultSet> RdbStoreImpl::QuerySql(const std::string &sql,
404     const std::vector<std::string> &selectionArgs)
405 {
406     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
407     auto resultSet = std::make_unique<SqliteSharedResultSet>(shared_from_this(), path, sql, selectionArgs);
408     return resultSet;
409 }
410 #endif
411 
412 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
Query(const AbsRdbPredicates & predicates,const std::vector<std::string> columns)413 std::unique_ptr<ResultSet> RdbStoreImpl::Query(
414     const AbsRdbPredicates &predicates, const std::vector<std::string> columns)
415 {
416     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
417     LOG_DEBUG("RdbStoreImpl::Query on called.");
418     std::vector<std::string> selectionArgs = predicates.GetWhereArgs();
419     std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
420     return QueryByStep(sql, selectionArgs);
421 }
422 #endif
423 
Count(int64_t & outValue,const AbsRdbPredicates & predicates)424 int RdbStoreImpl::Count(int64_t &outValue, const AbsRdbPredicates &predicates)
425 {
426     LOG_DEBUG("RdbStoreImpl::Count on called.");
427     std::vector<std::string> selectionArgs = predicates.GetWhereArgs();
428     std::string sql = SqliteSqlBuilder::BuildCountString(predicates);
429 
430     std::vector<ValueObject> bindArgs;
431     std::vector<std::string> whereArgs = predicates.GetWhereArgs();
432     for (const auto& whereArg : whereArgs) {
433         bindArgs.emplace_back(whereArg);
434     }
435 
436     return ExecuteAndGetLong(outValue, sql, bindArgs);
437 }
438 
ExecuteSql(const std::string & sql,const std::vector<ValueObject> & bindArgs)439 int RdbStoreImpl::ExecuteSql(const std::string &sql, const std::vector<ValueObject> &bindArgs)
440 {
441     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
442     int errCode = CheckAttach(sql);
443     if (errCode != E_OK) {
444         return errCode;
445     }
446 
447     std::shared_ptr<StoreSession> session = GetThreadSession();
448     errCode = session->ExecuteSql(sql, bindArgs);
449     if (errCode != E_OK) {
450         LOG_ERROR("RDB_STORE Execute SQL ERROR.");
451         ReleaseThreadSession();
452         return errCode;
453     }
454     int sqlType = SqliteUtils::GetSqlStatementType(sql);
455     if (sqlType == SqliteUtils::STATEMENT_DDL) {
456         if (connectionPool == nullptr) {
457             LOG_ERROR("connectionPool is null");
458             return E_ERROR;
459         }
460         errCode = connectionPool->ReOpenAvailableReadConnections();
461     }
462     ReleaseThreadSession();
463     return errCode;
464 }
465 
ExecuteAndGetLong(int64_t & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)466 int RdbStoreImpl::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs)
467 {
468     std::shared_ptr<StoreSession> session = GetThreadSession();
469     int errCode = session->ExecuteGetLong(outValue, sql, bindArgs);
470     ReleaseThreadSession();
471     return errCode;
472 }
473 
ExecuteAndGetString(std::string & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)474 int RdbStoreImpl::ExecuteAndGetString(
475     std::string &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs)
476 {
477     std::shared_ptr<StoreSession> session = GetThreadSession();
478     int errCode = session->ExecuteGetString(outValue, sql, bindArgs);
479     ReleaseThreadSession();
480     return errCode;
481 }
482 
ExecuteForLastInsertedRowId(int64_t & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)483 int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql,
484     const std::vector<ValueObject> &bindArgs)
485 {
486     std::shared_ptr<StoreSession> session = GetThreadSession();
487     int errCode = session->ExecuteForLastInsertedRowId(outValue, sql, bindArgs);
488     ReleaseThreadSession();
489     return errCode;
490 }
491 
ExecuteForChangedRowCount(int64_t & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)492 int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql,
493     const std::vector<ValueObject> &bindArgs)
494 {
495     std::shared_ptr<StoreSession> session = GetThreadSession();
496     int changeRow = 0;
497     int errCode = session->ExecuteForChangedRowCount(changeRow, sql, bindArgs);
498     outValue = changeRow;
499     ReleaseThreadSession();
500     return errCode;
501 }
502 
503 /**
504  * Restores a database from a specified encrypted or unencrypted database file.
505  */
Backup(const std::string databasePath,const std::vector<uint8_t> destEncryptKey)506 int RdbStoreImpl::Backup(const std::string databasePath, const std::vector<uint8_t> destEncryptKey)
507 {
508     if (databasePath.empty()) {
509         LOG_ERROR("Backup:Empty databasePath.");
510         return E_INVALID_FILE_PATH;
511     }
512     std::string backupFilePath;
513     if (ISFILE(databasePath)) {
514         backupFilePath = ExtractFilePath(path) + databasePath;
515     } else {
516         if (!PathToRealPath(ExtractFilePath(databasePath), backupFilePath)) {
517             LOG_ERROR("Backup:Invalid databasePath.");
518             return E_INVALID_FILE_PATH;
519         }
520         backupFilePath = databasePath;
521     }
522     std::shared_ptr<StoreSession> session = GetThreadSession();
523     int errCode = session->Backup(backupFilePath, destEncryptKey, isEncrypt_);
524     ReleaseThreadSession();
525     return errCode;
526 }
527 
IsHoldingConnection()528 bool RdbStoreImpl::IsHoldingConnection()
529 {
530     std::shared_ptr<StoreSession> session = GetThreadSession();
531     return session->IsHoldingConnection();
532 }
533 
GiveConnectionTemporarily(int64_t milliseconds)534 int RdbStoreImpl::GiveConnectionTemporarily(int64_t milliseconds)
535 {
536     std::shared_ptr<StoreSession> session = GetThreadSession();
537     return session->GiveConnectionTemporarily(milliseconds);
538 }
539 
540 /**
541  * Attaches a database.
542  */
Attach(const std::string & alias,const std::string & pathName,const std::vector<uint8_t> destEncryptKey)543 int RdbStoreImpl::Attach(const std::string &alias, const std::string &pathName,
544     const std::vector<uint8_t> destEncryptKey)
545 {
546     std::shared_ptr<StoreSession> session = GetThreadSession();
547     int errCode = session->Attach(alias, pathName, destEncryptKey, isEncrypt_);
548     ReleaseThreadSession();
549     return errCode;
550 }
551 
552 /**
553  * Obtains the database version.
554  */
GetVersion(int & version)555 int RdbStoreImpl::GetVersion(int &version)
556 {
557     int64_t value;
558     int errCode = ExecuteAndGetLong(value, "PRAGMA user_version;", std::vector<ValueObject>());
559     version = static_cast<int>(value);
560     return errCode;
561 }
562 
563 /**
564  * Sets the version of a new database.
565  */
SetVersion(int version)566 int RdbStoreImpl::SetVersion(int version)
567 {
568     std::string sql = "PRAGMA user_version = " + std::to_string(version);
569     return ExecuteSql(sql, std::vector<ValueObject>());
570 }
571 
572 /**
573  * Begins a transaction in EXCLUSIVE mode.
574  */
BeginTransaction()575 int RdbStoreImpl::BeginTransaction()
576 {
577     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
578     std::shared_ptr<StoreSession> session = GetThreadSession();
579     int errCode = session->BeginTransaction();
580     if (errCode != E_OK) {
581         ReleaseThreadSession();
582     }
583     return errCode;
584 }
585 
586 /**
587 * Begins a transaction in EXCLUSIVE mode.
588 */
RollBack()589 int RdbStoreImpl::RollBack()
590 {
591     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
592     std::shared_ptr<StoreSession> session = GetThreadSession();
593     int errCode = session->RollBack();
594     if (errCode != E_OK) {
595         ReleaseThreadSession();
596     }
597     return errCode;
598 }
599 
600 /**
601 * Begins a transaction in EXCLUSIVE mode.
602 */
Commit()603 int RdbStoreImpl::Commit()
604 {
605     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
606     LOG_DEBUG("Enter Commit");
607     std::shared_ptr<StoreSession> session = GetThreadSession();
608     int errCode = session->Commit();
609     if (errCode != E_OK) {
610         LOG_ERROR("RdbStoreImpl::Commit with error code %{public}d.", errCode);
611         ReleaseThreadSession();
612     }
613     return errCode;
614 }
615 
BeginTransactionWithObserver(TransactionObserver * transactionObserver)616 int RdbStoreImpl::BeginTransactionWithObserver(TransactionObserver *transactionObserver)
617 {
618     transactionObserverStack.push(transactionObserver);
619     std::shared_ptr<StoreSession> session = GetThreadSession();
620     int errCode = session->BeginTransaction(transactionObserver);
621     if (errCode != E_OK) {
622         ReleaseThreadSession();
623     }
624     return errCode;
625 }
626 
MarkAsCommit()627 int RdbStoreImpl::MarkAsCommit()
628 {
629     std::shared_ptr<StoreSession> session = GetThreadSession();
630     int errCode = session->MarkAsCommit();
631     ReleaseThreadSession();
632     return errCode;
633 }
634 
EndTransaction()635 int RdbStoreImpl::EndTransaction()
636 {
637     TransactionObserver *transactionObserver = nullptr;
638     if (transactionObserverStack.size() > 0) {
639         transactionObserver = transactionObserverStack.top();
640         transactionObserverStack.pop();
641     }
642 
643     std::shared_ptr<StoreSession> session = GetThreadSession();
644     int errCode = session->EndTransactionWithObserver(transactionObserver);
645     // release the session got in EndTransaction()
646     ReleaseThreadSession();
647     // release the session got in BeginTransaction()
648     ReleaseThreadSession();
649 
650     if (!transactionObserver) {
651         delete transactionObserver;
652     }
653 
654     return errCode;
655 }
656 
IsInTransaction()657 bool RdbStoreImpl::IsInTransaction()
658 {
659     std::shared_ptr<StoreSession> session = GetThreadSession();
660     bool inTransaction = session->IsInTransaction();
661     ReleaseThreadSession();
662     return inTransaction;
663 }
664 
BeginStepQuery(int & errCode,const std::string sql,const std::vector<std::string> & bindArgs)665 std::shared_ptr<SqliteStatement> RdbStoreImpl::BeginStepQuery(
666     int &errCode, const std::string sql, const std::vector<std::string> &bindArgs)
667 {
668     std::shared_ptr<StoreSession> session = GetThreadSession();
669     LOG_DEBUG("session connection count:%{public}d", session->GetConnectionUseCount());
670     return session->BeginStepQuery(errCode, sql, bindArgs);
671 }
672 
EndStepQuery()673 int RdbStoreImpl::EndStepQuery()
674 {
675     std::shared_ptr<StoreSession> session = GetThreadSession();
676     int err = session->EndStepQuery();
677     ReleaseThreadSession(); // release session got by EndStepQuery
678     ReleaseThreadSession(); // release session got by BeginStepQuery
679     return err;
680 }
681 
CheckAttach(const std::string & sql)682 int RdbStoreImpl::CheckAttach(const std::string &sql)
683 {
684     size_t index = sql.find_first_not_of(' ');
685     if (index == std::string::npos) {
686         return E_OK;
687     }
688 
689     /* The first 3 characters can determine the type */
690     std::string sqlType = sql.substr(index, 3);
691     sqlType = SqliteUtils::StrToUpper(sqlType);
692     if (sqlType != "ATT") {
693         return E_OK;
694     }
695 
696     std::string journalMode;
697     int errCode = ExecuteAndGetString(journalMode, "PRAGMA journal_mode", std::vector<ValueObject>());
698     if (errCode != E_OK) {
699         LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %{public}d", errCode);
700         return errCode;
701     }
702 
703     journalMode = SqliteUtils::StrToUpper(journalMode);
704     if (journalMode == "WAL") {
705         LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode");
706         return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE;
707     }
708 
709     return E_OK;
710 }
711 
712 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM)
713 
ExtractFilePath(const std::string & fileFullName)714 std::string RdbStoreImpl::ExtractFilePath(const std::string &fileFullName)
715 {
716 #ifdef WINDOWS_PLATFORM
717     return std::string(fileFullName).substr(0, fileFullName.rfind("\\") + 1);
718 #else
719     return std::string(fileFullName).substr(0, fileFullName.rfind("/") + 1);
720 #endif
721 }
722 
PathToRealPath(const std::string & path,std::string & realPath)723 bool RdbStoreImpl::PathToRealPath(const std::string &path, std::string &realPath)
724 {
725     if (path.empty()) {
726         LOG_ERROR("path is empty!");
727         return false;
728     }
729 
730     if ((path.length() >= PATH_MAX)) {
731         LOG_ERROR("path len is error, the len is: [%{public}zu]", path.length());
732         return false;
733     }
734 
735     char tmpPath[PATH_MAX] = { 0 };
736 #ifdef WINDOWS_PLATFORM
737     if (_fullpath(tmpPath, path.c_str(), PATH_MAX) == NULL) {
738         LOG_ERROR("path to realpath error");
739         return false;
740     }
741 #else
742     if (realpath(path.c_str(), tmpPath) == NULL) {
743         LOG_ERROR("path to realpath error");
744         return false;
745     }
746 #endif
747     realPath = tmpPath;
748     if (access(realPath.c_str(), F_OK) != 0) {
749         LOG_ERROR("check realpath (%{public}s) error", realPath.c_str());
750         return false;
751     }
752     return true;
753 }
754 #endif
755 
IsOpen() const756 bool RdbStoreImpl::IsOpen() const
757 {
758     return isOpen;
759 }
760 
GetPath()761 std::string RdbStoreImpl::GetPath()
762 {
763     return path;
764 }
765 
GetOrgPath()766 std::string RdbStoreImpl::GetOrgPath()
767 {
768     return orgPath;
769 }
770 
IsReadOnly() const771 bool RdbStoreImpl::IsReadOnly() const
772 {
773     return isReadOnly;
774 }
775 
IsMemoryRdb() const776 bool RdbStoreImpl::IsMemoryRdb() const
777 {
778     return isMemoryRdb;
779 }
780 
GetName()781 std::string RdbStoreImpl::GetName()
782 {
783     return name;
784 }
GetFileType()785 std::string RdbStoreImpl::GetFileType()
786 {
787     return fileType;
788 }
789 
PrepareAndGetInfo(const std::string & sql,bool & outIsReadOnly,int & numParameters,std::vector<std::string> & columnNames)790 int RdbStoreImpl::PrepareAndGetInfo(const std::string &sql, bool &outIsReadOnly, int &numParameters,
791     std::vector<std::string> &columnNames)
792 {
793     std::shared_ptr<StoreSession> session = GetThreadSession();
794 
795     int errCode = session->PrepareAndGetInfo(sql, outIsReadOnly, numParameters, columnNames);
796     ReleaseThreadSession();
797     return errCode;
798 }
799 
800 #ifdef RDB_SUPPORT_ICU
801 /**
802  * Sets the database locale.
803  */
ConfigLocale(const std::string localeStr)804 int RdbStoreImpl::ConfigLocale(const std::string localeStr)
805 {
806     if (isOpen == false) {
807         LOG_ERROR("The connection pool has been closed.");
808         return E_ERROR;
809     }
810 
811     if (connectionPool == nullptr) {
812         LOG_ERROR("connectionPool is null");
813         return E_ERROR;
814     }
815     return connectionPool->ConfigLocale(localeStr);
816 }
817 #endif
818 
Restore(const std::string backupPath,const std::vector<uint8_t> & newKey)819 int RdbStoreImpl::Restore(const std::string backupPath, const std::vector<uint8_t> &newKey)
820 {
821     return ChangeDbFileForRestore(path, backupPath, newKey);
822 }
823 
824 /**
825  * Restores a database from a specified encrypted or unencrypted database file.
826  */
ChangeDbFileForRestore(const std::string newPath,const std::string backupPath,const std::vector<uint8_t> & newKey)827 int RdbStoreImpl::ChangeDbFileForRestore(const std::string newPath, const std::string backupPath,
828     const std::vector<uint8_t> &newKey)
829 {
830     if (isOpen == false) {
831         LOG_ERROR("ChangeDbFileForRestore:The connection pool has been closed.");
832         return E_ERROR;
833     }
834 
835     if (connectionPool == nullptr) {
836         LOG_ERROR("ChangeDbFileForRestore:The connectionPool is null.");
837         return E_ERROR;
838     }
839     if (newPath.empty() || backupPath.empty()) {
840         LOG_ERROR("ChangeDbFileForRestore:Empty databasePath.");
841         return E_INVALID_FILE_PATH;
842     }
843     std::string backupFilePath;
844     std::string restoreFilePath;
845     if (ISFILE(backupPath)) {
846         backupFilePath = ExtractFilePath(path) + backupPath;
847     } else {
848         backupFilePath = backupPath;
849     }
850     if (access(backupFilePath.c_str(), F_OK) != E_OK) {
851         LOG_ERROR("ChangeDbFileForRestore:The backupPath does not exists.");
852         return E_INVALID_FILE_PATH;
853     }
854 
855     if (ISFILE(newPath)) {
856         restoreFilePath = ExtractFilePath(path) + newPath;
857     } else {
858         if (!PathToRealPath(ExtractFilePath(newPath), restoreFilePath)) {
859             LOG_ERROR("ChangeDbFileForRestore:Invalid newPath.");
860             return E_INVALID_FILE_PATH;
861         }
862         restoreFilePath = newPath;
863     }
864     if (backupFilePath == restoreFilePath) {
865         LOG_ERROR("ChangeDbFileForRestore:The backupPath and newPath should not be same.");
866         return E_INVALID_FILE_PATH;
867     }
868     if (backupFilePath == path) {
869         LOG_ERROR("ChangeDbFileForRestore:The backupPath and path should not be same.");
870         return E_INVALID_FILE_PATH;
871     }
872 
873     int ret = connectionPool->ChangeDbFileForRestore(restoreFilePath, backupFilePath, newKey);
874     if (ret == E_OK) {
875         path = restoreFilePath;
876     }
877     return ret;
878 }
879 
880 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
ExecuteForSharedBlock(int & rowNum,AppDataFwk::SharedBlock * sharedBlock,int startPos,int requiredPos,bool isCountAllRows,std::string sql,std::vector<ValueObject> & bindArgVec)881 int RdbStoreImpl::ExecuteForSharedBlock(int &rowNum, AppDataFwk::SharedBlock *sharedBlock, int startPos,
882     int requiredPos, bool isCountAllRows, std::string sql, std::vector<ValueObject> &bindArgVec)
883 {
884     std::shared_ptr<StoreSession> session = GetThreadSession();
885     int errCode =
886         session->ExecuteForSharedBlock(rowNum, sql, bindArgVec, sharedBlock, startPos, requiredPos, isCountAllRows);
887     ReleaseThreadSession();
888     return errCode;
889 }
890 #endif
891 
892 /**
893  * Queries data in the database based on specified conditions.
894  */
QueryByStep(const std::string & sql,const std::vector<std::string> & selectionArgs)895 std::unique_ptr<ResultSet> RdbStoreImpl::QueryByStep(const std::string &sql,
896     const std::vector<std::string> &selectionArgs)
897 {
898     std::unique_ptr<ResultSet> resultSet =
899         std::make_unique<StepResultSet>(shared_from_this(), sql, selectionArgs);
900     return resultSet;
901 }
902 
903 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM)
SetDistributedTables(const std::vector<std::string> & tables)904 int RdbStoreImpl::SetDistributedTables(const std::vector<std::string> &tables)
905 {
906     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
907     if (isEncrypt_) {
908         bool status = false;
909         RdbSecurityManager::GetInstance().GetKeyDistributedStatus(RdbSecurityManager::KeyFileType::PUB_KEY_FILE,
910             status);
911         if (!status) {
912             RdbPassword key =
913                 RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
914             syncerParam_.password_ = std::vector<uint8_t>(key.GetData(), key.GetData() + key.GetSize());
915         }
916     }
917 
918     std::shared_ptr<DistributedRdb::RdbService> service = nullptr;
919     int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service);
920     if (errCode != E_OK) {
921         LOG_DEBUG("GetRdbService failed, err is %{public}d.", errCode);
922         return errCode;
923     }
924     int32_t errorCode = service->SetDistributedTables(syncerParam_, tables);
925     if (errorCode != E_OK) {
926         LOG_ERROR("Fail to set distributed tables, error=%{public}d", errorCode);
927         syncerParam_.password_.assign(syncerParam_.password_.size(), 0);
928         syncerParam_.password_.clear();
929         return errorCode;
930     }
931 
932     if (isEncrypt_) {
933         syncerParam_.password_.assign(syncerParam_.password_.size(), 0);
934         syncerParam_.password_.clear();
935         RdbSecurityManager::GetInstance().SetKeyDistributedStatus(
936             RdbSecurityManager::KeyFileType::PUB_KEY_FILE, true);
937     }
938 
939     LOG_ERROR("success");
940     return E_OK;
941 }
942 
ObtainDistributedTableName(const std::string & device,const std::string & table,int & errCode)943 std::string RdbStoreImpl::ObtainDistributedTableName(
944     const std::string &device, const std::string &table, int &errCode)
945 {
946     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
947 
948     std::string uuid;
949     DeviceManagerAdaptor::RdbDeviceManagerAdaptor &deviceManager =
950         DeviceManagerAdaptor::RdbDeviceManagerAdaptor::GetInstance(syncerParam_.bundleName_);
951     errCode = deviceManager.GetEncryptedUuidByNetworkId(device, uuid);
952     if (errCode != E_OK) {
953         LOG_ERROR("GetUuid is failed");
954         return "";
955     }
956 
957     auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) {
958         return uuid;
959     };
960     DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall);
961 
962     return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table);
963 }
964 
Sync(const SyncOption & option,const AbsRdbPredicates & predicate,const SyncCallback & callback)965 int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const SyncCallback &callback)
966 {
967     DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
968     std::shared_ptr<DistributedRdb::RdbService> service = nullptr;
969     int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service);
970     if (errCode != E_OK) {
971         LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode);
972         return errCode;
973     }
974     errCode = service->Sync(syncerParam_, option, predicate.GetDistributedPredicates(), callback);
975     if (errCode != E_OK) {
976         LOG_ERROR("Sync is failed, err is %{public}d.", errCode);
977         return errCode;
978     }
979     return E_OK;
980 }
981 
Subscribe(const SubscribeOption & option,RdbStoreObserver * observer)982 int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer)
983 {
984     std::shared_ptr<DistributedRdb::RdbService> service = nullptr;
985     int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service);
986     if (errCode != E_OK) {
987         LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode);
988         return errCode;
989     }
990     return service->Subscribe(syncerParam_, option, observer);
991 }
992 
UnSubscribe(const SubscribeOption & option,RdbStoreObserver * observer)993 int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer)
994 {
995     std::shared_ptr<DistributedRdb::RdbService> service = nullptr;
996     int errCode = DistributedRdb::RdbManager::GetRdbService(syncerParam_, service);
997     if (errCode != E_OK) {
998         LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode);
999         return errCode;
1000     }
1001     return service->UnSubscribe(syncerParam_, option, observer);
1002 }
1003 
DropDeviceData(const std::vector<std::string> & devices,const DropOption & option)1004 bool RdbStoreImpl::DropDeviceData(const std::vector<std::string> &devices, const DropOption &option)
1005 {
1006     LOG_INFO("not implement");
1007     return true;
1008 }
1009 #endif
1010 } // namespace OHOS::NativeRdb