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> ¬ifyUris = 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> ¬ifyIds = 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 ¤tAlbumId, const int32_t referenceAlbumId,
1220 int32_t ¤tAlbumOrder, 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 ¤tAlbumOrder, 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 ¤tAlbumId, const int32_t referenceAlbumId,
1304 int32_t ¤tAlbumOrder, 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 ¤tAlbumId,
1359 const int32_t ¤tAlbumOrder, 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 ¤tAlbumId)
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 ¤tAlbumOrder, 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 ¤tAlbum,
1793 const MergeAlbumInfo &targetAlbum, const string ¤tFileId, 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 ¤tAlbum,
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