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