1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "rdb_store_impl.h"
17
18 #include <unistd.h>
19
20 #include <algorithm>
21 #include <sstream>
22
23 #include "logger.h"
24 #include "rdb_errno.h"
25 #include "rdb_sql_utils.h"
26 #include "rdb_store.h"
27 #include "rdb_trace.h"
28 #include "sqlite_global_config.h"
29 #include "sqlite_sql_builder.h"
30 #include "sqlite_utils.h"
31 #include "step_result_set.h"
32 #include "task_executor.h"
33 #include "traits.h"
34
35 #ifndef WINDOWS_PLATFORM
36 #include "directory_ex.h"
37 #endif
38
39 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
40 #include "iresult_set.h"
41 #include "raw_data_parser.h"
42 #include "rdb_device_manager_adapter.h"
43 #include "rdb_manager_impl.h"
44 #include "relational_store_manager.h"
45 #include "rdb_security_manager.h"
46 #include "result_set_proxy.h"
47 #include "runtime_config.h"
48 #include "sqlite_shared_result_set.h"
49 #endif
50
51 #ifdef WINDOWS_PLATFORM
52 #define ISFILE(filePath) (((filePath).find("\\") == std::string::npos))
53 #else
54 #define ISFILE(filePath) (((filePath).find("/") == std::string::npos))
55 #endif
56
57 namespace OHOS::NativeRdb {
58 using namespace OHOS::Rdb;
59
InnerOpen()60 int RdbStoreImpl::InnerOpen()
61 {
62 LOG_DEBUG("open %{public}s.", SqliteUtils::Anonymous(rdbStoreConfig.GetPath()).c_str());
63 int errCode = E_OK;
64 connectionPool = SqliteConnectionPool::Create(rdbStoreConfig, errCode);
65 if (connectionPool == nullptr) {
66 return errCode;
67 }
68 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
69 syncerParam_.bundleName_ = rdbStoreConfig.GetBundleName();
70 syncerParam_.hapName_ = rdbStoreConfig.GetModuleName();
71 syncerParam_.storeName_ = rdbStoreConfig.GetName();
72 syncerParam_.area_ = rdbStoreConfig.GetArea();
73 syncerParam_.level_ = static_cast<int32_t>(rdbStoreConfig.GetSecurityLevel());
74 syncerParam_.type_ = rdbStoreConfig.GetDistributedType();
75 syncerParam_.isEncrypt_ = rdbStoreConfig.IsEncrypt();
76 syncerParam_.password_ = {};
77 GetSchema(rdbStoreConfig);
78 #endif
79 return E_OK;
80 }
81
82 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
GetSchema(const RdbStoreConfig & config)83 void RdbStoreImpl::GetSchema(const RdbStoreConfig &config)
84 {
85 std::vector<uint8_t> key = config.GetEncryptKey();
86 RdbPassword rdbPwd;
87 if (config.IsEncrypt()) {
88 RdbSecurityManager::GetInstance().Init(config.GetBundleName(), config.GetPath());
89 rdbPwd = RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
90 key.assign(key.size(), 0);
91 key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
92 }
93 syncerParam_.password_ = std::vector<uint8_t>(key.data(), key.data() + key.size());
94 key.assign(key.size(), 0);
95 if (pool_ == nullptr) {
96 pool_ = TaskExecutor::GetInstance().GetExecutor();
97 }
98 if (pool_ != nullptr) {
99 auto param = syncerParam_;
100 pool_->Execute([param]() {
101 auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(param);
102 if (err != E_OK || service == nullptr) {
103 LOG_DEBUG("GetRdbService failed, err is %{public}d.", err);
104 return;
105 }
106 err = service->GetSchema(param);
107 if (err != E_OK) {
108 LOG_ERROR("GetSchema failed, err is %{public}d.", err);
109 }
110 });
111 }
112 }
113
GetModifyTime(const std::string & table,const std::string & columnName,std::vector<PRIKey> & keys)114 std::map<RdbStore::PRIKey, RdbStore::Date> RdbStoreImpl::GetModifyTime(
115 const std::string &table, const std::string &columnName, std::vector<PRIKey> &keys)
116 {
117 if (table.empty() || columnName.empty() || keys.empty()) {
118 LOG_ERROR("invalid para.");
119 return {};
120 }
121
122 auto logTable = DistributedDB::RelationalStoreManager::GetDistributedLogTableName(table);
123 if (SqliteUtils::StrToUpper(columnName) == ROW_ID) {
124 return GetModifyTimeByRowId(logTable, keys);
125 }
126 std::vector<ValueObject> hashKeys;
127 hashKeys.reserve(keys.size());
128 std::map<std::vector<uint8_t>, PRIKey> keyMap;
129 std::map<std::string, DistributedDB::Type> tmp;
130 for (const auto &key : keys) {
131 DistributedDB::Type value;
132 RawDataParser::Convert(key, value);
133 tmp[columnName] = value;
134 auto hashKey = DistributedDB::RelationalStoreManager::CalcPrimaryKeyHash(tmp);
135 if (hashKey.empty()) {
136 LOG_DEBUG("hash key fail");
137 continue;
138 }
139 hashKeys.emplace_back(ValueObject(hashKey));
140 keyMap[hashKey] = key;
141 }
142
143 std::string sql;
144 sql.append("select hash_key, timestamp/10000 from ");
145 sql.append(logTable);
146 sql.append(" where hash_key in (");
147 sql.append(GetSqlArgs(hashKeys.size()));
148 sql.append(")");
149 auto resultSet = QueryByStep(sql, hashKeys);
150 int count = 0;
151 if (resultSet == nullptr || resultSet->GetRowCount(count) != E_OK || count <= 0) {
152 LOG_ERROR("get resultSet err.");
153 return {};
154 }
155 std::map<PRIKey, Date> result;
156 for (int i = 0; i < count; i++) {
157 resultSet->GoToRow(i);
158 std::vector<uint8_t> hashKey;
159 int64_t timeStamp;
160 resultSet->GetBlob(0, hashKey);
161 resultSet->GetLong(1, timeStamp);
162 result[keyMap[hashKey]] = Date(timeStamp);
163 }
164 return result;
165 }
166
GetModifyTimeByRowId(const std::string & logTable,std::vector<PRIKey> & keys)167 std::map<RdbStore::PRIKey, RdbStore::Date> RdbStoreImpl::GetModifyTimeByRowId(
168 const std::string &logTable, std::vector<PRIKey> &keys)
169 {
170 std::string sql;
171 sql.append("select data_key, timestamp/10000 from ");
172 sql.append(logTable);
173 sql.append(" where data_key in (");
174 sql.append(GetSqlArgs(keys.size()));
175 sql.append(")");
176 std::vector<ValueObject> args;
177 args.reserve(keys.size());
178 for (auto &key : keys) {
179 ValueObject::Type value;
180 RawDataParser::Convert(key, value);
181 args.emplace_back(ValueObject(value));
182 }
183 auto resultSet = QueryByStep(sql, args);
184 int count = 0;
185 if (resultSet == nullptr || resultSet->GetRowCount(count) != E_OK || count <= 0) {
186 LOG_ERROR("get resultSet err.");
187 return {};
188 }
189 std::map<PRIKey, Date> result;
190 for (int i = 0; i < count; i++) {
191 resultSet->GoToRow(i);
192 int rowId;
193 int64_t timeStamp;
194 resultSet->GetInt(0, rowId);
195 resultSet->GetLong(1, timeStamp);
196 result[rowId] = Date(timeStamp);
197 }
198 return result;
199 }
200
GetSqlArgs(size_t size)201 std::string RdbStoreImpl::GetSqlArgs(size_t size)
202 {
203 std::string args((size << 1) - 1, '?');
204 for (size_t i = 1; i < size; ++i) {
205 args[(i << 1) - 1] = ',';
206 }
207 return args;
208 }
209 #endif
210
RdbStoreImpl(const RdbStoreConfig & config,int & errCode)211 RdbStoreImpl::RdbStoreImpl(const RdbStoreConfig &config, int &errCode)
212 : rdbStoreConfig(config), connectionPool(nullptr), isOpen(true), path(config.GetPath()), orgPath(config.GetPath()),
213 isReadOnly(config.IsReadOnly()), isMemoryRdb(config.IsMemoryRdb()), name(config.GetName()),
214 fileType(config.GetDatabaseFileType()), isEncrypt_(config.IsEncrypt())
215 {
216 errCode = InnerOpen();
217 if (errCode != E_OK) {
218 LOG_ERROR("RdbStoreManager GetRdbStore fail to open RdbStore, err is %{public}d", errCode);
219 if (connectionPool) {
220 delete connectionPool;
221 }
222 isOpen = false;
223 }
224 }
225
~RdbStoreImpl()226 RdbStoreImpl::~RdbStoreImpl()
227 {
228 LOG_DEBUG("destroy.");
229 if (connectionPool) {
230 delete connectionPool;
231 }
232 }
233
234 #ifdef WINDOWS_PLATFORM
Clear()235 void RdbStoreImpl::Clear()
236 {
237 delete connectionPool;
238 connectionPool = nullptr;
239 }
240 #endif
241
GetConfig()242 const RdbStoreConfig &RdbStoreImpl::GetConfig()
243 {
244 return rdbStoreConfig;
245 }
Insert(int64_t & outRowId,const std::string & table,const ValuesBucket & initialValues)246 int RdbStoreImpl::Insert(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues)
247 {
248 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
249 return InsertWithConflictResolution(outRowId, table, initialValues, ConflictResolution::ON_CONFLICT_NONE);
250 }
251
BatchInsert(int64_t & outInsertNum,const std::string & table,const std::vector<ValuesBucket> & initialBatchValues)252 int RdbStoreImpl::BatchInsert(int64_t &outInsertNum, const std::string &table,
253 const std::vector<ValuesBucket> &initialBatchValues)
254 {
255 if (initialBatchValues.empty()) {
256 outInsertNum = 0;
257 return E_OK;
258 }
259 // prepare batch data & sql
260 std::vector<std::pair<std::string, std::vector<ValueObject>>> vecVectorObj;
261 for (auto iter = initialBatchValues.begin(); iter != initialBatchValues.end(); iter++) {
262 auto values = (*iter).GetAll();
263 vecVectorObj.push_back(GetInsertParams(values, table));
264 }
265
266 // prepare BeginTransaction
267 int errCode = connectionPool->AcquireTransaction();
268 if (errCode != E_OK) {
269 return errCode;
270 }
271
272 SqliteConnection *connection = connectionPool->AcquireConnection(false);
273 if (connection == nullptr) {
274 return E_CON_OVER_LIMIT;
275 }
276
277 if (connection->IsInTransaction()) {
278 connectionPool->ReleaseTransaction();
279 connectionPool->ReleaseConnection(connection);
280 LOG_ERROR("Transaction is in excuting.");
281 return E_TRANSACTION_IN_EXECUTE;
282 }
283 BaseTransaction transaction(0);
284 connection->SetInTransaction(true);
285 errCode = connection->ExecuteSql(transaction.GetTransactionStr());
286 if (errCode != E_OK) {
287 LOG_ERROR("BeginTransaction with error code %{public}d.", errCode);
288 connection->SetInTransaction(false);
289 connectionPool->ReleaseConnection(connection);
290 connectionPool->ReleaseTransaction();
291 return errCode;
292 }
293
294 // batch insert the values
295 for (auto iter = vecVectorObj.begin(); iter != vecVectorObj.end(); iter++) {
296 outInsertNum++;
297 errCode = connection->ExecuteSql(iter->first, iter->second);
298 if (errCode != E_OK) {
299 LOG_ERROR("BatchInsert with error code %{public}d.", errCode);
300 outInsertNum = -1;
301 return FreeTransaction(connection, transaction.GetRollbackStr());
302 }
303 }
304 auto status = FreeTransaction(connection, transaction.GetCommitStr());
305 if (status == E_OK) {
306 DoCloudSync(table);
307 }
308 return status;
309 }
310
GetInsertParams(std::map<std::string,ValueObject> & valuesMap,const std::string & table)311 std::pair<std::string, std::vector<ValueObject>> RdbStoreImpl::GetInsertParams(
312 std::map<std::string, ValueObject> &valuesMap, const std::string &table)
313 {
314 std::stringstream sql;
315 std::vector<ValueObject> bindArgs;
316 sql << "INSERT INTO " << table << '(';
317 // prepare batch values & sql.columnName
318 for (auto valueIter = valuesMap.begin(); valueIter != valuesMap.end(); valueIter++) {
319 sql << ((valueIter == valuesMap.begin()) ? "" : ",");
320 sql << valueIter->first;
321 bindArgs.push_back(valueIter->second);
322 }
323 // prepare sql.value
324 sql << ") VALUES (";
325 for (size_t i = 0; i < valuesMap.size(); i++) {
326 sql << ((i == 0) ? "?" : ",?");
327 }
328 sql << ')';
329
330 // put sql & vec<value> into map<sql, args>
331 return std::make_pair(sql.str(), bindArgs);
332 }
333
Replace(int64_t & outRowId,const std::string & table,const ValuesBucket & initialValues)334 int RdbStoreImpl::Replace(int64_t &outRowId, const std::string &table, const ValuesBucket &initialValues)
335 {
336 return InsertWithConflictResolution(outRowId, table, initialValues, ConflictResolution::ON_CONFLICT_REPLACE);
337 }
338
InsertWithConflictResolution(int64_t & outRowId,const std::string & table,const ValuesBucket & initialValues,ConflictResolution conflictResolution)339 int RdbStoreImpl::InsertWithConflictResolution(int64_t &outRowId, const std::string &table,
340 const ValuesBucket &initialValues, ConflictResolution conflictResolution)
341 {
342 return InnerInsert(outRowId, table, initialValues, conflictResolution);
343 }
344
InnerInsert(int64_t & outRowId,const std::string & table,ValuesBucket values,ConflictResolution conflictResolution)345 int RdbStoreImpl::InnerInsert(int64_t &outRowId, const std::string &table,
346 ValuesBucket values, ConflictResolution conflictResolution)
347 {
348 if (table.empty()) {
349 return E_EMPTY_TABLE_NAME;
350 }
351
352 if (values.IsEmpty()) {
353 return E_EMPTY_VALUES_BUCKET;
354 }
355
356 std::string conflictClause;
357 int errCode = SqliteUtils::GetConflictClause(static_cast<int>(conflictResolution), conflictClause);
358 if (errCode != E_OK) {
359 return errCode;
360 }
361
362 std::stringstream sql;
363 sql << "INSERT" << conflictClause << " INTO " << table << '(';
364
365 std::vector<ValueObject> bindArgs;
366 const char *split = "";
367 for (auto &[key, val] : values.values_) {
368 sql << split;
369 sql << key; // columnName
370 if (val.GetType() == ValueObject::TYPE_ASSETS &&
371 conflictResolution == ConflictResolution::ON_CONFLICT_REPLACE) {
372 return E_INVALID_ARGS;
373 }
374 if (val.GetType() == ValueObject::TYPE_ASSET || val.GetType() == ValueObject::TYPE_ASSETS) {
375 SetAssetStatusWhileInsert(val);
376 }
377 bindArgs.push_back(val); // columnValue
378 split = ",";
379 }
380
381 sql << ") VALUES (";
382 for (size_t i = 0; i < bindArgs.size(); i++) {
383 sql << ((i == 0) ? "?" : ",?");
384 }
385 sql << ')';
386
387 SqliteConnection *connection = connectionPool->AcquireConnection(false);
388 if (connection == nullptr) {
389 return E_CON_OVER_LIMIT;
390 }
391
392 errCode = connection->ExecuteForLastInsertedRowId(outRowId, sql.str(), bindArgs);
393 connectionPool->ReleaseConnection(connection);
394 if (errCode == E_OK) {
395 DoCloudSync(table);
396 }
397 return errCode;
398 }
399
SetAssetStatusWhileInsert(ValueObject & val)400 void RdbStoreImpl::SetAssetStatusWhileInsert(ValueObject &val)
401 {
402 if (val.GetType() == ValueObject::TYPE_ASSET) {
403 auto *asset = Traits::get_if<ValueObject::Asset>(&val.value);
404 if (asset != nullptr) {
405 asset->status = AssetValue::STATUS_INSERT;
406 }
407 }
408 if (val.GetType() == ValueObject::TYPE_ASSETS) {
409 auto *assets = Traits::get_if<ValueObject::Assets>(&val.value);
410 if (assets != nullptr) {
411 for (auto &asset : *assets) {
412 asset.status = AssetValue::STATUS_INSERT;
413 }
414 }
415 }
416 }
417
Update(int & changedRows,const std::string & table,const ValuesBucket & values,const std::string & whereClause,const std::vector<std::string> & whereArgs)418 int RdbStoreImpl::Update(int &changedRows, const std::string &table, const ValuesBucket &values,
419 const std::string &whereClause, const std::vector<std::string> &whereArgs)
420 {
421 std::vector<ValueObject> bindArgs;
422 std::for_each(
423 whereArgs.begin(), whereArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
424 return UpdateWithConflictResolution(
425 changedRows, table, values, whereClause, bindArgs, ConflictResolution::ON_CONFLICT_NONE);
426 }
427
Update(int & changedRows,const std::string & table,const ValuesBucket & values,const std::string & whereClause,const std::vector<ValueObject> & bindArgs)428 int RdbStoreImpl::Update(int &changedRows, const std::string &table, const ValuesBucket &values,
429 const std::string &whereClause, const std::vector<ValueObject> &bindArgs)
430 {
431 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
432 return UpdateWithConflictResolution(
433 changedRows, table, values, whereClause, bindArgs, ConflictResolution::ON_CONFLICT_NONE);
434 }
435
Update(int & changedRows,const ValuesBucket & values,const AbsRdbPredicates & predicates)436 int RdbStoreImpl::Update(int &changedRows, const ValuesBucket &values, const AbsRdbPredicates &predicates)
437 {
438 return Update(
439 changedRows, predicates.GetTableName(), values, predicates.GetWhereClause(), predicates.GetBindArgs());
440 }
441
UpdateWithConflictResolution(int & changedRows,const std::string & table,const ValuesBucket & values,const std::string & whereClause,const std::vector<std::string> & whereArgs,ConflictResolution conflictResolution)442 int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
443 const std::string &whereClause, const std::vector<std::string> &whereArgs, ConflictResolution conflictResolution)
444 {
445 std::vector<ValueObject> bindArgs;
446 std::for_each(
447 whereArgs.begin(), whereArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
448 return UpdateWithConflictResolution(
449 changedRows, table, values, whereClause, bindArgs, conflictResolution);
450 }
451
UpdateWithConflictResolution(int & changedRows,const std::string & table,const ValuesBucket & values,const std::string & whereClause,const std::vector<ValueObject> & bindArgs,ConflictResolution conflictResolution)452 int RdbStoreImpl::UpdateWithConflictResolution(int &changedRows, const std::string &table, const ValuesBucket &values,
453 const std::string &whereClause, const std::vector<ValueObject> &bindArgs, ConflictResolution conflictResolution)
454 {
455 if (table.empty()) {
456 return E_EMPTY_TABLE_NAME;
457 }
458
459 if (values.IsEmpty()) {
460 return E_EMPTY_VALUES_BUCKET;
461 }
462
463 std::string conflictClause;
464 int errCode = SqliteUtils::GetConflictClause(static_cast<int>(conflictResolution), conflictClause);
465 if (errCode != E_OK) {
466 return errCode;
467 }
468
469 std::stringstream sql;
470 sql << "UPDATE" << conflictClause << " " << table << " SET ";
471
472 std::vector<ValueObject> tmpBindArgs;
473 const char *split = "";
474 for (auto &[key, val] : values.values_) {
475 sql << split;
476 if (val.GetType() == ValueObject::TYPE_ASSETS) {
477 sql << key << "=merge_assets(" << key << ", ?)"; // columnName
478 } else {
479 sql << key << "=?"; // columnName
480 }
481 tmpBindArgs.push_back(val); // columnValue
482 split = ",";
483 }
484
485 if (!whereClause.empty()) {
486 sql << " WHERE " << whereClause;
487 }
488
489 tmpBindArgs.insert(tmpBindArgs.end(), bindArgs.begin(), bindArgs.end());
490
491 SqliteConnection *connection = connectionPool->AcquireConnection(false);
492 if (connection == nullptr) {
493 return E_CON_OVER_LIMIT;
494 }
495
496 errCode = connection->ExecuteForChangedRowCount(changedRows, sql.str(), tmpBindArgs);
497 connectionPool->ReleaseConnection(connection);
498 if (errCode == E_OK) {
499 DoCloudSync(table);
500 }
501 return errCode;
502 }
503
Delete(int & deletedRows,const AbsRdbPredicates & predicates)504 int RdbStoreImpl::Delete(int &deletedRows, const AbsRdbPredicates &predicates)
505 {
506 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
507 return Delete(deletedRows, predicates.GetTableName(), predicates.GetWhereClause(), predicates.GetBindArgs());
508 }
509
Delete(int & deletedRows,const std::string & table,const std::string & whereClause,const std::vector<std::string> & whereArgs)510 int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
511 const std::vector<std::string> &whereArgs)
512 {
513 std::vector<ValueObject> bindArgs;
514 std::for_each(
515 whereArgs.begin(), whereArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
516 return Delete(deletedRows, table, whereClause, bindArgs);
517 }
518
Delete(int & deletedRows,const std::string & table,const std::string & whereClause,const std::vector<ValueObject> & bindArgs)519 int RdbStoreImpl::Delete(int &deletedRows, const std::string &table, const std::string &whereClause,
520 const std::vector<ValueObject> &bindArgs)
521 {
522 if (table.empty()) {
523 return E_EMPTY_TABLE_NAME;
524 }
525
526 std::stringstream sql;
527 sql << "DELETE FROM " << table;
528 if (!whereClause.empty()) {
529 sql << " WHERE " << whereClause;
530 }
531
532 SqliteConnection *connection = connectionPool->AcquireConnection(false);
533 if (connection == nullptr) {
534 return E_CON_OVER_LIMIT;
535 }
536
537 int errCode = connection->ExecuteForChangedRowCount(deletedRows, sql.str(), bindArgs);
538 connectionPool->ReleaseConnection(connection);
539 if (errCode == E_OK) {
540 DoCloudSync(table);
541 }
542 return errCode;
543 }
544
545 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
Query(const AbsRdbPredicates & predicates,const std::vector<std::string> & columns)546 std::shared_ptr<AbsSharedResultSet> RdbStoreImpl::Query(
547 const AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
548 {
549 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
550 std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
551 return QuerySql(sql, predicates.GetBindArgs());
552 }
553
QueryByStep(const AbsRdbPredicates & predicates,const std::vector<std::string> & columns)554 std::shared_ptr<ResultSet> RdbStoreImpl::QueryByStep(
555 const AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
556 {
557 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
558 std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
559 return QueryByStep(sql, predicates.GetBindArgs());
560 }
561
RemoteQuery(const std::string & device,const AbsRdbPredicates & predicates,const std::vector<std::string> & columns,int & errCode)562 std::shared_ptr<ResultSet> RdbStoreImpl::RemoteQuery(const std::string &device,
563 const AbsRdbPredicates &predicates, const std::vector<std::string> &columns, int &errCode)
564 {
565 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
566 std::vector<std::string> selectionArgs = predicates.GetWhereArgs();
567 std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
568 auto [err, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_);
569 errCode = err;
570 if (err != E_OK) {
571 LOG_ERROR("RdbStoreImpl::RemoteQuery get service failed");
572 return nullptr;
573 }
574 sptr<IRemoteObject> remoteResultSet;
575 if (service->RemoteQuery(syncerParam_, device, sql, selectionArgs, remoteResultSet) != E_OK) {
576 LOG_ERROR("RdbStoreImpl::RemoteQuery service RemoteQuery failed");
577 return nullptr;
578 }
579 return std::make_shared<ResultSetProxy>(remoteResultSet);
580 }
581
Query(int & errCode,bool distinct,const std::string & table,const std::vector<std::string> & columns,const std::string & whereClause,const std::vector<ValueObject> & bindArgs,const std::string & groupBy,const std::string & indexName,const std::string & orderBy,const int & limit,const int & offset)582 std::shared_ptr<AbsSharedResultSet> RdbStoreImpl::Query(int &errCode, bool distinct,
583 const std::string &table, const std::vector<std::string> &columns,
584 const std::string &whereClause, const std::vector<ValueObject> &bindArgs, const std::string &groupBy,
585 const std::string &indexName, const std::string &orderBy, const int &limit, const int &offset)
586 {
587 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
588 std::string sql;
589 errCode = SqliteSqlBuilder::BuildQueryString(
590 distinct, table, columns, whereClause, groupBy, indexName, orderBy, limit, offset, sql);
591 if (errCode != E_OK) {
592 return nullptr;
593 }
594
595 auto resultSet = QuerySql(sql, bindArgs);
596 return resultSet;
597 }
598
QuerySql(const std::string & sql,const std::vector<std::string> & sqlArgs)599 std::shared_ptr<AbsSharedResultSet> RdbStoreImpl::QuerySql(const std::string &sql,
600 const std::vector<std::string> &sqlArgs)
601 {
602 std::vector<ValueObject> bindArgs;
603 std::for_each(sqlArgs.begin(), sqlArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
604 return std::make_shared<SqliteSharedResultSet>(shared_from_this(), connectionPool, path, sql, bindArgs);
605 }
606
QuerySql(const std::string & sql,const std::vector<ValueObject> & bindArgs)607 std::shared_ptr<AbsSharedResultSet> RdbStoreImpl::QuerySql(const std::string &sql,
608 const std::vector<ValueObject> &bindArgs)
609 {
610 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
611 return std::make_shared<SqliteSharedResultSet>(shared_from_this(), connectionPool, path, sql, bindArgs);
612 }
613 #endif
614
615 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
Query(const AbsRdbPredicates & predicates,const std::vector<std::string> & columns)616 std::shared_ptr<ResultSet> RdbStoreImpl::Query(
617 const AbsRdbPredicates &predicates, const std::vector<std::string> &columns)
618 {
619 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
620 LOG_DEBUG("RdbStoreImpl::Query on called.");
621 std::string sql = SqliteSqlBuilder::BuildQueryString(predicates, columns);
622 return QueryByStep(sql, predicates.GetBindArgs());
623 }
624 #endif
625
Count(int64_t & outValue,const AbsRdbPredicates & predicates)626 int RdbStoreImpl::Count(int64_t &outValue, const AbsRdbPredicates &predicates)
627 {
628 std::string sql = SqliteSqlBuilder::BuildCountString(predicates);
629
630 return ExecuteAndGetLong(outValue, sql, predicates.GetBindArgs());
631 }
632
ExecuteSql(const std::string & sql,const std::vector<ValueObject> & bindArgs)633 int RdbStoreImpl::ExecuteSql(const std::string &sql, const std::vector<ValueObject> &bindArgs)
634 {
635 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
636 int errCode = CheckAttach(sql);
637 if (errCode != E_OK) {
638 return errCode;
639 }
640
641 SqliteConnection *connection;
642 errCode = BeginExecuteSql(sql, &connection);
643 if (errCode != E_OK) {
644 return errCode;
645 }
646 errCode = connection->ExecuteSql(sql, bindArgs);
647 connectionPool->ReleaseConnection(connection);
648 if (errCode != E_OK) {
649 LOG_ERROR("RDB_STORE Execute SQL ERROR.");
650 return errCode;
651 }
652 int sqlType = SqliteUtils::GetSqlStatementType(sql);
653 if (sqlType == SqliteUtils::STATEMENT_DDL) {
654 LOG_DEBUG("sql ddl execute.");
655 errCode = connectionPool->ReOpenAvailableReadConnections();
656 }
657
658 if (errCode == E_OK) {
659 DoCloudSync("");
660 }
661 return errCode;
662 }
663
ExecuteAndGetLong(int64_t & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)664 int RdbStoreImpl::ExecuteAndGetLong(int64_t &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs)
665 {
666 SqliteConnection *connection;
667 int errCode = BeginExecuteSql(sql, &connection);
668 if (errCode != E_OK) {
669 return errCode;
670 }
671 errCode = connection->ExecuteGetLong(outValue, sql, bindArgs);
672 if (errCode != E_OK) {
673 LOG_ERROR("RDB_STORE ExecuteAndGetLong ERROR is %{public}d.", errCode);
674 }
675 connectionPool->ReleaseConnection(connection);
676 return errCode;
677 }
678
ExecuteAndGetString(std::string & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)679 int RdbStoreImpl::ExecuteAndGetString(
680 std::string &outValue, const std::string &sql, const std::vector<ValueObject> &bindArgs)
681 {
682 SqliteConnection *connection;
683 int errCode = BeginExecuteSql(sql, &connection);
684 if (errCode != E_OK) {
685 return errCode;
686 }
687 connection->ExecuteGetString(outValue, sql, bindArgs);
688 connectionPool->ReleaseConnection(connection);
689 return errCode;
690 }
691
ExecuteForLastInsertedRowId(int64_t & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)692 int RdbStoreImpl::ExecuteForLastInsertedRowId(int64_t &outValue, const std::string &sql,
693 const std::vector<ValueObject> &bindArgs)
694 {
695 SqliteConnection *connection = connectionPool->AcquireConnection(false);
696 if (connection == nullptr) {
697 return E_CON_OVER_LIMIT;
698 }
699
700 int errCode = connection->ExecuteForLastInsertedRowId(outValue, sql, bindArgs);
701 connectionPool->ReleaseConnection(connection);
702 return errCode;
703 }
704
ExecuteForChangedRowCount(int64_t & outValue,const std::string & sql,const std::vector<ValueObject> & bindArgs)705 int RdbStoreImpl::ExecuteForChangedRowCount(int64_t &outValue, const std::string &sql,
706 const std::vector<ValueObject> &bindArgs)
707 {
708 int changeRow = 0;
709 SqliteConnection *connection = connectionPool->AcquireConnection(false);
710 if (connection == nullptr) {
711 return E_CON_OVER_LIMIT;
712 }
713
714 int errCode = connection->ExecuteForChangedRowCount(changeRow, sql, bindArgs);
715 connectionPool->ReleaseConnection(connection);
716 outValue = changeRow;
717 return errCode;
718 }
719
GetDataBasePath(const std::string & databasePath,std::string & backupFilePath)720 int RdbStoreImpl::GetDataBasePath(const std::string &databasePath, std::string &backupFilePath)
721 {
722 if (databasePath.empty()) {
723 LOG_ERROR("Empty databasePath.");
724 return E_INVALID_FILE_PATH;
725 }
726
727 if (ISFILE(databasePath)) {
728 backupFilePath = ExtractFilePath(path) + databasePath;
729 } else {
730 // 2 represents two characters starting from the len - 2 position
731 if (!PathToRealPath(ExtractFilePath(databasePath), backupFilePath) || databasePath.back() == '/' ||
732 databasePath.substr(databasePath.length() - 2, 2) == "\\") {
733 LOG_ERROR("Invalid databasePath.");
734 return E_INVALID_FILE_PATH;
735 }
736 backupFilePath = databasePath;
737 }
738
739 if (backupFilePath == path) {
740 LOG_ERROR("The backupPath and path should not be same.");
741 return E_INVALID_FILE_PATH;
742 }
743
744 LOG_INFO("databasePath is %{public}s.", SqliteUtils::Anonymous(backupFilePath).c_str());
745 return E_OK;
746 }
747
ExecuteSqlInner(const std::string & sql,const std::vector<ValueObject> & bindArgs)748 int RdbStoreImpl::ExecuteSqlInner(const std::string &sql, const std::vector<ValueObject> &bindArgs)
749 {
750 SqliteConnection *connection;
751 int errCode = BeginExecuteSql(sql, &connection);
752 if (errCode != 0) {
753 return errCode;
754 }
755
756 errCode = connection->ExecuteSql(sql, bindArgs);
757 connectionPool->ReleaseConnection(connection);
758 if (errCode != E_OK) {
759 LOG_ERROR("ExecuteSql ATTACH_BACKUP_SQL error %{public}d", errCode);
760 return errCode;
761 }
762 return errCode;
763 }
764
ExecuteGetLongInner(const std::string & sql,const std::vector<ValueObject> & bindArgs)765 int RdbStoreImpl::ExecuteGetLongInner(const std::string &sql, const std::vector<ValueObject> &bindArgs)
766 {
767 int64_t count;
768 SqliteConnection *connection;
769 int errCode = BeginExecuteSql(sql, &connection);
770 if (errCode != 0) {
771 return errCode;
772 }
773 errCode = connection->ExecuteGetLong(count, sql, bindArgs);
774 connectionPool->ReleaseConnection(connection);
775 if (errCode != E_OK) {
776 LOG_ERROR("ExecuteSql EXPORT_SQL error %{public}d", errCode);
777 return errCode;
778 }
779 return errCode;
780 }
781
782 /**
783 * Backup a database from a specified encrypted or unencrypted database file.
784 */
Backup(const std::string databasePath,const std::vector<uint8_t> destEncryptKey)785 int RdbStoreImpl::Backup(const std::string databasePath, const std::vector<uint8_t> destEncryptKey)
786 {
787 std::string backupFilePath;
788 int ret = GetDataBasePath(databasePath, backupFilePath);
789 if (ret != E_OK) {
790 return ret;
791 }
792 std::string tempPath = backupFilePath + "temp";
793 while (access(tempPath.c_str(), F_OK) == E_OK) {
794 tempPath += "temp";
795 }
796 if (access(backupFilePath.c_str(), F_OK) == E_OK) {
797 SqliteUtils::RenameFile(backupFilePath, tempPath);
798 ret = InnerBackup(backupFilePath, destEncryptKey);
799 if (ret == E_OK) {
800 SqliteUtils::DeleteFile(tempPath);
801 } else {
802 SqliteUtils::RenameFile(tempPath, backupFilePath);
803 }
804 return ret;
805 }
806 ret = InnerBackup(backupFilePath, destEncryptKey);
807 return ret;
808 }
809
810 /**
811 * Backup a database from a specified encrypted or unencrypted database file.
812 */
InnerBackup(const std::string databasePath,const std::vector<uint8_t> destEncryptKey)813 int RdbStoreImpl::InnerBackup(const std::string databasePath, const std::vector<uint8_t> destEncryptKey)
814 {
815 std::vector<ValueObject> bindArgs;
816 bindArgs.push_back(ValueObject(databasePath));
817 if (destEncryptKey.size() != 0 && !isEncrypt_) {
818 bindArgs.push_back(ValueObject(destEncryptKey));
819 ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
820 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
821 } else if (isEncrypt_) {
822 RdbPassword rdbPwd =
823 RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
824 std::vector<uint8_t> key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
825 bindArgs.push_back(ValueObject(key));
826 ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
827 #endif
828 } else {
829 std::string str = "";
830 bindArgs.push_back(ValueObject(str));
831 }
832
833 int ret = ExecuteSqlInner(GlobalExpr::ATTACH_BACKUP_SQL, bindArgs);
834 if (ret != E_OK) {
835 return ret;
836 }
837
838 ret = ExecuteGetLongInner(GlobalExpr::EXPORT_SQL, std::vector<ValueObject>());
839
840 int res = ExecuteSqlInner(GlobalExpr::DETACH_BACKUP_SQL, std::vector<ValueObject>());
841
842 return res == E_OK ? ret : res;
843 }
844
BeginExecuteSql(const std::string & sql,SqliteConnection ** connection)845 int RdbStoreImpl::BeginExecuteSql(const std::string &sql, SqliteConnection **connection)
846 {
847 int type = SqliteUtils::GetSqlStatementType(sql);
848 if (SqliteUtils::IsSpecial(type)) {
849 return E_TRANSACTION_IN_EXECUTE;
850 }
851
852 bool assumeReadOnly = SqliteUtils::IsSqlReadOnly(type);
853 bool isReadOnly = false;
854 *connection = connectionPool->AcquireConnection(assumeReadOnly);
855 if (*connection == nullptr) {
856 return E_CON_OVER_LIMIT;
857 }
858
859 int errCode = (*connection)->Prepare(sql, isReadOnly);
860 if (errCode != 0) {
861 connectionPool->ReleaseConnection(*connection);
862 return errCode;
863 }
864
865 if (isReadOnly == (*connection)->IsWriteConnection()) {
866 connectionPool->ReleaseConnection(*connection);
867 *connection = connectionPool->AcquireConnection(isReadOnly);
868 if (*connection == nullptr) {
869 return E_CON_OVER_LIMIT;
870 }
871
872 if (!isReadOnly && !(*connection)->IsWriteConnection()) {
873 LOG_ERROR("StoreSession BeginExecutea : read connection can not execute write operation");
874 connectionPool->ReleaseConnection(*connection);
875 return E_EXECUTE_WRITE_IN_READ_CONNECTION;
876 }
877 }
878
879 return E_OK;
880 }
IsHoldingConnection()881 bool RdbStoreImpl::IsHoldingConnection()
882
883 {
884 return connectionPool != nullptr;
885 }
886
GiveConnectionTemporarily(int64_t milliseconds)887 int RdbStoreImpl::GiveConnectionTemporarily(int64_t milliseconds)
888 {
889 SqliteConnection *connection = connectionPool->AcquireConnection(false);
890 if (connection == nullptr) {
891 return E_CON_OVER_LIMIT;
892 }
893
894 if (connection->IsInTransaction()) {
895 return E_STORE_SESSION_NOT_GIVE_CONNECTION_TEMPORARILY;
896 }
897 int errCode = BeginTransaction();
898 if (errCode != E_OK) {
899 return errCode;
900 }
901 std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
902 errCode = RollBack();
903 if (errCode != E_OK) {
904 return errCode;
905 }
906
907 return errCode;
908 }
909
910 /**
911 * Attaches a database.
912 */
Attach(const std::string & alias,const std::string & pathName,const std::vector<uint8_t> destEncryptKey)913 int RdbStoreImpl::Attach(const std::string &alias, const std::string &pathName,
914 const std::vector<uint8_t> destEncryptKey)
915 {
916 SqliteConnection *connection;
917 std::string sql = GlobalExpr::PRAGMA_JOUR_MODE_EXP;
918 int errCode = BeginExecuteSql(sql, &connection);
919 if (errCode != 0) {
920 return errCode;
921 }
922 std::string journalMode;
923 errCode = connection->ExecuteGetString(journalMode, sql, std::vector<ValueObject>());
924 if (errCode != E_OK) {
925 connectionPool->ReleaseConnection(connection);
926 LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %d", errCode);
927 return errCode;
928 }
929 journalMode = SqliteUtils::StrToUpper(journalMode);
930 if (journalMode == GlobalExpr::DEFAULT_JOURNAL_MODE) {
931 connectionPool->ReleaseConnection(connection);
932 LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode");
933 return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE;
934 }
935
936 std::vector<ValueObject> bindArgs;
937 bindArgs.push_back(ValueObject(pathName));
938 bindArgs.push_back(ValueObject(alias));
939 if (destEncryptKey.size() != 0 && !isEncrypt_) {
940 bindArgs.push_back(ValueObject(destEncryptKey));
941 ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
942 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
943 } else if (isEncrypt_) {
944 RdbPassword rdbPwd =
945 RdbSecurityManager::GetInstance().GetRdbPassword(RdbSecurityManager::KeyFileType::PUB_KEY_FILE);
946 std::vector<uint8_t> key = std::vector<uint8_t>(rdbPwd.GetData(), rdbPwd.GetData() + rdbPwd.GetSize());
947 bindArgs.push_back(ValueObject(key));
948 ExecuteSql(GlobalExpr::CIPHER_DEFAULT_ATTACH_HMAC_ALGO);
949 #endif
950 } else {
951 std::string str = "";
952 bindArgs.push_back(ValueObject(str));
953 }
954 sql = GlobalExpr::ATTACH_SQL;
955 errCode = connection->ExecuteSql(sql, bindArgs);
956 connectionPool->ReleaseConnection(connection);
957 if (errCode != E_OK) {
958 LOG_ERROR("ExecuteSql ATTACH_SQL error %d", errCode);
959 }
960
961 return errCode;
962 }
963
964 /**
965 * Obtains the database version.
966 */
GetVersion(int & version)967 int RdbStoreImpl::GetVersion(int &version)
968 {
969 int64_t value = 0;
970 int errCode = ExecuteAndGetLong(value, GlobalExpr::PRAGMA_VERSION, std::vector<ValueObject>());
971 version = static_cast<int>(value);
972 return errCode;
973 }
974
975 /**
976 * Sets the version of a new database.
977 */
SetVersion(int version)978 int RdbStoreImpl::SetVersion(int version)
979 {
980 std::string sql = std::string(GlobalExpr::PRAGMA_VERSION) + " = " + std::to_string(version);
981 return ExecuteSql(sql, std::vector<ValueObject>());
982 }
983 /**
984 * Begins a transaction in EXCLUSIVE mode.
985 */
BeginTransaction()986 int RdbStoreImpl::BeginTransaction()
987 {
988 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
989 BaseTransaction transaction(connectionPool->getTransactionStack().size());
990 SqliteConnection *connection = connectionPool->AcquireConnection(false);
991 if (connection == nullptr) {
992 return E_CON_OVER_LIMIT;
993 }
994
995 int errCode = connection->ExecuteSql(transaction.GetTransactionStr());
996 connectionPool->ReleaseConnection(connection);
997 if (errCode != E_OK) {
998 LOG_DEBUG("storeSession BeginTransaction Failed");
999 return errCode;
1000 }
1001
1002 connection->SetInTransaction(true);
1003 connectionPool->getTransactionStack().push(transaction);
1004 return E_OK;
1005 }
1006
1007 /**
1008 * Begins a transaction in EXCLUSIVE mode.
1009 */
RollBack()1010 int RdbStoreImpl::RollBack()
1011 {
1012 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
1013 if (connectionPool->getTransactionStack().empty()) {
1014 return E_NO_TRANSACTION_IN_SESSION;
1015 }
1016 BaseTransaction transaction = connectionPool->getTransactionStack().top();
1017 connectionPool->getTransactionStack().pop();
1018 if (transaction.GetType() != TransType::ROLLBACK_SELF && !connectionPool->getTransactionStack().empty()) {
1019 connectionPool->getTransactionStack().top().SetChildFailure(true);
1020 }
1021 SqliteConnection *connection = connectionPool->AcquireConnection(false);
1022 if (connection == nullptr) {
1023 return E_CON_OVER_LIMIT;
1024 }
1025
1026 int errCode = connection->ExecuteSql(transaction.GetRollbackStr());
1027 connectionPool->ReleaseConnection(connection);
1028 if (connectionPool->getTransactionStack().empty()) {
1029 connection->SetInTransaction(false);
1030 }
1031 if (errCode != E_OK) {
1032 LOG_ERROR("RollBack Failed");
1033 }
1034
1035 return E_OK;
1036 }
1037
1038 /**
1039 * Begins a transaction in EXCLUSIVE mode.
1040 */
Commit()1041 int RdbStoreImpl::Commit()
1042 {
1043 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
1044 LOG_DEBUG("Enter Commit.");
1045 if (connectionPool->getTransactionStack().empty()) {
1046 return E_OK;
1047 }
1048 BaseTransaction transaction = connectionPool->getTransactionStack().top();
1049 std::string sqlStr = transaction.GetCommitStr();
1050 if (sqlStr.size() <= 1) {
1051 connectionPool->getTransactionStack().pop();
1052 return E_OK;
1053 }
1054
1055 SqliteConnection *connection = connectionPool->AcquireConnection(false);
1056 if (connection == nullptr) {
1057 return E_CON_OVER_LIMIT;
1058 }
1059
1060 int errCode = connection->ExecuteSql(sqlStr);
1061 connectionPool->ReleaseConnection(connection);
1062 connection->SetInTransaction(false);
1063 connectionPool->getTransactionStack().pop();
1064 if (errCode != E_OK) {
1065 LOG_ERROR("Commit Failed.");
1066 }
1067 return E_OK;
1068 }
1069
FreeTransaction(SqliteConnection * connection,const std::string & sql)1070 int RdbStoreImpl::FreeTransaction(SqliteConnection *connection, const std::string &sql)
1071 {
1072 int errCode = connection->ExecuteSql(sql);
1073 if (errCode == E_OK) {
1074 connection->SetInTransaction(false);
1075 connectionPool->ReleaseTransaction();
1076 } else {
1077 LOG_ERROR("%{public}s with error code %{public}d.", sql.c_str(), errCode);
1078 }
1079 connectionPool->ReleaseConnection(connection);
1080 return errCode;
1081 }
1082
IsInTransaction()1083 bool RdbStoreImpl::IsInTransaction()
1084 {
1085 bool res = true;
1086 auto connection = connectionPool->AcquireConnection(false);
1087 if (connection != nullptr) {
1088 res = connection->IsInTransaction();
1089 connectionPool->ReleaseConnection(connection);
1090 }
1091 return res;
1092 }
1093
CheckAttach(const std::string & sql)1094 int RdbStoreImpl::CheckAttach(const std::string &sql)
1095 {
1096 size_t index = sql.find_first_not_of(' ');
1097 if (index == std::string::npos) {
1098 return E_OK;
1099 }
1100
1101 /* The first 3 characters can determine the type */
1102 std::string sqlType = sql.substr(index, 3);
1103 sqlType = SqliteUtils::StrToUpper(sqlType);
1104 if (sqlType != "ATT") {
1105 return E_OK;
1106 }
1107
1108 SqliteConnection *connection = connectionPool->AcquireConnection(false);
1109 if (connection == nullptr) {
1110 return E_CON_OVER_LIMIT;
1111 }
1112
1113 std::string journalMode;
1114 int errCode =
1115 connection->ExecuteGetString(journalMode, GlobalExpr::PRAGMA_JOUR_MODE_EXP, std::vector<ValueObject>());
1116 connectionPool->ReleaseConnection(connection);
1117 if (errCode != E_OK) {
1118 LOG_ERROR("RdbStoreImpl CheckAttach fail to get journal mode : %{public}d", errCode);
1119 return errCode;
1120 }
1121
1122 journalMode = SqliteUtils::StrToUpper(journalMode);
1123 if (journalMode == GlobalExpr::DEFAULT_JOURNAL_MODE) {
1124 LOG_ERROR("RdbStoreImpl attach is not supported in WAL mode");
1125 return E_NOT_SUPPORTED_ATTACH_IN_WAL_MODE;
1126 }
1127
1128 return E_OK;
1129 }
1130
1131 #if defined(WINDOWS_PLATFORM) || defined(MAC_PLATFORM) || defined(ANDROID_PLATFORM) || defined(IOS_PLATFORM)
1132
ExtractFilePath(const std::string & fileFullName)1133 std::string RdbStoreImpl::ExtractFilePath(const std::string &fileFullName)
1134 {
1135 #ifdef WINDOWS_PLATFORM
1136 return std::string(fileFullName).substr(0, fileFullName.rfind("\\") + 1);
1137 #else
1138 return std::string(fileFullName).substr(0, fileFullName.rfind("/") + 1);
1139 #endif
1140 }
1141
PathToRealPath(const std::string & path,std::string & realPath)1142 bool RdbStoreImpl::PathToRealPath(const std::string &path, std::string &realPath)
1143 {
1144 if (path.empty()) {
1145 LOG_ERROR("path is empty!");
1146 return false;
1147 }
1148
1149 if ((path.length() >= PATH_MAX)) {
1150 LOG_ERROR("path len is error, the len is: [%{public}zu]", path.length());
1151 return false;
1152 }
1153
1154 char tmpPath[PATH_MAX] = { 0 };
1155 #ifdef WINDOWS_PLATFORM
1156 if (_fullpath(tmpPath, path.c_str(), PATH_MAX) == NULL) {
1157 LOG_ERROR("path to realpath error");
1158 return false;
1159 }
1160 #else
1161 if (realpath(path.c_str(), tmpPath) == NULL) {
1162 LOG_ERROR("path (%{public}s) to realpath error", SqliteUtils::Anonymous(path).c_str());
1163 return false;
1164 }
1165 #endif
1166 realPath = tmpPath;
1167 if (access(realPath.c_str(), F_OK) != 0) {
1168 LOG_ERROR("check realpath (%{public}s) error", SqliteUtils::Anonymous(realPath).c_str());
1169 return false;
1170 }
1171 return true;
1172 }
1173 #endif
1174
IsOpen() const1175 bool RdbStoreImpl::IsOpen() const
1176 {
1177 return isOpen;
1178 }
1179
GetPath()1180 std::string RdbStoreImpl::GetPath()
1181 {
1182 return path;
1183 }
1184
GetOrgPath()1185 std::string RdbStoreImpl::GetOrgPath()
1186 {
1187 return orgPath;
1188 }
1189
IsReadOnly() const1190 bool RdbStoreImpl::IsReadOnly() const
1191 {
1192 return isReadOnly;
1193 }
1194
IsMemoryRdb() const1195 bool RdbStoreImpl::IsMemoryRdb() const
1196 {
1197 return isMemoryRdb;
1198 }
1199
GetName()1200 std::string RdbStoreImpl::GetName()
1201 {
1202 return name;
1203 }
1204
DoCloudSync(const std::string & table)1205 void RdbStoreImpl::DoCloudSync(const std::string &table)
1206 {
1207 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
1208 if (pool_ == nullptr) {
1209 return;
1210 }
1211 {
1212 std::shared_lock<decltype(rwMutex_)> lock(rwMutex_);
1213 if (cloudTables_.empty() || (!table.empty() && cloudTables_.find(table) == cloudTables_.end())) {
1214 return;
1215 }
1216 }
1217 {
1218 std::lock_guard<std::mutex> lock(mutex_);
1219 if (syncTables_ == nullptr) {
1220 syncTables_ = std::make_shared<std::set<std::string>>();
1221 }
1222 auto empty = syncTables_->empty();
1223 if (table.empty()) {
1224 syncTables_->insert(cloudTables_.begin(), cloudTables_.end());
1225 } else {
1226 syncTables_->insert(table);
1227 }
1228 if (!empty) {
1229 return;
1230 }
1231 }
1232 auto interval =
1233 std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::milliseconds(INTERVAL));
1234 pool_->Schedule(interval, [this]() {
1235 std::shared_ptr<std::set<std::string>> ptr;
1236 {
1237 std::lock_guard<std::mutex> lock(mutex_);
1238 ptr = syncTables_;
1239 syncTables_ = nullptr;
1240 }
1241 if (ptr == nullptr) {
1242 return;
1243 }
1244 SyncOption syncOption = { DistributedRdb::TIME_FIRST, false };
1245 Sync(syncOption, { ptr->begin(), ptr->end() }, nullptr);
1246 });
1247 #endif
1248 }
GetFileType()1249 std::string RdbStoreImpl::GetFileType()
1250 {
1251 return fileType;
1252 }
1253
1254 #ifdef RDB_SUPPORT_ICU
1255 /**
1256 * Sets the database locale.
1257 */
ConfigLocale(const std::string localeStr)1258 int RdbStoreImpl::ConfigLocale(const std::string localeStr)
1259 {
1260 if (isOpen == false) {
1261 LOG_ERROR("The connection pool has been closed.");
1262 return E_ERROR;
1263 }
1264
1265 if (connectionPool == nullptr) {
1266 LOG_ERROR("connectionPool is null");
1267 return E_ERROR;
1268 }
1269 return connectionPool->ConfigLocale(localeStr);
1270 }
1271 #endif
1272
Restore(const std::string backupPath,const std::vector<uint8_t> & newKey)1273 int RdbStoreImpl::Restore(const std::string backupPath, const std::vector<uint8_t> &newKey)
1274 {
1275 if (isOpen == false) {
1276 LOG_ERROR("The connection pool has been closed.");
1277 return E_ERROR;
1278 }
1279
1280 if (connectionPool == nullptr) {
1281 LOG_ERROR("The connectionPool is null.");
1282 return E_ERROR;
1283 }
1284
1285 std::string backupFilePath;
1286 int ret = GetDataBasePath(backupPath, backupFilePath);
1287 if (ret != E_OK) {
1288 return ret;
1289 }
1290
1291 if (access(backupFilePath.c_str(), F_OK) != E_OK) {
1292 LOG_ERROR("The backupFilePath does not exists.");
1293 return E_INVALID_FILE_PATH;
1294 }
1295
1296 return connectionPool->ChangeDbFileForRestore(path, backupFilePath, newKey);
1297 }
1298
1299 /**
1300 * Queries data in the database based on specified conditions.
1301 */
QueryByStep(const std::string & sql,const std::vector<std::string> & sqlArgs)1302 std::shared_ptr<ResultSet> RdbStoreImpl::QueryByStep(const std::string &sql,
1303 const std::vector<std::string> &sqlArgs)
1304 {
1305 std::vector<ValueObject> bindArgs;
1306 std::for_each(sqlArgs.begin(), sqlArgs.end(), [&bindArgs](const auto &it) { bindArgs.push_back(ValueObject(it)); });
1307 return std::make_shared<StepResultSet>(shared_from_this(), connectionPool, sql, bindArgs);
1308 }
1309
QueryByStep(const std::string & sql,const std::vector<ValueObject> & args)1310 std::shared_ptr<ResultSet> RdbStoreImpl::QueryByStep(const std::string &sql, const std::vector<ValueObject> &args)
1311 {
1312 return std::make_shared<StepResultSet>(shared_from_this(), connectionPool, sql, args);
1313 }
1314
1315 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
SetDistributedTables(const std::vector<std::string> & tables,int32_t type,const DistributedRdb::DistributedConfig & distributedConfig)1316 int RdbStoreImpl::SetDistributedTables(const std::vector<std::string> &tables, int32_t type,
1317 const DistributedRdb::DistributedConfig &distributedConfig)
1318 {
1319 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
1320 if (tables.empty()) {
1321 LOG_WARN("The distributed tables to be set is empty.");
1322 return E_OK;
1323 }
1324 auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_);
1325 if (errCode != E_OK) {
1326 return errCode;
1327 }
1328 int32_t errorCode = service->SetDistributedTables(syncerParam_, tables, type);
1329 if (errorCode != E_OK) {
1330 LOG_ERROR("Fail to set distributed tables, error=%{public}d", errorCode);
1331 return errorCode;
1332 }
1333 if (type != DistributedRdb::DISTRIBUTED_CLOUD || !distributedConfig.autoSync) {
1334 return E_OK;
1335 }
1336 {
1337 std::unique_lock<decltype(rwMutex_)> lock(rwMutex_);
1338 cloudTables_.insert(tables.begin(), tables.end());
1339 }
1340 for (auto &table : tables) {
1341 DoCloudSync(table);
1342 }
1343 return E_OK;
1344 }
1345
ObtainDistributedTableName(const std::string & device,const std::string & table,int & errCode)1346 std::string RdbStoreImpl::ObtainDistributedTableName(const std::string &device, const std::string &table, int &errCode)
1347 {
1348 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
1349
1350 std::string uuid;
1351 DeviceManagerAdaptor::RdbDeviceManagerAdaptor &deviceManager =
1352 DeviceManagerAdaptor::RdbDeviceManagerAdaptor::GetInstance(syncerParam_.bundleName_);
1353 errCode = deviceManager.GetEncryptedUuidByNetworkId(device, uuid);
1354 if (errCode != E_OK) {
1355 LOG_ERROR("GetUuid is failed");
1356 return "";
1357 }
1358
1359 auto translateCall = [uuid](const std::string &oriDevId, const DistributedDB::StoreInfo &info) {
1360 return uuid;
1361 };
1362 DistributedDB::RuntimeConfig::SetTranslateToDeviceIdCallback(translateCall);
1363
1364 return DistributedDB::RelationalStoreManager::GetDistributedTableName(uuid, table);
1365 }
1366
Sync(const SyncOption & option,const AbsRdbPredicates & predicate,const AsyncBrief & callback)1367 int RdbStoreImpl::Sync(const SyncOption &option, const AbsRdbPredicates &predicate, const AsyncBrief &callback)
1368 {
1369 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
1370 auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_);
1371 if (errCode != E_OK) {
1372 LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode);
1373 return errCode;
1374 }
1375 DistributedRdb::RdbService::Option rdbOption;
1376 rdbOption.mode = option.mode;
1377 rdbOption.isAsync = !option.isBlock;
1378 errCode =
1379 service->Sync(syncerParam_, rdbOption, predicate.GetDistributedPredicates(), [callback](Details &&details) {
1380 Briefs briefs;
1381 for (auto &[key, value] : details) {
1382 briefs.insert_or_assign(key, value.code);
1383 }
1384 if (callback != nullptr) {
1385 callback(briefs);
1386 }
1387 });
1388 if (errCode != E_OK) {
1389 LOG_ERROR("Sync is failed, err is %{public}d.", errCode);
1390 return errCode;
1391 }
1392 return E_OK;
1393 }
1394
Sync(const SyncOption & option,const std::vector<std::string> & tables,const AsyncDetail & async)1395 int RdbStoreImpl::Sync(const SyncOption &option, const std::vector<std::string> &tables,
1396 const AsyncDetail &async)
1397 {
1398 DISTRIBUTED_DATA_HITRACE(std::string(__FUNCTION__));
1399 auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_);
1400 if (errCode != E_OK) {
1401 LOG_ERROR("GetRdbService is failed, err is %{public}d.", errCode);
1402 return errCode;
1403 }
1404 DistributedRdb::RdbService::Option rdbOption;
1405 rdbOption.mode = option.mode;
1406 rdbOption.isAsync = !option.isBlock;
1407 errCode = service->Sync(syncerParam_, rdbOption, AbsRdbPredicates(tables).GetDistributedPredicates(), async);
1408 if (errCode != E_OK) {
1409 LOG_ERROR("Sync is failed, err is %{public}d.", errCode);
1410 return errCode;
1411 }
1412 return E_OK;
1413 }
1414
GetUri(const std::string & event)1415 Uri RdbStoreImpl::GetUri(const std::string &event)
1416 {
1417 std::string rdbUri;
1418 if (rdbStoreConfig.GetDataGroupId().empty()) {
1419 rdbUri = SCHEME_RDB + rdbStoreConfig.GetBundleName() + "/" + path + "/" + event;
1420 } else {
1421 rdbUri = SCHEME_RDB + rdbStoreConfig.GetDataGroupId() + "/" + path + "/" + event;
1422 }
1423 return Uri(rdbUri);
1424 }
1425
SubscribeLocal(const SubscribeOption & option,RdbStoreObserver * observer)1426 int RdbStoreImpl::SubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer)
1427 {
1428 std::lock_guard<std::mutex> lock(mutex_);
1429 localObservers_.try_emplace(option.event);
1430 auto &list = localObservers_.find(option.event)->second;
1431 for (auto it = list.begin(); it != list.end(); it++) {
1432 if ((*it)->getObserver() == observer) {
1433 LOG_ERROR("duplicate subscribe");
1434 return E_OK;
1435 }
1436 }
1437
1438 localObservers_[option.event].push_back(std::make_shared<RdbStoreLocalObserver>(observer));
1439 return E_OK;
1440 }
1441
SubscribeLocalShared(const SubscribeOption & option,RdbStoreObserver * observer)1442 int RdbStoreImpl::SubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer)
1443 {
1444 std::lock_guard<std::mutex> lock(mutex_);
1445 localSharedObservers_.try_emplace(option.event);
1446 auto &list = localSharedObservers_.find(option.event)->second;
1447 for (auto it = list.begin(); it != list.end(); it++) {
1448 if ((*it)->getObserver() == observer) {
1449 LOG_ERROR("duplicate subscribe");
1450 return E_OK;
1451 }
1452 }
1453
1454 auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance();
1455 if (client == nullptr) {
1456 LOG_ERROR("Failed to get DataObsMgrClient.");
1457 return E_GET_DATAOBSMGRCLIENT_FAIL;
1458 }
1459 sptr<RdbStoreLocalSharedObserver> localSharedObserver(new (std::nothrow) RdbStoreLocalSharedObserver(observer));
1460 int32_t err = client->RegisterObserver(GetUri(option.event), localSharedObserver);
1461 if (err != 0) {
1462 LOG_ERROR("Subscribe failed.");
1463 return err;
1464 }
1465 localSharedObservers_[option.event].push_back(std::move(localSharedObserver));
1466 return E_OK;
1467 }
1468
SubscribeRemote(const SubscribeOption & option,RdbStoreObserver * observer)1469 int RdbStoreImpl::SubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer)
1470 {
1471 auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_);
1472 if (errCode != E_OK) {
1473 return errCode;
1474 }
1475 return service->Subscribe(syncerParam_, option, observer);
1476 }
1477
Subscribe(const SubscribeOption & option,RdbStoreObserver * observer)1478 int RdbStoreImpl::Subscribe(const SubscribeOption &option, RdbStoreObserver *observer)
1479 {
1480 if (option.mode == SubscribeMode::LOCAL) {
1481 return SubscribeLocal(option, observer);
1482 }
1483 if (option.mode == SubscribeMode::LOCAL_SHARED) {
1484 return SubscribeLocalShared(option, observer);
1485 }
1486 return SubscribeRemote(option, observer);
1487 }
1488
UnSubscribeLocal(const SubscribeOption & option,RdbStoreObserver * observer)1489 int RdbStoreImpl::UnSubscribeLocal(const SubscribeOption& option, RdbStoreObserver *observer)
1490 {
1491 std::lock_guard<std::mutex> lock(mutex_);
1492 auto obs = localObservers_.find(option.event);
1493 if (obs == localObservers_.end()) {
1494 return E_OK;
1495 }
1496
1497 auto &list = obs->second;
1498 for (auto it = list.begin(); it != list.end(); it++) {
1499 if ((*it)->getObserver() == observer) {
1500 it = list.erase(it);
1501 break;
1502 }
1503 }
1504
1505 if (list.empty()) {
1506 localObservers_.erase(option.event);
1507 }
1508 return E_OK;
1509 }
1510
UnSubscribeLocalAll(const SubscribeOption & option)1511 int RdbStoreImpl::UnSubscribeLocalAll(const SubscribeOption& option)
1512 {
1513 std::lock_guard<std::mutex> lock(mutex_);
1514 auto obs = localObservers_.find(option.event);
1515 if (obs == localObservers_.end()) {
1516 return E_OK;
1517 }
1518
1519 localObservers_.erase(option.event);
1520 return E_OK;
1521 }
1522
UnSubscribeLocalShared(const SubscribeOption & option,RdbStoreObserver * observer)1523 int RdbStoreImpl::UnSubscribeLocalShared(const SubscribeOption& option, RdbStoreObserver *observer)
1524 {
1525 std::lock_guard<std::mutex> lock(mutex_);
1526 auto obs = localSharedObservers_.find(option.event);
1527 if (obs == localSharedObservers_.end()) {
1528 return E_OK;
1529 }
1530
1531 auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance();
1532 if (client == nullptr) {
1533 LOG_ERROR("Failed to get DataObsMgrClient.");
1534 return E_GET_DATAOBSMGRCLIENT_FAIL;
1535 }
1536
1537 auto &list = obs->second;
1538 for (auto it = list.begin(); it != list.end(); it++) {
1539 if ((*it)->getObserver() == observer) {
1540 int32_t err = client->UnregisterObserver(GetUri(option.event), *it);
1541 if (err != 0) {
1542 LOG_ERROR("UnSubscribeLocalShared failed.");
1543 return err;
1544 }
1545 list.erase(it);
1546 break;
1547 }
1548 }
1549 if (list.empty()) {
1550 localSharedObservers_.erase(option.event);
1551 }
1552 return E_OK;
1553 }
1554
UnSubscribeLocalSharedAll(const SubscribeOption & option)1555 int RdbStoreImpl::UnSubscribeLocalSharedAll(const SubscribeOption& option)
1556 {
1557 std::lock_guard<std::mutex> lock(mutex_);
1558 auto obs = localSharedObservers_.find(option.event);
1559 if (obs == localSharedObservers_.end()) {
1560 return E_OK;
1561 }
1562
1563 auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance();
1564 if (client == nullptr) {
1565 LOG_ERROR("Failed to get DataObsMgrClient.");
1566 return E_GET_DATAOBSMGRCLIENT_FAIL;
1567 }
1568
1569 auto &list = obs->second;
1570 auto it = list.begin();
1571 while (it != list.end()) {
1572 int32_t err = client->UnregisterObserver(GetUri(option.event), *it);
1573 if (err != 0) {
1574 LOG_ERROR("UnSubscribe failed.");
1575 return err;
1576 }
1577 it = list.erase(it);
1578 }
1579
1580 localSharedObservers_.erase(option.event);
1581 return E_OK;
1582 }
1583
UnSubscribeRemote(const SubscribeOption & option,RdbStoreObserver * observer)1584 int RdbStoreImpl::UnSubscribeRemote(const SubscribeOption& option, RdbStoreObserver *observer)
1585 {
1586 auto [errCode, service] = DistributedRdb::RdbManagerImpl::GetInstance().GetRdbService(syncerParam_);
1587 if (errCode != E_OK) {
1588 return errCode;
1589 }
1590 return service->UnSubscribe(syncerParam_, option, observer);
1591 }
1592
UnSubscribe(const SubscribeOption & option,RdbStoreObserver * observer)1593 int RdbStoreImpl::UnSubscribe(const SubscribeOption &option, RdbStoreObserver *observer)
1594 {
1595 if (option.mode == SubscribeMode::LOCAL && observer) {
1596 return UnSubscribeLocal(option, observer);
1597 } else if (option.mode == SubscribeMode::LOCAL && !observer) {
1598 return UnSubscribeLocalAll(option);
1599 } else if (option.mode == SubscribeMode::LOCAL_SHARED && observer) {
1600 return UnSubscribeLocalShared(option, observer);
1601 } else if (option.mode == SubscribeMode::LOCAL_SHARED && !observer) {
1602 return UnSubscribeLocalSharedAll(option);
1603 }
1604 return UnSubscribeRemote(option, observer);
1605 }
1606
Notify(const std::string & event)1607 int RdbStoreImpl::Notify(const std::string &event)
1608 {
1609 auto client = OHOS::AAFwk::DataObsMgrClient::GetInstance();
1610 if (client == nullptr) {
1611 LOG_ERROR("Failed to get DataObsMgrClient.");
1612 return E_GET_DATAOBSMGRCLIENT_FAIL;
1613 }
1614 int32_t err = client->NotifyChange(GetUri(event));
1615 if (err != 0) {
1616 LOG_ERROR("Notify failed.");
1617 }
1618
1619 std::lock_guard<std::mutex> lock(mutex_);
1620 auto obs = localObservers_.find(event);
1621 if (obs != localObservers_.end()) {
1622 auto &list = obs->second;
1623 for (auto &it : list) {
1624 it->OnChange();
1625 }
1626 }
1627 return E_OK;
1628 }
1629 #endif
1630 } // namespace OHOS::NativeRdb