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