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