• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021-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 "AlbumOperation"
16 
17 #include "medialibrary_album_operations.h"
18 
19 #include <cstddef>
20 #include <cstdio>
21 #include <cstring>
22 
23 #include "album_plugin_config.h"
24 #include "dfx_utils.h"
25 #include "directory_ex.h"
26 #include "media_analysis_helper.h"
27 #include "media_file_utils.h"
28 #include "media_log.h"
29 #include "medialibrary_album_fusion_utils.h"
30 #include "medialibrary_analysis_album_operations.h"
31 #include "medialibrary_asset_operations.h"
32 #include "medialibrary_data_manager.h"
33 #include "medialibrary_db_const.h"
34 #include "medialibrary_errno.h"
35 #include "medialibrary_notify.h"
36 #include "medialibrary_object_utils.h"
37 #include "medialibrary_rdb_utils.h"
38 #include "medialibrary_rdbstore.h"
39 #include "medialibrary_tracer.h"
40 #include "medialibrary_unistore_manager.h"
41 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
42 #include "enhancement_manager.h"
43 #endif
44 #include "multistages_capture_manager.h"
45 #include "photo_album_column.h"
46 #include "photo_map_column.h"
47 
48 #include "result_set_utils.h"
49 #include "story_album_column.h"
50 #include "story_cover_info_column.h"
51 #include "values_bucket.h"
52 #include "medialibrary_formmap_operations.h"
53 #include "media_file_uri.h"
54 #include "media_file_utils.h"
55 #include "vision_album_column.h"
56 #include "vision_column.h"
57 #include "vision_face_tag_column.h"
58 #include "vision_photo_map_column.h"
59 #include "vision_total_column.h"
60 #include "photo_owner_album_id_operation.h"
61 #include "photo_storage_operation.h"
62 #include "asset_accurate_refresh.h"
63 #include "refresh_business_name.h"
64 
65 using namespace std;
66 using namespace OHOS::NativeRdb;
67 using namespace OHOS::DataShare;
68 using namespace OHOS::RdbDataShareAdapter;
69 using namespace OHOS::Media::AccurateRefresh;
70 
71 namespace OHOS::Media {
72 using ChangeType = AAFwk::ChangeInfo::ChangeType;
73 constexpr int32_t THAN_AGR_SIZE = 1;
74 constexpr int32_t MERGE_ALBUM_COUNT = 2;
75 constexpr int32_t E_INDEX = -1;
76 constexpr int32_t PORTRAIT_FIRST_PAGE_MIN_COUNT = 50;
77 constexpr int32_t PORTRAIT_FIRST_PAGE_MIN_COUNT_RELATED_ME = 20;
78 constexpr int32_t PORTRAIT_SECOND_PAGE_MIN_PICTURES_COUNT = 10;
79 constexpr int32_t SUPPORT_QUERY_ISME_MIN_COUNT = 80;
80 constexpr int32_t PERCENTAGE_FOR_SUPPORT_QUERY_ISME = 100;
81 constexpr int32_t QUERY_PROB_IS_ME_VALUE = 1;
82 constexpr int32_t QUERY_IS_ME_VALUE = 2;
83 constexpr int32_t FACE_ANALYSISED_STATE = 3;
84 constexpr int32_t FACE_NO_NEED_ANALYSIS_STATE = -2;
85 constexpr int32_t ALBUM_NAME_NOT_NULL_ENABLED = 1;
86 constexpr int32_t ALBUM_PRIORITY_DEFAULT = 1;
87 constexpr int32_t ALBUM_SETNAME_OK = 1;
88 constexpr int32_t HIGHLIGHT_DELETED = -2;
89 constexpr int32_t HIGHLIGHT_COVER_STATUS_TITLE = 2;
90 constexpr int32_t HIGHLIGHT_COVER_STATUS_COVER = 1;
91 constexpr int32_t ALBUM_RENAMED = 2;
92 constexpr int32_t ALBUM_TO_RENAME_FOR_ANALYSIS = 3;
93 const std::string ALBUM_LPATH_PREFIX = "/Pictures/Users/";
94 const std::string SOURCE_PATH_PREFIX = "/storage/emulated/0";
95 
CreateAlbumOperation(MediaLibraryCommand & cmd)96 int32_t MediaLibraryAlbumOperations::CreateAlbumOperation(MediaLibraryCommand &cmd)
97 {
98     int64_t outRow = -1;
99     int32_t errCode = MediaLibraryObjectUtils::CreateDirObj(cmd, outRow);
100     if (errCode == E_SUCCESS) {
101         return outRow;
102     }
103     return errCode;
104 }
105 
106 // only support modify in the same parent folder, like: a/b/c --> a/b/d
ModifyAlbumOperation(MediaLibraryCommand & cmd)107 int32_t MediaLibraryAlbumOperations::ModifyAlbumOperation(MediaLibraryCommand &cmd)
108 {
109     string strId = cmd.GetOprnFileId();
110     string srcDirPath = MediaLibraryObjectUtils::GetPathByIdFromDb(strId);
111     if (srcDirPath.empty()) {
112         MEDIA_ERR_LOG("Get path of id %{private}s from database file!", strId.c_str());
113         return E_INVALID_PATH;
114     }
115 
116     auto values = cmd.GetValueBucket();
117     string dstDirName;
118     ValueObject valueObject;
119     if (values.GetObject(MEDIA_DATA_DB_NAME, valueObject)) {
120         valueObject.GetString(dstDirName);
121     }
122     int ret;
123     if (dstDirName.empty() && !values.IsEmpty()) {
124         ret = MediaLibraryObjectUtils::ModifyInfoByIdInDb(cmd);
125     } else {
126         string dstDirPath = MediaFileUtils::GetParentPath(srcDirPath) + "/" + dstDirName;
127         ret = MediaLibraryObjectUtils::RenameDirObj(cmd, srcDirPath, dstDirPath);
128     }
129     return ret;
130 }
131 
132 #ifdef MEDIALIBRARY_COMPATIBILITY
ReplaceRelativePath(string & selection,vector<string> & selectionArgs)133 static void ReplaceRelativePath(string &selection, vector<string> &selectionArgs)
134 {
135     for (size_t pos = 0; pos != string::npos;) {
136         pos = selection.find(MEDIA_DATA_DB_RELATIVE_PATH, pos);
137         if (pos == string::npos) {
138             break;
139         }
140         size_t argPos = selection.find('?', pos);
141         if (argPos == string::npos) {
142             break;
143         }
144         size_t argIndex = 0;
145         for (size_t i = 0; i < argPos; i++) {
146             if (selection[i] == '?') {
147                 argIndex++;
148             }
149         }
150         if (argIndex > selectionArgs.size() - 1) {
151             MEDIA_WARN_LOG("SelectionArgs size is not valid, selection format maybe incorrect: %{private}s",
152                 selection.c_str());
153             break;
154         }
155         const string &arg = selectionArgs[argIndex];
156         if (!arg.empty()) {
157             MEDIA_WARN_LOG("No empty args in ReplaceRelativePath");
158             return;
159         }
160         selection.replace(argPos, 1, "? OR 1=1)");
161         selection.replace(pos, MEDIA_DATA_DB_RELATIVE_PATH.length(), "(" + PhotoAlbumColumns::ALBUM_ID);
162 
163         selectionArgs[argIndex] = "1";
164         pos = argPos + 1;
165     }
166 }
167 
ReplaceMediaType(string & selection,vector<string> & selectionArgs)168 static void ReplaceMediaType(string &selection, vector<string> &selectionArgs)
169 {
170     for (size_t pos = 0; pos != string::npos;) {
171         pos = selection.find(MEDIA_DATA_DB_MEDIA_TYPE, pos);
172         if (pos == string::npos) {
173             break;
174         }
175         size_t argPos = selection.find('?', pos);
176         if (argPos == string::npos) {
177             break;
178         }
179         size_t argIndex = 0;
180         for (size_t i = 0; i < argPos; i++) {
181             if (selection[i] == '?') {
182                 argIndex++;
183             }
184         }
185         if (argIndex > selectionArgs.size() - 1) {
186             MEDIA_WARN_LOG("SelectionArgs size is not valid, selection format maybe incorrect: %{private}s",
187                 selection.c_str());
188             break;
189         }
190         selection.replace(argPos, 1, "? OR 1=1)");
191         selection.replace(pos, MEDIA_DATA_DB_MEDIA_TYPE.length(), "(" + PhotoAlbumColumns::ALBUM_ID);
192 
193         selectionArgs[argIndex] = "1";
194         pos = argPos + 1;
195     }
196 }
197 
GetSqlArgs(MediaLibraryCommand & cmd,string & sql,vector<string> & selectionArgs,const vector<string> & columns)198 static void GetSqlArgs(MediaLibraryCommand &cmd, string &sql, vector<string> &selectionArgs,
199     const vector<string> &columns)
200 {
201     string clause = cmd.GetAbsRdbPredicates()->GetWhereClause();
202     selectionArgs = cmd.GetAbsRdbPredicates()->GetWhereArgs();
203     sql = "SELECT ";
204     for (size_t i = 0; i < columns.size(); i++) {
205         if (i != columns.size() - 1) {
206             sql += columns[i] + ",";
207         } else {
208             sql += columns[i];
209         }
210     }
211     sql += " FROM " + cmd.GetAbsRdbPredicates()->GetTableName();
212     sql += " WHERE ";
213     ReplaceRelativePath(clause, selectionArgs);
214     ReplaceMediaType(clause, selectionArgs);
215     sql += clause;
216 }
217 
QueryAlbumDebug(MediaLibraryCommand & cmd,const vector<string> & columns,const shared_ptr<MediaLibraryRdbStore> store)218 static void QueryAlbumDebug(MediaLibraryCommand &cmd, const vector<string> &columns,
219     const shared_ptr<MediaLibraryRdbStore> store)
220 {
221     MEDIA_DEBUG_LOG("Querying album, table: %{private}s selections: %{private}s",
222         cmd.GetAbsRdbPredicates()->GetTableName().c_str(), cmd.GetAbsRdbPredicates()->GetWhereClause().c_str());
223     for (const auto &arg : cmd.GetAbsRdbPredicates()->GetWhereArgs()) {
224         MEDIA_DEBUG_LOG("Querying album, arg: %{private}s", arg.c_str());
225     }
226     for (const auto &col : columns) {
227         MEDIA_DEBUG_LOG("Querying album, col: %{private}s", col.c_str());
228     }
229 
230     auto resultSet = store->Query(cmd, columns);
231     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Failed to query file!");
232     int32_t count = -1;
233     int32_t err = resultSet->GetRowCount(count);
234     CHECK_AND_RETURN_LOG(err == E_OK, "Failed to get count, err: %{public}d", err);
235     MEDIA_DEBUG_LOG("Querying album, count: %{public}d", count);
236 }
237 
QuerySqlDebug(const string & sql,const vector<string> & selectionArgs,const vector<string> & columns,const shared_ptr<MediaLibraryRdbStore> store)238 static void QuerySqlDebug(const string &sql, const vector<string> &selectionArgs, const vector<string> &columns,
239     const shared_ptr<MediaLibraryRdbStore> store)
240 {
241     constexpr int32_t printMax = 512;
242     for (size_t pos = 0; pos < sql.size(); pos += printMax) {
243         MEDIA_DEBUG_LOG("Quering album sql: %{private}s", sql.substr(pos, printMax).c_str());
244     }
245     for (const auto &arg : selectionArgs) {
246         MEDIA_DEBUG_LOG("Quering album, arg: %{private}s", arg.c_str());
247     }
248     for (const auto &col : columns) {
249         MEDIA_DEBUG_LOG("Quering album, col: %{private}s", col.c_str());
250     }
251     auto resultSet = store->QuerySql(sql, selectionArgs);
252     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Failed to query album!");
253 
254     int32_t count = -1;
255     int32_t err = resultSet->GetRowCount(count);
256     CHECK_AND_RETURN_LOG(err == E_OK, "Failed to get count, err: %{public}d", err);
257     MEDIA_DEBUG_LOG("Quering album, count: %{public}d", count);
258 }
259 #endif
260 
QueryAlbumOperation(MediaLibraryCommand & cmd,const vector<string> & columns)261 shared_ptr<ResultSet> MediaLibraryAlbumOperations::QueryAlbumOperation(
262     MediaLibraryCommand &cmd, const vector<string> &columns)
263 {
264     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
265     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, nullptr, "uniStore is nullptr!");
266 
267     if (cmd.GetOprnObject() == OperationObject::MEDIA_VOLUME) {
268         return PhotoStorageOperation().FindStorage(uniStore);
269     }
270 
271     string whereClause = cmd.GetAbsRdbPredicates()->GetWhereClause();
272     if (whereClause.find(MEDIA_DATA_DB_RELATIVE_PATH) != string::npos ||
273         whereClause.find(MEDIA_DATA_DB_MEDIA_TYPE) != string::npos) {
274         string sql;
275         vector<string> selectionArgs;
276         GetSqlArgs(cmd, sql, selectionArgs, columns);
277         QuerySqlDebug(sql, selectionArgs, columns, uniStore);
278         return uniStore->QuerySql(sql, selectionArgs);
279     }
280 
281     QueryAlbumDebug(cmd, columns, uniStore);
282     return uniStore->Query(cmd, columns);
283 }
284 
GetStringObject(const ValuesBucket & values,const string & key,string & value)285 inline int32_t GetStringObject(const ValuesBucket &values, const string &key, string &value)
286 {
287     value = "";
288     ValueObject valueObject;
289     if (values.GetObject(key, valueObject)) {
290         valueObject.GetString(value);
291     } else {
292         return -EINVAL;
293     }
294     return E_OK;
295 }
296 
GetIntVal(const ValuesBucket & values,const string & key,int32_t & value)297 inline int32_t GetIntVal(const ValuesBucket &values, const string &key, int32_t &value)
298 {
299     value = 0;
300     ValueObject valueObject;
301     if (values.GetObject(key, valueObject)) {
302         valueObject.GetInt(value);
303     } else {
304         return -EINVAL;
305     }
306     return E_OK;
307 }
308 
ObtainMaxAlbumOrder(int32_t & maxAlbumOrder)309 static int32_t ObtainMaxAlbumOrder(int32_t &maxAlbumOrder)
310 {
311     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
312     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, -E_HAS_DB_ERROR, "uniStore is nullptr! failed query album order");
313     std::string queryMaxOrderSql = "SELECT Max(album_order) FROM " + PhotoAlbumColumns::TABLE;
314     auto resultSet = uniStore->QuerySql(queryMaxOrderSql);
315     bool cond = (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK);
316     CHECK_AND_RETURN_RET_LOG(!cond, -E_HAS_DB_ERROR, "Failed to query album!");
317     return resultSet->GetInt(0, maxAlbumOrder);
318 }
319 
PrepareUserAlbum(const string & albumName,ValuesBucket & values)320 static void PrepareUserAlbum(const string &albumName, ValuesBucket &values)
321 {
322     values.PutString(PhotoAlbumColumns::ALBUM_NAME, albumName);
323     values.PutInt(PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumType::USER);
324     values.PutInt(PhotoAlbumColumns::ALBUM_SUBTYPE, PhotoAlbumSubType::USER_GENERIC);
325     values.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
326     values.PutInt(PhotoAlbumColumns::ALBUM_IS_LOCAL, 1); // local album is 1.
327     values.PutInt(PhotoAlbumColumns::ALBUM_PRIORITY, ALBUM_PRIORITY_DEFAULT);
328     values.PutString(PhotoAlbumColumns::ALBUM_LPATH, ALBUM_LPATH_PREFIX + albumName);
329     values.PutLong(PhotoAlbumColumns::ALBUM_DATE_ADDED, MediaFileUtils::UTCTimeMilliSeconds());
330 }
331 
PrepareWhere(const string & albumName,const string & relativePath,RdbPredicates & predicates)332 inline void PrepareWhere(const string &albumName, const string &relativePath, RdbPredicates &predicates)
333 {
334     predicates.EqualTo(PhotoAlbumColumns::ALBUM_NAME, albumName);
335     predicates.EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::USER));
336     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
337     if (relativePath.empty()) {
338         predicates.IsNull(PhotoAlbumColumns::ALBUM_RELATIVE_PATH);
339     } else {
340         predicates.EqualTo(PhotoAlbumColumns::ALBUM_RELATIVE_PATH, relativePath);
341     }
342     predicates.NotEqualTo(PhotoAlbumColumns::ALBUM_DIRTY,
343         to_string(static_cast<int32_t>(DirtyTypes::TYPE_DELETED)));
344 }
345 
346 // Caller is responsible for checking @albumName AND @relativePath
DoCreatePhotoAlbum(const string & albumName,const string & relativePath,const ValuesBucket & albumValues)347 int DoCreatePhotoAlbum(const string &albumName, const string &relativePath, const ValuesBucket& albumValues)
348 {
349     // Build insert sql
350     string sql;
351     vector<ValueObject> bindArgs;
352     sql.append("INSERT").append(" OR ROLLBACK").append(" INTO ").append(PhotoAlbumColumns::TABLE).append(" ");
353 
354     MediaLibraryRdbStore::BuildValuesSql(albumValues, bindArgs, sql);
355 
356     RdbPredicates wherePredicates(PhotoAlbumColumns::TABLE);
357     PrepareWhere(albumName, relativePath, wherePredicates);
358     sql.append(" WHERE NOT EXISTS (");
359     MediaLibraryRdbStore::BuildQuerySql(wherePredicates, { PhotoAlbumColumns::ALBUM_ID }, bindArgs, sql);
360     sql.append(")");
361     MEDIA_DEBUG_LOG("DoCreatePhotoAlbum InsertSql: %{private}s", sql.c_str());
362 
363     int64_t lastInsertRowId = 0;
364     AlbumAccurateRefresh albumRefresh(AccurateRefresh::CREATE_PHOTO_TABLE_BUSSINESS_NAME);
365     albumRefresh.Init();
366     lastInsertRowId = albumRefresh.ExecuteForLastInsertedRowId(sql, bindArgs, RdbOperation::RDB_OPERATION_ADD);
367     CHECK_AND_RETURN_RET_LOG(lastInsertRowId >= 0, lastInsertRowId, "insert fail and rollback");
368     MEDIA_INFO_LOG("Create photo album success, id: %{public}" PRId64, lastInsertRowId);
369     if (lastInsertRowId > 0) {
370         albumRefresh.Notify();
371     }
372     return lastInsertRowId;
373 }
374 
QueryExistingAlbumByLpath(const string & albumName,bool & isDeleted,bool & isSameName)375 static int32_t QueryExistingAlbumByLpath(const string& albumName, bool& isDeleted, bool& isSameName)
376 {
377     const string lpath = ALBUM_LPATH_PREFIX + albumName;
378     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
379     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_FAIL, "fail to get rdbstore, lpath is: %{public}s", lpath.c_str());
380 
381     const string sql = "SELECT album_id, album_name, dirty FROM " + PhotoAlbumColumns::TABLE +
382         " WHERE LOWER(lpath) = LOWER(?)";
383     const vector<ValueObject> bindArgs { lpath };
384     auto resultSet = rdbStore->QueryByStep(sql, bindArgs);
385     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_FAIL, "Query failed, lpath is: %{public}s", lpath.c_str());
386 
387     int32_t rowCount;
388     CHECK_AND_RETURN_RET_LOG(resultSet->GetRowCount(rowCount) == NativeRdb::E_OK, E_FAIL,
389         "Failed to get row count, lpath is: %{public}s", lpath.c_str());
390     if (rowCount == 0) {
391         // No existing album with same lpath is found
392         return E_OK;
393     }
394     CHECK_AND_RETURN_RET_LOG(resultSet->GoToFirstRow() == NativeRdb::E_OK, E_FAIL,
395         "Failed to go to first row, lpath is: %{public}s", lpath.c_str());
396     isDeleted =
397         GetInt32Val(PhotoAlbumColumns::ALBUM_DIRTY, resultSet) == static_cast<int32_t>(DirtyTypes::TYPE_DELETED);
398     string existingName = GetStringVal(PhotoAlbumColumns::ALBUM_NAME, resultSet);
399     isSameName = existingName == albumName;
400     return GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet);
401 }
402 
UseDefaultCreateValue(const string & columnName,const pair<bool,string> & defaultValue,string & sql,vector<ValueObject> & bindArgs,int32_t albumId)403 static void UseDefaultCreateValue(const string& columnName, const pair<bool, string>& defaultValue,
404     string& sql, vector<ValueObject>& bindArgs, int32_t albumId)
405 {
406     // needs to set album order to the max value + 1
407     if (columnName == PhotoAlbumColumns::ALBUM_ORDER) {
408         sql.append("( SELECT COALESCE(MAX(album_order), 0) + 1 FROM PhotoAlbum WHERE album_id <> ?)");
409         bindArgs.push_back(ValueObject {albumId});
410     // otherwise, set the default value
411     } else if (defaultValue.first) {
412         sql.append("NULL");
413     } else {
414         sql.append(defaultValue.second);
415     }
416 }
417 
BuildReuseSql(int32_t id,const ValuesBucket & albumValues,const unordered_map<string,pair<bool,string>> & photoAlbumSchema,vector<ValueObject> & bindArgs)418 static string BuildReuseSql(int32_t id, const ValuesBucket& albumValues,
419     const unordered_map<string, pair<bool, string>>& photoAlbumSchema, vector<ValueObject>& bindArgs)
420 {
421     map<string, ValueObject> createUserValuesMap;
422     albumValues.GetAll(createUserValuesMap);
423     string sql;
424     sql.append("UPDATE PhotoAlbum SET ");
425     for (auto schemaIter = photoAlbumSchema.begin(); schemaIter != photoAlbumSchema.end(); schemaIter++) {
426         sql.append(schemaIter->first); // columnName
427         sql.append(" = ");
428         auto userValueIter = createUserValuesMap.find(schemaIter->first);
429         if (userValueIter != createUserValuesMap.end()) {
430             // Use the value from createUserValuesMap
431             sql.append("?");
432             bindArgs.push_back(userValueIter->second);
433         } else {
434             UseDefaultCreateValue(schemaIter->first, schemaIter->second, sql, bindArgs, id);
435         }
436         CHECK_AND_EXECUTE(std::next(schemaIter) == photoAlbumSchema.end(), sql.append(", "));
437     }
438     sql.append(" WHERE album_id = ?");
439     bindArgs.push_back(ValueObject {id});
440     return sql;
441 }
442 
QueryPhotoAlbumSchema()443 static unordered_map<string, pair<bool, string>> QueryPhotoAlbumSchema()
444 {
445     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
446     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, {}, "fail to get rdbstore");
447     const string queryScheme = "PRAGMA table_info([PhotoAlbum])";
448     auto resultSet = rdbStore->QueryByStep(queryScheme);
449     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, {}, "Query failed");
450 
451     unordered_map<string, pair<bool, string>> photoAlbumSchema;
452     while (resultSet->GoToNextRow() == E_OK) {
453         bool isPk = GetInt32Val("pk", resultSet) == 1;
454         if (!isPk) {
455             string colName = GetStringVal("name", resultSet);
456             string defaultValue = GetStringVal("dflt_value", resultSet);
457             bool isNull;
458             int32_t dfltIdx;
459             resultSet->GetColumnIndex("dflt_value", dfltIdx);
460             resultSet->IsColumnNull(dfltIdx, isNull);
461             photoAlbumSchema[colName] = make_pair(isNull, defaultValue);
462         }
463     }
464     return photoAlbumSchema;
465 }
466 
RenewDeletedPhotoAlbum(int32_t id,const ValuesBucket & albumValues,std::shared_ptr<TransactionOperations> trans,AlbumAccurateRefresh * albumRefresh)467 int32_t MediaLibraryAlbumOperations::RenewDeletedPhotoAlbum(int32_t id, const ValuesBucket& albumValues,
468     std::shared_ptr<TransactionOperations> trans, AlbumAccurateRefresh *albumRefresh)
469 {
470     MEDIA_INFO_LOG("Renew deleted PhotoAlbum start, album id: %{public}d", id);
471     unordered_map<string, pair<bool, string>> photoAlbumSchema = QueryPhotoAlbumSchema();
472     vector<NativeRdb::ValueObject> bindArgs;
473     string sql = BuildReuseSql(id, albumValues, photoAlbumSchema, bindArgs);
474     int32_t ret {};
475     if (albumRefresh) {
476         RdbPredicates predicates(PhotoAlbumColumns::TABLE);
477         predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(id));
478         albumRefresh->Init(predicates);
479         ret = albumRefresh->ExecuteSql(sql, bindArgs, RdbOperation::RDB_OPERATION_UPDATE);
480     } else if (trans) {
481         ret = trans->ExecuteSql(sql, bindArgs);
482     } else {
483         auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
484         CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR,
485             "Renew deleted PhotoAlbum execute sql failed, RdbStore is nullptr");
486         ret = rdbStore->ExecuteSql(sql, bindArgs);
487     }
488     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
489         "Renew deleted PhotoAlbum execute sql failed, id is: %{public}d", id);
490     return E_OK;
491 }
492 
IsCoverInSystemAlbum(RdbPredicates & predicates,int32_t albumSubtype)493 bool MediaLibraryAlbumOperations::IsCoverInSystemAlbum(RdbPredicates &predicates, int32_t albumSubtype)
494 {
495     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
496     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "Failed to get rdbStore when query");
497     vector<string> columns = {PhotoColumn::MEDIA_IS_FAV, PhotoColumn::MEDIA_TYPE, PhotoColumn::MEDIA_DATE_TRASHED,
498         PhotoColumn::PHOTO_STRONG_ASSOCIATION};
499     auto resultSet = rdbStore->Query(predicates, columns);
500     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "failed to acquire result from visitor query.");
501     bool ret = false;
502     if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
503         switch (albumSubtype) {
504             case PhotoAlbumSubType::FAVORITE:
505                 ret = get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_IS_FAV,
506                     resultSet, TYPE_INT32)) == 1;
507                 break;
508             case PhotoAlbumSubType::VIDEO:
509                 ret = get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_TYPE,
510                     resultSet, TYPE_INT32)) == MediaType::MEDIA_TYPE_VIDEO;
511                 break;
512             case PhotoAlbumSubType::IMAGE:
513                 ret = get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_TYPE,
514                     resultSet, TYPE_INT32)) == MediaType::MEDIA_TYPE_IMAGE;
515                 break;
516             case PhotoAlbumSubType::TRASH:
517                 ret = get<int64_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::MEDIA_DATE_TRASHED,
518                     resultSet, TYPE_INT64)) == 0;
519                 break;
520             case PhotoAlbumSubType::CLOUD_ENHANCEMENT:
521                 ret = get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_STRONG_ASSOCIATION,
522                     resultSet, TYPE_INT32)) == static_cast<int32_t>(StrongAssociationType::CLOUD_ENHANCEMENT);
523                 break;
524             default:
525                 MEDIA_ERR_LOG("albumSubtype is invalid: %{public}d", albumSubtype);
526                 break;
527         }
528     } else {
529         MEDIA_ERR_LOG("resultSet GoToNextRow failed, albumSubtype: %{public}d", albumSubtype);
530     }
531     return ret;
532 }
533 
IsCoverInAlbum(const string & fileId,int32_t albumSubtype,int32_t albumId)534 bool MediaLibraryAlbumOperations::IsCoverInAlbum(const string &fileId, int32_t albumSubtype, int32_t albumId)
535 {
536     // determine if the cover belongs to the album
537     // query owner_album_id
538     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
539     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore when query owner_album_id");
540     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
541     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
542 
543     if (albumSubtype != -1) { // system album
544         return IsCoverInSystemAlbum(predicates, albumSubtype);
545     }
546     // user album or source album
547     vector<string> columns = {PhotoColumn::PHOTO_OWNER_ALBUM_ID};
548     auto resultSet = rdbStore->Query(predicates, columns);
549     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "failed to acquire result from visitor query.");
550     int32_t ownerAlbumId = -1;
551     CHECK_AND_RETURN_RET_LOG(resultSet->GoToNextRow() == NativeRdb::E_OK, false, "resultSet GoToNextRow failed.");
552     ownerAlbumId =
553         get<int32_t>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_OWNER_ALBUM_ID, resultSet, TYPE_INT32));
554     return ownerAlbumId == albumId;
555 }
556 
CreatePhotoAlbum(const string & albumName)557 int CreatePhotoAlbum(const string &albumName)
558 {
559     int32_t err = MediaFileUtils::CheckAlbumName(albumName);
560     if (err < 0) {
561         MEDIA_ERR_LOG("Check album name failed, album name: %{private}s", albumName.c_str());
562         return err;
563     }
564 
565     ValuesBucket albumValues;
566     PrepareUserAlbum(albumName, albumValues);
567 
568     // try to reuse existing record with same lpath first
569     int32_t id = -1;
570     bool isDeleted = false;
571     bool isSameName = false;
572     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
573     AlbumAccurateRefresh albumRefresh(AccurateRefresh::CREATE_PHOTO_TABLE_BUSSINESS_NAME, trans);
574     std::function<int(void)> tryReuseDeleted = [&]()->int {
575         id = QueryExistingAlbumByLpath(albumName, isDeleted, isSameName);
576         if (id <= 0) {
577             // id < 0 means error has occurred, id == 0 means no existing record.
578             // needs to return in either case.
579             return id;
580         }
581         MEDIA_INFO_LOG("%{public}s photo album with the same lpath exists, reuse the record id %{public}d.",
582             isDeleted ? "Deleted" : "Existing", id);
583         if (isDeleted) {
584             int32_t ret = MediaLibraryAlbumOperations::RenewDeletedPhotoAlbum(id, albumValues, trans, &albumRefresh);
585             CHECK_AND_PRINT_LOG(ret == E_OK, "Failed to update deleted album: %{public}s", albumName.c_str());
586             return ret;
587         }
588         return E_OK;
589     };
590     int ret = trans->RetryTrans(tryReuseDeleted);
591     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_HAS_DB_ERROR, "Try trans fail!, ret: %{public}d", ret);
592     if (id > 0 && (!isSameName || isDeleted)) {
593         albumRefresh.Notify();
594         return id;
595     }
596     albumRefresh.CloseDfxReport();
597     // no existing record available, create a new one
598     return DoCreatePhotoAlbum(albumName, "", albumValues);
599 }
600 
CreatePhotoAlbum(MediaLibraryCommand & cmd)601 int CreatePhotoAlbum(MediaLibraryCommand &cmd)
602 {
603     string albumName;
604     string subtype;
605     int err = GetStringObject(cmd.GetValueBucket(), PhotoAlbumColumns::ALBUM_NAME, albumName);
606     GetStringObject(cmd.GetValueBucket(), PhotoAlbumColumns::ALBUM_SUBTYPE, subtype);
607     if (err < 0 && subtype != to_string(PORTRAIT) && subtype != to_string(GROUP_PHOTO)) {
608         return err;
609     }
610     int rowId;
611     if (OperationObject::ANALYSIS_PHOTO_ALBUM == cmd.GetOprnObject()) {
612         auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
613         CHECK_AND_RETURN_RET(rdbStore != nullptr, E_HAS_DB_ERROR);
614         int64_t outRowId = 0;
615         auto ret = rdbStore->Insert(cmd, outRowId);
616         CHECK_AND_RETURN_RET_LOG(ret == E_OK, outRowId, "insert fail, ret: %{public}d", ret);
617         rowId = outRowId;
618     } else {
619         rowId = CreatePhotoAlbum(albumName);
620     }
621     auto watch = MediaLibraryNotify::GetInstance();
622     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
623     if (rowId > 0) {
624         watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoAlbumColumns::ALBUM_URI_PREFIX, to_string(rowId)),
625             NotifyType::NOTIFY_ADD);
626     }
627     return rowId;
628 }
629 
IsAllUserPhotoAlbum(std::shared_ptr<MediaLibraryRdbStore> rdbStore,RdbPredicates & predicates)630 int32_t IsAllUserPhotoAlbum(std::shared_ptr<MediaLibraryRdbStore> rdbStore, RdbPredicates &predicates)
631 {
632     vector<string> albumIds = predicates.GetWhereArgs();
633     RdbPredicates queryPredicates(PhotoAlbumColumns::TABLE);
634     queryPredicates.In(PhotoAlbumColumns::ALBUM_ID, albumIds);
635     queryPredicates.And()->BeginWrap()->EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::USER));
636     queryPredicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
637     queryPredicates.EndWrap();
638 
639     vector<string> columns = {PhotoAlbumColumns::ALBUM_ID};
640     shared_ptr<ResultSet> resultSet = rdbStore->Query(queryPredicates, columns);
641     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "queryResultSet is null!");
642 
643     int32_t rowCount;
644     int32_t ret = resultSet->GetRowCount(rowCount);
645     if (ret != 0 || rowCount < 0) {
646         MEDIA_ERR_LOG("result set get row count err %{public}d", ret);
647         return E_HAS_DB_ERROR;
648     }
649     resultSet->Close();
650     if (static_cast<size_t>(rowCount) != albumIds.size()) {
651         int32_t nonUserAlbumUriCount = static_cast<int32_t>(albumIds.size()) - rowCount;
652         MEDIA_ERR_LOG("deleted Albums Uri Contains non-user albums count is %{public}d",
653             (int)nonUserAlbumUriCount);
654         return E_INVALID_URI;
655     }
656     return E_OK;
657 }
658 
DeletePhotoAlbum(RdbPredicates & predicates)659 int32_t MediaLibraryAlbumOperations::DeletePhotoAlbum(RdbPredicates &predicates)
660 {
661     // Only user generic albums can be deleted
662     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
663     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "DeletePhotoAlbum failed. rdbStore is null");
664 
665     int32_t ret = IsAllUserPhotoAlbum(rdbStore, predicates);
666     if (ret != E_OK) {
667         MEDIA_ERR_LOG("deleted Album is all not userAlbum type");
668         return E_INVALID_URI;
669     }
670 
671     MEDIA_INFO_LOG("Delete user generic albums start");
672     if (MediaLibraryRdbUtils::UpdateTrashedAssetOnAlbum(rdbStore, predicates) <= 0) {
673         MEDIA_ERR_LOG("Update trashed asset failed");
674         return E_HAS_DB_ERROR;
675     }
676     AlbumAccurateRefresh albumRefresh(AccurateRefresh::DELETE_PHOTO_ALBUMS_BUSSINESS_NAME);
677     int deleteRow = -1;
678     albumRefresh.LogicalDeleteReplaceByUpdate(predicates, deleteRow);
679     if (deleteRow > 0) {
680         albumRefresh.Notify();
681     }
682     auto watch = MediaLibraryNotify::GetInstance();
683     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
684     const vector<string> &notifyUris = predicates.GetWhereArgs();
685     size_t count = notifyUris.size();
686     for (size_t i = 0; i < count; i++) {
687         if (deleteRow > 0) {
688             watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoAlbumColumns::ALBUM_URI_PREFIX,
689                 notifyUris[i]), NotifyType::NOTIFY_REMOVE);
690         }
691     }
692     return deleteRow;
693 }
694 
DeleteHighlightAlbums(RdbPredicates & predicates)695 int32_t MediaLibraryAlbumOperations::DeleteHighlightAlbums(RdbPredicates &predicates)
696 {
697     // Only Highlight albums can be deleted by this way
698     MEDIA_INFO_LOG("Delete highlight albums");
699     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
700     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "DeleteHighlightAlbum failed. rdbStore is null");
701 
702     ValuesBucket values;
703     values.PutInt(HIGHLIGHT_STATUS, HIGHLIGHT_DELETED);
704     int32_t changedRows = 0;
705     int32_t result = rdbStore->Update(changedRows, values, predicates);
706     CHECK_AND_RETURN_RET_LOG(result == NativeRdb::E_OK, E_HAS_DB_ERROR,
707         "Delete highlight album failed, result is %{private}d", result);
708     auto watch = MediaLibraryNotify::GetInstance();
709     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
710 
711     const vector<string> &notifyUris = predicates.GetWhereArgs();
712     if (changedRows > 0) {
713         for (size_t i = 0; i < notifyUris.size(); ++i) {
714             watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX,
715                 notifyUris[i]), NotifyType::NOTIFY_REMOVE);
716         }
717     }
718     return changedRows;
719 }
720 
NotifyPortraitAlbum(const vector<int32_t> & changedAlbumIds)721 static void NotifyPortraitAlbum(const vector<int32_t> &changedAlbumIds)
722 {
723     if (changedAlbumIds.size() <= 0) {
724         return;
725     }
726     auto watch = MediaLibraryNotify::GetInstance();
727     CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
728     for (int32_t albumId : changedAlbumIds) {
729         watch->Notify(MediaFileUtils::GetUriByExtrConditions(
730             PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX, to_string(albumId)), NotifyType::NOTIFY_UPDATE);
731     }
732 }
733 
NotifyHighlightAlbum(const vector<int32_t> & changedAlbumIds)734 static void NotifyHighlightAlbum(const vector<int32_t> &changedAlbumIds)
735 {
736     CHECK_AND_RETURN(changedAlbumIds.size() > 0);
737     auto watch = MediaLibraryNotify::GetInstance();
738     for (int32_t albumId : changedAlbumIds) {
739         watch->Notify(MediaFileUtils::GetUriByExtrConditions(
740             PhotoAlbumColumns::ANALYSIS_ALBUM_URI_PREFIX, to_string(albumId)), NotifyType::NOTIFY_UPDATE);
741     }
742 }
743 
GetIntValueFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,int & value)744 int32_t GetIntValueFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, int &value)
745 {
746     int index = E_INDEX;
747     resultSet->GetColumnIndex(column, index);
748     if (index == E_INDEX) {
749         return E_HAS_DB_ERROR;
750     }
751     if (resultSet->GetInt(index, value) != NativeRdb::E_OK) {
752         return E_HAS_DB_ERROR;
753     }
754     return E_OK;
755 }
756 
GetStringValueFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,string & value)757 int32_t GetStringValueFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, string &value)
758 {
759     if (resultSet == nullptr) {
760         return E_HAS_DB_ERROR;
761     }
762     int index = E_INDEX;
763     resultSet->GetColumnIndex(column, index);
764     if (index == E_INDEX) {
765         return E_HAS_DB_ERROR;
766     }
767     if (resultSet->GetString(index, value) != NativeRdb::E_OK) {
768         return E_HAS_DB_ERROR;
769     }
770     return E_OK;
771 }
772 
GetDisplayLevelAlbumPredicates(const int32_t value,DataShare::DataSharePredicates & predicates)773 void GetDisplayLevelAlbumPredicates(const int32_t value, DataShare::DataSharePredicates &predicates)
774 {
775     string whereClause;
776     string whereClauseRelatedMe = "(SELECT " + MAP_ALBUM + " FROM " + ANALYSIS_PHOTO_MAP_TABLE +
777             " WHERE " + MAP_ASSET + " IN ( SELECT " + MediaColumn::MEDIA_ID + " FROM " + PhotoColumn::PHOTOS_TABLE +
778             " WHERE " + MediaColumn::MEDIA_ID + " IN (SELECT " + MAP_ASSET + " FROM " + ANALYSIS_PHOTO_MAP_TABLE +
779             " WHERE " + MAP_ASSET + " IN (SELECT " + MAP_ASSET + " FROM " + ANALYSIS_PHOTO_MAP_TABLE + " WHERE " +
780             MAP_ALBUM + " IN(SELECT " + ALBUM_ID + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + IS_ME + " = 1))" +
781             " GROUP BY " + MAP_ASSET + " HAVING count(" + MAP_ASSET + ") > 1) AND " + MediaColumn::MEDIA_DATE_TRASHED +
782             " = 0) AND " + MAP_ALBUM + " NOT IN (SELECT " + ALBUM_ID + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
783             IS_ME + " = 1)" + " GROUP BY " + MAP_ALBUM + " HAVING count(" + MAP_ALBUM + ") >= " +
784             to_string(PORTRAIT_FIRST_PAGE_MIN_COUNT_RELATED_ME) + ")";
785     std::string whereClauseAlbumName = ALBUM_NAME + " IS NOT NULL AND " + ALBUM_NAME + " != ''";
786 
787     if (value == FIRST_PAGE) {
788         string relatedMeFirstPage = ALBUM_ID + " IN " + whereClauseRelatedMe;
789         string whereClauseDisplay = USER_DISPLAY_LEVEL + " = 1";
790         string whereClauseIsMe = IS_ME + " = 1";
791         string whereClauseSatifyCount = COUNT + " >= " + to_string(PORTRAIT_FIRST_PAGE_MIN_COUNT) + " AND (" +
792             USER_DISPLAY_LEVEL + " != 2 OR " + USER_DISPLAY_LEVEL + " IS NULL)";
793         whereClause = ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) + " AND (((" + USER_DISPLAY_LEVEL + " != 3 AND " +
794                       USER_DISPLAY_LEVEL + " !=2) OR " + USER_DISPLAY_LEVEL + " IS NULL) AND ((" + whereClauseDisplay +
795                       ") OR (" + whereClauseIsMe + ") OR (" + relatedMeFirstPage + ") OR (" + whereClauseSatifyCount +
796                       ") OR (" + whereClauseAlbumName + "))) GROUP BY " + GROUP_TAG + " ORDER BY CASE WHEN " + IS_ME +
797                       " != 0 THEN 0 ELSE 1 END, CASE WHEN " + RENAME_OPERATION + " != 0 THEN 0 ELSE 1 END, " + COUNT +
798                       " DESC";
799     } else if (value == SECOND_PAGE) {
800         string whereClauseIsNotMe = IS_ME + " != 1 OR " + IS_ME + " IS NULL";
801         whereClause = ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) + " AND (" + USER_DISPLAY_LEVEL + " = 2 OR ((" +
802                       whereClauseIsNotMe + ") AND " + COUNT + " < " + to_string(PORTRAIT_FIRST_PAGE_MIN_COUNT) +
803                       " AND " + COUNT + " >= " + to_string(PORTRAIT_SECOND_PAGE_MIN_PICTURES_COUNT) + " AND (" +
804                       USER_DISPLAY_LEVEL + " != 1 OR " + USER_DISPLAY_LEVEL + " IS NULL) AND (" + USER_DISPLAY_LEVEL +
805                       " != 3 OR " + USER_DISPLAY_LEVEL + " IS NULL) " + " AND NOT (" + whereClauseAlbumName +
806                       ") AND (" + ALBUM_ID + " NOT IN " + whereClauseRelatedMe + ")))" + " GROUP BY " + GROUP_TAG +
807                       " ORDER BY CASE WHEN " + IS_ME + " != 0 THEN 0 ELSE 1 END, CASE WHEN " + RENAME_OPERATION +
808                       " != 0 THEN 0 ELSE 1 END, " + COUNT + " DESC";
809     } else if (value == FAVORITE_PAGE) {
810         whereClause = ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) + " AND (" + USER_DISPLAY_LEVEL + " = 3 )GROUP BY " +
811             GROUP_TAG + " ORDER BY " + RANK;
812     } else {
813         MEDIA_ERR_LOG("The display level is invalid");
814         whereClause = "";
815     }
816     predicates.SetWhereClause(whereClause);
817 }
818 
GetPortraitSubtype(const string & subtypeName,const string & whereClause,const vector<string> & whereArgs)819 int32_t GetPortraitSubtype(const string &subtypeName, const string &whereClause, const vector<string> &whereArgs)
820 {
821     size_t pos = whereClause.find(subtypeName);
822     if (pos == string::npos) {
823         MEDIA_ERR_LOG("whereClause is invalid");
824         return E_INDEX;
825     }
826     size_t argsIndex = 0;
827     for (size_t i = 0; i < pos; i++) {
828         if (whereClause[i] == '?') {
829             argsIndex++;
830         }
831     }
832     if (argsIndex > whereArgs.size() - 1) {
833         MEDIA_ERR_LOG("whereArgs is invalid");
834         return E_INDEX;
835     }
836     return atoi(whereArgs[argsIndex].c_str());
837 }
838 
IsSupportQueryIsMe()839 bool IsSupportQueryIsMe()
840 {
841     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
842     if (uniStore == nullptr) {
843         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
844         return false;
845     }
846     const std::string queryAnalyzedPic = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + VISION_TOTAL_TABLE + " WHERE " +
847         FACE + " = " + to_string(FACE_ANALYSISED_STATE) + " OR " +
848         FACE + " = " + to_string(FACE_NO_NEED_ANALYSIS_STATE);
849     auto resultSetAnalyzed = uniStore->QuerySql(queryAnalyzedPic);
850     bool cond = (resultSetAnalyzed == nullptr || resultSetAnalyzed->GoToFirstRow() != NativeRdb::E_OK);
851     CHECK_AND_RETURN_RET(!cond, false);
852 
853     int analyzedCount;
854     if (GetIntValueFromResultSet(resultSetAnalyzed, MEDIA_COLUMN_COUNT_1, analyzedCount) != NativeRdb::E_OK) {
855         return false;
856     }
857     if (analyzedCount <= 0) {
858         return false;
859     }
860 
861     const std::string queryAllPic = "SELECT " + MEDIA_COLUMN_COUNT_1 + " FROM " + VISION_TOTAL_TABLE;
862     auto resultSetTotal = uniStore->QuerySql(queryAnalyzedPic);
863     cond = (resultSetTotal == nullptr || resultSetTotal->GoToFirstRow() != NativeRdb::E_OK);
864     CHECK_AND_RETURN_RET(!cond, false);
865     int totleCount;
866     if (GetIntValueFromResultSet(resultSetTotal, MEDIA_COLUMN_COUNT_1, totleCount) != NativeRdb::E_OK) {
867         return false;
868     }
869     if (totleCount == 0 ||
870         (analyzedCount * PERCENTAGE_FOR_SUPPORT_QUERY_ISME / totleCount <= SUPPORT_QUERY_ISME_MIN_COUNT)) {
871         MEDIA_INFO_LOG("Analyzed proportion less than 80");
872         return false;
873     }
874     return true;
875 }
876 
GetIsMeAlbumPredicates(const int32_t value,DataShare::DataSharePredicates & predicates)877 void GetIsMeAlbumPredicates(const int32_t value, DataShare::DataSharePredicates &predicates)
878 {
879     string selection;
880     if (value == QUERY_PROB_IS_ME_VALUE) {
881         if (!IsSupportQueryIsMe()) {
882             MEDIA_ERR_LOG("Not support to query isMe");
883             return;
884         }
885         selection = ANALYSIS_ALBUM_TABLE + "." + ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) +
886             " GROUP BY " + ANALYSIS_ALBUM_TABLE + "." + GROUP_TAG + " HAVING SUM(CASE WHEN " +
887             PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_FRONT_CAMERA + " = 1 THEN 1 ELSE " +
888             " 0 END) > 0 " + " ORDER BY SUM(CASE WHEN " + PhotoColumn::PHOTOS_TABLE + "." +
889             PhotoColumn::PHOTO_FRONT_CAMERA + " = 1 THEN 1 ELSE 0 END) DESC ";
890     } else if (value == QUERY_IS_ME_VALUE) {
891         selection = ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) + " AND " + IS_ME + " = 1 GROUP BY " + GROUP_TAG;
892     } else {
893         MEDIA_ERR_LOG("The value is not support for query is me");
894         return;
895     }
896     predicates.SetWhereClause(selection);
897 }
898 
GetAlbumNameNotNullPredicates(int32_t value,DataShare::DataSharePredicates & predicates)899 void GetAlbumNameNotNullPredicates(int32_t value, DataShare::DataSharePredicates &predicates)
900 {
901     if (value != ALBUM_NAME_NOT_NULL_ENABLED) {
902         MEDIA_ERR_LOG("The value is not support for query not null");
903         return;
904     }
905     string selection = ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) + " AND " + PhotoAlbumColumns::ALBUM_NAME +
906         " IS NOT NULL GROUP BY " + GROUP_TAG;
907     predicates.SetWhereClause(selection);
908 }
909 
GetIsMeLeftJoinPredicates(RdbPredicates & rdbPredicates)910 void GetIsMeLeftJoinPredicates(RdbPredicates &rdbPredicates)
911 {
912     std::string onClause = ANALYSIS_ALBUM_TABLE + "." + ALBUM_ID + " = " +
913         ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ALBUM;
914     rdbPredicates.LeftOuterJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ onClause });
915     onClause = ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ASSET + " = " +
916         PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID;
917     rdbPredicates.LeftOuterJoin(PhotoColumn::PHOTOS_TABLE)->On({ onClause });
918 }
919 
QueryPortraitAlbum(MediaLibraryCommand & cmd,const std::vector<std::string> & columns)920 std::shared_ptr<NativeRdb::ResultSet> MediaLibraryAlbumOperations::QueryPortraitAlbum(MediaLibraryCommand &cmd,
921     const std::vector<std::string> &columns)
922 {
923     auto predicates = cmd.GetAbsRdbPredicates();
924     auto whereClause = predicates->GetWhereClause();
925     auto whereArgs = predicates->GetWhereArgs();
926     DataShare::DataSharePredicates predicatesPortrait;
927     if (whereClause.find(USER_DISPLAY_LEVEL) != string::npos) {
928         int32_t value = GetPortraitSubtype(USER_DISPLAY_LEVEL, whereClause, whereArgs);
929         if (value == E_INDEX) {
930             return nullptr;
931         }
932         GetDisplayLevelAlbumPredicates(value, predicatesPortrait);
933     } else if (whereClause.find(IS_ME) != string::npos) {
934         int32_t value = GetPortraitSubtype(IS_ME, whereClause, whereArgs);
935         bool cond = (value == E_INDEX || (value != QUERY_PROB_IS_ME_VALUE && value != QUERY_IS_ME_VALUE));
936         CHECK_AND_RETURN_RET(!cond, nullptr);
937         GetIsMeAlbumPredicates(value, predicatesPortrait);
938     } else if (whereClause.find(ALBUM_NAME_NOT_NULL) != string::npos) {
939         int32_t value = GetPortraitSubtype(ALBUM_NAME_NOT_NULL, whereClause, whereArgs);
940         bool cond = (value == E_INDEX || value != ALBUM_NAME_NOT_NULL_ENABLED);
941         CHECK_AND_RETURN_RET(!cond, nullptr);
942         GetAlbumNameNotNullPredicates(value, predicatesPortrait);
943     } else {
944         MEDIA_INFO_LOG("QueryPortraitAlbum whereClause is error");
945         return nullptr;
946     }
947     if (predicatesPortrait.GetWhereClause().empty()) {
948         return nullptr;
949     }
950     auto rdbPredicates = RdbUtils::ToPredicates(predicatesPortrait, ANALYSIS_ALBUM_TABLE);
951     if (whereClause.find(IS_ME) != string::npos &&
952         GetPortraitSubtype(IS_ME, whereClause, whereArgs) == QUERY_PROB_IS_ME_VALUE) {
953         GetIsMeLeftJoinPredicates(rdbPredicates);
954         std::vector<std::string> ismeColumns;
955         for (auto &item : columns) {
956             if (item.find(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, 0) == string::npos) {
957                 ismeColumns.push_back(item);
958             }
959         }
960         ismeColumns.push_back(ANALYSIS_ALBUM_TABLE + "." + PhotoAlbumColumns::ALBUM_DATE_MODIFIED);
961         ismeColumns.push_back("CAST(" + ANALYSIS_ALBUM_TABLE + "." + PhotoAlbumColumns::ALBUM_DATE_MODIFIED +
962             " / 1000 AS BIGINT) AS date_modified_s");
963         MEDIA_INFO_LOG("start query prob is me!!!");
964         return MediaLibraryRdbStore::QueryWithFilter(rdbPredicates, ismeColumns);
965     }
966     return MediaLibraryRdbStore::QueryWithFilter(rdbPredicates, columns);
967 }
968 
QueryPhotoAlbum(MediaLibraryCommand & cmd,const vector<string> & columns)969 shared_ptr<ResultSet> MediaLibraryAlbumOperations::QueryPhotoAlbum(MediaLibraryCommand &cmd,
970     const vector<string> &columns)
971 {
972     if (cmd.GetAbsRdbPredicates()->GetOrder().empty()) {
973         cmd.GetAbsRdbPredicates()->OrderByAsc(PhotoAlbumColumns::ALBUM_ORDER);
974     }
975     return MediaLibraryRdbStore::QueryWithFilter(*(cmd.GetAbsRdbPredicates()), columns);
976 }
977 
978 /*
979  * Check for conflicts with existing albums when setting album name
980  * returns:
981  *     - positive integer album id if needs to combine with an deleted album of same lpath
982  *     - 0 if no conflicts is found and new name album can be created
983  *     - negative integer if a conflict is found or error occurs and needs to abort
984  */
CheckConflictsWithExistingAlbum(const string & newAlbumName,const shared_ptr<MediaLibraryRdbStore> & rdbStore)985 static int32_t CheckConflictsWithExistingAlbum(const string &newAlbumName,
986     const shared_ptr<MediaLibraryRdbStore>& rdbStore)
987 {
988     const std::string newLPath = ALBUM_LPATH_PREFIX + newAlbumName;
989 
990     // Check if non-deleted album with same name exists
991     std::string sql = "SELECT * FROM PhotoAlbum WHERE album_name = ? AND dirty <> ?";
992     shared_ptr<NativeRdb::ResultSet> resultSetAlbum =
993         rdbStore->QueryByStep(sql, { newAlbumName, static_cast<int32_t>(DirtyTypes::TYPE_DELETED) });
994     CHECK_AND_RETURN_RET_LOG(resultSetAlbum != nullptr, E_ERR, "Query non-deleted album with same name failed");
995     int32_t rowCount = 0;
996     CHECK_AND_RETURN_RET_LOG(resultSetAlbum->GetRowCount(rowCount) == NativeRdb::E_OK, E_ERR,
997         "Get non-deleted album with same name row count failed");
998     CHECK_AND_RETURN_RET_LOG(rowCount <= 0, E_ERR, "Non-deleted album with same name exists");
999 
1000     // Check albums with same lpath
1001     sql = "SELECT * FROM PhotoAlbum WHERE lpath = ?";
1002     resultSetAlbum = rdbStore->QueryByStep(sql, { newLPath });
1003     CHECK_AND_RETURN_RET_LOG(resultSetAlbum != nullptr, E_ERR, "Query albums with same lpath failed");
1004     CHECK_AND_RETURN_RET_LOG(resultSetAlbum->GetRowCount(rowCount) == NativeRdb::E_OK, E_ERR,
1005         "Get albums with same lpath row count failed");
1006     if (rowCount > 0) {
1007         CHECK_AND_RETURN_RET_LOG(resultSetAlbum->GoToFirstRow() == NativeRdb::E_OK, E_ERR,
1008             "Albums with same lpath go to first row failed, row count is %{public}d", rowCount);
1009         bool isDeleted = GetInt32Val(PhotoAlbumColumns::ALBUM_DIRTY, resultSetAlbum) ==
1010             static_cast<int32_t>(DirtyTypes::TYPE_DELETED);
1011         if (isDeleted) {
1012             int32_t albumId = GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSetAlbum);
1013             MEDIA_INFO_LOG("Found deleted album %{public}d with same lpath", albumId);
1014             return albumId;
1015         } else {
1016             MEDIA_ERR_LOG("Non-deleted album with same lpath exists");
1017             return E_ERR;
1018         }
1019     }
1020     return E_OK;
1021 }
1022 
BuildNewNameValuesBucket(const shared_ptr<MediaLibraryRdbStore> & rdbStore,int32_t albumId,NativeRdb::ValuesBucket & newNameValues,const string & newAlbumName,bool & isCloudAlbum)1023 static bool BuildNewNameValuesBucket(const shared_ptr<MediaLibraryRdbStore>& rdbStore, int32_t albumId,
1024     NativeRdb::ValuesBucket& newNameValues, const string& newAlbumName, bool& isCloudAlbum)
1025 {
1026     const std::string QUERY_OLD_ALBUM_INFO =
1027         "SELECT * FROM PhotoAlbum WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumId) +
1028         " AND " + PhotoAlbumColumns::ALBUM_TYPE + " = " + to_string(PhotoAlbumType::USER);
1029     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(QUERY_OLD_ALBUM_INFO);
1030     CHECK_AND_RETURN_RET_LOG(TryToGoToFirstRow(resultSet), false,
1031         "Rename user album failed. Query old album info failed");
1032     MediaLibraryAlbumFusionUtils::BuildAlbumInsertValuesSetName(rdbStore, newNameValues, resultSet, newAlbumName);
1033     const string albumCloudId = GetStringVal(PhotoAlbumColumns::ALBUM_CLOUD_ID, resultSet);
1034     isCloudAlbum = !albumCloudId.empty();
1035     return true;
1036 }
1037 
SetNewNameExecute(shared_ptr<AccurateRefresh::AlbumAccurateRefresh> albumRefresh,shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh,std::shared_ptr<TransactionOperations> trans,const shared_ptr<MediaLibraryRdbStore> & rdbStore,int32_t oldAlbumId,int64_t & newAlbumId,NativeRdb::ValuesBucket & newNameValues,bool isCloudAlbum)1038 static bool SetNewNameExecute(shared_ptr<AccurateRefresh::AlbumAccurateRefresh> albumRefresh,
1039     shared_ptr<AccurateRefresh::AssetAccurateRefresh> assetRefresh,
1040     std::shared_ptr<TransactionOperations> trans,
1041     const shared_ptr<MediaLibraryRdbStore>& rdbStore,
1042     int32_t oldAlbumId, int64_t& newAlbumId, NativeRdb::ValuesBucket& newNameValues, bool isCloudAlbum)
1043 {
1044     if (newAlbumId > 0) {
1045         // Deleted album with same lpath exists
1046         int changeRows = 0;
1047         newNameValues.PutInt(PhotoAlbumColumns::ALBUM_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_MDIRTY));
1048         RdbPredicates rdbPredicatesNew(PhotoAlbumColumns::TABLE);
1049         rdbPredicatesNew.EqualTo(PhotoAlbumColumns::ALBUM_ID, newAlbumId);
1050         CHECK_AND_RETURN_RET_LOG(albumRefresh->Update(changeRows, newNameValues, rdbPredicatesNew) == NativeRdb::E_OK,
1051             false, "Failed to update deleted album with same name");
1052         CHECK_AND_RETURN_RET_LOG(MediaLibraryAlbumFusionUtils::DeleteAlbumAndUpdateRelationship(rdbStore, oldAlbumId,
1053             newAlbumId, false, trans, albumRefresh, assetRefresh) == E_OK,
1054             false, "Failed to merge old name album with new name album");
1055         MEDIA_INFO_LOG("Set photo album name: update deleted album with same name success,"
1056             "old album id: %{public}d, new album id: %{public}" PRId64, oldAlbumId, newAlbumId);
1057     } else {
1058         newNameValues.PutInt(PhotoAlbumColumns::ALBUM_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_NEW));
1059 
1060         CHECK_AND_RETURN_RET_LOG(albumRefresh->Insert(newAlbumId, PhotoAlbumColumns::TABLE,
1061             newNameValues) == NativeRdb::E_OK, false, "Failed to insert new name album");
1062         CHECK_AND_RETURN_RET_LOG(MediaLibraryAlbumFusionUtils::DeleteAlbumAndUpdateRelationship(rdbStore, oldAlbumId,
1063             newAlbumId, isCloudAlbum, trans, albumRefresh, assetRefresh) == E_OK,
1064             false, "Failed to merge old name album with new name album");
1065         MEDIA_INFO_LOG("Set photo album name: insert new name album success,"
1066             "old album id: %{public}d, new album id: %{public}" PRId64, oldAlbumId, newAlbumId);
1067     }
1068     return true;
1069 }
1070 
UpdateAnalysisIndexAfterRename(const vector<string> & fileIdsToUpdateIndex)1071 static void UpdateAnalysisIndexAfterRename(const vector<string>& fileIdsToUpdateIndex)
1072 {
1073     MEDIA_INFO_LOG("update index fileIdsToUpdateIndex size: %{public}zu", fileIdsToUpdateIndex.size());
1074     if (fileIdsToUpdateIndex.size() > 0) {
1075         MediaAnalysisHelper::AsyncStartMediaAnalysisService(
1076             static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX),
1077             fileIdsToUpdateIndex);
1078     }
1079 }
1080 
GetAssetIdsFromOldAlbum(const shared_ptr<MediaLibraryRdbStore> & rdbStore,int32_t oldAlbumId)1081 static vector<string> GetAssetIdsFromOldAlbum(const shared_ptr<MediaLibraryRdbStore>& rdbStore,
1082     int32_t oldAlbumId)
1083 {
1084     const std::string  QUERY_FILEID_TO_UPDATE_INDEX =
1085         "SELECT file_id FROM Photos WHERE dirty != '4' AND owner_album_id = " + to_string(oldAlbumId);
1086     vector<string> fileIds;
1087     shared_ptr<NativeRdb::ResultSet> queryIdsResultSet = rdbStore->QuerySql(QUERY_FILEID_TO_UPDATE_INDEX);
1088     CHECK_AND_PRINT_LOG(queryIdsResultSet != nullptr, "Query file id to update index failed");
1089     while (queryIdsResultSet != nullptr && queryIdsResultSet->GoToNextRow() == NativeRdb::E_OK) {
1090         fileIds.push_back(to_string(GetInt32Val("file_id", queryIdsResultSet)));
1091     }
1092     return fileIds;
1093 }
1094 
1095 // Set album name: delete old and build a new one
RenameUserAlbum(int32_t oldAlbumId,const string & newAlbumName)1096 static int32_t RenameUserAlbum(int32_t oldAlbumId, const string &newAlbumName)
1097 {
1098     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1099     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Rename user album failed. RdbStore is null");
1100     CHECK_AND_RETURN_RET_LOG(oldAlbumId > 0, E_INVALID_ARGS, "Rename user album failed. Invalid album id: %{public}d",
1101         oldAlbumId);
1102     CHECK_AND_RETURN_RET_LOG(MediaFileUtils::CheckAlbumName(newAlbumName) == E_OK, E_INVALID_ARGS,
1103         "Check album name failed");
1104     MEDIA_INFO_LOG("Start to set user album name of id %{public}d", oldAlbumId);
1105 
1106     vector<string> fileIdsToUpdateIndex = GetAssetIdsFromOldAlbum(rdbStore, oldAlbumId);
1107 
1108     bool argInvalid { false };
1109     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
1110     int64_t newAlbumId = -1;
1111 
1112     auto albumRefresh = make_shared<AccurateRefresh::AlbumAccurateRefresh>(
1113         AccurateRefresh::RENAME_USER_ALBUM_BUSSINESS_NAME, trans);
1114     auto dfxRefreshManager = albumRefresh->GetDfxRefreshManager();
1115     albumRefresh->CloseDfxReport();
1116     auto assetRefresh = make_shared<AccurateRefresh::AssetAccurateRefresh>(
1117         AccurateRefresh::RENAME_USER_ALBUM_BUSSINESS_NAME, trans);
1118     if (dfxRefreshManager != nullptr) {
1119         assetRefresh->SetDfxRefreshManager(dfxRefreshManager);
1120     }
1121     std::function<int(void)> trySetUserAlbumName = [&]()->int {
1122         newAlbumId = -1;
1123         int32_t ret = CheckConflictsWithExistingAlbum(newAlbumName, rdbStore);
1124         if (ret < 0) {
1125             MEDIA_ERR_LOG("New name conflicts with existing album");
1126             argInvalid = true;
1127             return E_OK;
1128         } else if (ret > 0) {
1129             newAlbumId = ret;
1130         }
1131         NativeRdb::ValuesBucket newNameValues {};
1132         bool isCloudAlbum {};
1133         if (!BuildNewNameValuesBucket(rdbStore, oldAlbumId, newNameValues, newAlbumName, isCloudAlbum)) {
1134             MEDIA_ERR_LOG("Build new name values bucket failed");
1135             argInvalid = true;
1136             return E_OK;
1137         }
1138         CHECK_AND_RETURN_RET_LOG(
1139             SetNewNameExecute(albumRefresh, assetRefresh,
1140             trans, rdbStore, oldAlbumId, newAlbumId, newNameValues, isCloudAlbum),
1141             E_HAS_DB_ERROR, "Set new name execute failed");
1142         return E_OK;
1143     };
1144     int ret = trans->RetryTrans(trySetUserAlbumName);
1145     if (argInvalid) {
1146         return E_INVALID_ARGS;
1147     }
1148     CHECK_AND_RETURN_RET_LOG(ret == E_OK, E_HAS_DB_ERROR, "Try trans fail!, ret: %{public}d", ret);
1149 
1150     UpdateAnalysisIndexAfterRename(fileIdsToUpdateIndex);
1151 
1152     auto watch = MediaLibraryNotify::GetInstance();
1153     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1154 
1155     albumRefresh->Notify();
1156     assetRefresh->Notify();
1157     watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoAlbumColumns::ALBUM_URI_PREFIX,
1158         to_string(newAlbumId)), NotifyType::NOTIFY_UPDATE);
1159     return ALBUM_SETNAME_OK;
1160 }
1161 
PrepareCoverUriUpdateValues(ValuesBucket & updateValues,const string & newCoverUri)1162 int32_t PrepareCoverUriUpdateValues(ValuesBucket& updateValues, const string& newCoverUri)
1163 {
1164     updateValues.PutString(PhotoAlbumColumns::ALBUM_COVER_URI, newCoverUri);
1165 
1166     if (updateValues.IsEmpty()) {
1167         return -EINVAL;
1168     }
1169     updateValues.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
1170     return E_OK;
1171 }
1172 
GetOldAlbumInfo(int32_t albumId,string & oldAlbumName,string & oldAlbumCoverUri)1173 static bool GetOldAlbumInfo(int32_t albumId, string& oldAlbumName, string& oldAlbumCoverUri)
1174 {
1175     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1176     if (rdbStore == nullptr) {
1177         MEDIA_ERR_LOG("Get old album info failed. RdbStore is null");
1178         return false;
1179     }
1180     const std::string QUERY_ALBUM_INFO =
1181         "SELECT album_name, cover_uri FROM PhotoAlbum WHERE " +
1182         PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumId);
1183     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(QUERY_ALBUM_INFO);
1184     if (resultSet == nullptr) {
1185         MEDIA_ERR_LOG("Get old album info failed. Query album info failed");
1186         return false;
1187     }
1188     if (resultSet->GoToNextRow() != NativeRdb::E_OK) {
1189         MEDIA_ERR_LOG("Get old album info failed. Go to next row failed");
1190         return false;
1191     }
1192     oldAlbumName = GetStringVal(PhotoAlbumColumns::ALBUM_NAME, resultSet);
1193     oldAlbumCoverUri = GetStringVal(PhotoAlbumColumns::ALBUM_COVER_URI, resultSet);
1194     return true;
1195 }
1196 
NotifyAlbumUpdate(const AbsRdbPredicates & predicates,const int32_t notIdArgs)1197 int32_t NotifyAlbumUpdate(const AbsRdbPredicates &predicates, const int32_t notIdArgs)
1198 {
1199     int32_t ret = E_OK;
1200     auto watch = MediaLibraryNotify::GetInstance();
1201     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1202         const vector<string> &notifyIds = predicates.GetWhereArgs();
1203     size_t count = notifyIds.size() - notIdArgs;
1204     for (size_t i = 0; i < count; i++) {
1205         ret = watch->Notify(MediaFileUtils::GetUriByExtrConditions(PhotoAlbumColumns::ALBUM_URI_PREFIX,
1206             notifyIds[i]), NotifyType::NOTIFY_UPDATE);
1207         CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Notify album update failed");
1208     }
1209     return ret;
1210 }
1211 
CommitModifyUpdateAlbumCoverUri(int32_t albumId,RdbPredicates & rdbPredicates,const string & newAlbumCoverUri,AlbumAccurateRefresh & albumRefresh)1212 static int32_t CommitModifyUpdateAlbumCoverUri(int32_t albumId, RdbPredicates& rdbPredicates,
1213     const string& newAlbumCoverUri, AlbumAccurateRefresh& albumRefresh)
1214 {
1215     ValuesBucket rdbValues;
1216     int32_t err = PrepareCoverUriUpdateValues(rdbValues, newAlbumCoverUri);
1217     CHECK_AND_RETURN_RET_LOG(err >= 0, err, "No values to update");
1218     // Only user generic albums can be updated
1219     rdbPredicates.And()->BeginWrap()->EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::USER));
1220     rdbPredicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
1221     rdbPredicates.Or()->EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::SMART));
1222     rdbPredicates.EndWrap();
1223 
1224     int32_t changedRows = -1;
1225     err = albumRefresh.Update(changedRows, rdbValues, rdbPredicates);
1226     CHECK_AND_PRINT_LOG(changedRows >= 0, "Update photo album failed: %{public}d", err);
1227     return changedRows;
1228 }
1229 
IsAlbumExist(int32_t albumId)1230 static bool IsAlbumExist(int32_t albumId)
1231 {
1232     RdbPredicates rdbPredicates(PhotoAlbumColumns::TABLE);
1233     rdbPredicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(albumId));
1234     rdbPredicates.And()->BeginWrap()->EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::USER));
1235     rdbPredicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
1236     rdbPredicates.Or()->EqualTo(PhotoAlbumColumns::ALBUM_TYPE, to_string(PhotoAlbumType::SMART));
1237     rdbPredicates.EndWrap();
1238     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1239     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "RdbStore is null");
1240     auto resultSet = rdbStore->QueryByStep(rdbPredicates, { PhotoAlbumColumns::ALBUM_ID });
1241     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "Query photo album failed");
1242     if (resultSet->GoToFirstRow() == NativeRdb::E_OK) {
1243         return true;
1244     }
1245     return false;
1246 }
1247 
UpdatePhotoAlbum(const ValuesBucket & values,const DataSharePredicates & predicates)1248 int32_t MediaLibraryAlbumOperations::UpdatePhotoAlbum(const ValuesBucket &values, const DataSharePredicates &predicates)
1249 {
1250     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, PhotoAlbumColumns::TABLE);
1251     CHECK_AND_RETURN_RET_LOG(!rdbPredicates.GetWhereArgs().empty(), E_INVALID_ARGS,
1252         "Update photo album failed. Predicates empty");
1253     int32_t albumId = atoi(rdbPredicates.GetWhereArgs()[0].c_str());
1254     CHECK_AND_RETURN_RET_LOG(albumId > 0, E_INVALID_ARGS,
1255         "Invalid album id: %{public}s", rdbPredicates.GetWhereArgs()[0].c_str());
1256 
1257     string oldAlbumName {};
1258     string oldAlbumCoverUri {};
1259     string newAlbumName {};
1260     string newAlbumCoverUri {};
1261     bool needChangeCover = false;
1262     bool needRename = false;
1263 
1264     CHECK_AND_RETURN_RET_LOG(GetOldAlbumInfo(albumId, oldAlbumName, oldAlbumCoverUri), E_OK,
1265         "Get old album info failed");
1266 
1267     if (GetStringObject(values, PhotoAlbumColumns::ALBUM_COVER_URI, newAlbumCoverUri) == E_OK &&
1268         oldAlbumCoverUri != newAlbumCoverUri) {
1269         needChangeCover = true;
1270     }
1271     if (GetStringObject(values, PhotoAlbumColumns::ALBUM_NAME, newAlbumName) == E_OK &&
1272         oldAlbumName != newAlbumName) {
1273         needRename = true;
1274     }
1275     if (!needChangeCover && !needRename) {
1276         MEDIA_WARN_LOG("Update photo album %{public}d with empty values, return", albumId);
1277         return E_OK;
1278     }
1279 
1280     MEDIA_INFO_LOG("Start to update album %{public}d, new name: %{public}s, new cover: %{public}s", albumId,
1281         needRename ? DfxUtils::GetSafeAlbumName(newAlbumName).c_str() : "null",
1282         needChangeCover ? DfxUtils::GetSafeUri(newAlbumCoverUri).c_str() : "null");
1283 
1284     int32_t changedRows = 0;
1285     if (needChangeCover) {
1286         AlbumAccurateRefresh albumRefresh(AccurateRefresh::UPDATE_PHOTO_ALBUM_BUSSINESS_NAME);
1287         changedRows = CommitModifyUpdateAlbumCoverUri(albumId, rdbPredicates, newAlbumCoverUri, albumRefresh);
1288         if (changedRows > 0 && !needRename) { // No need to notify if album is to be renamed. Rename process will notify
1289             albumRefresh.Notify();
1290             const int32_t notIdArgs = 3;
1291             auto ret = NotifyAlbumUpdate(rdbPredicates, notIdArgs);
1292             CHECK_AND_PRINT_LOG(ret == E_OK, "Notify album update failed, ret:%{public}d", ret);
1293         }
1294     } else {
1295         changedRows = (IsAlbumExist(albumId) ? 1 : 0);
1296     }
1297 
1298     if (needRename) {
1299         // Rename process changes the album id, so put the rename process at the end
1300         int32_t ret = RenameUserAlbum(albumId, newAlbumName);
1301         CHECK_AND_RETURN_RET_LOG(ret >= 0, ret, "Rename user album failed");
1302     }
1303 
1304     return changedRows;
1305 }
1306 
IsManunalCloudCover(const string & fileId,string & coverCloudId)1307 bool MediaLibraryAlbumOperations::IsManunalCloudCover(const string &fileId, string &coverCloudId)
1308 {
1309     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1310     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "Failed to get rdbStore when query");
1311     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1312     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1313 
1314     vector<string> columns = {PhotoColumn::PHOTO_CLOUD_ID};
1315     auto resultSet = rdbStore->Query(predicates, columns);
1316     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "failed to acquire result from visitor query.");
1317     bool ret = false;
1318     if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1319         coverCloudId = get<std::string>(ResultSetUtils::GetValFromColumn(PhotoColumn::PHOTO_CLOUD_ID,
1320             resultSet, TYPE_STRING));
1321         ret = coverCloudId != "";
1322     } else {
1323         MEDIA_ERR_LOG("resultSet GoToNextRow failed, fileId:%{public}s, coverCloudId:%{public}s",
1324             fileId.c_str(), coverCloudId.c_str());
1325     }
1326     resultSet->Close();
1327     return ret;
1328 }
1329 
UpdateCoverUriExecute(const SetCoverUriAlbumInfo & albumInfo,const string & coverUri,const string & fileId,int64_t coverDateTime,AlbumAccurateRefresh & albumRefresh)1330 int32_t MediaLibraryAlbumOperations::UpdateCoverUriExecute(const SetCoverUriAlbumInfo& albumInfo,
1331     const string &coverUri, const string &fileId, int64_t coverDateTime, AlbumAccurateRefresh& albumRefresh)
1332 {
1333     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
1334     ValuesBucket values;
1335     values.PutString(PhotoAlbumColumns::ALBUM_COVER_URI, coverUri);
1336     auto dateModified = MediaFileUtils::UTCTimeMilliSeconds();
1337     values.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, dateModified);
1338     values.PutLong(PhotoAlbumColumns::COVER_DATE_TIME, coverDateTime);
1339     string cloudId;
1340     bool isManunalCloudCover = IsManunalCloudCover(fileId, cloudId);
1341     MEDIA_INFO_LOG("albumId:%{public}d, coverUri:%{public}s, isManunalCloudCover:%{public}d",
1342         albumInfo.albumId, coverUri.c_str(), isManunalCloudCover);
1343     if (isManunalCloudCover) {
1344         values.PutInt(PhotoAlbumColumns::COVER_URI_SOURCE, CoverUriSource::MANUAL_CLOUD_COVER);
1345         values.PutString(PhotoAlbumColumns::COVER_CLOUD_ID, to_string(dateModified) + "," + cloudId);
1346         if (albumInfo.dirty == static_cast<int32_t>(DirtyTypes::TYPE_SYNCED)) {
1347             values.PutInt(PhotoAlbumColumns::ALBUM_DIRTY, static_cast<int32_t>(DirtyTypes::TYPE_MDIRTY));
1348         }
1349     } else {
1350         values.PutInt(PhotoAlbumColumns::COVER_URI_SOURCE, CoverUriSource::MANUAL_LOCAL_COVER);
1351         values.PutString(PhotoAlbumColumns::COVER_CLOUD_ID, to_string(dateModified) + ",");
1352     }
1353 
1354     string CHECK_COVER_VALID =
1355         PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumInfo.albumId) + " AND EXISTS (SELECT 1 FROM " +
1356         PhotoColumn::PHOTOS_TABLE + " WHERE " + MediaColumn::MEDIA_ID + " = " + fileId + " AND " +
1357         MediaColumn::MEDIA_DATE_TRASHED + " >= 0 AND " + MediaColumn::MEDIA_HIDDEN + " = 0 AND " +
1358         MediaColumn::MEDIA_TIME_PENDING + " = 0 AND " + PhotoColumn::PHOTO_IS_TEMP + " = 0 AND " +
1359         PhotoColumn::PHOTO_BURST_COVER_LEVEL + " = " + to_string(static_cast<int32_t>(BurstCoverLevelType::COVER)) +
1360         " AND " + PhotoColumn::PHOTO_SYNC_STATUS + " = 0 AND " + PhotoColumn::PHOTO_CLEAN_FLAG + " = 0)";
1361 
1362     predicates.SetWhereClause(CHECK_COVER_VALID);
1363     int32_t changedRows = albumRefresh.UpdateWithDateTime(values, predicates);
1364     CHECK_AND_PRINT_LOG(changedRows >= 0, "Update photo album failed: %{public}d", changedRows);
1365 
1366     return changedRows;
1367 }
1368 
GetQueryColumn(int32_t albumSubtype)1369 std::string GetQueryColumn(int32_t albumSubtype)
1370 {
1371     string queryColumn = MediaColumn::MEDIA_DATE_TAKEN;
1372     if (albumSubtype == PhotoAlbumSubType::VIDEO || albumSubtype == PhotoAlbumSubType::IMAGE) {
1373         queryColumn = MediaColumn::MEDIA_DATE_ADDED;
1374     }
1375     return queryColumn;
1376 }
1377 
GetCoverDateTime(const string & fileId,int32_t albumSubtype)1378 int64_t GetCoverDateTime(const string &fileId, int32_t albumSubtype)
1379 {
1380     auto columnName = GetQueryColumn(albumSubtype);
1381     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1382     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "Failed to get rdbStore when query");
1383     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1384     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1385 
1386     vector<string> columns = {columnName};
1387     auto resultSet = rdbStore->Query(predicates, columns);
1388     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false, "failed to acquire result from visitor query.");
1389     int64_t coverDateTime = 0;
1390     if (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1391         coverDateTime = get<int64_t>(ResultSetUtils::GetValFromColumn(columnName,
1392             resultSet, TYPE_INT64));
1393     } else {
1394         MEDIA_ERR_LOG("resultSet GoToNextRow failed, fileId:%{public}s", fileId.c_str());
1395     }
1396     resultSet->Close();
1397     return coverDateTime;
1398 }
1399 
QueryAlbumInfo(int32_t albumId,SetCoverUriAlbumInfo & albumInfo)1400 static int32_t QueryAlbumInfo(int32_t albumId, SetCoverUriAlbumInfo& albumInfo)
1401 {
1402     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1403     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_FAIL, "Failed to get rdbStore when query");
1404     const std::string QUERY_ALBUM_INFO =
1405         "SELECT dirty FROM PhotoAlbum WHERE album_id = ?";
1406     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(QUERY_ALBUM_INFO, { albumId });
1407     CHECK_AND_RETURN_RET_LOG(TryToGoToFirstRow(resultSet), E_FAIL, "Get album info failed. Query album info failed");
1408     albumInfo.albumId = albumId;
1409     albumInfo.dirty = GetInt32Val(PhotoAlbumColumns::ALBUM_DIRTY, resultSet);
1410     return E_OK;
1411 }
1412 
UpdateAlbumCoverUri(const ValuesBucket & values,const DataSharePredicates & predicates,bool isSystemAlbum)1413 int32_t MediaLibraryAlbumOperations::UpdateAlbumCoverUri(const ValuesBucket &values,
1414     const DataSharePredicates &predicates, bool isSystemAlbum)
1415 {
1416     // 1.get album id
1417     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, PhotoAlbumColumns::TABLE);
1418     CHECK_AND_RETURN_RET_LOG(!rdbPredicates.GetWhereArgs().empty(), E_INVALID_ARGS,
1419         "Update photo album failed. Predicates empty");
1420     int32_t albumId = atoi(rdbPredicates.GetWhereArgs()[0].c_str());
1421     CHECK_AND_RETURN_RET_LOG(albumId > 0, E_INVALID_ARGS,
1422         "Invalid album id: %{public}s", rdbPredicates.GetWhereArgs()[0].c_str());
1423 
1424     // 2.get fileId and determine if cover in the album
1425     string coverUri;
1426     int32_t ret = GetStringObject(values, PhotoAlbumColumns::ALBUM_COVER_URI, coverUri);
1427     CHECK_AND_RETURN_RET_LOG((ret == E_OK), ret, "GetStringObject error");
1428 
1429     int32_t albumSubtype = -1;
1430     if (isSystemAlbum) {
1431         int ret = GetIntVal(values, PhotoAlbumColumns::ALBUM_SUBTYPE, albumSubtype);
1432         CHECK_AND_RETURN_RET_LOG((ret == E_OK), ret, "GetIntVal error");
1433     }
1434     string fileId = MediaLibraryDataManagerUtils::GetFileIdFromPhotoUri(coverUri);
1435     auto coverDateTime = GetCoverDateTime(fileId, albumSubtype);
1436 
1437     // 3.update cover uri
1438     SetCoverUriAlbumInfo albumInfo;
1439     CHECK_AND_RETURN_RET_LOG(QueryAlbumInfo(albumId, albumInfo) == E_OK, E_ERR, "Query album info failed");
1440     AlbumAccurateRefresh albumRefresh;
1441     auto updateRows = UpdateCoverUriExecute(albumInfo, coverUri, fileId, coverDateTime, albumRefresh);
1442     CHECK_AND_RETURN_RET_LOG(updateRows == 1, E_ERR,
1443         "update coverUri failed ,maybe cover is invalid, updateRows = %{public}d", updateRows);
1444 
1445     // 4.notify photoalbum update
1446     albumRefresh.Notify();
1447     const int32_t notIdArgs = 0;
1448     ret = NotifyAlbumUpdate(rdbPredicates, notIdArgs);
1449     CHECK_AND_RETURN_RET_LOG(ret == E_OK, ret, "Notify album update failed");
1450     return updateRows;
1451 }
1452 
ResetCoverUri(const ValuesBucket & values,const DataSharePredicates & predicates)1453 int32_t MediaLibraryAlbumOperations::ResetCoverUri(const ValuesBucket &values, const DataSharePredicates &predicates)
1454 {
1455     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, PhotoAlbumColumns::TABLE);
1456     CHECK_AND_RETURN_RET_LOG(!rdbPredicates.GetWhereArgs().empty(), E_INVALID_ARGS,
1457         "Update photo album failed. Predicates empty");
1458     string albumId = rdbPredicates.GetWhereArgs()[0];
1459     CHECK_AND_RETURN_RET_LOG(atoi(albumId.c_str()) > 0, E_INVALID_ARGS,
1460         "Invalid album id: %{public}s", rdbPredicates.GetWhereArgs()[0].c_str());
1461 
1462     RdbPredicates newPredicates(PhotoAlbumColumns::TABLE);
1463     ValuesBucket updateValues;
1464     updateValues.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
1465     updateValues.PutInt(PhotoAlbumColumns::COVER_URI_SOURCE, CoverUriSource::DEFAULT_COVER);
1466 
1467     string UPDATE_CONDITION = PhotoAlbumColumns::ALBUM_ID + " = " + albumId + " AND " +
1468         PhotoAlbumColumns::COVER_URI_SOURCE + " > " + to_string(CoverUriSource::DEFAULT_COVER);
1469 
1470     newPredicates.SetWhereClause(UPDATE_CONDITION);
1471 
1472     int32_t changedRows = OHOS::Media::MediaLibraryRdbStore::UpdateWithDateTime(updateValues, newPredicates);
1473     CHECK_AND_PRINT_LOG(changedRows >= 0, "Update photo album failed: %{public}d", changedRows);
1474 
1475     int32_t albumSubtype = -1;
1476     int ret = GetIntVal(values, PhotoAlbumColumns::ALBUM_SUBTYPE, albumSubtype);
1477     CHECK_AND_RETURN_RET_LOG((ret == E_OK), ret, "GetIntVal error");
1478     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1479     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore.");
1480 
1481     const vector<string> subtypes = { to_string(albumSubtype) };
1482     const vector<string> albumIds = { albumId };
1483     if (albumSubtype == static_cast<int32_t>(PhotoAlbumSubType::USER_GENERIC)) {
1484         MediaLibraryRdbUtils::UpdateUserAlbumInternal(rdbStore, albumIds, true);
1485     } else if (albumSubtype == static_cast<int32_t>(PhotoAlbumSubType::SOURCE_GENERIC)) {
1486         MediaLibraryRdbUtils::UpdateSourceAlbumInternal(rdbStore, albumIds, true);
1487     } else {
1488         MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, subtypes, true);
1489     }
1490     return changedRows;
1491 }
1492 
GetLPathFromSourcePath(const string & sourcePath,string & lPath,int32_t mediaType)1493 int32_t MediaLibraryAlbumOperations::GetLPathFromSourcePath(const string& sourcePath, string& lPath,
1494                                                             int32_t mediaType)
1495 {
1496     size_t pos1 = SOURCE_PATH_PREFIX.length();
1497     size_t pos2 = sourcePath.find_last_of("/");
1498     CHECK_AND_RETURN_RET_LOG(
1499         sourcePath.find(SOURCE_PATH_PREFIX) != std::string::npos && pos2 != string::npos && pos1 < pos2,
1500         E_INDEX,
1501         "get no valid source path: %{public}s", sourcePath.c_str());
1502     lPath = sourcePath.substr(pos1, pos2 - pos1);
1503     /*
1504         if lPath from source path is /Pictures/Screenshots,
1505         it should be converted to /Pictures/Screenrecords if the asset is a video
1506     */
1507     bool cond = (lPath == AlbumPlugin::LPATH_SCREEN_SHOTS && mediaType == MEDIA_TYPE_VIDEO);
1508     CHECK_AND_EXECUTE(!cond, lPath = AlbumPlugin::LPATH_SCREEN_RECORDS);
1509     return E_OK;
1510 }
1511 
HasSameLpath(const string & lPath,const string & assetId)1512 static bool HasSameLpath(const string &lPath, const string &assetId)
1513 {
1514     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1515     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "Failed to get rdbStore.");
1516     const std::string QUERY_LPATH = "SELECT * FROM PhotoAlbum WHERE lpath = '" + lPath + "'";
1517     shared_ptr<NativeRdb::ResultSet> albumResultSet = rdbStore->QuerySql(QUERY_LPATH);
1518     if (albumResultSet == nullptr || albumResultSet->GoToFirstRow() != NativeRdb::E_OK) {
1519         return false;
1520     } else {
1521         int albumIdIndex;
1522         int32_t albumId;
1523         albumResultSet->GetColumnIndex(PhotoAlbumColumns::ALBUM_ID, albumIdIndex);
1524         CHECK_AND_RETURN_RET(albumResultSet->GetInt(albumIdIndex, albumId) == NativeRdb::E_OK, false);
1525         const std::string UPDATE_ALBUM_ID_IN_PHOTOS = "UPDATE Photos Set owner_album_id = " +
1526             to_string(albumId) + " WHERE file_id = " + assetId;
1527         int ret = rdbStore->ExecuteSql(UPDATE_ALBUM_ID_IN_PHOTOS);
1528         CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, false, "Update new album is fails");
1529     }
1530     return true;
1531 }
1532 
RecoverAlbum(const string & assetId,const string & lPath,bool & isUserAlbum,int64_t & newAlbumId)1533 void MediaLibraryAlbumOperations::RecoverAlbum(const string& assetId, const string& lPath,
1534                                                bool& isUserAlbum, int64_t& newAlbumId)
1535 {
1536     CHECK_AND_RETURN_LOG(!lPath.empty(), "lPath empty, cannot recover album");
1537     CHECK_AND_RETURN_LOG(!HasSameLpath(lPath, assetId), "Has same lpath, no need to build new one");
1538     const string userAlbumMark = "/Users/";
1539     CHECK_AND_EXECUTE(lPath.find(userAlbumMark) == string::npos, isUserAlbum = true);
1540 
1541     MEDIA_INFO_LOG("new album need to build, lpath is %{public}s", lPath.c_str());
1542     string albumName;
1543     string bundleName = "";
1544     auto albumType = PhotoAlbumType::SOURCE;
1545     auto albumSubType = PhotoAlbumSubType::SOURCE_GENERIC;
1546     string queryExpiredAlbumInfo = "SELECT * FROM album_plugin WHERE lpath = '" +
1547         lPath + "' AND priority = '1'";
1548     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1549     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
1550     shared_ptr<NativeRdb::ResultSet> albumPluginResultSet = rdbStore->QuerySql(queryExpiredAlbumInfo);
1551     if (albumPluginResultSet == nullptr || albumPluginResultSet->GoToFirstRow() != NativeRdb::E_OK) {
1552         size_t pos = lPath.find_last_of("/");
1553         CHECK_AND_RETURN_LOG(
1554             pos != string::npos && pos + 1 < lPath.length(),
1555             "get album name fail, lpath is %{public}s", lPath.c_str());
1556         albumName = lPath.substr(pos + 1);
1557         if (isUserAlbum) {
1558             albumType = PhotoAlbumType::USER;
1559             albumSubType = PhotoAlbumSubType::USER_GENERIC;
1560         }
1561     } else {
1562         GetStringValueFromResultSet(albumPluginResultSet, PhotoAlbumColumns::ALBUM_BUNDLE_NAME, bundleName);
1563         GetStringValueFromResultSet(albumPluginResultSet, PhotoAlbumColumns::ALBUM_NAME, albumName);
1564     }
1565 
1566     NativeRdb::ValuesBucket values;
1567     values.PutInt(PhotoAlbumColumns::ALBUM_PRIORITY, 1);
1568     values.PutInt(PhotoAlbumColumns::ALBUM_TYPE, albumType);
1569     values.PutInt(PhotoAlbumColumns::ALBUM_SUBTYPE, albumSubType);
1570     values.PutString(PhotoAlbumColumns::ALBUM_LPATH, lPath);
1571     values.PutString(PhotoAlbumColumns::ALBUM_NAME, albumName);
1572     values.PutString(PhotoAlbumColumns::ALBUM_BUNDLE_NAME, bundleName);
1573     values.PutLong(PhotoAlbumColumns::ALBUM_DATE_MODIFIED, MediaFileUtils::UTCTimeMilliSeconds());
1574     values.PutLong(PhotoAlbumColumns::ALBUM_DATE_ADDED, MediaFileUtils::UTCTimeMilliSeconds());
1575     int32_t ret = rdbStore->Insert(newAlbumId, PhotoAlbumColumns::TABLE, values);
1576 
1577     CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK, "Insert album failed on recover assets");
1578     const std::string UPDATE_NEW_ALBUM_ID_IN_PHOTOS = "UPDATE Photos SET owner_album_id = " +
1579         to_string(newAlbumId) + " WHERE file_id = " + assetId;
1580     ret = rdbStore->ExecuteSql(UPDATE_NEW_ALBUM_ID_IN_PHOTOS);
1581     CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK, "Update new album is fails");
1582 }
1583 
DealwithNoAlbumAssets(const vector<string> & whereArgs)1584 void MediaLibraryAlbumOperations::DealwithNoAlbumAssets(const vector<string> &whereArgs)
1585 {
1586     MediaLibraryTracer tracer;
1587     tracer.Start("MediaLibraryAlbumOperations::DealwithNoAlbumAssets");
1588     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1589     if (uniStore == nullptr) {
1590         MEDIA_ERR_LOG("get uniStore fail");
1591         return;
1592     }
1593     int32_t ret = PhotoOwnerAlbumIdOperation().SetRdbStore(uniStore).SetFileIds(whereArgs).FixPhotoRelation();
1594     CHECK_AND_RETURN_LOG(ret == E_OK, "Fix photo relation failed");
1595 }
1596 
isRecoverToHiddenAlbum(const string & uri)1597 static bool isRecoverToHiddenAlbum(const string& uri)
1598 {
1599     string fileId = MediaFileUtils::GetIdFromUri(uri);
1600     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1601     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
1602     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1603     if (uniStore == nullptr) {
1604         MEDIA_ERR_LOG("get uniStore fail");
1605         return false;
1606     }
1607     vector<string> columns = { MediaColumn::MEDIA_HIDDEN };
1608     auto resultSet = uniStore->Query(predicates, columns);
1609     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1610         MEDIA_ERR_LOG("fail to query file on photo");
1611         return false;
1612     }
1613     int isHiddenIndex = -1;
1614     int32_t isHidden = 0;
1615     resultSet->GetColumnIndex(MediaColumn::MEDIA_HIDDEN, isHiddenIndex);
1616     if (resultSet->GetInt(isHiddenIndex, isHidden) != NativeRdb::E_OK) {
1617         return false;
1618     }
1619     return isHidden == 1;
1620 }
1621 
RecoverPhotoAssets(const DataSharePredicates & predicates)1622 int32_t MediaLibraryAlbumOperations::RecoverPhotoAssets(const DataSharePredicates &predicates)
1623 {
1624     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, PhotoColumn::PHOTOS_TABLE);
1625     rdbPredicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
1626     vector<string> whereArgs = rdbPredicates.GetWhereArgs();
1627     MediaLibraryRdbStore::ReplacePredicatesUriToId(rdbPredicates);
1628 
1629     MediaLibraryAlbumOperations::DealwithNoAlbumAssets(rdbPredicates.GetWhereArgs());
1630     // notify deferred processing session to restore image
1631     MultiStagesCaptureManager::RestorePhotos(rdbPredicates);
1632 
1633     ValuesBucket rdbValues;
1634     rdbValues.PutInt(MediaColumn::MEDIA_DATE_TRASHED, 0);
1635 
1636     AssetAccurateRefresh assetRefresh(AccurateRefresh::RECOVER_ASSETS_BUSSINESS_NAME);
1637     int32_t changedRows = assetRefresh.UpdateWithDateTime(rdbValues, rdbPredicates);
1638     if (changedRows < 0) {
1639         return changedRows;
1640     }
1641 
1642     // set cloud enhancement to available
1643 #ifdef MEDIALIBRARY_FEATURE_CLOUD_ENHANCEMENT
1644     EnhancementManager::GetInstance().RecoverTrashUpdateInternal(rdbPredicates.GetWhereArgs());
1645 #endif
1646     MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
1647         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), whereArgs);
1648     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1649     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Failed to get rdbStore");
1650     MediaLibraryRdbUtils::UpdateAnalysisAlbumByUri(rdbStore, whereArgs);
1651     assetRefresh.RefreshAlbum(NotifyAlbumType::SYS_ALBUM);
1652 
1653     auto watch = MediaLibraryNotify::GetInstance();
1654     CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
1655     size_t count = whereArgs.size() - THAN_AGR_SIZE;
1656     for (size_t i = 0; i < count; i++) {
1657         string notifyUri = MediaFileUtils::Encode(whereArgs[i]);
1658         if (isRecoverToHiddenAlbum(notifyUri)) {
1659             watch->Notify(notifyUri, NotifyType::NOTIFY_UPDATE);
1660         } else {
1661             watch->Notify(notifyUri, NotifyType::NOTIFY_ADD);
1662             watch->Notify(notifyUri, NotifyType::NOTIFY_THUMB_ADD);
1663         }
1664         watch->Notify(notifyUri, NotifyType::NOTIFY_ALBUM_ADD_ASSET);
1665     }
1666     int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
1667     if (trashAlbumId > 0) {
1668         for (size_t i = 0; i < count; i++) {
1669             watch->Notify(MediaFileUtils::Encode(whereArgs[i]), NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, trashAlbumId);
1670         }
1671     }
1672     assetRefresh.Notify();
1673     return changedRows;
1674 }
1675 
DealWithHighlightSdTable(const DataSharePredicates & predicates)1676 void DealWithHighlightSdTable(const DataSharePredicates &predicates)
1677 {
1678     RdbPredicates assetMapPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_ASSET_MAP_TABLE);
1679     const vector<string> &whereUriArgs = assetMapPredicates.GetWhereArgs();
1680     vector<string> whereIdArgs;
1681     whereIdArgs.reserve(whereUriArgs.size());
1682     for (const auto &arg : whereUriArgs) {
1683         if (!MediaFileUtils::StartsWith(arg, PhotoColumn::PHOTO_URI_PREFIX)) {
1684             continue;
1685         }
1686         whereIdArgs.push_back(MediaFileUri::GetPhotoId(arg));
1687     }
1688     assetMapPredicates.SetWhereArgs(whereIdArgs);
1689 
1690     RdbPredicates predicatesSdMap(ANALYSIS_ASSET_SD_MAP_TABLE);
1691     predicatesSdMap.And()->In(MAP_ASSET_SOURCE, assetMapPredicates.GetWhereArgs());
1692     vector<string> columns = { MAP_ASSET_SOURCE, MAP_ASSET_DESTINATION };
1693     auto resultSetQuery = MediaLibraryRdbStore::QueryWithFilter(predicatesSdMap, columns);
1694     if (resultSetQuery == nullptr) {
1695         MEDIA_ERR_LOG("get highlight video failed");
1696         return;
1697     }
1698 
1699     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1700     if (rdbStore == nullptr) {
1701         MEDIA_ERR_LOG("Can not get rdbstore");
1702         return;
1703     }
1704     while (resultSetQuery->GoToNextRow() == NativeRdb::E_OK) {
1705         string assetId = to_string(GetInt32Val(MAP_ASSET_SOURCE, resultSetQuery));
1706         int32_t mapAssetDestination = GetInt32Val(MAP_ASSET_DESTINATION, resultSetQuery);
1707 
1708         string highlightVideoPath = "/storage/cloud/files/highlight/video/" + to_string(mapAssetDestination);
1709         MediaFileUtils::DeleteDir(highlightVideoPath);
1710         MEDIA_INFO_LOG("Delete highlight video path is: %{public}s", highlightVideoPath.c_str());
1711 
1712         const std::string DELETE_ITEM_FROM_SD_MAP =
1713             "DELETE FROM tab_analysis_asset_sd_map WHERE map_asset_source = " + assetId;
1714         int32_t ret = rdbStore->ExecuteSql(DELETE_ITEM_FROM_SD_MAP);
1715         CHECK_AND_CONTINUE_ERR_LOG(ret == NativeRdb::E_OK,
1716             "DELETE highlight video failed, id is: %{public}s", assetId.c_str());
1717 
1718         const std::string DELETE_ITEM_FROM_ALBUM_MAP =
1719             "DELETE FROM tab_analysis_album_asset_map WHERE map_asset = " + assetId;
1720         ret = rdbStore->ExecuteSql(DELETE_ITEM_FROM_ALBUM_MAP);
1721         CHECK_AND_CONTINUE_ERR_LOG(ret == NativeRdb::E_OK,
1722             "DELETE highlight video failed, id is: %{public}s", assetId.c_str());
1723     }
1724     MEDIA_INFO_LOG("Deal with highlight video finished");
1725 }
1726 
DeletePhotoAssets(const DataSharePredicates & predicates,const bool isAging,const bool compatible)1727 int32_t MediaLibraryAlbumOperations::DeletePhotoAssets(const DataSharePredicates &predicates,
1728     const bool isAging, const bool compatible)
1729 {
1730     DealWithHighlightSdTable(predicates);
1731     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, PhotoColumn::PHOTOS_TABLE);
1732     int32_t deletedRows = MediaLibraryAssetOperations::DeleteFromDisk(rdbPredicates, isAging, compatible);
1733     if (!isAging) {
1734         MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
1735             static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_DELETE_INDEX));
1736     }
1737     return deletedRows;
1738 }
1739 
DeletePhotoAssetsCompleted(const DataSharePredicates & predicates,const bool isAging)1740 int32_t MediaLibraryAlbumOperations::DeletePhotoAssetsCompleted(
1741     const DataSharePredicates &predicates, const bool isAging)
1742 {
1743     MEDIA_INFO_LOG("DeletePhotoAssetsCompleted start.");
1744     DealWithHighlightSdTable(predicates);
1745     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, PhotoColumn::PHOTOS_TABLE);
1746     int32_t deletedRows = MediaLibraryAssetOperations::DeletePermanently(rdbPredicates, isAging);
1747     CHECK_AND_EXECUTE(isAging,  MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
1748         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_DELETE_INDEX)));
1749     return deletedRows;
1750 }
1751 
AgingPhotoAssets(shared_ptr<int> countPtr)1752 int32_t AgingPhotoAssets(shared_ptr<int> countPtr)
1753 {
1754     auto time = MediaFileUtils::UTCTimeMilliSeconds();
1755     DataSharePredicates predicates;
1756     predicates.GreaterThan(MediaColumn::MEDIA_DATE_TRASHED, to_string(0));
1757     predicates.And()->LessThanOrEqualTo(MediaColumn::MEDIA_DATE_TRASHED, to_string(time - AGING_TIME));
1758     int32_t ret = MediaLibraryAlbumOperations::DeletePhotoAssets(predicates, true, false);
1759     if (ret < 0) {
1760         return ret;
1761     }
1762     if (countPtr != nullptr) {
1763         *countPtr = ret;
1764     }
1765     return E_OK;
1766 }
1767 
ObtainAlbumOrders(const int32_t & currentAlbumId,const int32_t referenceAlbumId,int32_t & currentAlbumOrder,int32_t & referenceAlbumOrder)1768 static int32_t ObtainAlbumOrders(const int32_t &currentAlbumId, const int32_t referenceAlbumId,
1769     int32_t &currentAlbumOrder, int32_t &referenceAlbumOrder)
1770 {
1771     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1772     if (uniStore == nullptr) {
1773         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
1774         return E_HAS_DB_ERROR;
1775     }
1776     const std::string queryCurrentAlbumOrder = "SELECT " + PhotoAlbumColumns::ALBUM_ORDER + " FROM " +
1777         PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId);
1778     const std::string queryReferenceAlbumOrder = "SELECT " + PhotoAlbumColumns::ALBUM_ORDER + " FROM " +
1779         PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(referenceAlbumId);
1780     auto resultSet = uniStore->QuerySql(queryCurrentAlbumOrder);
1781     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1782         return E_HAS_DB_ERROR;
1783     }
1784     int colIndex = -1;
1785     resultSet->GetColumnIndex(PhotoAlbumColumns::ALBUM_ORDER, colIndex);
1786     if (resultSet->GetInt(colIndex, currentAlbumOrder) != NativeRdb::E_OK) {
1787         return E_HAS_DB_ERROR;
1788     }
1789     resultSet = uniStore->QuerySql(queryReferenceAlbumOrder);
1790     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK
1791         || resultSet->GetInt(colIndex, referenceAlbumOrder) != NativeRdb::E_OK) {
1792         return E_HAS_DB_ERROR;
1793     }
1794     return E_OK;
1795 }
1796 
ExecuteSqls(AlbumAccurateRefresh & albumRefresh,const vector<string> & sqls,RdbOperation operation)1797 static int32_t ExecuteSqls(AlbumAccurateRefresh &albumRefresh, const vector<string> &sqls, RdbOperation operation)
1798 {
1799     int32_t err = NativeRdb::E_OK;
1800     for (const auto &sql : sqls) {
1801         err = albumRefresh.ExecuteSql(sql, operation);
1802         if (err != NativeRdb::E_OK) {
1803             MEDIA_ERR_LOG("Failed to exec: %{private}s", sql.c_str());
1804             break;
1805         }
1806     }
1807     return NativeRdb::E_OK;
1808 }
1809 
ExecSqls(const vector<string> & sqls,const shared_ptr<MediaLibraryRdbStore> store)1810 static int32_t ExecSqls(const vector<string> &sqls, const shared_ptr<MediaLibraryRdbStore> store)
1811 {
1812     int32_t err = NativeRdb::E_OK;
1813     for (const auto &sql : sqls) {
1814         err = store->ExecuteSql(sql);
1815         if (err != NativeRdb::E_OK) {
1816             MEDIA_ERR_LOG("Failed to exec: %{private}s", sql.c_str());
1817             break;
1818         }
1819     }
1820     return NativeRdb::E_OK;
1821 }
1822 
ObtainNotifyAlbumIds(int32_t & currentAlbumOrder,int32_t referenceAlbumOrder,vector<int32_t> & changedAlbumIds)1823 static int32_t ObtainNotifyAlbumIds(int32_t &currentAlbumOrder, int32_t referenceAlbumOrder,
1824     vector<int32_t> &changedAlbumIds)
1825 {
1826     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1827     if (uniStore == nullptr) {
1828         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
1829         return E_DB_FAIL;
1830     }
1831     std::string queryAlbumIds = "";
1832     if (currentAlbumOrder < referenceAlbumOrder) {
1833         queryAlbumIds = "SELECT " + PhotoAlbumColumns::ALBUM_ID + " FROM " +
1834             PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ORDER + " >= " +
1835             to_string(currentAlbumOrder) + " AND " + PhotoAlbumColumns::ALBUM_ORDER +
1836             " < " + to_string(referenceAlbumOrder);
1837     } else {
1838         queryAlbumIds = "SELECT " + PhotoAlbumColumns::ALBUM_ID + " FROM " +
1839             PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ORDER + " >= " +
1840             to_string(referenceAlbumOrder) + " AND " + PhotoAlbumColumns::ALBUM_ORDER +
1841             " <= " + to_string(currentAlbumOrder);
1842     }
1843     auto resultSet = uniStore->QuerySql(queryAlbumIds);
1844     if (resultSet == nullptr) {
1845         return E_DB_FAIL;
1846     }
1847     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1848         changedAlbumIds.push_back(GetInt32Val(PhotoAlbumColumns::ALBUM_ID, resultSet));
1849     }
1850     return E_OK;
1851 }
1852 
NotifyOrderChange(vector<int32_t> & changedAlbumIds)1853 static void NotifyOrderChange(vector<int32_t> &changedAlbumIds)
1854 {
1855     if (changedAlbumIds.size() <= 0) {
1856         return;
1857     }
1858     auto watch = MediaLibraryNotify::GetInstance();
1859     CHECK_AND_RETURN_LOG(watch != nullptr, "Can not get MediaLibraryNotify Instance");
1860     for (int32_t &albumId : changedAlbumIds) {
1861         watch->Notify(MediaFileUtils::GetUriByExtrConditions(
1862             PhotoAlbumColumns::ALBUM_URI_PREFIX, to_string(albumId)), NotifyType::NOTIFY_UPDATE);
1863     }
1864 }
1865 
UpdateSortedOrder(AlbumAccurateRefresh & albumRefresh,const int32_t & currentAlbumId,const int32_t referenceAlbumId,int32_t & currentAlbumOrder,int32_t & referenceAlbumOrder)1866 static int32_t UpdateSortedOrder(AlbumAccurateRefresh &albumRefresh, const int32_t &currentAlbumId,
1867     const int32_t referenceAlbumId, int32_t &currentAlbumOrder, int32_t &referenceAlbumOrder)
1868 {
1869     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1870     if (uniStore == nullptr) {
1871         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
1872         return E_DB_FAIL;
1873     }
1874     std::string updateOtherAlbumOrder = "";
1875     std::string updateCurrentAlbumOrder = "";
1876     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
1877     if (currentAlbumOrder < referenceAlbumOrder) {
1878         predicates.BeginWrap();
1879         predicates.GreaterThan(PhotoAlbumColumns::ALBUM_ORDER, to_string(currentAlbumOrder));
1880         predicates.LessThan(PhotoAlbumColumns::ALBUM_ORDER, to_string(referenceAlbumOrder));
1881         predicates.EndWrap();
1882         updateOtherAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE +
1883             " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " +
1884             PhotoAlbumColumns::ALBUM_ORDER + " -1 WHERE " + PhotoAlbumColumns::ALBUM_ORDER +
1885             " > " + to_string(currentAlbumOrder) +
1886             " and " + PhotoAlbumColumns::ALBUM_ORDER + " < " + to_string(referenceAlbumOrder);
1887         updateCurrentAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + " SET " + PhotoAlbumColumns::ALBUM_ORDER +
1888             " = " + to_string(referenceAlbumOrder) + " -1 WHERE " +
1889             PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId);
1890     } else {
1891         predicates.BeginWrap();
1892         predicates.GreaterThanOrEqualTo(PhotoAlbumColumns::ALBUM_ORDER, to_string(referenceAlbumOrder));
1893         predicates.LessThan(PhotoAlbumColumns::ALBUM_ORDER, to_string(currentAlbumOrder));
1894         predicates.EndWrap();
1895         updateOtherAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE +
1896             " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " +
1897             PhotoAlbumColumns::ALBUM_ORDER + " +1 WHERE " + PhotoAlbumColumns::ALBUM_ORDER + " >= " +
1898             to_string(referenceAlbumOrder) + " AND " + PhotoAlbumColumns::ALBUM_ORDER +
1899             " < " + to_string(currentAlbumOrder);
1900         updateCurrentAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE +
1901             " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " +
1902             to_string(referenceAlbumOrder) + " WHERE " +
1903             PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId);
1904     }
1905     predicates.Or();
1906     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(currentAlbumId));
1907     albumRefresh.Init(predicates);
1908     vector<string> updateSortedAlbumsSqls = { updateOtherAlbumOrder, updateCurrentAlbumOrder};
1909     return ExecuteSqls(albumRefresh, updateSortedAlbumsSqls, RdbOperation::RDB_OPERATION_UPDATE);
1910 }
1911 
ObtainCurrentAlbumOrder(const int32_t & albumId,int32_t & albumOrder)1912 static int32_t ObtainCurrentAlbumOrder(const int32_t &albumId, int32_t &albumOrder)
1913 {
1914     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1915     if (uniStore == nullptr) {
1916         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
1917         return E_HAS_DB_ERROR;
1918     }
1919     const std::string queryAlbumOrder = "SELECT " + PhotoAlbumColumns::ALBUM_ORDER + " FROM " +
1920         PhotoAlbumColumns::TABLE + " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumId);
1921     auto resultSet = uniStore->QuerySql(queryAlbumOrder);
1922     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
1923         return E_HAS_DB_ERROR;
1924     }
1925     int colIndex = -1;
1926     resultSet->GetColumnIndex(PhotoAlbumColumns::ALBUM_ORDER, colIndex);
1927     if (resultSet->GetInt(colIndex, albumOrder) != NativeRdb::E_OK) {
1928         return E_HAS_DB_ERROR;
1929     }
1930     return E_OK;
1931 }
1932 
UpdateNullReferenceOrder(const int32_t & currentAlbumId,const int32_t & currentAlbumOrder,const int32_t & maxAlbumOrder)1933 static int32_t UpdateNullReferenceOrder(const int32_t &currentAlbumId,
1934     const int32_t &currentAlbumOrder, const int32_t &maxAlbumOrder)
1935 {
1936     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1937     if (uniStore == nullptr) {
1938         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
1939         return E_DB_FAIL;
1940     }
1941     std::string updateOtherAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE + " SET " +
1942         PhotoAlbumColumns::ALBUM_ORDER + " = " + PhotoAlbumColumns::ALBUM_ORDER + " -1 WHERE " +
1943         PhotoAlbumColumns::ALBUM_ORDER + " > " + to_string(currentAlbumOrder) + " and " +
1944         PhotoAlbumColumns::ALBUM_ORDER + " <= " + to_string(maxAlbumOrder);
1945     std::string updateCurrentAlbumOrder = "UPDATE " + PhotoAlbumColumns::TABLE +
1946         " SET " + PhotoAlbumColumns::ALBUM_ORDER + " = " + to_string(maxAlbumOrder) +
1947         " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = " + to_string(currentAlbumId);
1948     vector<string> updateSortedAlbumsSqls = { updateOtherAlbumOrder, updateCurrentAlbumOrder};
1949     return ExecSqls(updateSortedAlbumsSqls, uniStore);
1950 }
1951 
HandleNullReferenceCondition(const int32_t & currentAlbumId)1952 static int32_t HandleNullReferenceCondition(const int32_t &currentAlbumId)
1953 {
1954     int32_t maxAlbumOrder = 0;
1955     int err = ObtainMaxAlbumOrder(maxAlbumOrder);
1956     if (err != E_OK) {
1957         return E_HAS_DB_ERROR;
1958     }
1959     int32_t currentAlbumOrder = -1;
1960     err = ObtainCurrentAlbumOrder(currentAlbumId, currentAlbumOrder);
1961     if (err != E_OK) {
1962         return err;
1963     }
1964     vector<int32_t> changedAlbumIds;
1965     ObtainNotifyAlbumIds(currentAlbumOrder, maxAlbumOrder + 1, changedAlbumIds); // 1: move order curosr to the end
1966     err = UpdateNullReferenceOrder(currentAlbumId, currentAlbumOrder, maxAlbumOrder);
1967     if (err == E_OK) {
1968         NotifyOrderChange(changedAlbumIds);
1969     }
1970     return err;
1971 }
1972 
UpdatePortraitNullReferenceOrder(const int32_t currentAlbumId,const int32_t currentAlbumOrder,const int32_t maxAlbumOrder)1973 static int32_t UpdatePortraitNullReferenceOrder(const int32_t currentAlbumId,
1974     const int32_t currentAlbumOrder, const int32_t maxAlbumOrder)
1975 {
1976     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1977     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_DB_FAIL, "uniStore is nullptr! failed query album order");
1978     std::string updateOtherAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " +
1979         RANK + " = " + RANK + " -1 WHERE " +
1980         RANK + " > " + to_string(currentAlbumOrder) + " and " +
1981         RANK + " <= " + to_string(maxAlbumOrder);
1982     std::string updateCurrentAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE +
1983         " SET " + RANK + " = " + to_string(maxAlbumOrder) +
1984         " WHERE " + GROUP_TAG + " IN (SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE +
1985         " WHERE " + ALBUM_ID + " = " + to_string(currentAlbumId) + ")";
1986     vector<string> updateSortedAlbumsSqls = { updateOtherAlbumOrder, updateCurrentAlbumOrder };
1987     return ExecSqls(updateSortedAlbumsSqls, uniStore);
1988 }
1989 
ObtainNotifyPortraitAlbumIds(const int32_t currentAlbumOrder,const int32_t referenceAlbumOrder,vector<int32_t> & changedAlbumIds)1990 static int32_t ObtainNotifyPortraitAlbumIds(const int32_t currentAlbumOrder, const int32_t referenceAlbumOrder,
1991     vector<int32_t> &changedAlbumIds)
1992 {
1993     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
1994     if (uniStore == nullptr) {
1995         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
1996         return E_DB_FAIL;
1997     }
1998     std::string queryAlbumIds = "";
1999     if (currentAlbumOrder < referenceAlbumOrder) {
2000         queryAlbumIds = "SELECT " + ALBUM_ID + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + RANK + " >= " +
2001             to_string(currentAlbumOrder) + " AND " + RANK + " < " + to_string(referenceAlbumOrder);
2002     } else {
2003         queryAlbumIds = "SELECT " + ALBUM_ID + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + RANK + " >= " +
2004             to_string(referenceAlbumOrder) + " AND " + RANK + " <= " + to_string(currentAlbumOrder);
2005     }
2006     auto resultSet = uniStore->QuerySql(queryAlbumIds);
2007     if (resultSet == nullptr) {
2008         return E_DB_FAIL;
2009     }
2010     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2011         changedAlbumIds.push_back(GetInt32Val(ALBUM_ID, resultSet));
2012     }
2013     return E_OK;
2014 }
2015 
ObtainCurrentPortraitAlbumOrder(const int32_t albumId,int32_t & albumOrder)2016 static int32_t ObtainCurrentPortraitAlbumOrder(const int32_t albumId, int32_t &albumOrder)
2017 {
2018     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2019     if (uniStore == nullptr) {
2020         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2021         return E_HAS_DB_ERROR;
2022     }
2023     const std::string queryAlbumOrder = "SELECT " + RANK + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
2024         PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumId);
2025     auto resultSet = uniStore->QuerySql(queryAlbumOrder);
2026     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2027         return E_HAS_DB_ERROR;
2028     }
2029     return GetIntValueFromResultSet(resultSet, RANK, albumOrder);
2030 }
2031 
ObtainMaxPortraitAlbumOrder(int32_t & maxAlbumOrder)2032 static int32_t ObtainMaxPortraitAlbumOrder(int32_t &maxAlbumOrder)
2033 {
2034     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2035     if (uniStore == nullptr) {
2036         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2037         return -E_HAS_DB_ERROR;
2038     }
2039     std::string queryMaxOrderSql = "SELECT Max(rank) FROM " + ANALYSIS_ALBUM_TABLE;
2040     auto resultSet = uniStore->QuerySql(queryMaxOrderSql);
2041     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2042         MEDIA_ERR_LOG("Failed to query album!");
2043         return -E_HAS_DB_ERROR;
2044     }
2045 
2046     return resultSet->GetInt(0, maxAlbumOrder);
2047 }
2048 
HandlePortraitNullReferenceCondition(const int32_t currentAlbumId)2049 static int32_t HandlePortraitNullReferenceCondition(const int32_t currentAlbumId)
2050 {
2051     int32_t maxAlbumOrder = 0;
2052     int err = ObtainMaxPortraitAlbumOrder(maxAlbumOrder);
2053     CHECK_AND_RETURN_RET(err == E_OK, E_HAS_DB_ERROR);
2054     int32_t currentAlbumOrder = -1;
2055     err = ObtainCurrentPortraitAlbumOrder(currentAlbumId, currentAlbumOrder);
2056     CHECK_AND_RETURN_RET(err == E_OK, err);
2057 
2058     vector<int32_t> changedAlbumIds;
2059      // move order curosr to the end
2060     ObtainNotifyPortraitAlbumIds(currentAlbumOrder, maxAlbumOrder + 1, changedAlbumIds);
2061     err = UpdatePortraitNullReferenceOrder(currentAlbumId, currentAlbumOrder, maxAlbumOrder);
2062     CHECK_AND_EXECUTE(err != E_OK, NotifyPortraitAlbum(changedAlbumIds));
2063     return err;
2064 }
2065 
ObtainPortraitAlbumOrders(const int32_t currentAlbumId,const int32_t referenceAlbumId,int32_t & currentAlbumOrder,int32_t & referenceAlbumOrder)2066 static int32_t ObtainPortraitAlbumOrders(const int32_t currentAlbumId, const int32_t referenceAlbumId,
2067     int32_t &currentAlbumOrder, int32_t &referenceAlbumOrder)
2068 {
2069     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2070     if (uniStore == nullptr) {
2071         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2072         return E_HAS_DB_ERROR;
2073     }
2074     const std::string queryCurrentAlbumOrder = "SELECT " + RANK + " FROM " +
2075         ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " + to_string(currentAlbumId);
2076     auto resultSet = uniStore->QuerySql(queryCurrentAlbumOrder);
2077     bool cond = (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK);
2078     CHECK_AND_RETURN_RET(!cond, E_HAS_DB_ERROR);
2079     if (GetIntValueFromResultSet(resultSet, RANK, currentAlbumOrder) != NativeRdb::E_OK) {
2080         return E_HAS_DB_ERROR;
2081     }
2082 
2083     const std::string queryReferenceAlbumOrder = "SELECT " + RANK + " FROM " +
2084         ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " + to_string(referenceAlbumId);
2085     resultSet = uniStore->QuerySql(queryReferenceAlbumOrder);
2086     cond = (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK);
2087     CHECK_AND_RETURN_RET(!cond, E_HAS_DB_ERROR);
2088     if (GetIntValueFromResultSet(resultSet, RANK, referenceAlbumOrder) != NativeRdb::E_OK) {
2089         return E_HAS_DB_ERROR;
2090     }
2091     return E_OK;
2092 }
2093 
UpdatePortraitSortedOrder(const int32_t currentAlbumId,const int32_t referenceAlbumId,const int32_t currentAlbumOrder,const int32_t referenceAlbumOrder)2094 static int32_t UpdatePortraitSortedOrder(const int32_t currentAlbumId, const int32_t referenceAlbumId,
2095     const int32_t currentAlbumOrder, const int32_t referenceAlbumOrder)
2096 {
2097     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2098     if (uniStore == nullptr) {
2099         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2100         return E_DB_FAIL;
2101     }
2102     std::string updateOtherAlbumOrder = "";
2103     std::string updateCurrentAlbumOrder = "";
2104     if (currentAlbumOrder < referenceAlbumOrder) {
2105         updateOtherAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = " + RANK + " -1 WHERE " +
2106             RANK + " > " + to_string(currentAlbumOrder) + " and " + RANK + " < " + to_string(referenceAlbumOrder);
2107         updateCurrentAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = " +
2108             to_string(referenceAlbumOrder) + " -1 WHERE " + GROUP_TAG + " IN (SELECT " + GROUP_TAG + " FROM " +
2109             ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " + to_string(currentAlbumId) + ")";
2110     } else {
2111         updateOtherAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = " + RANK + " +1 WHERE " +
2112             RANK + " >= " + to_string(referenceAlbumOrder) + " AND " + RANK + " < " + to_string(currentAlbumOrder);
2113         updateCurrentAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = " +
2114             to_string(referenceAlbumOrder) + " WHERE " + GROUP_TAG + " IN (SELECT " + GROUP_TAG + " FROM " +
2115             ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " + to_string(currentAlbumId) + ")";
2116     }
2117     vector<string> updateSortedAlbumsSqls = { updateOtherAlbumOrder, updateCurrentAlbumOrder};
2118     return ExecSqls(updateSortedAlbumsSqls, uniStore);
2119 }
2120 
CheckIsFavoritePortraitAlbum(const int32_t currentAlbumId,const int32_t referenceAlbumId)2121 bool CheckIsFavoritePortraitAlbum(const int32_t currentAlbumId, const int32_t referenceAlbumId)
2122 {
2123     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2124     if (uniStore == nullptr) {
2125         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2126         return false;
2127     }
2128     std::string queryDisplayLevel = "SELECT " + USER_DISPLAY_LEVEL + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
2129         ALBUM_ID + " IN (" + to_string(currentAlbumId) + "," + to_string(referenceAlbumId) + ")";
2130     auto resultSet = uniStore->QuerySql(queryDisplayLevel);
2131     if (resultSet == nullptr) {
2132         MEDIA_ERR_LOG("Failed to query display level!");
2133         return false;
2134     }
2135     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2136         int32_t displayLevel;
2137         if (GetIntValueFromResultSet(resultSet, USER_DISPLAY_LEVEL, displayLevel) != E_OK) {
2138             MEDIA_ERR_LOG("Get display level fail");
2139             return false;
2140         }
2141         if (displayLevel != FAVORITE_PAGE) {
2142             MEDIA_ERR_LOG("this album is not favorite portrait album");
2143             return false;
2144         }
2145     }
2146     return true;
2147 }
2148 
OrderPortraitFavoriteAlbum(const int32_t currentAlbumId,const int32_t referenceAlbumId)2149 int32_t OrderPortraitFavoriteAlbum(const int32_t currentAlbumId, const int32_t referenceAlbumId)
2150 {
2151     if (!CheckIsFavoritePortraitAlbum(currentAlbumId, referenceAlbumId)) {
2152         return E_INVALID_VALUES;
2153     }
2154     if (referenceAlbumId == NULL_REFERENCE_ALBUM_ID) {
2155         return HandlePortraitNullReferenceCondition(currentAlbumId);
2156     }
2157 
2158     int32_t currentAlbumOrder = -1; // -1: default invalid value
2159     int32_t referenceAlbumOrder = -1; // -1: default invalid value
2160     int err = ObtainPortraitAlbumOrders(currentAlbumId, referenceAlbumId, currentAlbumOrder, referenceAlbumOrder);
2161     if (err != E_OK) {
2162         MEDIA_ERR_LOG("obtains album order error");
2163         return err;
2164     }
2165     vector<int32_t> changedAlbumIds;
2166     ObtainNotifyPortraitAlbumIds(currentAlbumOrder, referenceAlbumOrder, changedAlbumIds);
2167     err = UpdatePortraitSortedOrder(currentAlbumId, referenceAlbumId, currentAlbumOrder, referenceAlbumOrder);
2168     if (err == E_OK) {
2169         NotifyPortraitAlbum(changedAlbumIds);
2170     }
2171     return E_OK;
2172 }
2173 
2174 /**
2175  * Place the current album before the reference album
2176  * @param values contains current and reference album_id
2177  */
OrderSingleAlbum(const ValuesBucket & values)2178 int32_t MediaLibraryAlbumOperations::OrderSingleAlbum(const ValuesBucket &values)
2179 {
2180     int32_t currentAlbumId;
2181     int32_t referenceAlbumId;
2182     int err = GetIntVal(values, PhotoAlbumColumns::ALBUM_ID, currentAlbumId);
2183     if (err < 0 || currentAlbumId <= 0) {
2184         MEDIA_ERR_LOG("invalid album id");
2185         return E_INVALID_VALUES;
2186     }
2187     err = GetIntVal(values, PhotoAlbumColumns::REFERENCE_ALBUM_ID, referenceAlbumId);
2188     if (err < 0 || referenceAlbumId == 0 || referenceAlbumId < NULL_REFERENCE_ALBUM_ID) {
2189         MEDIA_ERR_LOG("invalid reference album id");
2190         return E_INVALID_VALUES;
2191     }
2192     if (currentAlbumId == referenceAlbumId) { // same album, no need to order
2193         return E_OK;
2194     }
2195 
2196     int32_t albumType;
2197     int32_t albumSubtype;
2198     err = GetIntVal(values, PhotoAlbumColumns::ALBUM_TYPE, albumType);
2199     int errorSubtype = GetIntVal(values, PhotoAlbumColumns::ALBUM_SUBTYPE, albumSubtype);
2200     bool cond = (err == E_OK && errorSubtype == E_OK &&
2201         (albumType == PhotoAlbumType::SMART && albumSubtype == PORTRAIT));
2202     CHECK_AND_RETURN_RET(!cond, OrderPortraitFavoriteAlbum(currentAlbumId, referenceAlbumId));
2203     if (referenceAlbumId == NULL_REFERENCE_ALBUM_ID) {
2204         return HandleNullReferenceCondition(currentAlbumId);
2205     }
2206     int32_t currentAlbumOrder = -1; // -1: default invalid value
2207     int32_t referenceAlbumOrder = -1;
2208     err = ObtainAlbumOrders(currentAlbumId, referenceAlbumId, currentAlbumOrder, referenceAlbumOrder);
2209     if (err != E_OK) {
2210         MEDIA_ERR_LOG("obtains album order error");
2211         return err;
2212     }
2213     vector<int32_t> changedAlbumIds;
2214     ObtainNotifyAlbumIds(currentAlbumOrder, referenceAlbumOrder, changedAlbumIds);
2215     AlbumAccurateRefresh albumRefresh(AccurateRefresh::ORDER_SINGLE_ALBUM_BUSSINESS_NAME);
2216     err = UpdateSortedOrder(albumRefresh, currentAlbumId, referenceAlbumId, currentAlbumOrder, referenceAlbumOrder);
2217     if (err == E_OK) {
2218         albumRefresh.Notify();
2219         NotifyOrderChange(changedAlbumIds);
2220     }
2221     return E_OK;
2222 }
2223 
GetStringVal(const ValuesBucket & values,const string & key,string & value)2224 inline int32_t GetStringVal(const ValuesBucket &values, const string &key, string &value)
2225 {
2226     value = "";
2227     ValueObject valueObject;
2228     if (values.GetObject(key, valueObject)) {
2229         valueObject.GetString(value);
2230     } else {
2231         return -EINVAL;
2232     }
2233     return E_OK;
2234 }
2235 
GetMergeAlbumCount(const int32_t currentAlbumId,const int32_t targetAlbumId)2236 int GetMergeAlbumCount(const int32_t currentAlbumId, const int32_t targetAlbumId)
2237 {
2238     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2239     if (uniStore == nullptr) {
2240         MEDIA_ERR_LOG("uniStore is nullptr! failed query merge album info");
2241         return E_DB_FAIL;
2242     }
2243 
2244     string queryCount = "SELECT COUNT(DISTINCT file_id) FROM " + PhotoColumn::PHOTOS_TABLE + " p INNER JOIN " +
2245         ANALYSIS_PHOTO_MAP_TABLE + " apm ON p." + PhotoColumn::MEDIA_ID + " = apm." + MAP_ASSET + " INNER JOIN " +
2246         ANALYSIS_ALBUM_TABLE + " aa ON aa." + ALBUM_ID + " = apm." + MAP_ALBUM + " INNER JOIN (SELECT " + GROUP_TAG +
2247         " FROM "+ ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " IN (" + to_string(currentAlbumId) + "," +
2248         to_string(targetAlbumId) + ")) ag ON ag." + GROUP_TAG + " = " + " aa." + GROUP_TAG + " WHERE " +
2249         PhotoColumn::MEDIA_DATE_TRASHED + " = 0 AND " + PhotoColumn::MEDIA_TIME_PENDING + " = 0 AND " +
2250         PhotoColumn::MEDIA_HIDDEN + " = 0";
2251     auto resultSet = uniStore->QuerySql(queryCount);
2252     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2253         MEDIA_ERR_LOG("Failed to query album!");
2254         return E_HAS_DB_ERROR;
2255     }
2256     int count;
2257     if (resultSet->GetInt(0, count) != E_OK) {
2258         return E_HAS_DB_ERROR;
2259     }
2260     return count;
2261 }
2262 
ParseFileIdFromCoverUri(const string & uri)2263 string ParseFileIdFromCoverUri(const string &uri)
2264 {
2265     if (PhotoColumn::PHOTO_URI_PREFIX.size() >= uri.size()) {
2266         return "";
2267     }
2268     string midStr = uri.substr(PhotoColumn::PHOTO_URI_PREFIX.size());
2269     string delimiter = "/";
2270     size_t pos = midStr.find(delimiter);
2271     if (pos == string::npos) {
2272         MEDIA_ERR_LOG("ParseFileIdFromCoverUri fail");
2273         return "";
2274     }
2275     return midStr.substr(0, pos);
2276 }
2277 
UpdateForReduceOneOrder(const int32_t referenceOrder)2278 static int32_t UpdateForReduceOneOrder(const int32_t referenceOrder)
2279 {
2280     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2281     if (uniStore == nullptr) {
2282         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2283         return E_DB_FAIL;
2284     }
2285     std::string updateOtherAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = " + RANK +
2286         " -1 WHERE " + RANK + " > " + to_string(referenceOrder);
2287     vector<string> updateSortedAlbumsSqls = { updateOtherAlbumOrder};
2288     return ExecSqls(updateSortedAlbumsSqls, uniStore);
2289 }
2290 
UpdateForMergeAlbums(const MergeAlbumInfo & updateAlbumInfo,const int32_t currentAlbumId,const int32_t targetAlbumId)2291 int32_t UpdateForMergeAlbums(const MergeAlbumInfo &updateAlbumInfo, const int32_t currentAlbumId,
2292     const int32_t targetAlbumId)
2293 {
2294     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2295     if (uniStore == nullptr) {
2296         MEDIA_ERR_LOG("uniStore is nullptr! failed update for merge albums");
2297         return E_DB_FAIL;
2298     }
2299 
2300     std::string updateForMergeAlbums = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + GROUP_TAG + " = " +
2301         updateAlbumInfo.groupTag + "," + COUNT + " = " + to_string(updateAlbumInfo.count) + "," + IS_ME + " = " +
2302         to_string(updateAlbumInfo.isMe) + "," + COVER_URI + " = '" + updateAlbumInfo.coverUri + "'," +
2303         USER_DISPLAY_LEVEL + " = " + to_string(updateAlbumInfo.userDisplayLevel) + "," + RANK + " = " +
2304         to_string(updateAlbumInfo.rank) + "," + USER_OPERATION + " = " + to_string(updateAlbumInfo.userOperation) +
2305         "," + RENAME_OPERATION + " = " + to_string(updateAlbumInfo.renameOperation) + "," + ALBUM_NAME + " = '" +
2306         updateAlbumInfo.albumName + "'," + IS_COVER_SATISFIED + " = " + to_string(updateAlbumInfo.isCoverSatisfied) +
2307         " WHERE " + GROUP_TAG + " IN(SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID +
2308         " = " + to_string(currentAlbumId) + " OR " + ALBUM_ID + " = " + to_string(targetAlbumId) + ")";
2309     vector<string> updateSqls = { updateForMergeAlbums};
2310     return ExecSqls(updateSqls, uniStore);
2311 }
2312 
GetMergeAlbumsInfo(vector<MergeAlbumInfo> & mergeAlbumInfo,const int32_t currentAlbumId,const int32_t targetAlbumId)2313 int32_t GetMergeAlbumsInfo(vector<MergeAlbumInfo> &mergeAlbumInfo, const int32_t currentAlbumId,
2314     const int32_t targetAlbumId)
2315 {
2316     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2317     if (uniStore == nullptr) {
2318         MEDIA_ERR_LOG("uniStore is nullptr! failed query merge album info");
2319         return E_DB_FAIL;
2320     }
2321     const std::string queryAlbumInfo = "SELECT " + ALBUM_ID + "," + GROUP_TAG + "," + COUNT + "," + IS_ME + "," +
2322         COVER_URI + "," + USER_DISPLAY_LEVEL + "," + RANK + "," + USER_OPERATION + "," + RENAME_OPERATION + "," +
2323         ALBUM_NAME + "," + IS_COVER_SATISFIED + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " +
2324         to_string(currentAlbumId) + " OR " + ALBUM_ID + " = " + to_string(targetAlbumId);
2325 
2326     auto resultSet = uniStore->QuerySql(queryAlbumInfo);
2327     if (resultSet == nullptr) {
2328         MEDIA_ERR_LOG("Database query failed");
2329         return E_HAS_DB_ERROR;
2330     }
2331     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2332         MergeAlbumInfo albumInfo;
2333         int isCoverSatisfied = 0;
2334         if (GetIntValueFromResultSet(resultSet, ALBUM_ID, albumInfo.albumId) != E_OK ||
2335             GetStringValueFromResultSet(resultSet, GROUP_TAG, albumInfo.groupTag) != E_OK ||
2336             GetIntValueFromResultSet(resultSet, COUNT, albumInfo.count) != E_OK ||
2337             GetIntValueFromResultSet(resultSet, IS_ME, albumInfo.isMe) != E_OK ||
2338             GetStringValueFromResultSet(resultSet, GROUP_TAG, albumInfo.groupTag) != E_OK ||
2339             GetStringValueFromResultSet(resultSet, COVER_URI, albumInfo.coverUri) != E_OK ||
2340             GetIntValueFromResultSet(resultSet, USER_DISPLAY_LEVEL, albumInfo.userDisplayLevel) != E_OK ||
2341             GetIntValueFromResultSet(resultSet, RANK, albumInfo.rank) != E_OK ||
2342             GetIntValueFromResultSet(resultSet, RENAME_OPERATION, albumInfo.renameOperation) != E_OK ||
2343             GetStringValueFromResultSet(resultSet, ALBUM_NAME, albumInfo.albumName) != E_OK ||
2344             GetIntValueFromResultSet(resultSet, IS_COVER_SATISFIED, isCoverSatisfied) != E_OK) {
2345                 MEDIA_ERR_LOG("Failed to get values from result set");
2346                 return E_HAS_DB_ERROR;
2347             }
2348         albumInfo.isCoverSatisfied = static_cast<uint8_t>(isCoverSatisfied);
2349         mergeAlbumInfo.push_back(albumInfo);
2350     }
2351     return E_OK;
2352 }
2353 
JoinCandidateIds(const vector<string> & candidateIds)2354 inline string JoinCandidateIds(const vector<string> &candidateIds)
2355 {
2356     return accumulate(candidateIds.begin() + 1, candidateIds.end(), candidateIds[0],
2357         [](const string &a, const string &b) { return a + ", " + b; });
2358 }
2359 
GetCandidateIdsAndSetCoverSatisfied(MergeAlbumInfo & updateAlbumInfo,const MergeAlbumInfo & currentAlbum,const MergeAlbumInfo & targetAlbum,const string & currentFileId,const string & targetFileId)2360 string GetCandidateIdsAndSetCoverSatisfied(MergeAlbumInfo &updateAlbumInfo, const MergeAlbumInfo &currentAlbum,
2361     const MergeAlbumInfo &targetAlbum, const string &currentFileId, const string &targetFileId)
2362 {
2363     vector<string> candidateIds;
2364     if (currentAlbum.isCoverSatisfied & static_cast<uint8_t>(CoverSatisfiedType::USER_SETTING)) {
2365         candidateIds.push_back(currentFileId);
2366     }
2367     if (targetAlbum.isCoverSatisfied & static_cast<uint8_t>(CoverSatisfiedType::USER_SETTING)) {
2368         candidateIds.push_back(targetFileId);
2369     }
2370     if (!candidateIds.empty()) {
2371         updateAlbumInfo.isCoverSatisfied = static_cast<uint8_t>(CoverSatisfiedType::USER_SETTING_EDITE);
2372         return JoinCandidateIds(candidateIds);
2373     }
2374 
2375     if (currentAlbum.isCoverSatisfied & static_cast<uint8_t>(CoverSatisfiedType::BEAUTY_SETTING)) {
2376         candidateIds.push_back(currentFileId);
2377     }
2378     if (targetAlbum.isCoverSatisfied & static_cast<uint8_t>(CoverSatisfiedType::BEAUTY_SETTING)) {
2379         candidateIds.push_back(targetFileId);
2380     }
2381     if (!candidateIds.empty()) {
2382         updateAlbumInfo.isCoverSatisfied = static_cast<uint8_t>(CoverSatisfiedType::BEAUTY_SETTING_EDITE);
2383         return JoinCandidateIds(candidateIds);
2384     }
2385 
2386     if (currentAlbum.isCoverSatisfied & static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING)) {
2387         candidateIds.push_back(currentFileId);
2388     }
2389     if (targetAlbum.isCoverSatisfied & static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING)) {
2390         candidateIds.push_back(targetFileId);
2391     }
2392     if (!candidateIds.empty()) {
2393         updateAlbumInfo.isCoverSatisfied = static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING);
2394         return JoinCandidateIds(candidateIds);
2395     }
2396 
2397     updateAlbumInfo.isCoverSatisfied = static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING);
2398     return currentFileId + ", " + targetFileId;
2399 }
2400 
GetMergeAlbumCoverUriAndSatisfied(MergeAlbumInfo & updateAlbumInfo,const MergeAlbumInfo & currentAlbum,const MergeAlbumInfo & targetAlbum)2401 int32_t GetMergeAlbumCoverUriAndSatisfied(MergeAlbumInfo &updateAlbumInfo, const MergeAlbumInfo &currentAlbum,
2402     const MergeAlbumInfo &targetAlbum)
2403 {
2404     string currentFileId = ParseFileIdFromCoverUri(currentAlbum.coverUri);
2405     string targetFileId = ParseFileIdFromCoverUri(targetAlbum.coverUri);
2406     if (currentFileId.empty() || targetFileId.empty()) {
2407         return E_DB_FAIL;
2408     }
2409     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2410     if (uniStore == nullptr) {
2411         MEDIA_ERR_LOG("uniStore is nullptr! failed query get merge album cover uri");
2412         return E_DB_FAIL;
2413     }
2414     string candidateIds =
2415         GetCandidateIdsAndSetCoverSatisfied(updateAlbumInfo, currentAlbum, targetAlbum, currentFileId, targetFileId);
2416 
2417     const std::string queryAlbumInfo = "SELECT " + MediaColumn::MEDIA_ID + "," + MediaColumn::MEDIA_TITLE + "," +
2418         MediaColumn::MEDIA_NAME + ", MAX(" + MediaColumn::MEDIA_DATE_ADDED + ") FROM " + PhotoColumn::PHOTOS_TABLE +
2419         " WHERE " + MediaColumn::MEDIA_ID + " IN (" + candidateIds + " )";
2420 
2421     auto resultSet = uniStore->QuerySql(queryAlbumInfo);
2422     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2423         MEDIA_ERR_LOG("resultSet is nullptr! failed query get merge album cover uri");
2424         return E_HAS_DB_ERROR;
2425     }
2426     int mergeFileId;
2427     if (GetIntValueFromResultSet(resultSet, MediaColumn::MEDIA_ID, mergeFileId) != NativeRdb::E_OK) {
2428         MEDIA_ERR_LOG("resultSet is error! failed query get merge album cover uri");
2429         return E_HAS_DB_ERROR;
2430     }
2431 
2432     string mergeTitle;
2433     if (GetStringValueFromResultSet(resultSet, MediaColumn::MEDIA_TITLE, mergeTitle) != NativeRdb::E_OK) {
2434         MEDIA_ERR_LOG("resultSet is error! failed query get merge album cover uri");
2435         return E_HAS_DB_ERROR;
2436     }
2437 
2438     string mergeDisplayName;
2439     if (GetStringValueFromResultSet(resultSet, MediaColumn::MEDIA_NAME, mergeDisplayName) != NativeRdb::E_OK) {
2440         MEDIA_ERR_LOG("resultSet is error! failed query get merge album cover uri");
2441         return E_HAS_DB_ERROR;
2442     }
2443     updateAlbumInfo.coverUri = "file://media/Photo/" + to_string(mergeFileId) + "/" + mergeTitle + "/" +
2444         mergeDisplayName;
2445     return E_OK;
2446 }
2447 
MergeAlbumInfoToString(const MergeAlbumInfo & mergeAlbumInfo)2448 static string MergeAlbumInfoToString(const MergeAlbumInfo& mergeAlbumInfo)
2449 {
2450     string info = "album " + to_string(mergeAlbumInfo.albumId) + ", groupTag " + mergeAlbumInfo.groupTag + ", count " +
2451         to_string(mergeAlbumInfo.count) + ", isMe " + to_string(mergeAlbumInfo.isMe) + ", coverUri " +
2452         DfxUtils::GetSafeUri(mergeAlbumInfo.coverUri) + ", userDisplayLevel " +
2453         to_string(mergeAlbumInfo.userDisplayLevel) + ", rank " +
2454         to_string(mergeAlbumInfo.rank) + ", userOperation " + to_string(mergeAlbumInfo.userOperation) +
2455         ", renameOperation " + to_string(mergeAlbumInfo.renameOperation) + ", albumName " +
2456         DfxUtils::GetSafeAlbumName(mergeAlbumInfo.albumName) +
2457         ", isCoverSatisfied " + to_string(mergeAlbumInfo.isCoverSatisfied);
2458     return info;
2459 }
2460 
UpdateMergeAlbumsInfo(const vector<MergeAlbumInfo> & mergeAlbumInfo,int32_t currentAlbumId)2461 static int32_t UpdateMergeAlbumsInfo(const vector<MergeAlbumInfo> &mergeAlbumInfo, int32_t currentAlbumId)
2462 {
2463     MergeAlbumInfo updateAlbumInfo;
2464     if (GetMergeAlbumCoverUriAndSatisfied(updateAlbumInfo, mergeAlbumInfo[0], mergeAlbumInfo[1]) != E_OK) {
2465         return E_HAS_DB_ERROR;
2466     }
2467     updateAlbumInfo.count = GetMergeAlbumCount(mergeAlbumInfo[0].albumId, mergeAlbumInfo[1].albumId);
2468     updateAlbumInfo.groupTag = "'" + mergeAlbumInfo[0].groupTag + "|" + mergeAlbumInfo[1].groupTag + "'";
2469     updateAlbumInfo.isMe = (mergeAlbumInfo[0].isMe == 1 || mergeAlbumInfo[1].isMe == 1) ? 1 : 0;
2470     updateAlbumInfo.userOperation = 1;
2471     updateAlbumInfo.albumName =
2472         mergeAlbumInfo[0].albumId == currentAlbumId ? mergeAlbumInfo[0].albumName : mergeAlbumInfo[1].albumName;
2473     if (updateAlbumInfo.albumName == "") {
2474         updateAlbumInfo.albumName =
2475             mergeAlbumInfo[0].albumId != currentAlbumId ? mergeAlbumInfo[0].albumName : mergeAlbumInfo[1].albumName;
2476     }
2477     updateAlbumInfo.renameOperation =
2478         (mergeAlbumInfo[0].albumName != "" || mergeAlbumInfo[1].albumName != "") ? 1 : 0;
2479     int currentLevel = mergeAlbumInfo[0].userDisplayLevel;
2480     int targetLevel = mergeAlbumInfo[1].userDisplayLevel;
2481     if ((currentLevel == targetLevel) && (currentLevel == FIRST_PAGE || currentLevel == SECOND_PAGE ||
2482         currentLevel == UNFAVORITE_PAGE)) {
2483         updateAlbumInfo.userDisplayLevel = currentLevel;
2484         updateAlbumInfo.rank = 0;
2485     } else if ((currentLevel == targetLevel) && (currentLevel == FAVORITE_PAGE)) {
2486         updateAlbumInfo.userDisplayLevel = currentLevel;
2487         updateAlbumInfo.rank = min(mergeAlbumInfo[0].rank, mergeAlbumInfo[1].rank);
2488         if (UpdateForReduceOneOrder(max(mergeAlbumInfo[0].rank, mergeAlbumInfo[1].rank)) != E_OK) {
2489             return E_HAS_DB_ERROR;
2490         }
2491     } else if (currentLevel == FAVORITE_PAGE || targetLevel == FAVORITE_PAGE) {
2492         updateAlbumInfo.userDisplayLevel = FAVORITE_PAGE;
2493         updateAlbumInfo.rank = max(mergeAlbumInfo[0].rank, mergeAlbumInfo[1].rank);
2494     } else if (currentLevel == FIRST_PAGE || targetLevel == FIRST_PAGE) {
2495         updateAlbumInfo.userDisplayLevel = FIRST_PAGE;
2496         updateAlbumInfo.rank = 0;
2497     } else {
2498         updateAlbumInfo.userDisplayLevel = SECOND_PAGE;
2499         updateAlbumInfo.rank = 0;
2500     }
2501     MEDIA_INFO_LOG("After merge: %{public}s", MergeAlbumInfoToString(updateAlbumInfo).c_str());
2502     return UpdateForMergeAlbums(updateAlbumInfo, mergeAlbumInfo[0].albumId, mergeAlbumInfo[1].albumId);
2503 }
2504 
2505 /**
2506  * Merge album
2507  * @param values contains current and target album_id
2508  */
MergePortraitAlbums(const ValuesBucket & values)2509 int32_t MediaLibraryAlbumOperations::MergePortraitAlbums(const ValuesBucket &values)
2510 {
2511     int32_t currentAlbumId;
2512     int32_t targetAlbumId;
2513     int err = GetIntVal(values, ALBUM_ID, currentAlbumId);
2514     if (err < 0 || currentAlbumId <= 0) {
2515         MEDIA_ERR_LOG("invalid album id");
2516         return E_INVALID_VALUES;
2517     }
2518     err = GetIntVal(values, TARGET_ALBUM_ID, targetAlbumId);
2519     if (err < 0 || targetAlbumId <= 0) {
2520         MEDIA_ERR_LOG("invalid target album id");
2521         return E_INVALID_VALUES;
2522     }
2523     if (currentAlbumId == targetAlbumId) { // same album, no need to merge
2524         MEDIA_WARN_LOG("Ignore invalid portrait album merge request, "
2525             "current album id and target album id are the same");
2526         return E_OK;
2527     }
2528     MEDIA_INFO_LOG("Start merge portrait albums, current album id: %{public}d, target album id: %{public}d",
2529         currentAlbumId, targetAlbumId);
2530     vector<MergeAlbumInfo> mergeAlbumInfo;
2531     if (GetMergeAlbumsInfo(mergeAlbumInfo, currentAlbumId, targetAlbumId)) {
2532         MEDIA_ERR_LOG("Get merge albums info fail");
2533         return E_HAS_DB_ERROR;
2534     }
2535     if (mergeAlbumInfo.size() != MERGE_ALBUM_COUNT) { // merge album count
2536         MEDIA_ERR_LOG("invalid mergeAlbumInfo size");
2537         return E_INVALID_VALUES;
2538     }
2539     MEDIA_INFO_LOG("Before merge: %{public}s", MergeAlbumInfoToString(mergeAlbumInfo[0]).c_str());
2540     MEDIA_INFO_LOG("Before merge: %{public}s", MergeAlbumInfoToString(mergeAlbumInfo[1]).c_str());
2541     err = UpdateMergeAlbumsInfo(mergeAlbumInfo, currentAlbumId);
2542     if (err != E_OK) {
2543         MEDIA_ERR_LOG("MergeAlbum failed");
2544         return err;
2545     }
2546     err = MediaLibraryAnalysisAlbumOperations::UpdateMergeGroupAlbumsInfo(mergeAlbumInfo);
2547     if (err != E_OK) {
2548         MEDIA_ERR_LOG("MergeGroupAlbum failed");
2549         return err;
2550     }
2551     vector<int32_t> changeAlbumIds = { currentAlbumId };
2552     NotifyPortraitAlbum(changeAlbumIds);
2553     return err;
2554 }
2555 
UpdateDisplayLevel(const int32_t value,const int32_t albumId)2556 static int32_t UpdateDisplayLevel(const int32_t value, const int32_t albumId)
2557 {
2558     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2559     if (uniStore == nullptr) {
2560         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2561         return E_DB_FAIL;
2562     }
2563     std::string updateDisplayLevel = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + USER_DISPLAY_LEVEL + " = " +
2564         to_string(value) + " WHERE " + GROUP_TAG + " IN (SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE +
2565         " WHERE " + ALBUM_ID + " = " + to_string(albumId) + ")";
2566     vector<string> updateDisplayLevelAlbumsSqls = { updateDisplayLevel };
2567     return ExecSqls(updateDisplayLevelAlbumsSqls, uniStore);
2568 }
2569 
UpdateFavoritesOrder(const int32_t value,const int32_t currentAlbumId)2570 static int32_t UpdateFavoritesOrder(const int32_t value, const int32_t currentAlbumId)
2571 {
2572     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2573     if (uniStore == nullptr) {
2574         MEDIA_ERR_LOG("uniStore is nullptr! failed query album order");
2575         return E_DB_FAIL;
2576     }
2577     std::string updateOtherAlbumOrder;
2578     std::string updateCurrentAlbumOrder;
2579     vector<string> updateSortedAlbumsSqls;
2580     if (value == FAVORITE_PAGE) {
2581         int maxAlbumOrder;
2582         ObtainMaxPortraitAlbumOrder(maxAlbumOrder);
2583         updateCurrentAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = " + to_string(maxAlbumOrder) +
2584             " +1 WHERE " + GROUP_TAG + " IN (SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE +
2585             " WHERE " + ALBUM_ID + " = " + to_string(currentAlbumId) + ")";
2586         updateSortedAlbumsSqls.push_back(updateCurrentAlbumOrder);
2587     } else {
2588         int rank;
2589         int err = ObtainCurrentPortraitAlbumOrder(currentAlbumId, rank);
2590         if (err != E_OK) {
2591             return err;
2592         }
2593         updateOtherAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = " + RANK + " -1 WHERE " +
2594             USER_DISPLAY_LEVEL + " = " + to_string(FAVORITE_PAGE) + " AND " + RANK + ">" + to_string(rank);
2595         updateCurrentAlbumOrder = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RANK + " = 0" +
2596             " WHERE " + GROUP_TAG + " IN (SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE +
2597             " WHERE " + ALBUM_ID + " = " + to_string(currentAlbumId) + ")";
2598         updateSortedAlbumsSqls.push_back(updateOtherAlbumOrder);
2599         updateSortedAlbumsSqls.push_back(updateCurrentAlbumOrder);
2600     }
2601     return ExecSqls(updateSortedAlbumsSqls, uniStore);
2602 }
2603 
UpdateFavorites(int32_t value,const int32_t albumId)2604 static int32_t UpdateFavorites(int32_t value, const int32_t albumId)
2605 {
2606     int err = UpdateFavoritesOrder(value, albumId);
2607     if (err != E_OK) {
2608         MEDIA_ERR_LOG("UpdateFavoritesOrder fail");
2609         return E_DB_FAIL;
2610     }
2611     if (value == UNFAVORITE_PAGE) {
2612         value = FIRST_PAGE;
2613     }
2614     return UpdateDisplayLevel(value, albumId);
2615 }
2616 
SetDisplayLevel(const ValuesBucket & values,const DataSharePredicates & predicates)2617 int32_t MediaLibraryAlbumOperations::SetDisplayLevel(const ValuesBucket &values, const DataSharePredicates &predicates)
2618 {
2619     int32_t displayLevelValue;
2620     int err = GetIntVal(values, USER_DISPLAY_LEVEL, displayLevelValue);
2621     if (err < 0 || !MediaFileUtils::CheckDisplayLevel(displayLevelValue)) {
2622         MEDIA_ERR_LOG("invalid display level");
2623         return E_INVALID_VALUES;
2624     }
2625 
2626     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
2627     auto whereArgs = rdbPredicates.GetWhereArgs();
2628     if (whereArgs.size() == 0) {
2629         MEDIA_ERR_LOG("no target album id");
2630         return E_INVALID_VALUES;
2631     }
2632     int32_t albumId = atoi(whereArgs[0].c_str());
2633     if (albumId <= 0) {
2634         MEDIA_ERR_LOG("invalid album id");
2635         return E_INVALID_VALUES;
2636     }
2637     MEDIA_INFO_LOG("Start set display level, album id: %{public}d, display level: %{public}d",
2638         albumId, displayLevelValue);
2639     vector<int32_t> changedAlbumIds;
2640     if (displayLevelValue == FIRST_PAGE || displayLevelValue == SECOND_PAGE) {
2641         err = UpdateDisplayLevel(displayLevelValue, albumId);
2642         changedAlbumIds.push_back(albumId);
2643     } else {
2644         err = UpdateFavorites(displayLevelValue, albumId);
2645         changedAlbumIds.push_back(albumId);
2646     }
2647     if (err == E_OK) {
2648         NotifyPortraitAlbum(changedAlbumIds);
2649     }
2650     return err;
2651 }
2652 
SetMyOldAlbum(vector<string> & updateSqls,shared_ptr<MediaLibraryRdbStore> uniStore)2653 void SetMyOldAlbum(vector<string>& updateSqls, shared_ptr<MediaLibraryRdbStore> uniStore)
2654 {
2655     std::string queryIsMe = "SELECT COUNT(DISTINCT album_id)," + ALBUM_NAME +
2656         " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + IS_ME + " = 1 ";
2657     auto resultSet = uniStore->QuerySql(queryIsMe);
2658     if (resultSet == nullptr || resultSet->GoToFirstRow() != NativeRdb::E_OK) {
2659         MEDIA_ERR_LOG("Failed to query isMe!");
2660         return;
2661     }
2662     int count;
2663     if (resultSet->GetInt(0, count) != E_OK) {
2664         return;
2665     }
2666     std::string clearIsMeAlbum = "";
2667     if (count > 0) {
2668         string albumName = "";
2669         GetStringValueFromResultSet(resultSet, ALBUM_NAME, albumName);
2670         int renameOperation = albumName != "" ? 1 : 0;
2671         clearIsMeAlbum= "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + IS_ME + " = 0, " + RENAME_OPERATION +
2672             " = " + to_string(renameOperation) + " WHERE " + IS_ME + " = 1";
2673         updateSqls.push_back(clearIsMeAlbum);
2674     }
2675 }
2676 
GetHighlightCoverStatus(const string & albumId,int32_t & currentCoverStatus)2677 static void GetHighlightCoverStatus(const string &albumId, int32_t &currentCoverStatus)
2678 {
2679     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2680     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "rdbStore is nullptr! failed update index");
2681     const std::string queryCoverStatus =
2682         "SELECT status FROM " + HIGHLIGHT_COVER_INFO_TABLE + " WHERE album_id = "
2683         "(SELECT id FROM tab_highlight_album WHERE album_id = " + albumId + " LIMIT 1)";
2684     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(queryCoverStatus);
2685     CHECK_AND_RETURN_LOG(resultSet != nullptr, "resultSet is nullptr! failed update index");
2686     CHECK_AND_EXECUTE(resultSet->GoToNextRow() != NativeRdb::E_OK,
2687         currentCoverStatus = GetInt32Val(COVER_STATUS, resultSet));
2688 }
2689 
SetHighlightCoverUri(const ValuesBucket & values,const DataSharePredicates & predicates)2690 int32_t MediaLibraryAlbumOperations::SetHighlightCoverUri(const ValuesBucket &values,
2691     const DataSharePredicates &predicates)
2692 {
2693     MEDIA_INFO_LOG("Start set highlight cover uri");
2694     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
2695     auto whereArgs = rdbPredicates.GetWhereArgs();
2696     CHECK_AND_RETURN_RET_LOG(whereArgs.size() != 0, E_INVALID_VALUES, "no target album id");
2697 
2698     string targetAlbumId = whereArgs[0];
2699     CHECK_AND_RETURN_RET_LOG(!targetAlbumId.empty() && MediaLibraryDataManagerUtils::IsNumber(targetAlbumId),
2700         E_INVALID_VALUES, "target album id not exists");
2701     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2702     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_DB_FAIL,
2703         "uniStore is nullptr! failed update for set highlight cover uri");
2704 
2705     string coverUri;
2706     int err = GetStringVal(values, COVER_URI, coverUri);
2707     bool cond = (err < 0 || coverUri.empty());
2708     CHECK_AND_RETURN_RET_LOG(!cond, E_INVALID_VALUES, "invalid album cover uri");
2709 
2710     int32_t currentCoverStatus = 0;
2711     GetHighlightCoverStatus(targetAlbumId, currentCoverStatus);
2712     int32_t newCoverStatus = static_cast<uint32_t>(currentCoverStatus) | HIGHLIGHT_COVER_STATUS_COVER;
2713     std::string updateAnalysisAlbum = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + COVER_URI + " = '" + coverUri +
2714         "', " + IS_COVER_SATISFIED + " = 2 WHERE " + ALBUM_ID + " = " + targetAlbumId;
2715     std::string updateCoverInfoTable = "UPDATE " + HIGHLIGHT_COVER_INFO_TABLE +
2716         " SET " + COVER_STATUS + " = " + to_string(newCoverStatus) +
2717         " WHERE " + ALBUM_ID + " = (SELECT id FROM tab_highlight_album WHERE album_id = " + targetAlbumId + " LIMIT 1)";
2718     vector<string> updateSqls = { updateAnalysisAlbum, updateCoverInfoTable };
2719     err = ExecSqls(updateSqls, uniStore);
2720     if (err == E_OK) {
2721         vector<int32_t> changeAlbumIds = { atoi(targetAlbumId.c_str()) };
2722         NotifyHighlightAlbum(changeAlbumIds);
2723     }
2724     return err;
2725 }
2726 
SetHighlightAlbumName(const ValuesBucket & values,const DataSharePredicates & predicates)2727 int32_t MediaLibraryAlbumOperations::SetHighlightAlbumName(const ValuesBucket &values,
2728     const DataSharePredicates &predicates)
2729 {
2730     MEDIA_INFO_LOG("Start set highlight album name");
2731     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
2732     auto whereArgs = rdbPredicates.GetWhereArgs();
2733     CHECK_AND_RETURN_RET_LOG(whereArgs.size() != 0, E_INVALID_VALUES, "no target highlight album id");
2734 
2735     string highlightAlbumId = whereArgs[0];
2736     CHECK_AND_RETURN_RET_LOG(!highlightAlbumId.empty() && MediaLibraryDataManagerUtils::IsNumber(highlightAlbumId),
2737         E_INVALID_VALUES, "highlight album id not exists");
2738     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2739     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_DB_FAIL,
2740         "uniStore is nullptr! failed update for set highlight album name");
2741 
2742     string albumName;
2743     int err = GetStringVal(values, ALBUM_NAME, albumName);
2744     bool cond = (err < 0 || albumName.empty());
2745     CHECK_AND_RETURN_RET_LOG(!cond, E_INVALID_VALUES, "invalid album name");
2746 
2747     int32_t currentCoverStatus = 0;
2748     GetHighlightCoverStatus(highlightAlbumId, currentCoverStatus);
2749     int32_t newCoverStatus = static_cast<uint32_t>(currentCoverStatus) | HIGHLIGHT_COVER_STATUS_TITLE;
2750     std::string updateAlbumName = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + ALBUM_NAME + " = '" + albumName +
2751         "' WHERE " + ALBUM_ID + " = " + highlightAlbumId;
2752     std::string updateCoverInfoTable = "UPDATE " + HIGHLIGHT_COVER_INFO_TABLE + " SET " +
2753         COVER_STATUS + " = " + to_string(newCoverStatus) + " WHERE " +
2754         ALBUM_ID + " = (SELECT id FROM tab_highlight_album WHERE album_id = " + highlightAlbumId + " LIMIT 1)";
2755     vector<string> updateSqls = { updateAlbumName, updateCoverInfoTable };
2756     err = ExecSqls(updateSqls, uniStore);
2757     if (err == E_OK) {
2758         vector<int32_t> changeAlbumIds = { atoi(highlightAlbumId.c_str()) };
2759         NotifyHighlightAlbum(changeAlbumIds);
2760     }
2761     return err;
2762 }
2763 
SetHighlightSubtitle(const ValuesBucket & values,const DataSharePredicates & predicates)2764 int32_t MediaLibraryAlbumOperations::SetHighlightSubtitle(const ValuesBucket &values,
2765     const DataSharePredicates &predicates)
2766 {
2767     MEDIA_INFO_LOG("Start set highlight subtitle");
2768     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
2769     auto whereArgs = rdbPredicates.GetWhereArgs();
2770     CHECK_AND_RETURN_RET_LOG(whereArgs.size() != 0, E_INVALID_VALUES, "no target highlight album id");
2771 
2772     string highlightAlbumId = whereArgs[0];
2773     CHECK_AND_RETURN_RET_LOG(!highlightAlbumId.empty() && MediaLibraryDataManagerUtils::IsNumber(highlightAlbumId),
2774         E_INVALID_VALUES, "highlight album id not exists");
2775     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2776     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_DB_FAIL,
2777         "uniStore is nullptr! failed update for set highlight album name");
2778 
2779     string albumSubtitle;
2780     int err = GetStringVal(values, SUB_TITLE, albumSubtitle);
2781     CHECK_AND_RETURN_RET_LOG(err >= 0, E_INVALID_VALUES, "invalid album name");
2782 
2783     MEDIA_INFO_LOG("New highlight subtitle is: %{public}s, album id is %{public}s",
2784         albumSubtitle.c_str(), highlightAlbumId.c_str());
2785     int32_t currentCoverStatus = 0;
2786     GetHighlightCoverStatus(highlightAlbumId, currentCoverStatus);
2787     int32_t newCoverStatus = static_cast<uint32_t>(currentCoverStatus) | HIGHLIGHT_COVER_STATUS_TITLE;
2788     std::string updateAlbumName = "UPDATE " + HIGHLIGHT_ALBUM_TABLE + " SET " + SUB_TITLE + " = '" + albumSubtitle +
2789         "', " + HIGHLIGHT_USE_SUBTITLE + " = 1" + " WHERE " + ALBUM_ID + " = " + highlightAlbumId;
2790     std::string updateCoverInfoTable = "UPDATE " + HIGHLIGHT_COVER_INFO_TABLE + " SET " +
2791         COVER_STATUS + " = " + to_string(newCoverStatus) + " WHERE " +
2792         ALBUM_ID + " = (SELECT id FROM tab_highlight_album WHERE album_id = " + highlightAlbumId + " LIMIT 1)";
2793     vector<string> updateSqls = { updateAlbumName, updateCoverInfoTable };
2794     err = ExecSqls(updateSqls, uniStore);
2795     if (err == E_OK) {
2796         vector<int32_t> changeAlbumIds = { atoi(highlightAlbumId.c_str()) };
2797         NotifyHighlightAlbum(changeAlbumIds);
2798     }
2799     return err;
2800 }
2801 
2802 /**
2803  * set target album is me
2804  * @param values is_me
2805  * @param predicates target album
2806  */
SetIsMe(const ValuesBucket & values,const DataSharePredicates & predicates)2807 int32_t MediaLibraryAlbumOperations::SetIsMe(const ValuesBucket &values, const DataSharePredicates &predicates)
2808 {
2809     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
2810     auto whereArgs = rdbPredicates.GetWhereArgs();
2811     if (whereArgs.size() == 0) {
2812         MEDIA_ERR_LOG("no target album id");
2813         return E_INVALID_VALUES;
2814     }
2815     string targetAlbumId = whereArgs[0];
2816     CHECK_AND_RETURN_RET_LOG(!targetAlbumId.empty() && MediaLibraryDataManagerUtils::IsNumber(targetAlbumId),
2817         E_INVALID_VALUES, "target album id not exists");
2818     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2819     if (uniStore == nullptr) {
2820         MEDIA_ERR_LOG("uniStore is nullptr! failed update for merge albums");
2821         return E_DB_FAIL;
2822     }
2823     vector<string> updateSqls;
2824     SetMyOldAlbum(updateSqls, uniStore);
2825     std::string queryTargetAlbum = "SELECT " + USER_DISPLAY_LEVEL + " FROM " + ANALYSIS_ALBUM_TABLE +
2826         " WHERE " + ALBUM_ID + " = " + targetAlbumId;
2827     auto targetResultSet = uniStore->QuerySql(queryTargetAlbum);
2828     if (targetResultSet == nullptr || targetResultSet->GoToFirstRow() != NativeRdb::E_OK) {
2829         MEDIA_ERR_LOG("Failed to query target album!");
2830         return -E_HAS_DB_ERROR;
2831     }
2832     targetResultSet->Close();
2833 
2834     MEDIA_INFO_LOG("Start set is me, album id: %{public}s", targetAlbumId.c_str());
2835     std::string updateForSetIsMe = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + IS_ME + " = 1, " + RENAME_OPERATION +
2836         " = 1 WHERE " + GROUP_TAG + " IN(SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
2837         ALBUM_ID + " = " + targetAlbumId + ")";
2838     std::string updateReNameOperation = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RENAME_OPERATION + " = " +
2839         std::to_string(ALBUM_TO_RENAME_FOR_ANALYSIS) + " WHERE " + ALBUM_ID + " IN (SELECT " + ALBUM_ID + " FROM " +
2840         ANALYSIS_ALBUM_TABLE + " WHERE " + GROUP_TAG + " LIKE ( SELECT CONCAT('%', " + GROUP_TAG + ", '%') FROM " +
2841         ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " + targetAlbumId + ") AND " +
2842         PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + std::to_string(PhotoAlbumSubType::GROUP_PHOTO) + " AND (" +
2843         RENAME_OPERATION + " != " + std::to_string(ALBUM_RENAMED) + " OR " + RENAME_OPERATION + " IS NULL))";
2844     updateSqls.push_back(updateForSetIsMe);
2845     updateSqls.push_back(updateReNameOperation);
2846     int32_t err = ExecSqls(updateSqls, uniStore);
2847     if (err == E_OK) {
2848         vector<int32_t> changeAlbumIds = { atoi(targetAlbumId.c_str()) };
2849         NotifyPortraitAlbum(changeAlbumIds);
2850     }
2851     return err;
2852 }
2853 
GetUpdateSqlForSetAlbumName(std::string targetAlbumId,std::string albumName)2854 std::vector<std::string> GetUpdateSqlForSetAlbumName(std::string targetAlbumId, std::string albumName)
2855 {
2856     std::string updateForSetAlbumName = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + ALBUM_NAME + " = '" + albumName +
2857         "' , " + RENAME_OPERATION + " = 1 WHERE " + GROUP_TAG + " IN(SELECT " + GROUP_TAG + " FROM " +
2858         ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " + targetAlbumId + ")";
2859     std::string updateReNameOperation = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + RENAME_OPERATION + " = " +
2860         std::to_string(ALBUM_TO_RENAME_FOR_ANALYSIS) + " WHERE " + ALBUM_ID + " IN (SELECT " + ALBUM_ID + " FROM " +
2861         ANALYSIS_ALBUM_TABLE + " WHERE " + GROUP_TAG + " LIKE ( SELECT CONCAT('%', " + GROUP_TAG + ", '%') FROM " +
2862         ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID + " = " + targetAlbumId + ") AND " +
2863         PhotoAlbumColumns::ALBUM_SUBTYPE + " = " + std::to_string(PhotoAlbumSubType::GROUP_PHOTO) + " AND (" +
2864         RENAME_OPERATION + " != " + std::to_string(ALBUM_RENAMED) + " OR " + RENAME_OPERATION + " IS NULL))";
2865     vector<string> updateSqls = {updateForSetAlbumName, updateReNameOperation};
2866     return updateSqls;
2867 }
2868 
2869 /**
2870  * set target album name
2871  * @param values album_name
2872  * @param predicates target album
2873  */
SetAlbumName(const ValuesBucket & values,const DataSharePredicates & predicates)2874 int32_t MediaLibraryAlbumOperations::SetAlbumName(const ValuesBucket &values, const DataSharePredicates &predicates)
2875 {
2876     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
2877     auto whereArgs = rdbPredicates.GetWhereArgs();
2878     if (whereArgs.size() == 0) {
2879         MEDIA_ERR_LOG("no target album id");
2880         return E_INVALID_VALUES;
2881     }
2882     string targetAlbumId = whereArgs[0];
2883     CHECK_AND_RETURN_RET_LOG(!targetAlbumId.empty() && MediaLibraryDataManagerUtils::IsNumber(targetAlbumId),
2884         E_INVALID_VALUES, "target album id not exists");
2885     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2886     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_DB_FAIL, "uniStore is nullptr! failed update for set album name");
2887     string albumName;
2888     int err = GetStringVal(values, ALBUM_NAME, albumName);
2889     if (err < 0 || albumName.empty()) {
2890         MEDIA_ERR_LOG("invalid album name");
2891         return E_INVALID_VALUES;
2892     }
2893     MEDIA_INFO_LOG("Set analysis album name, album id: %{public}s, album name: %{public}s",
2894         targetAlbumId.c_str(), DfxUtils::GetSafeAlbumName(albumName).c_str());
2895     std::vector<std::string> updateSqls = GetUpdateSqlForSetAlbumName(targetAlbumId, albumName);
2896     err = ExecSqls(updateSqls, uniStore);
2897     if (err == E_OK) {
2898         vector<int32_t> changeAlbumIds = { atoi(targetAlbumId.c_str()) };
2899         NotifyPortraitAlbum(changeAlbumIds);
2900     }
2901 
2902     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2903     if (rdbStore == nullptr) {
2904         MEDIA_ERR_LOG("rdbStore is nullptr! failed update index");
2905         return err;
2906     }
2907     const std::string  QUERY_MAP_ASSET_TO_UPDATE_INDEX =
2908         "SELECT map_asset FROM AnalysisPhotoMap WHERE map_album = " + targetAlbumId;
2909     vector<string> mapAssets;
2910     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(QUERY_MAP_ASSET_TO_UPDATE_INDEX);
2911     if (resultSet == nullptr) {
2912         MEDIA_ERR_LOG("resultSet is nullptr! failed update index");
2913         return err;
2914     }
2915     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2916         mapAssets.push_back(to_string(GetInt32Val("map_asset", resultSet)));
2917     }
2918     MEDIA_INFO_LOG("update index map_asset size: %{public}zu", mapAssets.size());
2919     MediaAnalysisHelper::AsyncStartMediaAnalysisService(
2920         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), mapAssets);
2921 
2922     return err;
2923 }
2924 
2925 /**
2926  * set target album uri
2927  * @param values cover_uri
2928  * @param predicates target album
2929  */
SetCoverUri(const ValuesBucket & values,const DataSharePredicates & predicates)2930 int32_t MediaLibraryAlbumOperations::SetCoverUri(const ValuesBucket &values, const DataSharePredicates &predicates)
2931 {
2932     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, ANALYSIS_ALBUM_TABLE);
2933     auto whereArgs = rdbPredicates.GetWhereArgs();
2934     if (whereArgs.size() == 0) {
2935         MEDIA_ERR_LOG("no target album id");
2936         return E_INVALID_VALUES;
2937     }
2938     string targetAlbumId = whereArgs[0];
2939     CHECK_AND_RETURN_RET_LOG(!targetAlbumId.empty() && MediaLibraryDataManagerUtils::IsNumber(targetAlbumId),
2940         E_INVALID_VALUES, "target album id not exists");
2941     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2942     if (uniStore == nullptr) {
2943         MEDIA_ERR_LOG("uniStore is nullptr! failed update for set album cover uri");
2944         return E_DB_FAIL;
2945     }
2946     string coverUri;
2947     int err = GetStringVal(values, COVER_URI, coverUri);
2948     if (err < 0 || coverUri.empty()) {
2949         MEDIA_ERR_LOG("invalid album cover uri");
2950         return E_INVALID_VALUES;
2951     }
2952     MEDIA_INFO_LOG("Set analysis album cover uri, album id: %{public}s, cover uri: %{public}s",
2953         targetAlbumId.c_str(), DfxUtils::GetSafeUri(coverUri).c_str());
2954     std::string updateForSetCoverUri = "UPDATE " + ANALYSIS_ALBUM_TABLE + " SET " + COVER_URI + " = '" + coverUri +
2955         "', " + IS_COVER_SATISFIED + " = " + to_string(static_cast<uint8_t>(CoverSatisfiedType::USER_SETTING)) +
2956         " WHERE " + GROUP_TAG + " IN(SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " + ALBUM_ID +
2957         " = " + targetAlbumId + ")";
2958     vector<string> updateSqls = { updateForSetCoverUri };
2959     err = ExecSqls(updateSqls, uniStore);
2960     if (err == E_OK) {
2961         vector<int32_t> changeAlbumIds = { atoi(targetAlbumId.c_str()) };
2962         NotifyPortraitAlbum(changeAlbumIds);
2963     }
2964     return err;
2965 }
2966 
GetArgsSetUserAlbumName(const ValuesBucket & values,const DataSharePredicates & predicates,int32_t & oldAlbumId,string & newAlbumName)2967 static bool GetArgsSetUserAlbumName(const ValuesBucket& values,
2968     const DataSharePredicates& predicates, int32_t& oldAlbumId, string& newAlbumName)
2969 {
2970     RdbPredicates rdbPredicates = RdbUtils::ToPredicates(predicates, PhotoAlbumColumns::TABLE);
2971     CHECK_AND_RETURN_RET_LOG(!rdbPredicates.GetWhereArgs().empty(), false,
2972         "Rename user album failed. Args is empty");
2973     oldAlbumId = atoi(rdbPredicates.GetWhereArgs()[0].c_str());
2974     CHECK_AND_RETURN_RET_LOG(oldAlbumId > 0, false, "Rename user album failed. Invalid album id: %{public}s",
2975         rdbPredicates.GetWhereArgs()[0].c_str());
2976     CHECK_AND_RETURN_RET_LOG(GetStringObject(values, PhotoAlbumColumns::ALBUM_NAME, newAlbumName) == E_OK, false,
2977         "Rename user album failed. Get new album name failed");
2978     return true;
2979 }
2980 
HandleSetAlbumNameRequest(const ValuesBucket & values,const DataSharePredicates & predicates)2981 int32_t MediaLibraryAlbumOperations::HandleSetAlbumNameRequest(const ValuesBucket &values,
2982     const DataSharePredicates &predicates)
2983 {
2984     int32_t oldAlbumId {};
2985     string newAlbumName {};
2986     CHECK_AND_RETURN_RET_LOG(GetArgsSetUserAlbumName(values, predicates, oldAlbumId, newAlbumName),
2987         E_INVALID_ARGS, "Set album name args invalid");
2988     return RenameUserAlbum(oldAlbumId, newAlbumName);
2989 }
2990 
HandleAnalysisPhotoAlbum(const OperationType & opType,const NativeRdb::ValuesBucket & values,const DataShare::DataSharePredicates & predicates,std::shared_ptr<int> countPtr)2991 int32_t MediaLibraryAlbumOperations::HandleAnalysisPhotoAlbum(const OperationType &opType,
2992     const NativeRdb::ValuesBucket &values, const DataShare::DataSharePredicates &predicates,
2993     std::shared_ptr<int> countPtr)
2994 {
2995     switch (opType) {
2996         case OperationType::PORTRAIT_DISPLAY_LEVEL:
2997             return SetDisplayLevel(values, predicates);
2998         case OperationType::PORTRAIT_MERGE_ALBUM:
2999             return MergePortraitAlbums(values);
3000         case OperationType::PORTRAIT_IS_ME:
3001             return SetIsMe(values, predicates);
3002         case OperationType::PORTRAIT_ALBUM_NAME:
3003             return SetAlbumName(values, predicates);
3004         case OperationType::PORTRAIT_COVER_URI:
3005             return SetCoverUri(values, predicates);
3006         case OperationType::HIGHLIGHT_ALBUM_NAME:
3007             return SetHighlightAlbumName(values, predicates);
3008         case OperationType::HIGHLIGHT_COVER_URI:
3009             return SetHighlightCoverUri(values, predicates);
3010         case OperationType::HIGHLIGHT_SUBTITLE:
3011             return SetHighlightSubtitle(values, predicates);
3012         case OperationType::DISMISS:
3013         case OperationType::GROUP_ALBUM_NAME:
3014         case OperationType::GROUP_COVER_URI:
3015             return MediaLibraryAnalysisAlbumOperations::HandleGroupPhotoAlbum(opType, values, predicates);
3016         default:
3017             MEDIA_ERR_LOG("Unknown operation type: %{public}d", opType);
3018             return E_ERR;
3019     }
3020 }
3021 
HandlePhotoAlbum(const OperationType & opType,const ValuesBucket & values,const DataSharePredicates & predicates,shared_ptr<int> countPtr)3022 int32_t MediaLibraryAlbumOperations::HandlePhotoAlbum(const OperationType &opType, const ValuesBucket &values,
3023     const DataSharePredicates &predicates, shared_ptr<int> countPtr)
3024 {
3025     switch (opType) {
3026         case OperationType::UPDATE:
3027             return UpdatePhotoAlbum(values, predicates);
3028         case OperationType::SET_USER_ALBUM_COVER_URI:
3029         case OperationType::SET_SOURCE_ALBUM_COVER_URI:
3030             return UpdateAlbumCoverUri(values, predicates, false);
3031         case OperationType::SET_SYSTEM_ALBUM_COVER_URI:
3032             return UpdateAlbumCoverUri(values, predicates, true);
3033         case OperationType::RESET_COVER_URI:
3034             return ResetCoverUri(values, predicates);
3035         case OperationType::ALBUM_RECOVER_ASSETS:
3036             return MediaLibraryAlbumOperations::RecoverPhotoAssets(predicates);
3037         case OperationType::ALBUM_DELETE_ASSETS:
3038             return DeletePhotoAssets(predicates, false, false);
3039         case OperationType::COMPAT_ALBUM_DELETE_ASSETS:
3040             return DeletePhotoAssets(predicates, false, true);
3041         case OperationType::DELETE_LOCAL_ASSETS_PERMANENTLY:
3042             return DeletePhotoAssetsCompleted(predicates, false);
3043         case OperationType::AGING:
3044             return AgingPhotoAssets(countPtr);
3045         case OperationType::ALBUM_ORDER:
3046             return OrderSingleAlbum(values);
3047         case OperationType::ALBUM_SET_NAME:
3048             return HandleSetAlbumNameRequest(values, predicates);
3049         default:
3050             MEDIA_ERR_LOG("Unknown operation type: %{public}d", opType);
3051             return E_ERR;
3052     }
3053 }
3054 
HandlePhotoAlbumOperations(MediaLibraryCommand & cmd)3055 int MediaLibraryAlbumOperations::HandlePhotoAlbumOperations(MediaLibraryCommand &cmd)
3056 {
3057     switch (cmd.GetOprnType()) {
3058         case OperationType::CREATE:
3059             return CreatePhotoAlbum(cmd);
3060         default:
3061             MEDIA_ERR_LOG("Unknown operation type: %{public}d", cmd.GetOprnType());
3062             return E_ERR;
3063     }
3064 }
3065 
UpdateOneAlbumOrder(const shared_ptr<MediaLibraryRdbStore> & rdbStore,const NativeRdb::ValuesBucket & ValuesBucket,const NativeRdb::RdbPredicates & predicates)3066 int32_t UpdateOneAlbumOrder(const shared_ptr<MediaLibraryRdbStore> &rdbStore,
3067     const NativeRdb::ValuesBucket &ValuesBucket, const NativeRdb::RdbPredicates &predicates)
3068 {
3069     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "get rdbStore failed");
3070 
3071     int32_t changeRows = 0;
3072     auto ret = rdbStore->Update(changeRows, ValuesBucket, predicates);
3073     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, ret, "Failed to update album order");
3074     return ret;
3075 }
3076 
UpdatePhotoAlbumOrder(const vector<NativeRdb::ValuesBucket> & valuesBuckets,const vector<NativeRdb::RdbPredicates> & predicatesArray)3077 int32_t MediaLibraryAlbumOperations::UpdatePhotoAlbumOrder(const vector<NativeRdb::ValuesBucket> &valuesBuckets,
3078     const vector<NativeRdb::RdbPredicates> &predicatesArray)
3079 {
3080     CHECK_AND_RETURN_RET_LOG(valuesBuckets.size() == predicatesArray.size(), E_INNER_FAIL,
3081         "valuesBuckets.size() not equal to predicatesArray.size(), can not update album order");
3082 
3083     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
3084     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_INNER_FAIL, "get rdbStore failed");
3085 
3086     int32_t err = 0;
3087     int32_t successSetOrderRows = 0;
3088     if (!valuesBuckets.empty() && !predicatesArray.empty()) {
3089         for (size_t i = 0; i < valuesBuckets.size(); i++) {
3090             err = UpdateOneAlbumOrder(rdbStore, valuesBuckets[i], predicatesArray[i]);
3091             CHECK_AND_EXECUTE(err != NativeRdb::E_OK, ++successSetOrderRows);
3092         }
3093         MEDIA_INFO_LOG("success update order album size: %{public}d", successSetOrderRows);
3094 
3095         auto watch = MediaLibraryNotify::GetInstance();
3096         CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
3097         watch->Notify(PhotoAlbumColumns::ALBUM_URI_PREFIX, NotifyType::NOTIFY_UPDATE);
3098     }
3099     return successSetOrderRows == 0 ? E_INNER_FAIL : E_OK;
3100 }
3101 } // namespace OHOS::Media
3102