• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &currentAlbum,
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