• 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 #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