• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #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