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