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