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