1 /*
2 * Copyright (c) 2021 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 #ifdef RELATIONAL_STORE
16 #include "sqlite_relational_store_connection.h"
17 #include "db_errno.h"
18 #include "log_print.h"
19 #include "sqlite_relational_utils.h"
20
21 namespace DistributedDB {
SQLiteRelationalStoreConnection(SQLiteRelationalStore * store)22 SQLiteRelationalStoreConnection::SQLiteRelationalStoreConnection(SQLiteRelationalStore *store)
23 : RelationalStoreConnection(store)
24 {
25 OnKill([this]() {
26 auto *store = GetDB<SQLiteRelationalStore>();
27 if (store == nullptr) {
28 return;
29 }
30 UnlockObj();
31 store->StopSync(GetConnectionId());
32 LockObj();
33 });
34 }
35 // Close and release the connection.
Close()36 int SQLiteRelationalStoreConnection::Close()
37 {
38 if (store_ == nullptr) {
39 return -E_INVALID_CONNECTION;
40 }
41
42 if (isExclusive_.load()) {
43 return -E_BUSY;
44 }
45
46 // check if transaction closed
47 {
48 std::lock_guard<std::mutex> transactionLock(transactionMutex_);
49 if (writeHandle_ != nullptr) {
50 LOGW("Transaction started, need to rollback before close.");
51 int errCode = RollBack();
52 if (errCode != E_OK) {
53 LOGE("Rollback transaction failed, %d.", errCode);
54 }
55 ReleaseExecutor(writeHandle_);
56 }
57 }
58
59 static_cast<SQLiteRelationalStore *>(store_)->ReleaseDBConnection(GetConnectionId(), this);
60 return E_OK;
61 }
62
GetIdentifier()63 std::string SQLiteRelationalStoreConnection::GetIdentifier()
64 {
65 if (store_ == nullptr) {
66 return {};
67 }
68 return store_->GetProperties().GetStringProp(RelationalDBProperties::IDENTIFIER_DATA, "");
69 }
70
GetExecutor(bool isWrite,int & errCode) const71 SQLiteSingleVerRelationalStorageExecutor *SQLiteRelationalStoreConnection::GetExecutor(bool isWrite, int &errCode) const
72 {
73 auto *store = GetDB<SQLiteRelationalStore>();
74 if (store == nullptr) { // LCOV_EXCL_BR_LINE
75 errCode = -E_NOT_INIT;
76 LOGE("[RelationalConnection] store is null, get executor failed! errCode = [%d]", errCode);
77 return nullptr;
78 }
79
80 return store->GetHandle(isWrite, errCode);
81 }
82
ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor * & executor) const83 void SQLiteRelationalStoreConnection::ReleaseExecutor(SQLiteSingleVerRelationalStorageExecutor *&executor) const
84 {
85 auto *store = GetDB<SQLiteRelationalStore>();
86 if (store != nullptr) { // LCOV_EXCL_BR_LINE
87 store->ReleaseHandle(executor);
88 }
89 }
90
StartTransaction()91 int SQLiteRelationalStoreConnection::StartTransaction()
92 {
93 std::lock_guard<std::mutex> lock(transactionMutex_);
94 if (writeHandle_ != nullptr) { // LCOV_EXCL_BR_LINE
95 LOGD("Transaction started already.");
96 return -E_TRANSACT_STATE;
97 }
98
99 int errCode = E_OK;
100 auto *handle = GetExecutor(true, errCode);
101 if (handle == nullptr) { // LCOV_EXCL_BR_LINE
102 return errCode;
103 }
104
105 errCode = handle->StartTransaction(TransactType::DEFERRED);
106 if (errCode != E_OK) { // LCOV_EXCL_BR_LINE
107 ReleaseExecutor(handle);
108 return errCode;
109 }
110
111 writeHandle_ = handle;
112 return E_OK;
113 }
114
115 // Commit the transaction
Commit()116 int SQLiteRelationalStoreConnection::Commit()
117 {
118 std::lock_guard<std::mutex> lock(transactionMutex_);
119 if (writeHandle_ == nullptr) { // LCOV_EXCL_BR_LINE
120 LOGE("single version database is null or the transaction has not been started");
121 return -E_INVALID_DB;
122 }
123
124 int errCode = writeHandle_->Commit();
125 ReleaseExecutor(writeHandle_);
126 LOGD("connection commit transaction!");
127 return errCode;
128 }
129
130 // Roll back the transaction
RollBack()131 int SQLiteRelationalStoreConnection::RollBack()
132 {
133 std::lock_guard<std::mutex> lock(transactionMutex_);
134 if (writeHandle_ == nullptr) { // LCOV_EXCL_BR_LINE
135 LOGE("Invalid handle for rollback or the transaction has not been started.");
136 return -E_INVALID_DB;
137 }
138
139 int errCode = writeHandle_->Rollback();
140 ReleaseExecutor(writeHandle_);
141 LOGI("connection rollback transaction!");
142 return errCode;
143 }
144
CreateDistributedTable(const std::string & tableName,TableSyncType syncType)145 int SQLiteRelationalStoreConnection::CreateDistributedTable(const std::string &tableName, TableSyncType syncType)
146 {
147 auto *store = GetDB<SQLiteRelationalStore>();
148 if (store == nullptr) {
149 LOGE("[RelationalConnection] store is null, get DB failed!");
150 return -E_INVALID_CONNECTION;
151 }
152
153 int errCode = store->CreateDistributedTable(tableName, syncType);
154 if (errCode != E_OK) {
155 LOGE("[RelationalConnection] create distributed table failed. %d", errCode);
156 }
157 return errCode;
158 }
159
RemoveDeviceData()160 int SQLiteRelationalStoreConnection::RemoveDeviceData()
161 {
162 auto *store = GetDB<SQLiteRelationalStore>();
163 if (store == nullptr) {
164 LOGE("[RelationalConnection] store is null, get DB failed!");
165 return -E_INVALID_CONNECTION;
166 }
167
168 int errCode = store->RemoveDeviceData();
169 if (errCode != E_OK) {
170 LOGE("[RelationalConnection] remove device data failed. %d", errCode);
171 }
172 return errCode;
173 }
174
175 #ifdef USE_DISTRIBUTEDDB_CLOUD
GetCloudSyncTaskCount()176 int32_t SQLiteRelationalStoreConnection::GetCloudSyncTaskCount()
177 {
178 auto *store = GetDB<SQLiteRelationalStore>();
179 if (store == nullptr) {
180 LOGE("[RelationalConnection] store is null, get DB failed!");
181 return -1;
182 }
183 int32_t count = store->GetCloudSyncTaskCount();
184 if (count == -1) {
185 LOGE("[RelationalConnection] failed to get cloud sync task count");
186 }
187 return count;
188 }
189
DoClean(ClearMode mode)190 int SQLiteRelationalStoreConnection::DoClean(ClearMode mode)
191 {
192 auto *store = GetDB<SQLiteRelationalStore>();
193 if (store == nullptr) {
194 LOGE("[RelationalConnection] store is null, get DB failed!");
195 return -E_INVALID_CONNECTION;
196 }
197
198 int errCode = store->CleanCloudData(mode);
199 if (errCode != E_OK) {
200 LOGE("[RelationalConnection] failed to clean cloud data, %d.", errCode);
201 }
202 return errCode;
203 }
204 #endif
205
RemoveDeviceData(const std::string & device)206 int SQLiteRelationalStoreConnection::RemoveDeviceData(const std::string &device)
207 {
208 return RemoveDeviceData(device, {});
209 }
210
RemoveDeviceData(const std::string & device,const std::string & tableName)211 int SQLiteRelationalStoreConnection::RemoveDeviceData(const std::string &device, const std::string &tableName)
212 {
213 auto *store = GetDB<SQLiteRelationalStore>();
214 if (store == nullptr) {
215 LOGE("[RelationalConnection] store is null, get DB failed!");
216 return -E_INVALID_CONNECTION;
217 }
218
219 int errCode = store->RemoveDeviceData(device, tableName);
220 if (errCode != E_OK) {
221 LOGE("[RelationalConnection] remove device data failed. %d", errCode);
222 }
223 return errCode;
224 }
225
Pragma(int cmd,void * parameter)226 int SQLiteRelationalStoreConnection::Pragma(int cmd, void *parameter) // reserve for interface function fix
227 {
228 (void)cmd;
229 (void)parameter;
230 return E_OK;
231 }
232
SyncToDevice(SyncInfo & info)233 int SQLiteRelationalStoreConnection::SyncToDevice(SyncInfo &info)
234 {
235 auto *store = GetDB<SQLiteRelationalStore>();
236 if (store == nullptr) {
237 LOGE("[RelationalConnection] store is null, get executor failed!");
238 return -E_INVALID_CONNECTION;
239 }
240
241 ISyncer::SyncParma syncParam;
242 syncParam.devices = info.devices;
243 syncParam.mode = info.mode;
244 syncParam.wait = info.wait;
245 syncParam.isQuerySync = true;
246 syncParam.relationOnComplete = info.onComplete;
247 syncParam.syncQuery = QuerySyncObject(info.query);
248 if (syncParam.syncQuery.GetSortType() != SortType::NONE) {
249 LOGE("not support order by timestamp, type: %d", static_cast<int>(syncParam.syncQuery.GetSortType()));
250 return -E_NOT_SUPPORT;
251 }
252 if (syncParam.syncQuery.GetValidStatus() != E_OK) {
253 LOGE("invalid sync query origin valid status %d", syncParam.syncQuery.GetValidStatus());
254 return syncParam.syncQuery.GetValidStatus();
255 }
256 return store->Sync(syncParam, GetConnectionId());
257 }
258
RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier & notifier)259 int SQLiteRelationalStoreConnection::RegisterLifeCycleCallback(const DatabaseLifeCycleNotifier ¬ifier)
260 {
261 auto *store = GetDB<SQLiteRelationalStore>();
262 if (store == nullptr) {
263 LOGE("[RelationalConnection] store is null, get executor failed!");
264 return -E_INVALID_CONNECTION;
265 }
266
267 return store->RegisterLifeCycleCallback(notifier);
268 }
269
RegisterObserverAction(const StoreObserver * observer,const RelationalObserverAction & action)270 int SQLiteRelationalStoreConnection::RegisterObserverAction(const StoreObserver *observer,
271 const RelationalObserverAction &action)
272 {
273 return static_cast<SQLiteRelationalStore *>(store_)->RegisterObserverAction(GetConnectionId(), observer, action);
274 }
275
UnRegisterObserverAction(const StoreObserver * observer)276 int SQLiteRelationalStoreConnection::UnRegisterObserverAction(const StoreObserver *observer)
277 {
278 return static_cast<SQLiteRelationalStore *>(store_)->UnRegisterObserverAction(GetConnectionId(), observer);
279 }
280
RemoteQuery(const std::string & device,const RemoteCondition & condition,uint64_t timeout,std::shared_ptr<ResultSet> & result)281 int SQLiteRelationalStoreConnection::RemoteQuery(const std::string &device, const RemoteCondition &condition,
282 uint64_t timeout, std::shared_ptr<ResultSet> &result)
283 {
284 auto *store = GetDB<SQLiteRelationalStore>();
285 if (store == nullptr) {
286 LOGE("[RelationalConnection] store is null, get executor failed!");
287 return -E_INVALID_CONNECTION;
288 }
289 return store->RemoteQuery(device, condition, timeout, GetConnectionId(), result);
290 }
291
292 #ifdef USE_DISTRIBUTEDDB_CLOUD
SetCloudDB(const std::shared_ptr<ICloudDb> & cloudDb)293 int SQLiteRelationalStoreConnection::SetCloudDB(const std::shared_ptr<ICloudDb> &cloudDb)
294 {
295 auto *store = GetDB<SQLiteRelationalStore>();
296 if (store == nullptr) {
297 LOGE("[RelationalConnection] store is null, get DB failed!");
298 return -E_INVALID_CONNECTION;
299 }
300
301 return store->SetCloudDB(cloudDb);
302 }
303
PrepareAndSetCloudDbSchema(const DataBaseSchema & schema)304 int SQLiteRelationalStoreConnection::PrepareAndSetCloudDbSchema(const DataBaseSchema &schema)
305 {
306 auto *store = GetDB<SQLiteRelationalStore>();
307 if (store == nullptr) {
308 LOGE("[RelationalConnection] store is null, get DB failed!");
309 return -E_INVALID_CONNECTION;
310 }
311
312 int ret = store->PrepareAndSetCloudDbSchema(schema);
313 if (ret != E_OK) {
314 LOGE("[RelationalConnection] PrepareAndSetCloudDbSchema failed. %d", ret);
315 }
316 return ret;
317 }
318
SetIAssetLoader(const std::shared_ptr<IAssetLoader> & loader)319 int SQLiteRelationalStoreConnection::SetIAssetLoader(const std::shared_ptr<IAssetLoader> &loader)
320 {
321 auto *store = GetDB<SQLiteRelationalStore>();
322 if (store == nullptr) {
323 LOGE("[RelationalConnection] store is null, get DB failed!");
324 return -E_INVALID_CONNECTION;
325 }
326
327 int ret = store->SetIAssetLoader(loader);
328 if (ret != E_OK) {
329 LOGE("[RelationalConnection] Set asset loader failed. %d", ret);
330 }
331 return ret;
332 }
333 #endif
334
GetStoreInfo(std::string & userId,std::string & appId,std::string & storeId)335 int SQLiteRelationalStoreConnection::GetStoreInfo(std::string &userId, std::string &appId, std::string &storeId)
336 {
337 auto *store = GetDB<SQLiteRelationalStore>();
338 if (store == nullptr) {
339 LOGE("[RelationalConnection] store is null, get storeInfo failed!");
340 return -E_INVALID_CONNECTION;
341 }
342 auto properties = store->GetProperties();
343 userId = properties.GetStringProp(RelationalDBProperties::USER_ID, "");
344 appId = properties.GetStringProp(RelationalDBProperties::APP_ID, "");
345 storeId = properties.GetStringProp(RelationalDBProperties::STORE_ID, "");
346 return E_OK;
347 }
348
SetTrackerTable(const TrackerSchema & schema)349 int SQLiteRelationalStoreConnection::SetTrackerTable(const TrackerSchema &schema)
350 {
351 auto *store = GetDB<SQLiteRelationalStore>();
352 if (store == nullptr) {
353 LOGE("[RelationalConnection] store is null, get DB failed!");
354 return -E_INVALID_CONNECTION;
355 }
356 int errCode = store->SetTrackerTable(schema);
357 if (errCode != E_OK && errCode != -E_WITH_INVENTORY_DATA) {
358 LOGE("[RelationalConnection] set tracker table failed. %d", errCode);
359 }
360 return errCode;
361 }
362
ExecuteSql(const SqlCondition & condition,std::vector<VBucket> & records)363 int SQLiteRelationalStoreConnection::ExecuteSql(const SqlCondition &condition, std::vector<VBucket> &records)
364 {
365 auto *store = GetDB<SQLiteRelationalStore>();
366 if (store == nullptr) {
367 LOGE("[RelationalConnection] store is null, get executor failed!");
368 return -E_INVALID_CONNECTION;
369 }
370 return store->ExecuteSql(condition, records);
371 }
372
SetReference(const std::vector<TableReferenceProperty> & tableReferenceProperty)373 int SQLiteRelationalStoreConnection::SetReference(const std::vector<TableReferenceProperty> &tableReferenceProperty)
374 {
375 auto *store = GetDB<SQLiteRelationalStore>();
376 if (store == nullptr) {
377 LOGE("[SetReference] store is null, get DB failed!");
378 return -E_INVALID_CONNECTION;
379 }
380 return store->SetReference(tableReferenceProperty);
381 }
382
CleanTrackerData(const std::string & tableName,int64_t cursor)383 int SQLiteRelationalStoreConnection::CleanTrackerData(const std::string &tableName, int64_t cursor)
384 {
385 auto *store = GetDB<SQLiteRelationalStore>();
386 if (store == nullptr) { // LCOV_EXCL_BR_LINE
387 LOGE("[RelationalConnection] store is null, get executor failed!");
388 return -E_INVALID_CONNECTION;
389 }
390 return store->CleanTrackerData(tableName, cursor);
391 }
392
Pragma(PragmaCmd cmd,PragmaData & pragmaData)393 int SQLiteRelationalStoreConnection::Pragma(PragmaCmd cmd, PragmaData &pragmaData)
394 {
395 auto *store = GetDB<SQLiteRelationalStore>();
396 if (store == nullptr) {
397 LOGE("[RelationalConnection] store is null, get executor failed!");
398 return -E_INVALID_CONNECTION;
399 }
400 return store->Pragma(cmd, pragmaData);
401 }
402
UpsertData(RecordStatus status,const std::string & tableName,const std::vector<VBucket> & records)403 int SQLiteRelationalStoreConnection::UpsertData(RecordStatus status, const std::string &tableName,
404 const std::vector<VBucket> &records)
405 {
406 auto *store = GetDB<SQLiteRelationalStore>();
407 if (store == nullptr) {
408 LOGE("[RelationalConnection] store is null, upsert dara failed!");
409 return -E_INVALID_CONNECTION;
410 }
411 return store->UpsertData(status, tableName, records);
412 }
413
414 #ifdef USE_DISTRIBUTEDDB_CLOUD
SetCloudSyncConfig(const CloudSyncConfig & config)415 int SQLiteRelationalStoreConnection::SetCloudSyncConfig(const CloudSyncConfig &config)
416 {
417 auto *store = GetDB<SQLiteRelationalStore>();
418 if (store == nullptr) { // LCOV_EXCL_BR_LINE
419 LOGE("[RelationalConnection] store is null, set cloud sync config failed!");
420 return -E_INVALID_CONNECTION;
421 }
422 return store->SetCloudSyncConfig(config);
423 }
424
Sync(const CloudSyncOption & option,const SyncProcessCallback & onProcess,uint64_t taskId)425 int SQLiteRelationalStoreConnection::Sync(const CloudSyncOption &option, const SyncProcessCallback &onProcess,
426 uint64_t taskId)
427 {
428 auto *store = GetDB<SQLiteRelationalStore>();
429 if (store == nullptr) {
430 LOGE("[RelationalConnection] store is null, get executor failed!");
431 return -E_INVALID_CONNECTION;
432 }
433 {
434 AutoLock lockGuard(this);
435 if (IsKilled()) {
436 // If this happens, users are using a closed connection.
437 LOGE("[RelationalConnection] Sync on a closed connection.");
438 return -E_STALE;
439 }
440 IncObjRef(this);
441 }
442 int errCode = store->Sync(option, onProcess, taskId);
443 DecObjRef(this);
444 return errCode;
445 }
446
GetCloudTaskStatus(uint64_t taskId)447 SyncProcess SQLiteRelationalStoreConnection::GetCloudTaskStatus(uint64_t taskId)
448 {
449 auto *store = GetDB<SQLiteRelationalStore>();
450 if (store == nullptr) {
451 LOGE("[RelationalConnection] store is null, get executor failed!");
452 SyncProcess process;
453 process.errCode = DB_ERROR;
454 return process;
455 }
456 {
457 AutoLock lockGuard(this);
458 if (IsKilled()) {
459 // If this happens, users are using a closed connection.
460 LOGE("[RelationalConnection] Get sync task on a closed connection.");
461 SyncProcess process;
462 process.errCode = DB_ERROR;
463 return process;
464 }
465 IncObjRef(this);
466 }
467 SyncProcess process = store->GetCloudTaskStatus(taskId);
468 DecObjRef(this);
469 return process;
470 }
471 #endif
472
SetDistributedDbSchema(const DistributedSchema & schema,bool isForceUpgrade)473 int SQLiteRelationalStoreConnection::SetDistributedDbSchema(const DistributedSchema &schema, bool isForceUpgrade)
474 {
475 auto *store = GetDB<SQLiteRelationalStore>();
476 if (store == nullptr) {
477 LOGE("[RelationalConnection] store is null when set distributed schema");
478 return -E_INVALID_CONNECTION;
479 }
480 return store->SetDistributedSchema(SQLiteRelationalUtils::FilterRepeatDefine(schema), isForceUpgrade);
481 }
482
GetDownloadingAssetsCount(int32_t & count)483 int SQLiteRelationalStoreConnection::GetDownloadingAssetsCount(int32_t &count)
484 {
485 auto *store = GetDB<SQLiteRelationalStore>();
486 if (store == nullptr) {
487 LOGE("[RelationalConnection] store is null, get executor failed!");
488 return -E_INVALID_CONNECTION;
489 }
490 return store->GetDownloadingAssetsCount(count);
491 }
492
SetTableMode(DistributedTableMode tableMode)493 int SQLiteRelationalStoreConnection::SetTableMode(DistributedTableMode tableMode)
494 {
495 auto *store = GetDB<SQLiteRelationalStore>();
496 if (store == nullptr) {
497 LOGE("[RelationalConnection] store is null when set distributed table mode.");
498 return -E_INVALID_CONNECTION;
499 }
500 return store->SetTableMode(tableMode);
501 }
502 }
503 #endif