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 #define MLOG_TAG "RdbStore"
16
17 #include "medialibrary_rdbstore.h"
18
19 #include <mutex>
20
21 #include "cloud_sync_helper.h"
22 #include "media_file_uri.h"
23 #include "media_file_utils.h"
24 #include "media_log.h"
25 #ifdef DISTRIBUTED
26 #include "medialibrary_device.h"
27 #endif
28 #include "medialibrary_errno.h"
29 #include "medialibrary_object_utils.h"
30 #include "medialibrary_tracer.h"
31 #include "media_scanner.h"
32 #include "media_scanner_manager.h"
33 #include "medialibrary_unistore_manager.h"
34 #include "photo_album_column.h"
35 #include "photo_map_column.h"
36 #include "rdb_sql_utils.h"
37 #include "result_set_utils.h"
38
39 using namespace std;
40 using namespace OHOS::NativeRdb;
41
42 namespace OHOS::Media {
43 shared_ptr<NativeRdb::RdbStore> MediaLibraryRdbStore::rdbStore_;
44 struct UniqueMemberValuesBucket {
45 std::string assetMediaType;
46 int32_t startNumber;
47 };
48
CloudSyncTriggerFunc(const std::vector<std::string> & args)49 const std::string MediaLibraryRdbStore::CloudSyncTriggerFunc(const std::vector<std::string> &args)
50 {
51 CloudSyncHelper::GetInstance()->StartSync();
52 return "";
53 }
54
IsCallerSelfFunc(const std::vector<std::string> & args)55 const std::string MediaLibraryRdbStore::IsCallerSelfFunc(const std::vector<std::string> &args)
56 {
57 return "true";
58 }
59
MediaLibraryRdbStore(const shared_ptr<OHOS::AbilityRuntime::Context> & context)60 MediaLibraryRdbStore::MediaLibraryRdbStore(const shared_ptr<OHOS::AbilityRuntime::Context> &context)
61 {
62 if (context == nullptr) {
63 MEDIA_ERR_LOG("Failed to get context");
64 return;
65 }
66 string databaseDir = context->GetDatabaseDir();
67 string name = MEDIA_DATA_ABILITY_DB_NAME;
68 int32_t errCode = 0;
69 string realPath = RdbSqlUtils::GetDefaultDatabasePath(databaseDir, name, errCode);
70 config_.SetName(move(name));
71 config_.SetPath(move(realPath));
72 config_.SetBundleName(context->GetBundleName());
73 config_.SetArea(context->GetArea());
74 config_.SetSecurityLevel(SecurityLevel::S3);
75 config_.SetScalarFunction("cloud_sync_func", 0, CloudSyncTriggerFunc);
76 config_.SetScalarFunction("is_caller_self_func", 0, IsCallerSelfFunc);
77 isInTransaction_.store(false);
78 }
79
Init()80 int32_t MediaLibraryRdbStore::Init()
81 {
82 MEDIA_INFO_LOG("Init rdb store");
83 if (rdbStore_ != nullptr) {
84 return E_OK;
85 }
86
87 int32_t errCode = 0;
88 MediaLibraryDataCallBack rdbDataCallBack;
89 rdbStore_ = RdbHelper::GetRdbStore(config_, MEDIA_RDB_VERSION, rdbDataCallBack, errCode);
90 if (rdbStore_ == nullptr) {
91 MEDIA_ERR_LOG("GetRdbStore is failed ");
92 return E_ERR;
93 }
94 MEDIA_INFO_LOG("SUCCESS");
95 return E_OK;
96 }
97
98 MediaLibraryRdbStore::~MediaLibraryRdbStore() = default;
99
Stop()100 void MediaLibraryRdbStore::Stop()
101 {
102 if (rdbStore_ == nullptr) {
103 return;
104 }
105
106 rdbStore_ = nullptr;
107 }
108
ExecSqls(const vector<string> & sqls,RdbStore & store)109 static int32_t ExecSqls(const vector<string> &sqls, RdbStore &store)
110 {
111 int32_t err = NativeRdb::E_OK;
112 for (const auto &sql : sqls) {
113 err = store.ExecuteSql(sql);
114 if (err != NativeRdb::E_OK) {
115 MEDIA_ERR_LOG("Failed to exec: %{public}s", sql.c_str());
116 /* try update as much as possible */
117 continue;
118 }
119 }
120 return NativeRdb::E_OK;
121 }
122
123 #ifdef DISTRIBUTED
GetAllNetworkId(vector<string> & networkIds)124 void GetAllNetworkId(vector<string> &networkIds)
125 {
126 vector<OHOS::DistributedHardware::DmDeviceInfo> deviceList;
127 MediaLibraryDevice::GetInstance()->GetAllNetworkId(deviceList);
128 for (auto& deviceInfo : deviceList) {
129 networkIds.push_back(deviceInfo.networkId);
130 }
131 }
132 #endif
133
Insert(MediaLibraryCommand & cmd,int64_t & rowId)134 int32_t MediaLibraryRdbStore::Insert(MediaLibraryCommand &cmd, int64_t &rowId)
135 {
136 MediaLibraryTracer tracer;
137 tracer.Start("MediaLibraryRdbStore::Insert");
138 if (rdbStore_ == nullptr) {
139 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
140 return E_HAS_DB_ERROR;
141 }
142
143 int32_t ret = rdbStore_->Insert(rowId, cmd.GetTableName(), cmd.GetValueBucket());
144 if (ret != NativeRdb::E_OK) {
145 MEDIA_ERR_LOG("rdbStore_->Insert failed, ret = %{public}d", ret);
146 return E_HAS_DB_ERROR;
147 }
148
149 MEDIA_DEBUG_LOG("rdbStore_->Insert end, rowId = %d, ret = %{public}d", (int)rowId, ret);
150 return ret;
151 }
152
DoDeleteFromPredicates(NativeRdb::RdbStore & rdb,const AbsRdbPredicates & predicates,int32_t & deletedRows)153 static int32_t DoDeleteFromPredicates(NativeRdb::RdbStore &rdb, const AbsRdbPredicates &predicates,
154 int32_t &deletedRows)
155 {
156 int32_t ret = NativeRdb::E_ERROR;
157 string tableName = predicates.GetTableName();
158 ValuesBucket valuesBucket;
159 if (tableName == MEDIALIBRARY_TABLE || tableName == PhotoColumn::PHOTOS_TABLE) {
160 valuesBucket.PutInt(MEDIA_DATA_DB_DIRTY, static_cast<int32_t>(DirtyType::TYPE_DELETED));
161 valuesBucket.PutInt(MEDIA_DATA_DB_SYNC_STATUS, static_cast<int32_t>(SyncStatusType::TYPE_UPLOAD));
162 ret = rdb.Update(deletedRows, tableName, valuesBucket, predicates.GetWhereClause(),
163 predicates.GetWhereArgs());
164 } else if (tableName == PhotoAlbumColumns::TABLE) {
165 valuesBucket.PutInt(PhotoAlbumColumns::ALBUM_DIRTY, static_cast<int32_t>(DirtyType::TYPE_DELETED));
166 ret = rdb.Update(deletedRows, tableName, valuesBucket, predicates.GetWhereClause(),
167 predicates.GetWhereArgs());
168 } else if (tableName == PhotoMap::TABLE) {
169 valuesBucket.PutInt(PhotoMap::DIRTY, static_cast<int32_t>(DirtyType::TYPE_DELETED));
170 ret = rdb.Update(deletedRows, tableName, valuesBucket, predicates.GetWhereClause(),
171 predicates.GetWhereArgs());
172 } else {
173 ret = rdb.Delete(deletedRows, tableName, predicates.GetWhereClause(), predicates.GetWhereArgs());
174 }
175 return ret;
176 }
177
Delete(MediaLibraryCommand & cmd,int32_t & deletedRows)178 int32_t MediaLibraryRdbStore::Delete(MediaLibraryCommand &cmd, int32_t &deletedRows)
179 {
180 if (rdbStore_ == nullptr) {
181 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
182 return E_HAS_DB_ERROR;
183 }
184 MediaLibraryTracer tracer;
185 tracer.Start("RdbStore->DeleteByCmd");
186 /* local delete */
187 int32_t ret = DoDeleteFromPredicates(*rdbStore_, *(cmd.GetAbsRdbPredicates()), deletedRows);
188 if (ret != NativeRdb::E_OK) {
189 MEDIA_ERR_LOG("rdbStore_->Delete failed, ret = %{public}d", ret);
190 return E_HAS_DB_ERROR;
191 }
192 CloudSyncHelper::GetInstance()->StartSync();
193 return ret;
194 }
195
Update(MediaLibraryCommand & cmd,int32_t & changedRows)196 int32_t MediaLibraryRdbStore::Update(MediaLibraryCommand &cmd, int32_t &changedRows)
197 {
198 if (rdbStore_ == nullptr) {
199 MEDIA_ERR_LOG("rdbStore_ is nullptr");
200 return E_HAS_DB_ERROR;
201 }
202
203 MediaLibraryTracer tracer;
204 tracer.Start("RdbStore->UpdateByCmd");
205 int32_t ret = rdbStore_->Update(changedRows, cmd.GetTableName(), cmd.GetValueBucket(),
206 cmd.GetAbsRdbPredicates()->GetWhereClause(), cmd.GetAbsRdbPredicates()->GetWhereArgs());
207 if (ret != NativeRdb::E_OK) {
208 MEDIA_ERR_LOG("rdbStore_->Update failed, ret = %{public}d", ret);
209 return E_HAS_DB_ERROR;
210 }
211 return ret;
212 }
213
GetQueryFilter(const string & tableName)214 static inline string GetQueryFilter(const string &tableName)
215 {
216 if (tableName == MEDIALIBRARY_TABLE) {
217 return MEDIALIBRARY_TABLE + "." + MEDIA_DATA_DB_SYNC_STATUS + " = " +
218 to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
219 } else if (tableName == PhotoColumn::PHOTOS_TABLE) {
220 return PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_SYNC_STATUS + " = " +
221 to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
222 } else if (tableName == PhotoAlbumColumns::TABLE) {
223 return PhotoAlbumColumns::TABLE + "." + PhotoAlbumColumns::ALBUM_DIRTY + " != " +
224 to_string(static_cast<int32_t>(DirtyTypes::TYPE_DELETED));
225 } else if (tableName == PhotoMap::TABLE) {
226 return PhotoMap::TABLE + "." + PhotoMap::DIRTY + " != " + to_string(static_cast<int32_t>(
227 DirtyTypes::TYPE_DELETED));
228 }
229 return "";
230 }
231
GetIndexOfUri(const AbsRdbPredicates & predicates,const vector<string> & columns,const string & id)232 shared_ptr<NativeRdb::ResultSet> MediaLibraryRdbStore::GetIndexOfUri(const AbsRdbPredicates &predicates,
233 const vector<string> &columns, const string &id)
234 {
235 if (rdbStore_ == nullptr) {
236 MEDIA_ERR_LOG("rdbStore_ is nullptr");
237 return nullptr;
238 }
239 MediaLibraryTracer tracer;
240 tracer.Start("GetIndexOfUri");
241 string sql;
242 sql.append("SELECT ").append(PHOTO_INDEX).append(" From (");
243 sql.append(RdbSqlUtils::BuildQueryString(predicates, columns));
244 sql.append(") where "+ MediaColumn::MEDIA_ID + " = ").append(id);
245 MEDIA_DEBUG_LOG("sql = %{public}s", sql.c_str());
246 for (auto &arg : predicates.GetWhereArgs()) {
247 MEDIA_DEBUG_LOG("arg = %{public}s", arg.c_str());
248 }
249 return rdbStore_->QuerySql(sql, predicates.GetWhereArgs());
250 }
251
Query(MediaLibraryCommand & cmd,const vector<string> & columns)252 shared_ptr<NativeRdb::ResultSet> MediaLibraryRdbStore::Query(MediaLibraryCommand &cmd,
253 const vector<string> &columns)
254 {
255 if (rdbStore_ == nullptr) {
256 MEDIA_ERR_LOG("rdbStore_ is nullptr");
257 return nullptr;
258 }
259
260 MediaLibraryTracer tracer;
261 tracer.Start("RdbStore->QueryByCmd");
262 #ifdef MEDIALIBRARY_COMPATIBILITY
263 auto predicates = cmd.GetAbsRdbPredicates();
264 MEDIA_DEBUG_LOG("tablename = %{public}s", predicates->GetTableName().c_str());
265 for (const auto &col : columns) {
266 MEDIA_DEBUG_LOG("col = %{public}s", col.c_str());
267 }
268 MEDIA_DEBUG_LOG("whereClause = %{public}s", predicates->GetWhereClause().c_str());
269 for (auto &arg : predicates->GetWhereArgs()) {
270 MEDIA_DEBUG_LOG("whereArgs = %{public}s", arg.c_str());
271 }
272 MEDIA_DEBUG_LOG("limit = %{public}d", predicates->GetLimit());
273 #endif
274
275 /*
276 * adapter pattern:
277 * Reuse predicates-based query so that no need to modify both func
278 * if later logic changes take place
279 */
280 return Query(*cmd.GetAbsRdbPredicates(), columns);
281 }
282
AddQueryFilter(AbsRdbPredicates & predicates)283 static void AddQueryFilter(AbsRdbPredicates &predicates)
284 {
285 /* build all-table vector */
286 string tableName = predicates.GetTableName();
287 vector<string> joinTables = predicates.GetJoinTableNames();
288 joinTables.push_back(tableName);
289 /* add filters */
290 string filters;
291 for (auto &t : joinTables) {
292 string filter = GetQueryFilter(t);
293 if (filters.empty()) {
294 filters += filter;
295 } else {
296 filters += " AND " + filter;
297 }
298 }
299 if (filters.empty()) {
300 return;
301 }
302
303 /* rebuild */
304 string queryCondition = predicates.GetWhereClause();
305 queryCondition = queryCondition.empty() ? filters : filters + " AND " + queryCondition;
306 predicates.SetWhereClause(queryCondition);
307 }
308
Query(const AbsRdbPredicates & predicates,const vector<string> & columns)309 shared_ptr<NativeRdb::ResultSet> MediaLibraryRdbStore::Query(const AbsRdbPredicates &predicates,
310 const vector<string> &columns)
311 {
312 if (rdbStore_ == nullptr) {
313 MEDIA_ERR_LOG("rdbStore_ is nullptr");
314 return nullptr;
315 }
316
317 /* add filter */
318 AddQueryFilter(const_cast<AbsRdbPredicates &>(predicates));
319
320 MediaLibraryTracer tracer;
321 tracer.Start("RdbStore->QueryByPredicates");
322 return rdbStore_->Query(predicates, columns);
323 }
324
ExecuteSql(const string & sql)325 int32_t MediaLibraryRdbStore::ExecuteSql(const string &sql)
326 {
327 if (rdbStore_ == nullptr) {
328 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
329 return E_HAS_DB_ERROR;
330 }
331
332 MediaLibraryTracer tracer;
333 tracer.Start("RdbStore->ExecuteSql");
334 int32_t ret = rdbStore_->ExecuteSql(sql);
335 if (ret != NativeRdb::E_OK) {
336 MEDIA_ERR_LOG("rdbStore_->ExecuteSql failed, ret = %{public}d", ret);
337 return E_HAS_DB_ERROR;
338 }
339 return ret;
340 }
341
BuildValuesSql(const NativeRdb::ValuesBucket & values,vector<ValueObject> & bindArgs,string & sql)342 void MediaLibraryRdbStore::BuildValuesSql(const NativeRdb::ValuesBucket &values, vector<ValueObject> &bindArgs,
343 string &sql)
344 {
345 map<string, ValueObject> valuesMap;
346 values.GetAll(valuesMap);
347 sql.append("(");
348 for (auto iter = valuesMap.begin(); iter != valuesMap.end(); iter++) {
349 sql.append(((iter == valuesMap.begin()) ? "" : ", "));
350 sql.append(iter->first); // columnName
351 bindArgs.push_back(iter->second); // columnValue
352 }
353
354 sql.append(") select ");
355 for (size_t i = 0; i < valuesMap.size(); i++) {
356 sql.append(((i == 0) ? "?" : ", ?"));
357 }
358 sql.append(" ");
359 }
360
BuildQuerySql(const AbsRdbPredicates & predicates,const vector<string> & columns,vector<ValueObject> & bindArgs,string & sql)361 void MediaLibraryRdbStore::BuildQuerySql(const AbsRdbPredicates &predicates, const vector<string> &columns,
362 vector<ValueObject> &bindArgs, string &sql)
363 {
364 sql.append(RdbSqlUtils::BuildQueryString(predicates, columns));
365 for (auto &arg : predicates.GetWhereArgs()) {
366 bindArgs.emplace_back(arg);
367 }
368 }
369
370 /**
371 * Returns last insert row id. If insert succeed but no new rows inserted, then return -1.
372 * Return E_HAS_DB_ERROR on error cases.
373 */
ExecuteForLastInsertedRowId(const string & sql,const vector<ValueObject> & bindArgs)374 int32_t MediaLibraryRdbStore::ExecuteForLastInsertedRowId(const string &sql, const vector<ValueObject> &bindArgs)
375 {
376 if (rdbStore_ == nullptr) {
377 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
378 return E_HAS_DB_ERROR;
379 }
380
381 int64_t lastInsertRowId = 0;
382 int32_t err = rdbStore_->ExecuteForLastInsertedRowId(lastInsertRowId, sql, bindArgs);
383 if (err != E_OK) {
384 MEDIA_ERR_LOG("Failed to execute insert, err: %{public}d", err);
385 return E_HAS_DB_ERROR;
386 }
387 return lastInsertRowId;
388 }
389
Delete(const AbsRdbPredicates & predicates)390 int32_t MediaLibraryRdbStore::Delete(const AbsRdbPredicates &predicates)
391 {
392 if (rdbStore_ == nullptr) {
393 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
394 return E_HAS_DB_ERROR;
395 }
396 int err = E_ERR;
397 int32_t deletedRows = 0;
398 err = DoDeleteFromPredicates(*rdbStore_, predicates, deletedRows);
399 if (err != E_OK) {
400 MEDIA_ERR_LOG("Failed to execute delete, err: %{public}d", err);
401 return E_HAS_DB_ERROR;
402 }
403 CloudSyncHelper::GetInstance()->StartSync();
404 return deletedRows;
405 }
406
407 /**
408 * Return changed rows on success, or negative values on error cases.
409 */
Update(const ValuesBucket & values,const AbsRdbPredicates & predicates)410 int32_t MediaLibraryRdbStore::Update(const ValuesBucket &values,
411 const AbsRdbPredicates &predicates)
412 {
413 if (rdbStore_ == nullptr) {
414 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
415 return E_HAS_DB_ERROR;
416 }
417
418 MediaLibraryTracer tracer;
419 tracer.Start("MediaLibraryRdbStore::Update by predicates");
420 int32_t changedRows = -1;
421 int err = rdbStore_->Update(changedRows, values, predicates);
422 if (err != E_OK) {
423 MEDIA_ERR_LOG("Failed to execute update, err: %{public}d", err);
424 return E_HAS_DB_ERROR;
425 }
426 return changedRows;
427 }
428
QuerySql(const string & sql,const vector<string> & selectionArgs)429 shared_ptr<NativeRdb::ResultSet> MediaLibraryRdbStore::QuerySql(const string &sql, const vector<string> &selectionArgs)
430 {
431 if (rdbStore_ == nullptr) {
432 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
433 return nullptr;
434 }
435
436 MediaLibraryTracer tracer;
437 tracer.Start("RdbStore->QuerySql");
438 return rdbStore_->QuerySql(sql, selectionArgs);
439 }
440
BeginTransaction()441 int32_t MediaLibraryRdbStore::BeginTransaction()
442 {
443 if (rdbStore_ == nullptr) {
444 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
445 return E_HAS_DB_ERROR;
446 }
447
448 unique_lock<mutex> cvLock(transactionMutex_);
449 if (isInTransaction_.load()) {
450 transactionCV_.wait_for(cvLock, chrono::milliseconds(RDB_TRANSACTION_WAIT_MS),
451 [this] () { return !(isInTransaction_.load()); });
452 }
453
454 if (rdbStore_->IsInTransaction()) {
455 MEDIA_ERR_LOG("RdbStore is still in transaction");
456 return E_HAS_DB_ERROR;
457 }
458
459 isInTransaction_.store(true);
460 int32_t errCode = rdbStore_->BeginTransaction();
461 if (errCode != NativeRdb::E_OK) {
462 MEDIA_ERR_LOG("Start Transaction failed, errCode=%{public}d", errCode);
463 isInTransaction_.store(false);
464 transactionCV_.notify_one();
465 return E_HAS_DB_ERROR;
466 }
467
468 return E_OK;
469 }
470
Commit()471 int32_t MediaLibraryRdbStore::Commit()
472 {
473 if (rdbStore_ == nullptr) {
474 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
475 return E_HAS_DB_ERROR;
476 }
477
478 if (!(isInTransaction_.load()) || !(rdbStore_->IsInTransaction())) {
479 MEDIA_ERR_LOG("no transaction now");
480 return E_HAS_DB_ERROR;
481 }
482
483 int32_t errCode = rdbStore_->Commit();
484 isInTransaction_.store(false);
485 transactionCV_.notify_all();
486 if (errCode != NativeRdb::E_OK) {
487 MEDIA_ERR_LOG("commit failed, errCode=%{public}d", errCode);
488 return E_HAS_DB_ERROR;
489 }
490
491 return E_OK;
492 }
493
RollBack()494 int32_t MediaLibraryRdbStore::RollBack()
495 {
496 if (rdbStore_ == nullptr) {
497 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
498 return E_HAS_DB_ERROR;
499 }
500 if (!(isInTransaction_.load()) || !(rdbStore_->IsInTransaction())) {
501 MEDIA_ERR_LOG("no transaction now");
502 return E_HAS_DB_ERROR;
503 }
504
505 int32_t errCode = rdbStore_->RollBack();
506 isInTransaction_.store(false);
507 transactionCV_.notify_all();
508 if (errCode != NativeRdb::E_OK) {
509 MEDIA_ERR_LOG("rollback failed, errCode=%{public}d", errCode);
510 return E_HAS_DB_ERROR;
511 }
512
513 return E_OK;
514 }
515
GetRaw() const516 shared_ptr<NativeRdb::RdbStore> MediaLibraryRdbStore::GetRaw() const
517 {
518 return rdbStore_;
519 }
520
DeleteDbByFileId(const string & table,int32_t fileId)521 static inline int32_t DeleteDbByFileId(const string &table, int32_t fileId)
522 {
523 AbsRdbPredicates predicates(table);
524 predicates.EqualTo(MediaColumn::MEDIA_ID, to_string(fileId));
525 predicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
526 return MediaLibraryRdbStore::Delete(predicates);
527 }
528
DeleteFromDisk(const AbsRdbPredicates & predicates)529 int32_t MediaLibraryRdbStore::DeleteFromDisk(const AbsRdbPredicates &predicates)
530 {
531 vector<string> columns = {
532 MediaColumn::MEDIA_ID,
533 MediaColumn::MEDIA_FILE_PATH
534 };
535 auto resultSet = Query(predicates, columns);
536 if (resultSet == nullptr) {
537 return E_HAS_DB_ERROR;
538 }
539 int32_t count = 0;
540 int32_t err = resultSet->GetRowCount(count);
541 if (err != E_OK) {
542 return E_HAS_DB_ERROR;
543 }
544 int32_t deletedRows = 0;
545 for (int32_t i = 0; i < count; i++) {
546 err = resultSet->GoToNextRow();
547 if (err != E_OK) {
548 return E_HAS_DB_ERROR;
549 }
550
551 // Delete file from db.
552 int32_t fileId = get<int32_t>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_ID, resultSet, TYPE_INT32));
553 if (fileId <= 0) {
554 return E_HAS_DB_ERROR;
555 }
556 int32_t deletedRow = DeleteDbByFileId(predicates.GetTableName(), fileId);
557 if (deletedRow < 0) {
558 return E_HAS_DB_ERROR;
559 }
560 // If deletedRow is 0, the file may be deleted already somewhere else, so just continue.
561 if (deletedRow == 0) {
562 continue;
563 }
564
565 // Delete file from file system.
566 string filePath = get<string>(ResultSetUtils::GetValFromColumn(MediaColumn::MEDIA_FILE_PATH, resultSet,
567 TYPE_STRING));
568 if (filePath.empty()) {
569 return E_HAS_DB_ERROR;
570 }
571 if (!MediaFileUtils::DeleteFile(filePath) && (errno != -ENOENT)) {
572 MEDIA_ERR_LOG("Failed to delete file, errno: %{public}d, path: %{private}s", errno, filePath.c_str());
573 return E_HAS_FS_ERROR;
574 }
575 MediaLibraryObjectUtils::InvalidateThumbnail(to_string(fileId), predicates.GetTableName(), filePath);
576 deletedRows += deletedRow;
577 }
578 return deletedRows;
579 }
580
ReplacePredicatesUriToId(AbsRdbPredicates & predicates)581 void MediaLibraryRdbStore::ReplacePredicatesUriToId(AbsRdbPredicates &predicates)
582 {
583 const vector<string> &whereUriArgs = predicates.GetWhereArgs();
584 vector<string> whereIdArgs;
585 whereIdArgs.reserve(whereUriArgs.size());
586 for (const auto &arg : whereUriArgs) {
587 if (!MediaFileUtils::StartsWith(arg, PhotoColumn::PHOTO_URI_PREFIX)) {
588 whereIdArgs.push_back(arg);
589 continue;
590 }
591 whereIdArgs.push_back(MediaFileUri::GetPhotoId(arg));
592 }
593
594 predicates.SetWhereArgs(whereIdArgs);
595 }
596
GetInt(const shared_ptr<ResultSet> & resultSet,const string & column)597 int32_t MediaLibraryRdbStore::GetInt(const shared_ptr<ResultSet> &resultSet, const string &column)
598 {
599 return get<int32_t>(ResultSetUtils::GetValFromColumn(column, resultSet, TYPE_INT32));
600 }
601
GetString(const shared_ptr<ResultSet> & resultSet,const string & column)602 string MediaLibraryRdbStore::GetString(const shared_ptr<ResultSet> &resultSet, const string &column)
603 {
604 return get<string>(ResultSetUtils::GetValFromColumn(column, resultSet, TYPE_STRING));
605 }
606
BuildInsertSystemAlbumSql(const ValuesBucket & values,const AbsRdbPredicates & predicates,string & sql,vector<ValueObject> & bindArgs)607 inline void BuildInsertSystemAlbumSql(const ValuesBucket &values, const AbsRdbPredicates &predicates,
608 string &sql, vector<ValueObject> &bindArgs)
609 {
610 // Build insert sql
611 sql.append("INSERT").append(" OR ROLLBACK ").append(" INTO ").append(PhotoAlbumColumns::TABLE).append(" ");
612 MediaLibraryRdbStore::BuildValuesSql(values, bindArgs, sql);
613 sql.append(" WHERE NOT EXISTS (");
614 MediaLibraryRdbStore::BuildQuerySql(predicates, { PhotoAlbumColumns::ALBUM_ID }, bindArgs, sql);
615 sql.append(");");
616 }
617
PrepareSystemAlbums(RdbStore & store)618 int32_t PrepareSystemAlbums(RdbStore &store)
619 {
620 ValuesBucket values;
621 int32_t err = E_FAIL;
622 store.BeginTransaction();
623 for (int32_t i = PhotoAlbumSubType::SYSTEM_START; i <= PhotoAlbumSubType::SYSTEM_END; i++) {
624 values.PutInt(PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumType::SYSTEM);
625 values.PutInt(PhotoAlbumColumns::ALBUM_SUBTYPE, i);
626
627 AbsRdbPredicates predicates(PhotoAlbumColumns::TABLE);
628 predicates.EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::SYSTEM));
629 predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(i));
630
631 string sql;
632 vector<ValueObject> bindArgs;
633 BuildInsertSystemAlbumSql(values, predicates, sql, bindArgs);
634 err = store.ExecuteSql(sql, bindArgs);
635 if (err != E_OK) {
636 store.RollBack();
637 return err;
638 }
639 values.Clear();
640 }
641 store.Commit();
642 return E_OK;
643 }
644
PrepareDir(RdbStore & store)645 int32_t MediaLibraryDataCallBack::PrepareDir(RdbStore &store)
646 {
647 DirValuesBucket cameraDir = {
648 CAMERA_DIRECTORY_TYPE_VALUES, CAMERA_DIR_VALUES, CAMERA_TYPE_VALUES, CAMERA_EXTENSION_VALUES
649 };
650 DirValuesBucket videoDir = {
651 VIDEO_DIRECTORY_TYPE_VALUES, VIDEO_DIR_VALUES, VIDEO_TYPE_VALUES, VIDEO_EXTENSION_VALUES
652 };
653 DirValuesBucket pictureDir = {
654 PIC_DIRECTORY_TYPE_VALUES, PIC_DIR_VALUES, PIC_TYPE_VALUES, PIC_EXTENSION_VALUES
655 };
656 DirValuesBucket audioDir = {
657 AUDIO_DIRECTORY_TYPE_VALUES, AUDIO_DIR_VALUES, AUDIO_TYPE_VALUES, AUDIO_EXTENSION_VALUES
658 };
659 DirValuesBucket documentDir = {
660 DOC_DIRECTORY_TYPE_VALUES, DOC_DIR_VALUES, DOC_TYPE_VALUES, DOC_EXTENSION_VALUES
661 };
662 DirValuesBucket downloadDir = {
663 DOWNLOAD_DIRECTORY_TYPE_VALUES, DOWNLOAD_DIR_VALUES, DOWNLOAD_TYPE_VALUES, DOWNLOAD_EXTENSION_VALUES
664 };
665
666 vector<DirValuesBucket> dirValuesBuckets = {
667 cameraDir, videoDir, pictureDir, audioDir, documentDir, downloadDir
668 };
669
670 for (const auto& dirValuesBucket : dirValuesBuckets) {
671 if (InsertDirValues(dirValuesBucket, store) != NativeRdb::E_OK) {
672 MEDIA_ERR_LOG("PrepareDir failed");
673 return NativeRdb::E_ERROR;
674 }
675 }
676 return NativeRdb::E_OK;
677 }
678
InsertDirValues(const DirValuesBucket & dirValuesBucket,RdbStore & store)679 int32_t MediaLibraryDataCallBack::InsertDirValues(const DirValuesBucket &dirValuesBucket, RdbStore &store)
680 {
681 ValuesBucket valuesBucket;
682 valuesBucket.PutInt(DIRECTORY_DB_DIRECTORY_TYPE, dirValuesBucket.directoryType);
683 valuesBucket.PutString(DIRECTORY_DB_DIRECTORY, dirValuesBucket.dirValues);
684 valuesBucket.PutString(DIRECTORY_DB_MEDIA_TYPE, dirValuesBucket.typeValues);
685 valuesBucket.PutString(DIRECTORY_DB_EXTENSION, dirValuesBucket.extensionValues);
686 int64_t outRowId = -1;
687 int32_t insertResult = store.Insert(outRowId, MEDIATYPE_DIRECTORY_TABLE, valuesBucket);
688 MEDIA_DEBUG_LOG("insert dir outRowId: %{public}ld insertResult: %{public}d", (long)outRowId, insertResult);
689 return insertResult;
690 }
691
PrepareSmartAlbum(RdbStore & store)692 int32_t MediaLibraryDataCallBack::PrepareSmartAlbum(RdbStore &store)
693 {
694 SmartAlbumValuesBucket trashAlbum = {
695 TRASH_ALBUM_ID_VALUES, TRASH_ALBUM_NAME_VALUES, TRASH_ALBUM_TYPE_VALUES
696 };
697
698 SmartAlbumValuesBucket favAlbum = {
699 FAVOURITE_ALBUM_ID_VALUES, FAVOURTIE_ALBUM_NAME_VALUES, FAVOURITE_ALBUM_TYPE_VALUES
700 };
701
702 vector<SmartAlbumValuesBucket> smartAlbumValuesBuckets = {
703 trashAlbum, favAlbum
704 };
705
706 for (const auto& smartAlbum : smartAlbumValuesBuckets) {
707 if (InsertSmartAlbumValues(smartAlbum, store) != NativeRdb::E_OK) {
708 MEDIA_ERR_LOG("Prepare smartAlbum failed");
709 return NativeRdb::E_ERROR;
710 }
711 }
712 return NativeRdb::E_OK;
713 }
714
InsertSmartAlbumValues(const SmartAlbumValuesBucket & smartAlbum,RdbStore & store)715 int32_t MediaLibraryDataCallBack::InsertSmartAlbumValues(const SmartAlbumValuesBucket &smartAlbum, RdbStore &store)
716 {
717 ValuesBucket valuesBucket;
718 valuesBucket.PutInt(SMARTALBUM_DB_ID, smartAlbum.albumId);
719 valuesBucket.PutString(SMARTALBUM_DB_NAME, smartAlbum.albumName);
720 valuesBucket.PutInt(SMARTALBUM_DB_ALBUM_TYPE, smartAlbum.albumType);
721 int64_t outRowId = -1;
722 int32_t insertResult = store.Insert(outRowId, SMARTALBUM_TABLE, valuesBucket);
723 return insertResult;
724 }
725
InsertUniqueMemberTableValues(const UniqueMemberValuesBucket & uniqueMemberValues,RdbStore & store)726 static int32_t InsertUniqueMemberTableValues(const UniqueMemberValuesBucket &uniqueMemberValues,
727 RdbStore &store)
728 {
729 ValuesBucket valuesBucket;
730 valuesBucket.PutString(ASSET_MEDIA_TYPE, uniqueMemberValues.assetMediaType);
731 valuesBucket.PutInt(UNIQUE_NUMBER, uniqueMemberValues.startNumber);
732 int64_t outRowId = -1;
733 int32_t insertResult = store.Insert(outRowId, ASSET_UNIQUE_NUMBER_TABLE, valuesBucket);
734 return insertResult;
735 }
736
PrepareUniqueMemberTable(RdbStore & store)737 static int32_t PrepareUniqueMemberTable(RdbStore &store)
738 {
739 string queryRowSql = "SELECT COUNT(*) as count FROM " + ASSET_UNIQUE_NUMBER_TABLE;
740 auto resultSet = store.QuerySql(queryRowSql);
741 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
742 MEDIA_ERR_LOG("Can not get AssetUniqueNumberTable count");
743 return NativeRdb::E_ERROR;
744 }
745 if (GetInt32Val("count", resultSet) != 0) {
746 MEDIA_DEBUG_LOG("AssetUniqueNumberTable is already inited");
747 return E_OK;
748 }
749
750 UniqueMemberValuesBucket imageBucket = { IMAGE_ASSET_TYPE, 0 };
751 UniqueMemberValuesBucket videoBucket = { VIDEO_ASSET_TYPE, 0 };
752 UniqueMemberValuesBucket audioBucket = { AUDIO_ASSET_TYPE, 0 };
753
754 vector<UniqueMemberValuesBucket> uniqueNumberValueBuckets = {
755 imageBucket, videoBucket, audioBucket
756 };
757
758 for (const auto& uniqueNumberValueBucket : uniqueNumberValueBuckets) {
759 if (InsertUniqueMemberTableValues(uniqueNumberValueBucket, store) != NativeRdb::E_OK) {
760 MEDIA_ERR_LOG("Prepare smartAlbum failed");
761 return NativeRdb::E_ERROR;
762 }
763 }
764 return NativeRdb::E_OK;
765 }
766
TriggerDeleteAlbumClearMap()767 static const string &TriggerDeleteAlbumClearMap()
768 {
769 static const string TRIGGER_CLEAR_MAP = BaseColumn::CreateTrigger() + "photo_album_clear_map" +
770 " AFTER DELETE ON " + PhotoAlbumColumns::TABLE +
771 " BEGIN " +
772 "DELETE FROM " + PhotoMap::TABLE +
773 " WHERE " + PhotoMap::ALBUM_ID + "=" + "OLD." + PhotoAlbumColumns::ALBUM_ID + ";" +
774 " END;";
775 return TRIGGER_CLEAR_MAP;
776 }
777
TriggerAddAssets()778 static const string &TriggerAddAssets()
779 {
780 static const string TRIGGER_ADD_ASSETS = BaseColumn::CreateTrigger() + "photo_album_insert_asset" +
781 " AFTER INSERT ON " + PhotoMap::TABLE +
782 " BEGIN " +
783 "UPDATE " + PhotoAlbumColumns::TABLE + " SET " +
784 PhotoAlbumColumns::ALBUM_COUNT + " = " + PhotoAlbumColumns::ALBUM_COUNT + " + 1 " +
785 "WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + "NEW." + PhotoMap::ALBUM_ID + ";" +
786 " END;";
787 return TRIGGER_ADD_ASSETS;
788 }
789
TriggerRemoveAssets()790 static const string &TriggerRemoveAssets()
791 {
792 static const string TRIGGER_REMOVE_ASSETS = BaseColumn::CreateTrigger() + "photo_album_delete_asset" +
793 " AFTER DELETE ON " + PhotoMap::TABLE +
794 " BEGIN " +
795 "UPDATE " + PhotoAlbumColumns::TABLE + " SET " +
796 PhotoAlbumColumns::ALBUM_COUNT + " = " + PhotoAlbumColumns::ALBUM_COUNT + " - 1 " +
797 "WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + "OLD." + PhotoMap::ALBUM_ID + ";" +
798 " END;";
799 return TRIGGER_REMOVE_ASSETS;
800 }
801
TriggerDeletePhotoClearMap()802 static const string &TriggerDeletePhotoClearMap()
803 {
804 static const string TRIGGER_DELETE_ASSETS = BaseColumn::CreateTrigger() + "delete_photo_clear_map" +
805 " AFTER DELETE ON " + PhotoColumn::PHOTOS_TABLE +
806 " BEGIN " +
807 "DELETE FROM " + PhotoMap::TABLE +
808 " WHERE " + PhotoMap::ASSET_ID + "=" + "OLD." + MediaColumn::MEDIA_ID + ";" +
809 " END;";
810 return TRIGGER_DELETE_ASSETS;
811 }
812
QueryAlbumJoinMap()813 static const string &QueryAlbumJoinMap()
814 {
815 static const string QUERY_ALBUM_JOIN_MAP = " SELECT " + PhotoAlbumColumns::ALBUM_ID +
816 " FROM " + PhotoAlbumColumns::TABLE + " INNER JOIN " + PhotoMap::TABLE + " ON " +
817 PhotoAlbumColumns::ALBUM_ID + " = " + PhotoMap::ALBUM_ID + " AND " +
818 PhotoMap::ASSET_ID + " = " + "NEW." + MediaColumn::MEDIA_ID;
819 return QUERY_ALBUM_JOIN_MAP;
820 }
821
SetHiddenUpdateCount()822 static const string &SetHiddenUpdateCount()
823 {
824 // Photos.hidden 1 -> 0
825 static const string SET_HIDDEN_UPDATE_COUNT = " UPDATE " + PhotoAlbumColumns::TABLE +
826 " SET " + PhotoAlbumColumns::ALBUM_COUNT + " = " + PhotoAlbumColumns::ALBUM_COUNT + " + 1" +
827 " WHERE " + PhotoAlbumColumns::ALBUM_ID + " IN (" +
828 QueryAlbumJoinMap() + " WHERE " +
829 "NEW." + MediaColumn::MEDIA_HIDDEN + " = 0" + " AND " +
830 "(OLD." + MediaColumn::MEDIA_HIDDEN + " - NEW." + MediaColumn::MEDIA_HIDDEN + " > 0)" +
831 ");";
832 return SET_HIDDEN_UPDATE_COUNT;
833 }
834
SetTrashUpdateCount()835 static const string &SetTrashUpdateCount()
836 {
837 // Photos.date_trashed timestamp -> 0
838 static const string SET_TRASH_UPDATE_COUNT = " UPDATE " + PhotoAlbumColumns::TABLE +
839 " SET " + PhotoAlbumColumns::ALBUM_COUNT + " = " + PhotoAlbumColumns::ALBUM_COUNT + " + 1" +
840 " WHERE " + PhotoAlbumColumns::ALBUM_ID + " IN (" +
841 QueryAlbumJoinMap() + " WHERE " +
842 "SIGN(NEW." + MediaColumn::MEDIA_DATE_TRASHED + ") = 0" + " AND " +
843 "NEW." + MediaColumn::MEDIA_HIDDEN + " = 0" + " AND " +
844 "(" +
845 "SIGN(OLD." + MediaColumn::MEDIA_DATE_TRASHED + ") - " +
846 "SIGN(NEW." + MediaColumn::MEDIA_DATE_TRASHED + ") > 0" +
847 ")" +
848 ");";
849 return SET_TRASH_UPDATE_COUNT;
850 }
851
UnSetHiddenUpdateCount()852 static const string &UnSetHiddenUpdateCount()
853 {
854 // Photos.hidden 0 -> 1
855 static const string UNSET_HIDDEN_UPDATE_COUNT = " UPDATE " + PhotoAlbumColumns::TABLE +
856 " SET " + PhotoAlbumColumns::ALBUM_COUNT + " = " + PhotoAlbumColumns::ALBUM_COUNT + " - 1" +
857 " WHERE " + PhotoAlbumColumns::ALBUM_ID + " IN (" +
858 QueryAlbumJoinMap() + " WHERE " +
859 "NEW." + MediaColumn::MEDIA_HIDDEN + " = 1" + " AND " +
860 "(NEW." + MediaColumn::MEDIA_HIDDEN + " - OLD." + MediaColumn::MEDIA_HIDDEN + " > 0)" +
861 ");";
862 return UNSET_HIDDEN_UPDATE_COUNT;
863 }
864
UnSetTrashUpdateCount()865 static const string &UnSetTrashUpdateCount()
866 {
867 // Photos.date_trashed 0 -> timestamp
868 static const string UNSET_TRASH_UPDATE_COUNT = " UPDATE " + PhotoAlbumColumns::TABLE +
869 " SET " + PhotoAlbumColumns::ALBUM_COUNT + " = " + PhotoAlbumColumns::ALBUM_COUNT + " - 1" +
870 " WHERE " + PhotoAlbumColumns::ALBUM_ID + " IN (" +
871 QueryAlbumJoinMap() + " WHERE " +
872 "SIGN(NEW." + MediaColumn::MEDIA_DATE_TRASHED + ") = 1" + " AND " +
873 "NEW." + MediaColumn::MEDIA_HIDDEN + " = 0" + " AND " +
874 "(" +
875 "SIGN(NEW." + MediaColumn::MEDIA_DATE_TRASHED + ") - "
876 "SIGN(OLD." + MediaColumn::MEDIA_DATE_TRASHED + ") > 0" +
877 ")" +
878 ");";
879 return UNSET_TRASH_UPDATE_COUNT;
880 }
881
TriggerUpdateUserAlbumCount()882 static const string &TriggerUpdateUserAlbumCount()
883 {
884 static const string TRIGGER_UPDATE_USER_ALBUM_COUNT = BaseColumn::CreateTrigger() + "update_user_album_count" +
885 " AFTER UPDATE ON " + PhotoColumn::PHOTOS_TABLE +
886 " BEGIN " +
887 SetHiddenUpdateCount() +
888 SetTrashUpdateCount() +
889 UnSetHiddenUpdateCount() +
890 UnSetTrashUpdateCount() +
891 " END;";
892 return TRIGGER_UPDATE_USER_ALBUM_COUNT;
893 }
894
ExecuteSql(RdbStore & store)895 static int32_t ExecuteSql(RdbStore &store)
896 {
897 static const vector<string> executeSqlStrs = {
898 CREATE_MEDIA_TABLE,
899 PhotoColumn::CREATE_PHOTO_TABLE,
900 PhotoColumn::INDEX_STHP_ADDTIME,
901 PhotoColumn::INDEX_CAMERA_SHOT_KEY,
902 PhotoColumn::CREATE_PHOTOS_DELETE_TRIGGER,
903 PhotoColumn::CREATE_PHOTOS_FDIRTY_TRIGGER,
904 PhotoColumn::CREATE_PHOTOS_MDIRTY_TRIGGER,
905 PhotoColumn::CREATE_PHOTOS_INSERT_CLOUD_SYNC,
906 AudioColumn::CREATE_AUDIO_TABLE,
907 CREATE_SMARTALBUM_TABLE,
908 CREATE_SMARTALBUMMAP_TABLE,
909 CREATE_DEVICE_TABLE,
910 CREATE_CATEGORY_SMARTALBUMMAP_TABLE,
911 CREATE_ASSET_UNIQUE_NUMBER_TABLE,
912 CREATE_IMAGE_VIEW,
913 CREATE_VIDEO_VIEW,
914 CREATE_AUDIO_VIEW,
915 CREATE_ALBUM_VIEW,
916 CREATE_SMARTALBUMASSETS_VIEW,
917 CREATE_ASSETMAP_VIEW,
918 CREATE_MEDIATYPE_DIRECTORY_TABLE,
919 CREATE_BUNDLE_PREMISSION_TABLE,
920 CREATE_MEDIALIBRARY_ERROR_TABLE,
921 CREATE_REMOTE_THUMBNAIL_TABLE,
922 CREATE_FILES_DELETE_TRIGGER,
923 CREATE_FILES_MDIRTY_TRIGGER,
924 CREATE_FILES_FDIRTY_TRIGGER,
925 CREATE_INSERT_CLOUD_SYNC_TRIGGER,
926 PhotoAlbumColumns::CREATE_TABLE,
927 PhotoAlbumColumns::INDEX_ALBUM_TYPES,
928 PhotoAlbumColumns::CREATE_ALBUM_INSERT_TRIGGER,
929 PhotoAlbumColumns::CREATE_ALBUM_MDIRTY_TRIGGER,
930 PhotoAlbumColumns::CREATE_ALBUM_DELETE_TRIGGER,
931 PhotoMap::CREATE_TABLE,
932 PhotoMap::CREATE_NEW_TRIGGER,
933 PhotoMap::CREATE_DELETE_TRIGGER,
934 TriggerDeleteAlbumClearMap(),
935 TriggerDeletePhotoClearMap(),
936 };
937
938 for (const string& sqlStr : executeSqlStrs) {
939 if (store.ExecuteSql(sqlStr) != NativeRdb::E_OK) {
940 return NativeRdb::E_ERROR;
941 }
942 }
943 return NativeRdb::E_OK;
944 }
945
OnCreate(RdbStore & store)946 int32_t MediaLibraryDataCallBack::OnCreate(RdbStore &store)
947 {
948 if (ExecuteSql(store) != NativeRdb::E_OK) {
949 return NativeRdb::E_ERROR;
950 }
951
952 if (PrepareSystemAlbums(store) != NativeRdb::E_OK) {
953 return NativeRdb::E_ERROR;
954 }
955
956 if (PrepareDir(store) != NativeRdb::E_OK) {
957 return NativeRdb::E_ERROR;
958 }
959
960 if (PrepareSmartAlbum(store) != NativeRdb::E_OK) {
961 return NativeRdb::E_ERROR;
962 }
963
964 if (PrepareUniqueMemberTable(store) != NativeRdb::E_OK) {
965 return NativeRdb::E_ERROR;
966 }
967 return NativeRdb::E_OK;
968 }
969
VersionAddCloud(RdbStore & store)970 void VersionAddCloud(RdbStore &store)
971 {
972 const std::string alterCloudId = "ALTER TABLE " + MEDIALIBRARY_TABLE +
973 " ADD COLUMN " + MEDIA_DATA_DB_CLOUD_ID +" TEXT";
974 int32_t result = store.ExecuteSql(alterCloudId);
975 if (result != NativeRdb::E_OK) {
976 MEDIA_ERR_LOG("Upgrade rdb cloud_id error %{private}d", result);
977 }
978 const std::string alterDirty = "ALTER TABLE " + MEDIALIBRARY_TABLE +
979 " ADD COLUMN " + MEDIA_DATA_DB_DIRTY +" INT DEFAULT 0";
980 result = store.ExecuteSql(alterDirty);
981 if (result != NativeRdb::E_OK) {
982 MEDIA_ERR_LOG("Upgrade rdb dirty error %{private}d", result);
983 }
984 const std::string alterSyncStatus = "ALTER TABLE " + MEDIALIBRARY_TABLE +
985 " ADD COLUMN " + MEDIA_DATA_DB_SYNC_STATUS +" INT DEFAULT 0";
986 result = store.ExecuteSql(alterSyncStatus);
987 if (result != NativeRdb::E_OK) {
988 MEDIA_ERR_LOG("Upgrade rdb syncStatus error %{private}d", result);
989 }
990 const std::string alterPosition = "ALTER TABLE " + MEDIALIBRARY_TABLE +
991 " ADD COLUMN " + MEDIA_DATA_DB_POSITION +" INT DEFAULT 1";
992 result = store.ExecuteSql(alterPosition);
993 if (result != NativeRdb::E_OK) {
994 MEDIA_ERR_LOG("Upgrade rdb position error %{private}d", result);
995 }
996 }
997
AddMetaModifiedColumn(RdbStore & store)998 void AddMetaModifiedColumn(RdbStore &store)
999 {
1000 const std::string alterMetaModified =
1001 "ALTER TABLE " + MEDIALIBRARY_TABLE + " ADD COLUMN " +
1002 MEDIA_DATA_DB_META_DATE_MODIFIED + " BIGINT DEFAULT 0";
1003 int32_t result = store.ExecuteSql(alterMetaModified);
1004 if (result != NativeRdb::E_OK) {
1005 MEDIA_ERR_LOG("Upgrade rdb meta_date_modified error %{private}d", result);
1006 }
1007 const std::string alterSyncStatus = "ALTER TABLE " + MEDIALIBRARY_TABLE +
1008 " ADD COLUMN " + MEDIA_DATA_DB_SYNC_STATUS + " INT DEFAULT 0";
1009 result = store.ExecuteSql(alterSyncStatus);
1010 if (result != NativeRdb::E_OK) {
1011 MEDIA_ERR_LOG("Upgrade rdb syncStatus error %{private}d", result);
1012 }
1013 }
1014
AddTableType(RdbStore & store)1015 void AddTableType(RdbStore &store)
1016 {
1017 const std::string alterTableName =
1018 "ALTER TABLE " + BUNDLE_PERMISSION_TABLE + " ADD COLUMN " +
1019 PERMISSION_TABLE_TYPE + " INT";
1020 int32_t result = store.ExecuteSql(alterTableName);
1021 if (result != NativeRdb::E_OK) {
1022 MEDIA_ERR_LOG("Upgrade rdb table_name error %{private}d", result);
1023 }
1024 }
1025
API10TableCreate(RdbStore & store)1026 void API10TableCreate(RdbStore &store)
1027 {
1028 static const vector<string> executeSqlStrs = {
1029 PhotoColumn::CREATE_PHOTO_TABLE,
1030 PhotoColumn::INDEX_STHP_ADDTIME,
1031 PhotoColumn::INDEX_CAMERA_SHOT_KEY,
1032 PhotoColumn::CREATE_PHOTOS_DELETE_TRIGGER,
1033 PhotoColumn::CREATE_PHOTOS_FDIRTY_TRIGGER,
1034 PhotoColumn::CREATE_PHOTOS_MDIRTY_TRIGGER,
1035 PhotoColumn::CREATE_PHOTOS_INSERT_CLOUD_SYNC,
1036 AudioColumn::CREATE_AUDIO_TABLE,
1037 CREATE_ASSET_UNIQUE_NUMBER_TABLE,
1038 CREATE_FILES_DELETE_TRIGGER,
1039 CREATE_FILES_MDIRTY_TRIGGER,
1040 CREATE_FILES_FDIRTY_TRIGGER,
1041 CREATE_INSERT_CLOUD_SYNC_TRIGGER,
1042 PhotoAlbumColumns::CREATE_TABLE,
1043 PhotoAlbumColumns::INDEX_ALBUM_TYPES,
1044 PhotoMap::CREATE_TABLE,
1045 TriggerDeleteAlbumClearMap(),
1046 TriggerAddAssets(),
1047 TriggerRemoveAssets(),
1048 TriggerDeletePhotoClearMap(),
1049 TriggerUpdateUserAlbumCount(),
1050 };
1051
1052 for (size_t i = 0; i < executeSqlStrs.size(); i++) {
1053 if (store.ExecuteSql(executeSqlStrs[i]) != NativeRdb::E_OK) {
1054 MEDIA_ERR_LOG("upgrade fail idx:%{public}zu", i);
1055 }
1056 }
1057 }
1058
ModifySyncStatus(RdbStore & store)1059 void ModifySyncStatus(RdbStore &store)
1060 {
1061 const std::string dropSyncStatus = "ALTER TABLE " + MEDIALIBRARY_TABLE + " DROP column syncing";
1062 auto result = store.ExecuteSql(dropSyncStatus);
1063 if (result != NativeRdb::E_OK) {
1064 MEDIA_ERR_LOG("Upgrade rdb syncing error %{private}d", result);
1065 }
1066
1067 const std::string addSyncStatus = "ALTER TABLE " + MEDIALIBRARY_TABLE + " ADD COLUMN " +
1068 MEDIA_DATA_DB_SYNC_STATUS +" INT DEFAULT 0";
1069 result = store.ExecuteSql(addSyncStatus);
1070 if (result != NativeRdb::E_OK) {
1071 MEDIA_ERR_LOG("Upgrade rdb syncStatus error %{private}d", result);
1072 }
1073 }
1074
ModifyDeleteTrigger(RdbStore & store)1075 void ModifyDeleteTrigger(RdbStore &store)
1076 {
1077 /* drop old delete trigger */
1078 const std::string dropDeleteTrigger = "DROP TRIGGER IF EXISTS photos_delete_trigger";
1079 if (store.ExecuteSql(dropDeleteTrigger) != NativeRdb::E_OK) {
1080 MEDIA_ERR_LOG("upgrade fail: drop old delete trigger");
1081 }
1082
1083 /* create new delete trigger */
1084 if (store.ExecuteSql(PhotoColumn::CREATE_PHOTOS_DELETE_TRIGGER) != NativeRdb::E_OK) {
1085 MEDIA_ERR_LOG("upgrade fail: create new delete trigger");
1086 }
1087 }
1088
AddCloudVersion(RdbStore & store)1089 void AddCloudVersion(RdbStore &store)
1090 {
1091 const std::string addSyncStatus = "ALTER TABLE " + PhotoColumn::PHOTOS_TABLE + " ADD COLUMN " +
1092 PhotoColumn::PHOTO_CLOUD_VERSION +" BIGINT DEFAULT 0";
1093 auto result = store.ExecuteSql(addSyncStatus);
1094 if (result != NativeRdb::E_OK) {
1095 MEDIA_ERR_LOG("Upgrade rdb cloudVersion error %{private}d", result);
1096 }
1097 }
1098
UpdateCloudPathSql(const string & table,const string & column)1099 static string UpdateCloudPathSql(const string &table, const string &column)
1100 {
1101 static const string LOCAL_PATH = "/storage/media/local/";
1102 static const string CLOUD_PATH = "/storage/cloud/";
1103 /*
1104 * replace only once:
1105 * UPDATE photos
1106 * SET data = ([replace](substring(data, 1, len(local_path)), local_path, cloud_path) ||
1107 * substring(data, len(local_path) + 1));
1108 */
1109 return "UPDATE " + table + " SET " + column + " = (REPLACE(SUBSTRING(" +
1110 column + ", 1, " + to_string(LOCAL_PATH.length()) + "), '" +
1111 LOCAL_PATH + "', '" + CLOUD_PATH + "') || SUBSTRING(" + column + ", " +
1112 to_string(LOCAL_PATH.length() + 1) + "))" +
1113 " WHERE " + column + " LIKE '" + LOCAL_PATH + "%';";
1114 }
1115
UpdateCloudPath(RdbStore & store)1116 static int32_t UpdateCloudPath(RdbStore &store)
1117 {
1118 const vector<string> updateCloudPath = {
1119 UpdateCloudPathSql(MEDIALIBRARY_TABLE, MEDIA_DATA_DB_FILE_PATH),
1120 UpdateCloudPathSql(MEDIALIBRARY_TABLE, MEDIA_DATA_DB_RECYCLE_PATH),
1121 UpdateCloudPathSql(MEDIALIBRARY_ERROR_TABLE, MEDIA_DATA_ERROR),
1122 UpdateCloudPathSql(PhotoColumn::PHOTOS_TABLE, MediaColumn::MEDIA_FILE_PATH),
1123 };
1124 return ExecSqls(updateCloudPath, store);
1125 }
1126
UpdateAPI10Table(RdbStore & store)1127 void UpdateAPI10Table(RdbStore &store)
1128 {
1129 store.ExecuteSql("DROP INDEX IF EXISTS idx_sthp_dateadded");
1130 store.ExecuteSql("DROP INDEX IF EXISTS photo_album_types");
1131
1132 store.ExecuteSql("DROP TRIGGER IF EXISTS photos_delete_trigger");
1133 store.ExecuteSql("DROP TRIGGER IF EXISTS photos_fdirty_trigger");
1134 store.ExecuteSql("DROP TRIGGER IF EXISTS photos_mdirty_trigger");
1135 store.ExecuteSql("DROP TRIGGER IF EXISTS photo_insert_cloud_sync_trigger");
1136
1137 store.ExecuteSql("DROP TRIGGER IF EXISTS delete_trigger");
1138 store.ExecuteSql("DROP TRIGGER IF EXISTS mdirty_trigger");
1139 store.ExecuteSql("DROP TRIGGER IF EXISTS fdirty_trigger");
1140 store.ExecuteSql("DROP TRIGGER IF EXISTS insert_cloud_sync_trigger");
1141
1142 store.ExecuteSql("DROP TRIGGER IF EXISTS photo_album_clear_map");
1143 store.ExecuteSql("DROP TRIGGER IF EXISTS photo_album_insert_asset");
1144 store.ExecuteSql("DROP TRIGGER IF EXISTS photo_album_delete_asset");
1145 store.ExecuteSql("DROP TRIGGER IF EXISTS delete_photo_clear_map");
1146 store.ExecuteSql("DROP TRIGGER IF EXISTS update_user_album_count");
1147
1148 store.ExecuteSql("DROP TABLE IF EXISTS Photos");
1149 store.ExecuteSql("DROP TABLE IF EXISTS Audios");
1150 store.ExecuteSql("DROP TABLE IF EXISTS UniqueNumber");
1151 store.ExecuteSql("DROP TABLE IF EXISTS PhotoAlbum");
1152 store.ExecuteSql("DROP TABLE IF EXISTS PhotoMap");
1153
1154 API10TableCreate(store);
1155 PrepareSystemAlbums(store);
1156 PrepareUniqueMemberTable(store);
1157
1158 // set scan error
1159 MediaScannerManager::GetInstance()->ErrorRecord();
1160 }
1161
UpdateAPI10Tables()1162 void MediaLibraryRdbStore::UpdateAPI10Tables()
1163 {
1164 if (rdbStore_ == nullptr) {
1165 MEDIA_ERR_LOG("Pointer rdbStore_ is nullptr. Maybe it didn't init successfully.");
1166 }
1167
1168 UpdateAPI10Table(*rdbStore_);
1169 }
1170
AddPackageNameColumnOnTables(RdbStore & store)1171 static void AddPackageNameColumnOnTables(RdbStore &store)
1172 {
1173 static const string ADD_PACKAGE_NAME_ON_PHOTOS = "ALTER TABLE " + PhotoColumn::PHOTOS_TABLE +
1174 " ADD COLUMN " + PhotoColumn::MEDIA_PACKAGE_NAME + " TEXT";
1175 static const string ADD_PACKAGE_NAME_ON_AUDIOS = "ALTER TABLE " + AudioColumn::AUDIOS_TABLE +
1176 " ADD COLUMN " + AudioColumn::MEDIA_PACKAGE_NAME + " TEXT";
1177 static const string ADD_PACKAGE_NAME_ON_FILES = "ALTER TABLE " + MEDIALIBRARY_TABLE +
1178 " ADD COLUMN " + MEDIA_DATA_DB_PACKAGE_NAME + " TEXT";
1179
1180 int32_t result = store.ExecuteSql(ADD_PACKAGE_NAME_ON_PHOTOS);
1181 if (result != NativeRdb::E_OK) {
1182 MEDIA_ERR_LOG("Failed to update PHOTOS");
1183 }
1184 result = store.ExecuteSql(ADD_PACKAGE_NAME_ON_AUDIOS);
1185 if (result != NativeRdb::E_OK) {
1186 MEDIA_ERR_LOG("Failed to update AUDIOS");
1187 }
1188 result = store.ExecuteSql(ADD_PACKAGE_NAME_ON_FILES);
1189 if (result != NativeRdb::E_OK) {
1190 MEDIA_ERR_LOG("Failed to update FILES");
1191 }
1192 }
1193
UpdateCloudAlbum(RdbStore & store)1194 void UpdateCloudAlbum(RdbStore &store)
1195 {
1196 /* album - add columns */
1197 const std::string addAlbumDirty = "ALTER TABLE " + PhotoAlbumColumns::TABLE +
1198 " ADD COLUMN " + PhotoAlbumColumns::ALBUM_DIRTY + " INT DEFAULT " +
1199 to_string(static_cast<int32_t>(DirtyTypes::TYPE_NEW)) + ";";
1200 int32_t ret = store.ExecuteSql(addAlbumDirty);
1201 if (ret != NativeRdb::E_OK) {
1202 MEDIA_ERR_LOG("upgrade fail %{public}d: add ablum dirty", ret);
1203 }
1204 const std::string addAlbumCloudId = "ALTER TABLE " + PhotoAlbumColumns::TABLE +
1205 " ADD COLUMN " + PhotoAlbumColumns::ALBUM_CLOUD_ID + " TEXT;";
1206 ret = store.ExecuteSql(addAlbumCloudId);
1207 if (ret != NativeRdb::E_OK) {
1208 MEDIA_ERR_LOG("upgrade fail %{public}d: add ablum cloud id", ret);
1209 }
1210 /* album - add triggers */
1211 ret = store.ExecuteSql(PhotoAlbumColumns::CREATE_ALBUM_INSERT_TRIGGER);
1212 if (ret != NativeRdb::E_OK) {
1213 MEDIA_ERR_LOG("upgrade fail %{public}d: create album insert trigger", ret);
1214 }
1215 ret = store.ExecuteSql(PhotoAlbumColumns::CREATE_ALBUM_MDIRTY_TRIGGER);
1216 if (ret != NativeRdb::E_OK) {
1217 MEDIA_ERR_LOG("upgrade fail %{public}d: create album modify trigger", ret);
1218 }
1219 ret = store.ExecuteSql(PhotoAlbumColumns::CREATE_ALBUM_DELETE_TRIGGER);
1220 if (ret != NativeRdb::E_OK) {
1221 MEDIA_ERR_LOG("upgrade fail %{public}d: create album delete trigger", ret);
1222 }
1223 /* album map - add columns */
1224 const std::string addAlbumMapColumns = "ALTER TABLE " + PhotoMap::TABLE +
1225 " ADD COLUMN " + PhotoMap::DIRTY +" INT DEFAULT " +
1226 to_string(static_cast<int32_t>(DirtyTypes::TYPE_NEW)) + ";";
1227 ret = store.ExecuteSql(addAlbumMapColumns);
1228 if (ret != NativeRdb::E_OK) {
1229 MEDIA_ERR_LOG("upgrade fail %{public}d: add ablum columns", ret);
1230 }
1231 /* album map - add triggers */
1232 ret = store.ExecuteSql(PhotoMap::CREATE_NEW_TRIGGER);
1233 if (ret != NativeRdb::E_OK) {
1234 MEDIA_ERR_LOG("upgrade fail %{public}d: create album map insert trigger", ret);
1235 }
1236 ret = store.ExecuteSql(PhotoMap::CREATE_DELETE_TRIGGER);
1237 if (ret != NativeRdb::E_OK) {
1238 MEDIA_ERR_LOG("upgrade fail %{public}d: create album map delete trigger", ret);
1239 }
1240 }
1241
AddCameraShotKey(RdbStore & store)1242 static void AddCameraShotKey(RdbStore &store)
1243 {
1244 static const string ADD_CAMERA_SHOT_KEY_ON_PHOTOS = "ALTER TABLE " + PhotoColumn::PHOTOS_TABLE +
1245 " ADD COLUMN " + PhotoColumn::CAMERA_SHOT_KEY + " TEXT";
1246 int32_t result = store.ExecuteSql(ADD_CAMERA_SHOT_KEY_ON_PHOTOS);
1247 if (result != NativeRdb::E_OK) {
1248 MEDIA_ERR_LOG("Failed to update PHOTOS");
1249 }
1250 result = store.ExecuteSql(PhotoColumn::INDEX_CAMERA_SHOT_KEY);
1251 if (result != NativeRdb::E_OK) {
1252 MEDIA_ERR_LOG("Failed to create CAMERA_SHOT_KEY index");
1253 }
1254 }
1255
RemoveAlbumCountTrigger(RdbStore & store)1256 void RemoveAlbumCountTrigger(RdbStore &store)
1257 {
1258 const vector<string> removeAlbumCountTriggers = {
1259 BaseColumn::DropTrigger() + "update_user_album_count",
1260 BaseColumn::DropTrigger() + "photo_album_insert_asset",
1261 BaseColumn::DropTrigger() + "photo_album_delete_asset",
1262 };
1263 ExecSqls(removeAlbumCountTriggers, store);
1264 }
1265
AddExifAndUserComment(RdbStore & store)1266 void AddExifAndUserComment(RdbStore &store)
1267 {
1268 const string addUserCommentOnPhotos = "ALTER TABLE " + PhotoColumn::PHOTOS_TABLE +
1269 " ADD COLUMN " + PhotoColumn::PHOTO_USER_COMMENT + " TEXT";
1270
1271 const string addAllExifOnPhotos = "ALTER TABLE " + PhotoColumn::PHOTOS_TABLE +
1272 " ADD COLUMN " + PhotoColumn::PHOTO_ALL_EXIF + " TEXT";
1273
1274 const vector<string> addExifColumns = { addUserCommentOnPhotos, addAllExifOnPhotos };
1275 ExecSqls(addExifColumns, store);
1276 }
1277
OnUpgrade(RdbStore & store,int32_t oldVersion,int32_t newVersion)1278 int32_t MediaLibraryDataCallBack::OnUpgrade(RdbStore &store, int32_t oldVersion, int32_t newVersion)
1279 {
1280 MEDIA_DEBUG_LOG("OnUpgrade old:%d, new:%d", oldVersion, newVersion);
1281 if (oldVersion < VERSION_ADD_CLOUD) {
1282 VersionAddCloud(store);
1283 }
1284
1285 if (oldVersion < VERSION_ADD_META_MODIFED) {
1286 AddMetaModifiedColumn(store);
1287 }
1288
1289 if (oldVersion < VERSION_MODIFY_SYNC_STATUS) {
1290 ModifySyncStatus(store);
1291 }
1292
1293 if (oldVersion < VERSION_ADD_API10_TABLE) {
1294 API10TableCreate(store);
1295 }
1296
1297 if (oldVersion < VERSION_MODIFY_DELETE_TRIGGER) {
1298 ModifyDeleteTrigger(store);
1299 }
1300
1301 if (oldVersion < VERSION_ADD_CLOUD_VERSION) {
1302 AddCloudVersion(store);
1303 }
1304
1305 if (oldVersion < VERSION_UPDATE_CLOUD_PATH) {
1306 UpdateCloudPath(store);
1307 }
1308
1309 if (oldVersion < VERSION_UPDATE_API10_TABLE) {
1310 UpdateAPI10Table(store);
1311 }
1312
1313 if (oldVersion < VERSION_ADD_TABLE_TYPE) {
1314 AddTableType(store);
1315 }
1316
1317 if (oldVersion < VERSION_ADD_PACKAGE_NAME) {
1318 AddPackageNameColumnOnTables(store);
1319 }
1320
1321 if (oldVersion < VERSION_ADD_CLOUD_ALBUM) {
1322 UpdateCloudAlbum(store);
1323 }
1324
1325 if (oldVersion < VERSION_ADD_CAMERA_SHOT_KEY) {
1326 AddCameraShotKey(store);
1327 }
1328 if (oldVersion < VERSION_REMOVE_ALBUM_COUNT_TRIGGER) {
1329 RemoveAlbumCountTrigger(store);
1330 }
1331
1332 if (oldVersion < VERSION_ADD_ALL_EXIF) {
1333 AddExifAndUserComment(store);
1334 }
1335
1336 return NativeRdb::E_OK;
1337 }
1338
1339 #ifdef DISTRIBUTED
MediaLibraryRdbStoreObserver(const string & bundleName)1340 MediaLibraryRdbStoreObserver::MediaLibraryRdbStoreObserver(const string &bundleName)
1341 {
1342 bundleName_ = bundleName;
1343 isNotifyDeviceChange_ = false;
1344
1345 if (timer_ == nullptr) {
1346 timer_ = make_unique<OHOS::Utils::Timer>(bundleName_);
1347 timerId_ = timer_->Register(bind(&MediaLibraryRdbStoreObserver::NotifyDeviceChange, this),
1348 NOTIFY_TIME_INTERVAL);
1349 timer_->Setup();
1350 }
1351 }
1352
~MediaLibraryRdbStoreObserver()1353 MediaLibraryRdbStoreObserver::~MediaLibraryRdbStoreObserver()
1354 {
1355 if (timer_ != nullptr) {
1356 timer_->Shutdown();
1357 timer_->Unregister(timerId_);
1358 timer_ = nullptr;
1359 }
1360 }
1361
OnChange(const vector<string> & devices)1362 void MediaLibraryRdbStoreObserver::OnChange(const vector<string> &devices)
1363 {
1364 MEDIA_INFO_LOG("MediaLibraryRdbStoreObserver OnChange call");
1365 if (devices.empty() || bundleName_.empty()) {
1366 return;
1367 }
1368 MediaLibraryDevice::GetInstance()->NotifyRemoteFileChange();
1369 }
1370
NotifyDeviceChange()1371 void MediaLibraryRdbStoreObserver::NotifyDeviceChange()
1372 {
1373 if (isNotifyDeviceChange_) {
1374 MediaLibraryDevice::GetInstance()->NotifyDeviceChange();
1375 isNotifyDeviceChange_ = false;
1376 }
1377 }
1378 #endif
1379
TransactionOperations()1380 TransactionOperations::TransactionOperations()
1381 {
1382 rdbStore_ = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
1383 }
1384
~TransactionOperations()1385 TransactionOperations::~TransactionOperations()
1386 {
1387 if (isStart && !isFinish) {
1388 TransactionRollback();
1389 }
1390 }
1391
Start()1392 int32_t TransactionOperations::Start()
1393 {
1394 if (isStart || isFinish) {
1395 return E_OK;
1396 }
1397 int32_t errCode = BeginTransaction();
1398 if (errCode == NativeRdb::E_OK) {
1399 isStart = true;
1400 }
1401 return errCode;
1402 }
1403
Finish()1404 void TransactionOperations::Finish()
1405 {
1406 if (!isStart) {
1407 return;
1408 }
1409 if (!isFinish) {
1410 int32_t ret = TransactionCommit();
1411 if (ret == E_OK) {
1412 isFinish = true;
1413 } else {
1414 MEDIA_ERR_LOG("Failed to commit transaction, errCode=%{public}d", ret);
1415 }
1416 }
1417 }
1418
BeginTransaction()1419 int32_t TransactionOperations::BeginTransaction()
1420 {
1421 if (rdbStore_ == nullptr) {
1422 return E_HAS_DB_ERROR;
1423 }
1424 return rdbStore_->BeginTransaction();
1425 }
1426
TransactionCommit()1427 int32_t TransactionOperations::TransactionCommit()
1428 {
1429 if (rdbStore_ == nullptr) {
1430 return E_HAS_DB_ERROR;
1431 }
1432 return rdbStore_->Commit();
1433 }
1434
TransactionRollback()1435 int32_t TransactionOperations::TransactionRollback()
1436 {
1437 if (rdbStore_ == nullptr) {
1438 return E_HAS_DB_ERROR;
1439 }
1440 return rdbStore_->RollBack();
1441 }
1442 } // namespace OHOS::Media
1443