1 /*
2 * Copyright (C) 2024-2024 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 "AnalysisAlbumOperation"
16
17 #include "medialibrary_analysis_album_operations.h"
18
19 #include <cstddef>
20 #include <cstdio>
21 #include <cstring>
22 #include <algorithm>
23
24 #include "media_log.h"
25 #include "medialibrary_db_const.h"
26 #include "medialibrary_errno.h"
27 #include "medialibrary_notify.h"
28 #include "medialibrary_object_utils.h"
29 #include "medialibrary_unistore_manager.h"
30 #include "medialibrary_data_manager.h"
31 #include "medialibrary_rdb_transaction.h"
32 #include "media_file_uri.h"
33 #include "media_file_utils.h"
34 #include "result_set_utils.h"
35 #include "values_bucket.h"
36 #include "photo_album_column.h"
37 #include "photo_map_column.h"
38 #include "vision_album_column.h"
39 #include "vision_face_tag_column.h"
40 #include "vision_image_face_column.h"
41 #include "vision_photo_map_column.h"
42 #include "vision_total_column.h"
43
44 using namespace std;
45 using namespace OHOS::NativeRdb;
46 using namespace OHOS::DataShare;
47 using namespace OHOS::RdbDataShareAdapter;
48
49 namespace OHOS::Media {
50 constexpr int32_t E_INDEX = -1;
51 constexpr int32_t ALBUM_IS_ME = 1;
52 constexpr int32_t ALBUM_IS_NOT_ME = 0;
53 constexpr int32_t ALBUM_IS_REMOVED = 1;
54 constexpr int32_t SINGLE_FACE = 1;
55 constexpr int32_t LOCAL_ALBUM = 1;
56 constexpr int32_t ALBUM_NOT_FOUND = 0;
57 constexpr int32_t QUERY_GROUP_PHOTO_ALBUM_RELATED_TO_ME = 1;
58 const string GROUP_PHOTO_TAG = "group_photo_tag";
59 const string GROUP_PHOTO_IS_ME = "group_photo_is_me";
60 const string GROUP_PHOTO_ALBUM_NAME = "album_name";
61 static std::mutex updateGroupPhotoAlbumMutex;
62
ExecSqls(const vector<string> & sqls,const shared_ptr<MediaLibraryUnistore> & store)63 static int32_t ExecSqls(const vector<string> &sqls, const shared_ptr<MediaLibraryUnistore> &store)
64 {
65 int32_t err = NativeRdb::E_OK;
66 for (const auto &sql : sqls) {
67 err = store->ExecuteSql(sql);
68 if (err != NativeRdb::E_OK) {
69 MEDIA_ERR_LOG("Failed to exec: %{private}s", sql.c_str());
70 break;
71 }
72 }
73 return err;
74 }
75
GetArgsValueByName(const string & valueName,const string & whereClause,const vector<string> & whereArgs)76 static int32_t GetArgsValueByName(const string &valueName, const string &whereClause, const vector<string> &whereArgs)
77 {
78 size_t pos = whereClause.find(valueName);
79 if (pos == string::npos) {
80 MEDIA_ERR_LOG("whereClause is invalid");
81 return E_INDEX;
82 }
83 size_t argsIndex = 0;
84 for (size_t i = 0; i < pos; i++) {
85 if (whereClause[i] == '?') {
86 argsIndex++;
87 }
88 }
89 if (argsIndex > whereArgs.size() - 1) {
90 MEDIA_ERR_LOG("whereArgs is invalid");
91 return E_INDEX;
92 }
93 return atoi(whereArgs[argsIndex].c_str());
94 }
95
GetAlbumId(const string & whereClause,const vector<string> & whereArgs)96 static int32_t GetAlbumId(const string &whereClause, const vector<string> &whereArgs)
97 {
98 size_t pos = whereClause.find(PhotoAlbumColumns::ALBUM_ID);
99 if (pos == string::npos) {
100 MEDIA_ERR_LOG("whereClause is invalid");
101 return E_INDEX;
102 }
103 size_t argsIndex = 0;
104 for (size_t i = 0; i < pos; i++) {
105 if (whereClause[i] == '?') {
106 argsIndex++;
107 }
108 }
109 if (argsIndex > whereArgs.size() - 1) {
110 MEDIA_ERR_LOG("whereArgs is invalid");
111 return E_INDEX;
112 }
113 auto albumId = whereArgs[argsIndex];
114 if (MediaLibraryDataManagerUtils::IsNumber(albumId)) {
115 return atoi(albumId.c_str());
116 }
117 return E_INDEX;
118 }
119
GetIntValueFromResultSet(shared_ptr<NativeRdb::ResultSet> resultSet,const string & column,int & value)120 static int32_t GetIntValueFromResultSet(shared_ptr<NativeRdb::ResultSet> resultSet, const string &column, int &value)
121 {
122 int index = E_INDEX;
123 resultSet->GetColumnIndex(column, index);
124 if (index == E_INDEX) {
125 return E_HAS_DB_ERROR;
126 }
127 if (resultSet->GetInt(index, value) != NativeRdb::E_OK) {
128 return E_HAS_DB_ERROR;
129 }
130 return E_OK;
131 }
132
GetStringValueFromResultSet(shared_ptr<NativeRdb::ResultSet> resultSet,const string & column,string & value)133 static int32_t GetStringValueFromResultSet(shared_ptr<NativeRdb::ResultSet> resultSet, const string &column,
134 string &value)
135 {
136 if (resultSet == nullptr) {
137 return E_HAS_DB_ERROR;
138 }
139 int index = E_INDEX;
140 resultSet->GetColumnIndex(column, index);
141 if (index == E_INDEX) {
142 return E_HAS_DB_ERROR;
143 }
144 if (resultSet->GetString(index, value) != NativeRdb::E_OK) {
145 return E_HAS_DB_ERROR;
146 }
147 return E_OK;
148 }
149
GetCoverUri(int32_t fileId,const string & path,const string & displayName)150 static string GetCoverUri(int32_t fileId, const string &path, const string &displayName)
151 {
152 string fileName;
153 size_t lastSlash = path.find_last_of('/');
154 if (lastSlash != string::npos && path.size() > (lastSlash + 1)) {
155 fileName = path.substr(lastSlash + 1);
156 }
157 string fileTitle = fileName;
158 size_t lastDot = fileName.find_last_of('.');
159 if (lastDot != string::npos) {
160 fileTitle = fileName.substr(0, lastDot);
161 }
162 return PhotoColumn::PHOTO_URI_PREFIX + to_string(fileId) + "/" + fileTitle + "/" + displayName;
163 }
164
GetStringObject(const ValuesBucket & values,const string & key,string & value)165 inline int32_t GetStringObject(const ValuesBucket &values, const string &key, string &value)
166 {
167 value = "";
168 ValueObject valueObject;
169 if (values.GetObject(key, valueObject)) {
170 valueObject.GetString(value);
171 } else {
172 return -EINVAL;
173 }
174 return E_OK;
175 }
176
NotifyGroupAlbum(const vector<int32_t> & changedAlbumIds)177 static void NotifyGroupAlbum(const vector<int32_t> &changedAlbumIds)
178 {
179 if (changedAlbumIds.size() <= 0) {
180 return;
181 }
182 auto watch = MediaLibraryNotify::GetInstance();
183 for (int32_t albumId : changedAlbumIds) {
184 watch->Notify(MediaFileUtils::GetUriByExtrConditions(
185 PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX, to_string(albumId)), NotifyType::NOTIFY_UPDATE);
186 }
187 }
188
ClearEmptyGroupPhotoAlbumInfo(const vector<GroupPhotoAlbumInfo> & clearAlbums)189 static void ClearEmptyGroupPhotoAlbumInfo(const vector<GroupPhotoAlbumInfo> &clearAlbums)
190 {
191 if (clearAlbums.empty()) {
192 return;
193 }
194 ValuesBucket values;
195 values.PutInt(PhotoAlbumColumns::ALBUM_COUNT, 0);
196 values.PutString(PhotoAlbumColumns::ALBUM_COVER_URI, "");
197 values.PutInt(IS_COVER_SATISFIED, static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING));
198 values.PutInt(IS_ME, ALBUM_IS_NOT_ME);
199
200 RdbPredicates rdbPredicates(ANALYSIS_ALBUM_TABLE);
201 stringstream ss;
202 for (size_t i = 0; i < clearAlbums.size(); i++) {
203 ss << clearAlbums[i].albumId;
204 if (i != clearAlbums.size() - 1) {
205 ss << ", ";
206 }
207 }
208 string clause = PhotoAlbumColumns::ALBUM_ID + " IN (" + ss.str() + ") AND ";
209 rdbPredicates.SetWhereClause(clause);
210 rdbPredicates.EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::SMART));
211 rdbPredicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::GROUP_PHOTO));
212 auto ret = MediaLibraryRdbStore::UpdateWithDateTime(values, rdbPredicates);
213 if (ret != NativeRdb::E_OK) {
214 MEDIA_ERR_LOG("Clear empty group photo album info failed! Error: %{public}d", ret);
215 }
216 }
217
BuildUpdateGroupPhotoAlbumSql(const GroupPhotoAlbumInfo & albumInfo)218 static string BuildUpdateGroupPhotoAlbumSql(const GroupPhotoAlbumInfo &albumInfo)
219 {
220 string withSql;
221 string coverUriValueSql;
222 string isCoverSatisfiedValueSql;
223 if (albumInfo.isCoverSatisfied == static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING)) {
224 coverUriValueSql = "'" + albumInfo.candidateUri + "'";
225 isCoverSatisfiedValueSql = to_string(static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING));
226 } else {
227 string oldCoverId = MediaFileUri::GetPhotoId(albumInfo.coverUri);
228 if (!oldCoverId.empty() && MediaLibraryDataManagerUtils::IsNumber(oldCoverId)) {
229 withSql = "WITH temp_table AS (SELECT COUNT(1) > 0 AS is_cover_exist FROM " + ANALYSIS_ALBUM_TABLE +
230 " INNER JOIN " + ANALYSIS_PHOTO_MAP_TABLE + " ON " +
231 MAP_ALBUM + " = " + ALBUM_ID + " AND INSTR('" + albumInfo.tagId + "', " + GROUP_TAG + ") > 0" +
232 " INNER JOIN " + VISION_IMAGE_FACE_TABLE + " F ON " +
233 MAP_ASSET + " = F." + MediaColumn::MEDIA_ID +
234 " INNER JOIN " + PhotoColumn::PHOTOS_TABLE + " P ON " +
235 MAP_ASSET + " = P." + MediaColumn::MEDIA_ID + " AND " +
236 MediaColumn::MEDIA_DATE_TRASHED + " = 0 AND " +
237 MediaColumn::MEDIA_HIDDEN + " = 0 AND " +
238 MediaColumn::MEDIA_TIME_PENDING + " = 0 AND P." +
239 MediaColumn::MEDIA_ID + " = " + oldCoverId + ")";
240 coverUriValueSql = "CASE (SELECT is_cover_exist FROM temp_table) WHEN 1 THEN '" + albumInfo.coverUri +
241 "' ELSE '" + albumInfo.candidateUri + "' END";
242 isCoverSatisfiedValueSql = "CASE (SELECT is_cover_exist FROM temp_table) WHEN 1 THEN " +
243 to_string(albumInfo.isCoverSatisfied) + " ELSE " +
244 to_string(static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING)) + " END";
245 } else {
246 coverUriValueSql = "'" + albumInfo.candidateUri + "'";
247 isCoverSatisfiedValueSql = to_string(static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING));
248 }
249 }
250 string albumNameArg = "";
251 if (!albumInfo.albumName.empty()) {
252 albumNameArg = ", " + GROUP_PHOTO_ALBUM_NAME + " = '" + albumInfo.albumName + "'";
253 }
254 string updateSql = withSql + " UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " +
255 PhotoAlbumColumns::ALBUM_COUNT + " = " + to_string(albumInfo.count) + ", " +
256 IS_ME + " = " + to_string(albumInfo.isMe) + ", " +
257 PhotoAlbumColumns::ALBUM_COVER_URI + " = " + coverUriValueSql + ", " +
258 IS_REMOVED + " = " + to_string(albumInfo.isRemoved) + ", " +
259 RENAME_OPERATION + " = " + to_string(albumInfo.renameOperation) + ", " +
260 IS_COVER_SATISFIED + " = " + isCoverSatisfiedValueSql + albumNameArg +
261 " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumInfo.albumId) + ";";
262 return updateSql;
263 }
264
UpdateGroupPhotoAlbumInfo(const vector<GroupPhotoAlbumInfo> & updateAlbums)265 static void UpdateGroupPhotoAlbumInfo(const vector<GroupPhotoAlbumInfo> &updateAlbums)
266 {
267 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
268 if (rdbStore == nullptr) {
269 MEDIA_ERR_LOG("Update group photo album info failed. rdbStore is null");
270 return;
271 }
272 auto rdbStorePtr = rdbStore;
273 if (rdbStorePtr == nullptr) {
274 MEDIA_ERR_LOG("Update group photo album info failed. rdbStorePtr is null");
275 return;
276 }
277 for (auto album : updateAlbums) {
278 string sql = BuildUpdateGroupPhotoAlbumSql(album);
279 auto ret = rdbStorePtr->ExecuteSql(sql);
280 if (ret != NativeRdb::E_OK) {
281 MEDIA_ERR_LOG("Update group photo album failed! Error: %{public}d", ret);
282 }
283 }
284 }
285
InsertGroupPhotoAlbumInfo(const vector<GroupPhotoAlbumInfo> & insertAlbums,vector<int32_t> & insertAlbumsId)286 static void InsertGroupPhotoAlbumInfo(const vector<GroupPhotoAlbumInfo> &insertAlbums, vector<int32_t> &insertAlbumsId)
287 {
288 if (insertAlbums.empty()) {
289 return;
290 }
291 vector<DataShare::DataShareValuesBucket> insertValues;
292 for (auto album : insertAlbums) {
293 DataShare::DataShareValuesBucket values;
294 values.Put(PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumType::SMART);
295 values.Put(PhotoAlbumColumns::ALBUM_SUBTYPE, PhotoAlbumSubType::GROUP_PHOTO);
296 values.Put(PhotoAlbumColumns::ALBUM_COVER_URI, album.candidateUri);
297 values.Put(PhotoAlbumColumns::ALBUM_COUNT, album.count);
298 values.Put(TAG_ID, album.tagId);
299 values.Put(GROUP_TAG, album.tagId);
300 values.Put(IS_ME, album.isMe);
301 values.Put(IS_LOCAL, LOCAL_ALBUM);
302 values.Put(IS_COVER_SATISFIED, static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING));
303 insertValues.push_back(values);
304 }
305 Uri uri(PAH_INSERT_ANA_PHOTO_ALBUM);
306 MediaLibraryCommand cmd(uri);
307 auto ret = MediaLibraryDataManager::GetInstance()->BatchInsert(cmd, insertValues);
308 if (ret >= 0) {
309 MEDIA_INFO_LOG("Insert %{public}d group photo album info.", ret);
310 RdbPredicates rdbPredicates(ANALYSIS_ALBUM_TABLE);
311 rdbPredicates.SetWhereClause(PhotoAlbumColumns::ALBUM_SUBTYPE + " = ?");
312 rdbPredicates.SetWhereArgs({ to_string(PhotoAlbumSubType::GROUP_PHOTO) });
313 rdbPredicates.OrderByDesc(PhotoAlbumColumns::ALBUM_ID);
314 std::vector<std::string> columns = { PhotoAlbumColumns::ALBUM_ID };
315 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rdbPredicates, columns);
316 if (resultSet == nullptr) {
317 return;
318 }
319 for (auto i = 0; i < ret; i++) {
320 resultSet->GoTo(i);
321 insertAlbumsId.push_back(GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet));
322 }
323 } else {
324 MEDIA_ERR_LOG("Insert group photo album info failed! Error: %{public}d.", ret);
325 }
326 }
327
GetGroupPhotoAlbumSql()328 static string GetGroupPhotoAlbumSql()
329 {
330 string innerJoinAnalysisAlbum = "INNER JOIN " + ANALYSIS_ALBUM_TABLE + " AA ON F." +
331 TAG_ID + " = AA." + TAG_ID + " AND " + TOTAL_FACES + " > " + to_string(SINGLE_FACE) +
332 " AND (" + ALBUM_NAME + " IS NOT NULL OR " + IS_ME + " = " + to_string(ALBUM_IS_ME) + ")";
333 string innerJoinAnalysisPhotoMap = "INNER JOIN " + ANALYSIS_PHOTO_MAP_TABLE + " ON " +
334 MAP_ALBUM + " = AA." + PhotoAlbumColumns::ALBUM_ID + " AND " +
335 MAP_ASSET + " = F." + MediaColumn::MEDIA_ID;
336 string innerJoinPhotos = "INNER JOIN " + PhotoColumn::PHOTOS_TABLE + " P ON F." +
337 MediaColumn::MEDIA_ID + " = P." + MediaColumn::MEDIA_ID + " AND " +
338 MediaColumn::MEDIA_DATE_TRASHED + " = 0 AND " +
339 MediaColumn::MEDIA_HIDDEN + " = 0 AND " +
340 MediaColumn::MEDIA_TIME_PENDING + " = 0";
341 string innerSql = "SELECT F." + MediaColumn::MEDIA_ID + ", " + MediaColumn::MEDIA_FILE_PATH + ", " +
342 MediaColumn::MEDIA_NAME + ", " + MediaColumn::MEDIA_DATE_ADDED + ", " +
343 TOTAL_FACES + ", " + GROUP_TAG + ", " + IS_ME + " FROM " + VISION_IMAGE_FACE_TABLE + " F " +
344 innerJoinAnalysisAlbum + " " + innerJoinAnalysisPhotoMap + " " + innerJoinPhotos +
345 " ORDER BY F." + MediaColumn::MEDIA_ID + ", " + GROUP_TAG;
346 string queryGroupPhotoIsMe = "CASE WHEN MAX(" + IS_ME + ") = " + to_string(ALBUM_IS_ME) + " THEN " +
347 to_string(ALBUM_IS_ME) + " ELSE " + to_string(ALBUM_IS_NOT_ME) + " END AS " + GROUP_PHOTO_IS_ME;
348 string groupPhotoTagSql = "SELECT " + MediaColumn::MEDIA_ID + ", " + MediaColumn::MEDIA_FILE_PATH + ", " +
349 MediaColumn::MEDIA_NAME + ", " + MediaColumn::MEDIA_DATE_ADDED + ", " + queryGroupPhotoIsMe +
350 ", GROUP_CONCAT(DISTINCT " + GROUP_TAG + ") AS " + GROUP_PHOTO_TAG +
351 " FROM (" + innerSql + ") GROUP BY " + MediaColumn::MEDIA_ID +
352 " HAVING COUNT(" + GROUP_TAG +") = " + TOTAL_FACES + " AND COUNT(DISTINCT " + GROUP_TAG + ") > " +
353 to_string(SINGLE_FACE);
354 string leftJoinAnalysisAlbum = "LEFT JOIN " + ANALYSIS_ALBUM_TABLE + " AA ON " +
355 GROUP_PHOTO_TAG + " = AA." + TAG_ID + " AND AA." + ALBUM_SUBTYPE + " = " +
356 to_string(PhotoAlbumSubType::GROUP_PHOTO);
357 string fullSql = "SELECT " + GROUP_PHOTO_TAG + ", " + PhotoAlbumColumns::ALBUM_ID + ", " +
358 PhotoAlbumColumns::ALBUM_COVER_URI + ", " + IS_COVER_SATISFIED + ", " +
359 MediaColumn::MEDIA_ID + ", " + MediaColumn::MEDIA_FILE_PATH + ", " + MediaColumn::MEDIA_NAME + ", " +
360 GROUP_PHOTO_ALBUM_NAME + ", " + IS_REMOVED + ", " + RENAME_OPERATION + ", " +
361 "COUNT (DISTINCT " + MediaColumn::MEDIA_ID + ") AS " + PhotoAlbumColumns::ALBUM_COUNT + ", " +
362 GROUP_PHOTO_IS_ME + ", " + "MAX(" + MediaColumn::MEDIA_DATE_ADDED + ") FROM (" + groupPhotoTagSql + ") " +
363 leftJoinAnalysisAlbum + " GROUP BY " + GROUP_PHOTO_TAG + ";";
364 return fullSql;
365 }
366
CheckGroupPhotoAlbumInfo(const GroupPhotoAlbumInfo & info,const GroupPhotoAlbumInfo & lastInfo)367 static bool CheckGroupPhotoAlbumInfo(const GroupPhotoAlbumInfo &info, const GroupPhotoAlbumInfo &lastInfo)
368 {
369 bool hasUpdated = ((info.albumName.compare(lastInfo.albumName) != 0) ||
370 (info.coverUri.compare(lastInfo.coverUri) != 0) ||
371 (info.count != lastInfo.count) ||
372 (info.isMe != lastInfo.isMe) ||
373 (info.isRemoved != lastInfo.isRemoved) ||
374 (info.renameOperation != lastInfo.renameOperation) ||
375 (info.isCoverSatisfied != lastInfo.isCoverSatisfied));
376 return hasUpdated;
377 }
378
AssemblyInfo(shared_ptr<NativeRdb::ResultSet> resultSet)379 static GroupPhotoAlbumInfo AssemblyInfo(shared_ptr<NativeRdb::ResultSet> resultSet)
380 {
381 string tagId = GetStringVal(GROUP_PHOTO_TAG, resultSet);
382 int32_t isCoverSatisfied = GetInt32Val(IS_COVER_SATISFIED, resultSet);
383 int32_t count = GetInt32Val(PhotoAlbumColumns::ALBUM_COUNT, resultSet);
384 int32_t isMe = GetInt32Val(GROUP_PHOTO_IS_ME, resultSet);
385 int32_t albumId = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
386 string coverUri = GetStringVal(PhotoAlbumColumns::ALBUM_COVER_URI, resultSet);
387 int32_t fileId = GetInt32Val(MediaColumn::MEDIA_ID, resultSet);
388 string path = GetStringVal(MediaColumn::MEDIA_FILE_PATH, resultSet);
389 string displayName = GetStringVal(MediaColumn::MEDIA_NAME, resultSet);
390 string candidateUri = GetCoverUri(fileId, path, displayName);
391 string albumName = GetStringVal(GROUP_PHOTO_ALBUM_NAME, resultSet);
392 int32_t isRemoved = GetInt32Val(IS_REMOVED, resultSet);
393 int32_t renameOperation = GetInt32Val(RENAME_OPERATION, resultSet);
394 GroupPhotoAlbumInfo info {albumId, tagId, coverUri, isCoverSatisfied, count, fileId, candidateUri, isMe,
395 albumName, isRemoved, renameOperation};
396 return info;
397 }
398
GetAnalysisAlbumInfo()399 static std::map<int32_t, GroupPhotoAlbumInfo> GetAnalysisAlbumInfo()
400 {
401 std::map<int32_t, GroupPhotoAlbumInfo> lastResultMap;
402 const string queryAnalysisAlbumSql = "SELECT * FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
403 PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(PhotoAlbumType::SMART) + " AND " +
404 PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(PhotoAlbumSubType::GROUP_PHOTO);
405 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
406 if (rdbStore == nullptr) {
407 MEDIA_ERR_LOG("Get AnalysisAlbum failed. rdbStore is null");
408 return lastResultMap;
409 }
410 auto rdbStorePtr = rdbStore;
411 if (rdbStorePtr == nullptr) {
412 MEDIA_ERR_LOG("Get AnalysisAlbum failed. rdbStorePtr is null");
413 return lastResultMap;
414 }
415 auto resultSet = rdbStorePtr->QuerySql(queryAnalysisAlbumSql);
416 if (resultSet == nullptr) {
417 MEDIA_ERR_LOG("Get AnalysisAlbum failed, query resultSet is null.");
418 return lastResultMap;
419 }
420 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
421 int32_t albumId = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
422 lastResultMap[albumId].albumId = albumId;
423 lastResultMap[albumId].albumName = GetStringVal(GROUP_PHOTO_ALBUM_NAME, resultSet);
424 lastResultMap[albumId].coverUri = GetStringVal(PhotoAlbumColumns::ALBUM_COVER_URI, resultSet);
425 lastResultMap[albumId].count = GetInt32Val(PhotoAlbumColumns::ALBUM_COUNT, resultSet);
426 lastResultMap[albumId].isMe = GetInt32Val(IS_ME, resultSet);
427 lastResultMap[albumId].isRemoved = GetInt32Val(IS_REMOVED, resultSet);
428 lastResultMap[albumId].renameOperation = GetInt32Val(RENAME_OPERATION, resultSet);
429 lastResultMap[albumId].isCoverSatisfied = GetInt32Val(IS_COVER_SATISFIED, resultSet);
430 }
431 return lastResultMap;
432 }
433
UpdateGroupPhotoAlbum(vector<GroupPhotoAlbumInfo> & updateAlbums,vector<GroupPhotoAlbumInfo> & insertAlbums,vector<GroupPhotoAlbumInfo> & clearAlbums,vector<int32_t> & insertAlbumsId)434 static bool UpdateGroupPhotoAlbum(vector<GroupPhotoAlbumInfo> &updateAlbums, vector<GroupPhotoAlbumInfo> &insertAlbums,
435 vector<GroupPhotoAlbumInfo> &clearAlbums, vector<int32_t> &insertAlbumsId)
436 {
437 auto lastResultMap = GetAnalysisAlbumInfo();
438 const string querySql = GetGroupPhotoAlbumSql();
439 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
440 if (rdbStore == nullptr) {
441 MEDIA_ERR_LOG("Update group photo album failed. rdbStore is null");
442 return false;
443 }
444 auto rdbStorePtr = rdbStore;
445 if (rdbStorePtr == nullptr) {
446 MEDIA_ERR_LOG("Update group photo album failed. rdbStorePtr is null");
447 return false;
448 }
449 auto resultSet = rdbStorePtr->QuerySql(querySql);
450 if (resultSet == nullptr) {
451 MEDIA_ERR_LOG("Update group photo album failed, query resultSet is null.");
452 return false;
453 }
454
455 bool hasUpdated = false;
456 while (resultSet->GoToNextRow() == E_OK) {
457 int32_t albumId = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
458 auto info = AssemblyInfo(resultSet);
459 if (albumId == ALBUM_NOT_FOUND) {
460 insertAlbums.push_back(info);
461 hasUpdated = true;
462 } else {
463 if (CheckGroupPhotoAlbumInfo(info, lastResultMap[albumId])) {
464 hasUpdated = true;
465 updateAlbums.push_back(info);
466 }
467 lastResultMap.erase(albumId);
468 }
469 }
470
471 UpdateGroupPhotoAlbumInfo(updateAlbums);
472 InsertGroupPhotoAlbumInfo(insertAlbums, insertAlbumsId);
473 if (lastResultMap.size() > 0) {
474 hasUpdated = true;
475 for (auto iter = lastResultMap.begin(); iter != lastResultMap.end(); ++iter) {
476 clearAlbums.push_back(iter->second);
477 }
478 ClearEmptyGroupPhotoAlbumInfo(clearAlbums);
479 }
480 return hasUpdated;
481 }
482
UpdateGroupPhotoAlbumAsync(AsyncTaskData * data)483 static void UpdateGroupPhotoAlbumAsync(AsyncTaskData *data)
484 {
485 lock_guard<mutex> lock(updateGroupPhotoAlbumMutex);
486 vector<GroupPhotoAlbumInfo> updateAlbums;
487 vector<GroupPhotoAlbumInfo> insertAlbums;
488 vector<GroupPhotoAlbumInfo> clearAlbums;
489 vector<int32_t> insertAlbumsId;
490 bool hasUpdated = UpdateGroupPhotoAlbum(updateAlbums, insertAlbums, clearAlbums, insertAlbumsId);
491 if (hasUpdated) {
492 vector<int32_t> changeAlbumIds {};
493 for (auto info : updateAlbums) {
494 changeAlbumIds.push_back(info.albumId);
495 }
496 for (auto albumId : insertAlbumsId) {
497 changeAlbumIds.push_back(albumId);
498 }
499 for (auto info : clearAlbums) {
500 changeAlbumIds.push_back(info.albumId);
501 }
502 NotifyGroupAlbum(changeAlbumIds);
503 }
504 }
505
QueryGroupPhotoAlbum(MediaLibraryCommand & cmd,const std::vector<std::string> & columns)506 std::shared_ptr<NativeRdb::ResultSet> MediaLibraryAnalysisAlbumOperations::QueryGroupPhotoAlbum(
507 MediaLibraryCommand &cmd, const std::vector<std::string> &columns)
508 {
509 auto whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
510 auto whereArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
511 RdbPredicates rdbPredicates(ANALYSIS_ALBUM_TABLE);
512 auto albumId = GetAlbumId(whereClause, whereArgs);
513
514 string clause = "";
515 if (albumId != E_INDEX) {
516 clause = PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(PhotoAlbumType::SMART) + " AND " +
517 PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(PhotoAlbumSubType::GROUP_PHOTO) + " AND " +
518 PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumId) + " AND " +
519 IS_REMOVED + " IS NOT " + to_string(ALBUM_IS_REMOVED);
520 } else {
521 clause = PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(PhotoAlbumType::SMART) + " AND " +
522 PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(PhotoAlbumSubType::GROUP_PHOTO) + " AND " +
523 IS_REMOVED + " IS NOT " + to_string(ALBUM_IS_REMOVED);
524 if (whereClause.find(IS_ME) != string::npos) {
525 int32_t value = GetArgsValueByName(IS_ME, whereClause, whereArgs);
526 if (value == QUERY_GROUP_PHOTO_ALBUM_RELATED_TO_ME) {
527 clause += " AND " + IS_ME + " = " + to_string(ALBUM_IS_ME);
528 }
529 }
530 }
531
532 rdbPredicates.SetWhereClause(clause);
533 rdbPredicates.OrderByDesc(RENAME_OPERATION);
534 rdbPredicates.OrderByDesc("(SELECT LENGTH(" + TAG_ID + ") - LENGTH([REPLACE](" + TAG_ID + ", ',', '')))");
535 auto resultSet = MediaLibraryRdbStore::QueryWithFilter(rdbPredicates, columns);
536 if (albumId != E_INDEX) {
537 return resultSet;
538 }
539
540 auto asyncWorker = MediaLibraryAsyncWorker::GetInstance();
541 if (asyncWorker != nullptr) {
542 auto updateGroupTask = make_shared<MediaLibraryAsyncTask>(UpdateGroupPhotoAlbumAsync, nullptr);
543 if (updateGroupTask != nullptr) {
544 asyncWorker->AddTask(updateGroupTask, true);
545 } else {
546 MEDIA_ERR_LOG("Failed to create async task for query group photo album.");
547 }
548 } else {
549 MEDIA_ERR_LOG("Can not get asyncWorker");
550 }
551 return resultSet;
552 }
553
GetMergeAlbumCoverUri(MergeAlbumInfo & updateAlbumInfo,const MergeAlbumInfo & currentAlbum,const MergeAlbumInfo & targetAlbum)554 static int32_t GetMergeAlbumCoverUri(MergeAlbumInfo &updateAlbumInfo, const MergeAlbumInfo ¤tAlbum,
555 const MergeAlbumInfo &targetAlbum)
556 {
557 string currentFileId = MediaFileUri::GetPhotoId(currentAlbum.coverUri);
558 string targetFileId = MediaFileUri::GetPhotoId(targetAlbum.coverUri);
559 if (currentFileId.empty() || targetFileId.empty()) {
560 return E_DB_FAIL;
561 }
562 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
563 if (uniStore == nullptr) {
564 MEDIA_ERR_LOG("uniStore is nullptr! failed query get merge album cover uri");
565 return E_DB_FAIL;
566 }
567 string candidateIds;
568 if (currentAlbum.isCoverSatisfied == targetAlbum.isCoverSatisfied) {
569 candidateIds = currentFileId + ", " + targetFileId;
570 } else {
571 candidateIds = currentAlbum.isCoverSatisfied != static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING) ?
572 currentFileId :
573 targetFileId;
574 }
575 const std::string queryAlbumInfo = "SELECT " + MediaColumn::MEDIA_ID + "," + MediaColumn::MEDIA_TITLE + "," +
576 MediaColumn::MEDIA_NAME + ", MAX(" + MediaColumn::MEDIA_DATE_ADDED + ") FROM " + PhotoColumn::PHOTOS_TABLE +
577 " WHERE " + MediaColumn::MEDIA_ID + " IN (" + candidateIds + " )";
578
579 auto resultSet = uniStore->QuerySql(queryAlbumInfo);
580 if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
581 MEDIA_ERR_LOG("Failed to query merge album cover uri");
582 return E_HAS_DB_ERROR;
583 }
584 int mergeFileId;
585 if (GetIntValueFromResultSet(resultSet, MediaColumn::MEDIA_ID, mergeFileId) != NativeRdb::E_OK) {
586 MEDIA_ERR_LOG("Failed to get file id of merge album cover uri.");
587 return E_HAS_DB_ERROR;
588 }
589
590 string mergeTitle;
591 if (GetStringValueFromResultSet(resultSet, MediaColumn::MEDIA_TITLE, mergeTitle) != NativeRdb::E_OK) {
592 MEDIA_ERR_LOG("Failed to get title of merge album cover uri.");
593 return E_HAS_DB_ERROR;
594 }
595
596 string mergeDisplayName;
597 if (GetStringValueFromResultSet(resultSet, MediaColumn::MEDIA_NAME, mergeDisplayName) != NativeRdb::E_OK) {
598 MEDIA_ERR_LOG("Failed to get display name of merge album cover uri.");
599 return E_HAS_DB_ERROR;
600 }
601 updateAlbumInfo.coverUri = "file://media/Photo/" + to_string(mergeFileId) + "/" + mergeTitle + "/" +
602 mergeDisplayName;
603 return E_OK;
604 }
605
UpdateForMergeGroupAlbums(const shared_ptr<MediaLibraryRdbStore> store,const vector<int> & deleteId,const std::unordered_map<string,MergeAlbumInfo> updateMap)606 static int32_t UpdateForMergeGroupAlbums(const shared_ptr<MediaLibraryRdbStore> store, const vector<int> &deleteId,
607 const std::unordered_map<string, MergeAlbumInfo> updateMap)
608 {
609 for (auto it : deleteId) {
610 RdbPredicates rdbPredicates(ANALYSIS_ALBUM_TABLE);
611 rdbPredicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(it));
612 MediaLibraryRdbStore::Delete(rdbPredicates);
613 }
614 vector<string> updateSqls;
615 for (auto it : updateMap) {
616 string sql = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + TAG_ID + " = '" + it.first + "', " +
617 GROUP_TAG + " = '" + it.first + "', " + COVER_URI + " = '" + it.second.coverUri + "', " +
618 IS_REMOVED + " = 0, " + IS_COVER_SATISFIED + " = " + to_string(it.second.isCoverSatisfied) +
619 " WHERE " + ALBUM_ID + " = " + to_string(it.second.albumId);
620 updateSqls.push_back(sql);
621 }
622 return ExecSqls(updateSqls, store);
623 }
624
ReorderTagId(string target,const vector<MergeAlbumInfo> & mergeAlbumInfo)625 static string ReorderTagId(string target, const vector<MergeAlbumInfo> &mergeAlbumInfo)
626 {
627 string reordererTagId;
628 vector<string> splitResult;
629 if (target.empty()) {
630 return reordererTagId;
631 }
632 string pattern = ",";
633 string strs = target + pattern;
634 size_t pos = strs.find(pattern);
635 while (pos != strs.npos) {
636 string groupTag = strs.substr(0, pos);
637 strs = strs.substr(pos + 1, strs.size());
638 pos = strs.find(pattern);
639 if (groupTag.compare(mergeAlbumInfo[0].groupTag) != 0 && groupTag.compare(mergeAlbumInfo[1].groupTag) != 0) {
640 splitResult.push_back(groupTag);
641 }
642 }
643 if (splitResult.empty()) {
644 return reordererTagId;
645 }
646 string newTagId = mergeAlbumInfo[0].groupTag + "|" + mergeAlbumInfo[1].groupTag;
647 splitResult.push_back(newTagId);
648 std::sort(splitResult.begin(), splitResult.end());
649 for (auto tagId : splitResult) {
650 reordererTagId += (tagId + ",");
651 }
652 reordererTagId = reordererTagId.substr(0, reordererTagId.size() - 1);
653 return reordererTagId;
654 }
655
GetMergeAlbumInfo(shared_ptr<NativeRdb::ResultSet> resultSet,MergeAlbumInfo & info)656 int32_t GetMergeAlbumInfo(shared_ptr<NativeRdb::ResultSet> resultSet, MergeAlbumInfo &info)
657 {
658 int isCoverSatisfied = 0;
659 if (GetIntValueFromResultSet(resultSet, ALBUM_ID, info.albumId) != E_OK ||
660 GetStringValueFromResultSet(resultSet, TAG_ID, info.tagId) != E_OK ||
661 GetStringValueFromResultSet(resultSet, COVER_URI, info.coverUri) != E_OK ||
662 GetIntValueFromResultSet(resultSet, IS_COVER_SATISFIED, isCoverSatisfied) != E_OK) {
663 return E_HAS_DB_ERROR;
664 }
665 info.isCoverSatisfied = static_cast<uint8_t>(isCoverSatisfied);
666 return E_OK;
667 }
668
UpdateMergeGroupAlbumsInfo(const vector<MergeAlbumInfo> & mergeAlbumInfo)669 int32_t MediaLibraryAnalysisAlbumOperations::UpdateMergeGroupAlbumsInfo(const vector<MergeAlbumInfo> &mergeAlbumInfo)
670 {
671 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
672 if (uniStore == nullptr) {
673 MEDIA_ERR_LOG("UniStore is nullptr! Query album order failed.");
674 return E_DB_FAIL;
675 }
676 string queryTagId = "SELECT " + ALBUM_ID + ", " + COVER_URI + ", " + IS_COVER_SATISFIED + ", " + TAG_ID +
677 " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_SUBTYPE + " = " + to_string(GROUP_PHOTO) +
678 " AND (INSTR(" + TAG_ID + ", '" + mergeAlbumInfo[0].groupTag + "') > 0 OR INSTR(" + TAG_ID + ", '" +
679 mergeAlbumInfo[1].groupTag + "') > 0)";
680 auto resultSet = uniStore->QuerySql(queryTagId);
681 if (resultSet == nullptr) {
682 return E_HAS_DB_ERROR;
683 }
684
685 std::vector<int> deleteId;
686 std::unordered_map<string, MergeAlbumInfo> updateMap;
687 while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
688 MergeAlbumInfo info;
689 if (GetMergeAlbumInfo(resultSet, info) != E_OK) {
690 return E_HAS_DB_ERROR;
691 }
692 string reorderedTagId = ReorderTagId(info.tagId, mergeAlbumInfo);
693 auto it = updateMap.find(reorderedTagId);
694 if (reorderedTagId.empty()) {
695 deleteId.push_back(info.albumId);
696 } else if (it == updateMap.end()) {
697 updateMap.insert(std::make_pair(reorderedTagId, info));
698 } else {
699 MergeAlbumInfo newInfo;
700 if (it->second.coverUri.empty()) {
701 updateMap[reorderedTagId].coverUri = info.coverUri;
702 updateMap[reorderedTagId].isCoverSatisfied = info.isCoverSatisfied;
703 deleteId.push_back(info.albumId);
704 continue;
705 } else if (info.coverUri.empty()) {
706 deleteId.push_back(info.albumId);
707 continue;
708 } else if (GetMergeAlbumCoverUri(newInfo, info, it->second) != E_OK) {
709 return E_HAS_DB_ERROR;
710 }
711 if (info.isCoverSatisfied != static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING) ||
712 it->second.isCoverSatisfied != static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING)) {
713 updateMap[reorderedTagId].isCoverSatisfied = static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING);
714 }
715 updateMap[reorderedTagId].coverUri = newInfo.coverUri;
716 deleteId.push_back(info.albumId);
717 }
718 }
719 return UpdateForMergeGroupAlbums(uniStore, deleteId, updateMap);
720 }
721
SetGroupAlbumName(const ValuesBucket & values,const DataSharePredicates & predicates)722 static int32_t SetGroupAlbumName(const ValuesBucket &values, const DataSharePredicates &predicates)
723 {
724 RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
725 auto whereArgs = rdbPredicates.GetWhereArgs();
726 if (whereArgs.size() == 0) {
727 MEDIA_ERR_LOG("no target album id");
728 return E_INVALID_VALUES;
729 }
730 string targetAlbumId = whereArgs[0];
731 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
732 if (uniStore == nullptr) {
733 MEDIA_ERR_LOG("uniStore is nullptr! failed update for set album name");
734 return E_DB_FAIL;
735 }
736 string albumName;
737 int err = GetStringObject(values, ALBUM_NAME, albumName);
738 if (err < 0 || albumName.empty()) {
739 MEDIA_ERR_LOG("invalid album name");
740 return E_INVALID_VALUES;
741 }
742 std::string updateForSetAlbumName = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + ALBUM_NAME + " = '" + albumName +
743 "' , " + RENAME_OPERATION + " = 1 WHERE " + ALBUM_ID + " = " + targetAlbumId;
744 vector<string> updateSqls = { updateForSetAlbumName };
745 err = ExecSqls(updateSqls, uniStore);
746 if (err == E_OK) {
747 vector<int32_t> changeAlbumIds = { atoi(targetAlbumId.c_str()) };
748 NotifyGroupAlbum(changeAlbumIds);
749 }
750 return err;
751 }
752
SetGroupCoverUri(const ValuesBucket & values,const DataSharePredicates & predicates)753 static int32_t SetGroupCoverUri(const ValuesBucket &values, const DataSharePredicates &predicates)
754 {
755 RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
756 auto whereArgs = rdbPredicates.GetWhereArgs();
757 if (whereArgs.size() == 0) {
758 MEDIA_ERR_LOG("no target album id");
759 return E_INVALID_VALUES;
760 }
761 string targetAlbumId = whereArgs[0];
762 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
763 if (uniStore == nullptr) {
764 MEDIA_ERR_LOG("uniStore is nullptr! failed update for set album cover uri");
765 return E_DB_FAIL;
766 }
767 string coverUri;
768 int err = GetStringObject(values, COVER_URI, coverUri);
769 if (err < 0 || coverUri.empty()) {
770 MEDIA_ERR_LOG("invalid album cover uri");
771 return E_INVALID_VALUES;
772 }
773 std::string updateForSetCoverUri = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + COVER_URI + " = '" + coverUri +
774 "', " + IS_COVER_SATISFIED + " = " + to_string(static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING)) +
775 " WHERE " + ALBUM_ID + " = " + targetAlbumId;
776 vector<string> updateSqls = { updateForSetCoverUri };
777 err = ExecSqls(updateSqls, uniStore);
778 if (err == E_OK) {
779 vector<int32_t> changeAlbumIds = { atoi(targetAlbumId.c_str()) };
780 NotifyGroupAlbum(changeAlbumIds);
781 }
782 return err;
783 }
784
DismissGroupPhotoAlbum(const ValuesBucket & values,const DataSharePredicates & predicates)785 static int32_t DismissGroupPhotoAlbum(const ValuesBucket &values, const DataSharePredicates &predicates)
786 {
787 RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
788 auto whereArgs = rdbPredicates.GetWhereArgs();
789 if (whereArgs.size() == 0) {
790 MEDIA_ERR_LOG("no target album id");
791 return E_INVALID_VALUES;
792 }
793 string targetAlbumId = whereArgs[0];
794 auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
795 if (uniStore == nullptr) {
796 MEDIA_ERR_LOG("uniStore is nullptr! failed update for set album cover uri");
797 return E_DB_FAIL;
798 }
799 std::string updateForDeleteGroupAlbum = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + IS_REMOVED + " = 1 WHERE " +
800 ALBUM_ID + " = " + targetAlbumId;
801 vector<string> updateSqls = { updateForDeleteGroupAlbum };
802 int err = ExecSqls(updateSqls, uniStore);
803 if (err == E_OK) {
804 vector<int32_t> changeAlbumIds = { atoi(targetAlbumId.c_str()) };
805 NotifyGroupAlbum(changeAlbumIds);
806 }
807 return err;
808 }
809
HandleGroupPhotoAlbum(const OperationType & opType,const NativeRdb::ValuesBucket & values,const DataShare::DataSharePredicates & predicates)810 int32_t MediaLibraryAnalysisAlbumOperations::HandleGroupPhotoAlbum(const OperationType &opType,
811 const NativeRdb::ValuesBucket &values, const DataShare::DataSharePredicates &predicates)
812 {
813 switch (opType) {
814 case OperationType::DISMISS:
815 return DismissGroupPhotoAlbum(values, predicates);
816 case OperationType::GROUP_ALBUM_NAME:
817 return SetGroupAlbumName(values, predicates);
818 case OperationType::GROUP_COVER_URI:
819 return SetGroupCoverUri(values, predicates);
820 default:
821 MEDIA_ERR_LOG("Unknown operation type: %{public}d", opType);
822 return E_ERR;
823 }
824 }
825
UpdateGroupPhotoAlbumById(int32_t albumId)826 void MediaLibraryAnalysisAlbumOperations::UpdateGroupPhotoAlbumById(int32_t albumId)
827 {
828 const string &querySql = GetGroupPhotoAlbumSql();
829 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
830 if (rdbStore == nullptr) {
831 MEDIA_ERR_LOG("Update group photo album by id: %{public}d failed, rdbStore is null.", albumId);
832 return;
833 }
834 auto rdbStorePtr = rdbStore;
835 if (rdbStorePtr == nullptr) {
836 MEDIA_ERR_LOG("Update group photo album by id: %{public}d failed, rdbStorePtr is null.", albumId);
837 return;
838 }
839 auto resultSet = rdbStorePtr->QuerySql(querySql);
840 if (resultSet == nullptr) {
841 MEDIA_ERR_LOG("Update group photo album by id: %{public}d failed, query resultSet is null.", albumId);
842 return;
843 }
844
845 vector<GroupPhotoAlbumInfo> updateAlbums;
846 while (resultSet->GoToNextRow() == E_OK) {
847 int32_t id = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
848 if (id == albumId) {
849 auto info = AssemblyInfo(resultSet);
850 updateAlbums.push_back(info);
851 break;
852 }
853 }
854 UpdateGroupPhotoAlbumInfo(updateAlbums);
855 }
856
UpdatePortraitAlbumCoverSatisfied(int32_t fileId)857 void MediaLibraryAnalysisAlbumOperations::UpdatePortraitAlbumCoverSatisfied(int32_t fileId)
858 {
859 auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
860 if (rdbStore == nullptr) {
861 MEDIA_ERR_LOG("UpdatePortraitAlbumCoverSatisfied failed, fileId: %{public}d, rdbStore is null.", fileId);
862 return;
863 }
864 const string coverUriPrefix = "'" + PhotoColumn::PHOTO_URI_PREFIX + to_string(fileId) + "/%'";
865
866 const string updateSql = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + IS_COVER_SATISFIED + " = " +
867 IS_COVER_SATISFIED + " | " + to_string(static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING)) + " WHERE " +
868 PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + to_string(static_cast<int32_t>(PhotoAlbumSubType::PORTRAIT)) +
869 " AND " + PhotoAlbumColumns::ALBUM_COVER_URI + " LIKE " + coverUriPrefix;
870
871 int32_t ret = rdbStore->ExecuteSql(updateSql);
872 if (ret != E_OK) {
873 MEDIA_ERR_LOG("ExecuteSql error, fileId: %{public}d, ret: %{public}d.", fileId, ret);
874 return;
875 }
876 }
877 } // namespace OHOS::Media
878