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> ¬ifyUris = 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> ¬ifyUris = 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> ¬ifyIds = 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 ¤tAlbumId, const int32_t referenceAlbumId,
1769 int32_t ¤tAlbumOrder, 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 ¤tAlbumOrder, 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 ¤tAlbumId,
1867 const int32_t referenceAlbumId, int32_t ¤tAlbumOrder, 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 ¤tAlbumId,
1934 const int32_t ¤tAlbumOrder, 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 ¤tAlbumId)
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 ¤tAlbumOrder, 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 ¤tAlbum,
2361 const MergeAlbumInfo &targetAlbum, const string ¤tFileId, 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 ¤tAlbum,
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 ¤tCoverStatus)
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