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