1 /*
2 * Copyright (C) 2023 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 "PhotoMapOperation"
16
17 #include "photo_map_operations.h"
18
19 #include "media_column.h"
20 #include "media_file_uri.h"
21 #include "media_file_utils.h"
22 #include "medialibrary_album_operations.h"
23 #include "medialibrary_db_const.h"
24 #include "medialibrary_errno.h"
25 #include "medialibrary_notify.h"
26 #include "medialibrary_rdbstore.h"
27 #include "medialibrary_unistore_manager.h"
28 #include "medialibrary_asset_operations.h"
29 #include "photo_album_column.h"
30 #include "photo_map_column.h"
31 #include "value_object.h"
32
33 namespace OHOS::Media {
34 using namespace std;
35 using namespace OHOS::NativeRdb;
36 using namespace OHOS::DataShare;
37
AddSingleAsset(const DataShareValuesBucket & value)38 int32_t PhotoMapOperations::AddSingleAsset(const DataShareValuesBucket &value)
39 {
40 /**
41 * Build insert sql:
42 * INSERT INTO PhotoMap (map_album, map_asset) SELECT
43 * ?, ?
44 * WHERE
45 * (NOT EXISTS (SELECT * FROM PhotoMap WHERE map_album = ? AND map_asset = ?))
46 * AND (EXISTS (SELECT file_id FROM Files WHERE file_id = ?))
47 * AND (EXISTS (SELECT album_id FROM PhotoAlbum WHERE album_id = ? AND album_type = ? AND album_subtype = ?));
48 */
49 static const string INSERT_MAP_SQL = "INSERT INTO " + PhotoMap::TABLE +
50 " (" + PhotoMap::ALBUM_ID + ", " + PhotoMap::ASSET_ID + ") " +
51 "SELECT ?, ? WHERE " +
52 "(NOT EXISTS (SELECT * FROM " + PhotoMap::TABLE + " WHERE " +
53 PhotoMap::ALBUM_ID + " = ? AND " + PhotoMap::ASSET_ID + " = ?)) " +
54 "AND (EXISTS (SELECT " + MediaColumn::MEDIA_ID + " FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
55 MediaColumn::MEDIA_ID + " = ?)) " +
56 "AND (EXISTS (SELECT " + PhotoAlbumColumns::ALBUM_ID + " FROM " + PhotoAlbumColumns::TABLE +
57 " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = ? AND " + PhotoAlbumColumns::ALBUM_TYPE + " = ? AND " +
58 PhotoAlbumColumns::ALBUM_SUBTYPE + " = ?));";
59 bool isValid = false;
60 int32_t albumId = value.Get(PhotoMap::ALBUM_ID, isValid);
61 if (!isValid) {
62 return -EINVAL;
63 }
64 string assetUri = value.Get(PhotoMap::ASSET_ID, isValid);
65 if (!isValid) {
66 return -EINVAL;
67 }
68
69 string assetId = MediaFileUri::GetPhotoId(assetUri);
70 if (assetId.empty()) {
71 return -EINVAL;
72 }
73 vector<ValueObject> bindArgs;
74 bindArgs.emplace_back(albumId);
75 bindArgs.emplace_back(assetId);
76 bindArgs.emplace_back(albumId);
77 bindArgs.emplace_back(assetId);
78 bindArgs.emplace_back(assetId);
79 bindArgs.emplace_back(albumId);
80 bindArgs.emplace_back(PhotoAlbumType::USER);
81 bindArgs.emplace_back(PhotoAlbumSubType::USER_GENERIC);
82 int errCode = MediaLibraryRdbStore::ExecuteForLastInsertedRowId(INSERT_MAP_SQL, bindArgs);
83 auto watch = MediaLibraryNotify::GetInstance();
84 if (errCode > 0) {
85 watch->Notify(MediaFileUtils::Encode(assetUri), NotifyType::NOTIFY_ALBUM_ADD_ASSERT, albumId);
86 }
87 return errCode;
88 }
89
AddPhotoAssets(const vector<DataShareValuesBucket> & values)90 int32_t PhotoMapOperations::AddPhotoAssets(const vector<DataShareValuesBucket> &values)
91 {
92 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStoreRaw();
93 if (rdbStore == nullptr) {
94 return E_HAS_DB_ERROR;
95 }
96
97 int32_t changedRows = 0;
98 rdbStore->BeginTransaction();
99 for (const auto &value : values) {
100 auto ret = AddSingleAsset(value);
101 if (ret == E_HAS_DB_ERROR) {
102 rdbStore->RollBack();
103 return ret;
104 }
105 if (ret > 0) {
106 changedRows++;
107 }
108 }
109 rdbStore->Commit();
110 if (!values.empty()) {
111 bool isValid = false;
112 int32_t albumId = values[0].Get(PhotoMap::ALBUM_ID, isValid);
113 if (!isValid) {
114 MEDIA_WARN_LOG("Ignore failure on get album id, album updation possibly would be lost");
115 return changedRows;
116 }
117 MediaLibraryAlbumOperations::UpdateUserAlbumInternal({ to_string(albumId) });
118 }
119
120 return changedRows;
121 }
122
RemovePhotoAssets(RdbPredicates & predicates)123 int32_t PhotoMapOperations::RemovePhotoAssets(RdbPredicates &predicates)
124 {
125 vector<string> whereArgs = predicates.GetWhereArgs();
126 MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
127 int deleteRow = MediaLibraryRdbStore::Delete(predicates);
128 if (deleteRow <= 0) {
129 return deleteRow;
130 }
131
132 string strAlbumId = predicates.GetWhereArgs()[0];
133 if (strAlbumId.empty()) {
134 MEDIA_ERR_LOG("Failed to get albumId");
135 return deleteRow;
136 }
137 int32_t albumId = atoi(strAlbumId.c_str());
138
139 auto watch = MediaLibraryNotify::GetInstance();
140 for (size_t i = 1; i < whereArgs.size(); i++) {
141 watch->Notify(MediaFileUtils::Encode(whereArgs[i]), NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, albumId);
142 }
143 MediaLibraryAlbumOperations::UpdateUserAlbumInternal({ strAlbumId });
144 return deleteRow;
145 }
146
QueryPhotoAssets(const RdbPredicates & rdbPredicate,const vector<string> & columns)147 shared_ptr<ResultSet> PhotoMapOperations::QueryPhotoAssets(const RdbPredicates &rdbPredicate,
148 const vector<string> &columns)
149 {
150 return MediaLibraryRdbStore::Query(rdbPredicate, columns);
151 }
152 } // namespace OHOS::Media