• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 "PhotoMapOperation"
16 
17 #include "photo_map_operations.h"
18 
19 #include "media_analysis_helper.h"
20 #include "media_column.h"
21 #include "media_file_uri.h"
22 #include "media_file_utils.h"
23 #include "medialibrary_album_operations.h"
24 #include "medialibrary_analysis_album_operations.h"
25 #include "medialibrary_asset_operations.h"
26 #include "medialibrary_db_const.h"
27 #include "medialibrary_data_manager.h"
28 #include "medialibrary_errno.h"
29 #include "medialibrary_notify.h"
30 #include "medialibrary_photo_operations.h"
31 #include "medialibrary_rdb_transaction.h"
32 #include "medialibrary_rdb_utils.h"
33 #include "medialibrary_rdbstore.h"
34 #include "medialibrary_unistore_manager.h"
35 #include "photo_album_column.h"
36 #include "photo_map_column.h"
37 #include "value_object.h"
38 #include "vision_column.h"
39 #include "rdb_utils.h"
40 #include "result_set_utils.h"
41 #include "vision_album_column.h"
42 #include "vision_face_tag_column.h"
43 #include "vision_image_face_column.h"
44 #include "vision_photo_map_column.h"
45 #include "dfx_manager.h"
46 #include "dfx_const.h"
47 #include "asset_accurate_refresh.h"
48 #include "refresh_business_name.h"
49 
50 namespace OHOS::Media {
51 using namespace std;
52 using namespace OHOS::NativeRdb;
53 using namespace OHOS::DataShare;
54 
55 constexpr int32_t ALBUM_IS_REMOVED = 1;
56 unordered_map<string, string> dateTypeSecondsMap = {
57     {MEDIA_DATA_DB_DATE_ADDED_TO_SECOND, "CAST(P.date_added / 1000 AS BIGINT) AS date_added_s"},
58     {MEDIA_DATA_DB_DATE_TRASHED_TO_SECOND, "CAST(P.date_trashed / 1000 AS BIGINT) AS date_trashed_s"},
59     {MEDIA_DATA_DB_DATE_MODIFIED_TO_SECOND, "CAST(P.date_modified / 1000 AS BIGINT) AS date_modified_s"},
60     {MEDIA_DATA_DB_DATE_TAKEN_TO_SECOND, "CAST(P.date_taken / 1000 AS BIGINT) AS date_taken_s"}
61 };
62 
InsertAnalysisAsset(const DataShareValuesBucket & value,std::shared_ptr<TransactionOperations> trans)63 static int32_t InsertAnalysisAsset(const DataShareValuesBucket &value,
64     std::shared_ptr<TransactionOperations> trans)
65 {
66     CHECK_AND_RETURN_RET_LOG(trans != nullptr, -EINVAL, "transactionOperations is null");
67     /**
68      * Build insert sql:
69      * INSERT INTO AnalysisPhotoMap (map_album, map_asset, order_position) SELECT
70      * ?, ?, ?
71      * WHERE
72      *     (NOT EXISTS (SELECT * FROM AnalysisPhotoMap WHERE map_album = ? AND map_asset = ?))
73      *     AND (EXISTS (SELECT file_id FROM Photos WHERE file_id = ?))
74      *     AND (EXISTS (SELECT album_id FROM AnalysisAlbum WHERE album_id = ?));
75      */
76     static const std::string INSERT_MAP_SQL = "INSERT OR IGNORE INTO " + ANALYSIS_PHOTO_MAP_TABLE +
77         " (" + PhotoMap::ALBUM_ID + ", " + PhotoMap::ASSET_ID + ", " + ORDER_POSITION + ") " +
78         "SELECT ?, ?, ? WHERE " +
79         "(NOT EXISTS (SELECT 1 FROM " + ANALYSIS_PHOTO_MAP_TABLE + " WHERE " +
80             PhotoMap::ALBUM_ID + " = ? AND " + PhotoMap::ASSET_ID + " = ?)) " +
81         "AND (EXISTS (SELECT 1 FROM " + PhotoColumn::PHOTOS_TABLE + " WHERE " +
82             MediaColumn::MEDIA_ID + " = ?)) " +
83         "AND (EXISTS (SELECT 1 FROM " + ANALYSIS_ALBUM_TABLE +
84             " WHERE " + PhotoAlbumColumns::ALBUM_ID + " = ? ));";
85     bool isValid = false;
86     int32_t albumId = value.Get(PhotoMap::ALBUM_ID, isValid);
87     CHECK_AND_RETURN_RET(isValid, -EINVAL);
88     int32_t assetId = value.Get(PhotoMap::ASSET_ID, isValid);
89     CHECK_AND_RETURN_RET(isValid, -EINVAL);
90     const int defaultValue = -1;
91     int32_t orderPosition = value.Get(ORDER_POSITION, isValid);
92     if (!isValid) {
93         orderPosition = defaultValue;
94     }
95 
96     vector<ValueObject> bindArgs = { albumId, assetId, orderPosition, albumId, assetId, assetId, albumId};
97     return trans->ExecuteForLastInsertedRowId(INSERT_MAP_SQL, bindArgs);
98 }
99 
AddPhotoAssets(const vector<DataShareValuesBucket> & values)100 int32_t PhotoMapOperations::AddPhotoAssets(const vector<DataShareValuesBucket> &values)
101 {
102     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
103     if (rdbStore == nullptr) {
104         return E_HAS_DB_ERROR;
105     }
106 
107     int32_t changedRows = 0;
108     vector<int32_t> updateIds;
109     if (!values.empty()) {
110         bool isValid = false;
111         int32_t albumId = values[0].Get(PhotoColumn::PHOTO_OWNER_ALBUM_ID, isValid);
112         if (!isValid || albumId <= 0) {
113             MEDIA_WARN_LOG("Ignore failure on get album id when add assets. isValid: %{public}d, albumId: %{public}d",
114                 isValid, albumId);
115             return changedRows;
116         }
117         bool hidden = false;
118         changedRows = MediaLibraryRdbUtils::UpdateOwnerAlbumId(rdbStore, values, updateIds, hidden);
119         MediaLibraryRdbUtils::UpdateUserAlbumInternal(rdbStore, { to_string(albumId) }, false, !hidden);
120         MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, {
121             to_string(PhotoAlbumSubType::IMAGE), to_string(PhotoAlbumSubType::VIDEO),
122             to_string(PhotoAlbumSubType::FAVORITE), to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT)
123         });
124 
125         MEDIA_INFO_LOG("AddPhotoAssets idToUpdateIndex size: %{public}zu", updateIds.size());
126         if (!updateIds.empty()) {
127             vector<string> idToUpdateIndex;
128             for (size_t i = 0; i < updateIds.size(); i++) {
129                 idToUpdateIndex.push_back(to_string(updateIds[i]));
130             }
131             MediaAnalysisHelper::AsyncStartMediaAnalysisService(
132                 static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), idToUpdateIndex);
133         }
134 
135         auto watch = MediaLibraryNotify::GetInstance();
136         CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
137         for (const auto &id : updateIds) {
138             string notifyUri = PhotoColumn::PHOTO_URI_PREFIX + to_string(id);
139             watch->Notify(MediaFileUtils::Encode(notifyUri), NotifyType::NOTIFY_ALBUM_ADD_ASSET, albumId);
140             watch->Notify(MediaFileUtils::Encode(notifyUri), NotifyType::NOTIFY_ALBUM_ADD_ASSET,
141                 watch->GetAlbumIdBySubType(PhotoAlbumSubType::IMAGE));
142             watch->Notify(MediaFileUtils::Encode(notifyUri), NotifyType::NOTIFY_ALBUM_ADD_ASSET,
143                 watch->GetAlbumIdBySubType(PhotoAlbumSubType::VIDEO));
144             watch->Notify(MediaFileUtils::Encode(notifyUri), NotifyType::NOTIFY_ALBUM_ADD_ASSET,
145                 watch->GetAlbumIdBySubType(PhotoAlbumSubType::FAVORITE));
146             watch->Notify(MediaFileUtils::Encode(notifyUri), NotifyType::NOTIFY_ADD);
147         }
148     }
149     return changedRows;
150 }
151 
GetPortraitAlbumIds(const string & albumId,vector<string> & portraitAlbumIds)152 static int32_t GetPortraitAlbumIds(const string &albumId, vector<string> &portraitAlbumIds)
153 {
154     auto uniStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
155     CHECK_AND_RETURN_RET_LOG(uniStore != nullptr, E_HAS_DB_ERROR, "uniStore is nullptr! failed query album order");
156     const std::string queryPortraitAlbumIds = "SELECT " + ALBUM_ID + " FROM " + ANALYSIS_ALBUM_TABLE + " WHERE " +
157         GROUP_TAG + " IN(SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE +
158         " WHERE " + ALBUM_ID + " = " + albumId + " AND " + ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) +")";
159 
160     auto resultSet = uniStore->QuerySql(queryPortraitAlbumIds);
161     CHECK_AND_RETURN_RET(resultSet != nullptr, E_DB_FAIL);
162     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
163         portraitAlbumIds.push_back(to_string(GetInt32Val(ALBUM_ID, resultSet)));
164     }
165     return E_OK;
166 }
167 
AddHighlightPhotoAssets(const vector<DataShareValuesBucket> & values)168 int32_t PhotoMapOperations::AddHighlightPhotoAssets(const vector<DataShareValuesBucket> &values)
169 {
170     MEDIA_INFO_LOG("Add highlight assets start");
171     CHECK_AND_RETURN_RET(!values.empty(), E_DB_FAIL);
172 
173     bool isValid = false;
174     int32_t albumId = values[0].Get(PhotoMap::ALBUM_ID, isValid);
175     bool cond = (!isValid || albumId <= 0);
176     CHECK_AND_RETURN_RET(!cond, E_DB_FAIL);
177 
178     MEDIA_INFO_LOG("Add highlight assets, id is %{puiblic}d", albumId);
179     vector<string> uris;
180     std::vector<ValuesBucket> insertValues;
181     for (auto value : values) {
182         bool isValidValue = false;
183         std::string assetUri = value.Get(PhotoMap::ASSET_ID, isValidValue);
184         uris.push_back(assetUri);
185         int32_t photoId = std::stoi(MediaFileUri::GetPhotoId(assetUri));
186         DataShare::DataShareValuesBucket pair;
187         pair.Put(PhotoMap::ALBUM_ID, albumId);
188         pair.Put(PhotoMap::ASSET_ID, photoId);
189         ValuesBucket valueInsert = RdbDataShareAdapter::RdbUtils::ToValuesBucket(pair);
190         insertValues.push_back(valueInsert);
191     }
192 
193     int64_t outRowId = -1;
194     int32_t ret = MediaLibraryRdbStore::BatchInsert(outRowId, ANALYSIS_PHOTO_MAP_TABLE, insertValues);
195     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, ret, "Batch insert highlight assets fail, err = %{public}d", ret);
196     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
197     CHECK_AND_RETURN_RET(rdbStore != nullptr, E_HAS_DB_ERROR);
198 
199     MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(rdbStore, { to_string(albumId) });
200     auto watch = MediaLibraryNotify::GetInstance();
201     for (auto uri : uris) {
202         watch->Notify(MediaFileUtils::Encode(uri), NotifyType::NOTIFY_ALBUM_ADD_ASSET, albumId);
203     }
204     return ret;
205 }
206 
AddAnaLysisPhotoAssets(const vector<DataShareValuesBucket> & values)207 int32_t PhotoMapOperations::AddAnaLysisPhotoAssets(const vector<DataShareValuesBucket> &values)
208 {
209     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
210     CHECK_AND_RETURN_RET(rdbStore != nullptr, E_HAS_DB_ERROR);
211     if (values.empty()) {
212         return 0;
213     }
214     std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
215     int32_t changedRows = 0;
216     int32_t err = NativeRdb::E_OK;
217     std::function<int(void)> func = [&]()->int {
218         for (const auto &value : values) {
219             int ret =  InsertAnalysisAsset(value, trans);
220             if (ret == E_HAS_DB_ERROR) {
221                 MEDIA_WARN_LOG("InsertAnalysisAsset for db error, changedRows now: %{public}d", changedRows);
222                 return ret;
223             }
224             if (ret > 0) {
225                 changedRows++;
226             }
227         }
228         return NativeRdb::E_OK;
229     };
230     err = trans->RetryTrans(func);
231     CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "AddAnaLysisPhotoAssets: trans retry fail!, ret:%{public}d", err);
232 
233     bool isValid = false;
234     std::vector<string> albumIdList;
235     for (const auto &value : values) {
236         int32_t albumId = value.Get(PhotoMap::ALBUM_ID, isValid);
237         if (!isValid || albumId <= 0) {
238             MEDIA_WARN_LOG("Ignore failure on get album id when add assets. isValid: %{public}d, albumId: %{public}d",
239                 isValid, albumId);
240             continue;
241         }
242         albumIdList.push_back(to_string(albumId));
243     }
244     MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(rdbStore, albumIdList);
245     return changedRows;
246 }
247 
GetDismissAssetsPredicates(NativeRdb::RdbPredicates & rdbPredicate,vector<string> & updateAlbumIds,PhotoAlbumSubType subtype,const string & albumId,const vector<string> & assetsArray)248 static void GetDismissAssetsPredicates(NativeRdb::RdbPredicates &rdbPredicate, vector<string> &updateAlbumIds,
249     PhotoAlbumSubType subtype, const string &albumId, const vector<string> &assetsArray)
250 {
251     if (subtype == PhotoAlbumSubType::PORTRAIT) {
252         GetPortraitAlbumIds(albumId, updateAlbumIds);
253         rdbPredicate.In(MAP_ALBUM, updateAlbumIds);
254         rdbPredicate.And()->In(MAP_ASSET, assetsArray);
255     } else {
256         rdbPredicate.EqualTo(MAP_ALBUM, albumId);
257         rdbPredicate.And()->In(MAP_ASSET, assetsArray);
258         updateAlbumIds.push_back(albumId);
259     }
260 }
261 
DoDismissAssets(int32_t subtype,const string & albumId,const vector<string> & assetIds)262 int32_t DoDismissAssets(int32_t subtype, const string &albumId, const vector<string> &assetIds)
263 {
264     int32_t deleteRow = 0;
265     int32_t secondDeleteRow = 0;
266     if (subtype == PhotoAlbumSubType::GROUP_PHOTO) {
267         NativeRdb::RdbPredicates rdbPredicate { VISION_IMAGE_FACE_TABLE };
268         rdbPredicate.In(MediaColumn::MEDIA_ID, assetIds);
269         deleteRow = MediaLibraryRdbStore::Delete(rdbPredicate);
270 
271         NativeRdb::RdbPredicates mapTablePredicate { ANALYSIS_PHOTO_MAP_TABLE };
272         mapTablePredicate.EqualTo(MAP_ALBUM, albumId);
273         mapTablePredicate.And()->In(MAP_ASSET, assetIds);
274         secondDeleteRow = MediaLibraryRdbStore::Delete(mapTablePredicate);
275         if (deleteRow != 0 && secondDeleteRow != 0 && MediaLibraryDataManagerUtils::IsNumber(albumId)) {
276             MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(
277                 MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), {albumId});
278         }
279         return deleteRow;
280     }
281 
282     if (subtype == PhotoAlbumSubType::HIGHLIGHT || subtype == PhotoAlbumSubType::HIGHLIGHT_SUGGESTIONS) {
283         auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
284         if (rdbStore == nullptr) {
285             MEDIA_ERR_LOG("RdbStore is nullptr");
286         } else {
287             int32_t updateHighlight = MediaLibraryRdbUtils::UpdateHighlightPlayInfo(rdbStore, albumId);
288             CHECK_AND_PRINT_LOG(updateHighlight >= 0, "Update highlight playinfo fail");
289         }
290     }
291     vector<string> updateAlbumIds;
292     NativeRdb::RdbPredicates rdbPredicate { ANALYSIS_PHOTO_MAP_TABLE };
293     GetDismissAssetsPredicates(rdbPredicate, updateAlbumIds,
294         static_cast<PhotoAlbumSubType>(subtype), albumId, assetIds);
295     deleteRow = MediaLibraryRdbStore::Delete(rdbPredicate);
296     if (deleteRow <= 0) {
297         return deleteRow;
298     }
299     MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(
300         MediaLibraryUnistoreManager::GetInstance().GetRdbStore(), updateAlbumIds);
301     return deleteRow;
302 }
303 
DismissAssets(NativeRdb::RdbPredicates & predicates)304 int32_t PhotoMapOperations::DismissAssets(NativeRdb::RdbPredicates &predicates)
305 {
306     vector<string> whereArgsUri = predicates.GetWhereArgs();
307     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
308 
309     const vector<string> &whereArgsId = predicates.GetWhereArgs();
310     if (whereArgsId.size() == 0 || whereArgsUri.size() == 0) {
311         MEDIA_ERR_LOG("No fileAsset to delete");
312         return E_INVALID_ARGUMENTS;
313     }
314     string strAlbumId = whereArgsId[0];
315     if (strAlbumId.empty()) {
316         MEDIA_ERR_LOG("Failed to get albumId");
317         return E_INVALID_ARGUMENTS;
318     }
319 
320     int32_t albumId = atoi(strAlbumId.c_str());
321     if (albumId <= 0) {
322         MEDIA_WARN_LOG("Ignore failure on get album id when remove assets, album updating would be lost");
323         return E_INVALID_ARGUMENTS;
324     }
325     string strSubtype = whereArgsId[whereArgsId.size() - 1];
326     int32_t subtype = atoi(strSubtype.c_str());
327     if (subtype != PhotoAlbumSubType::CLASSIFY && subtype != PhotoAlbumSubType::PORTRAIT &&
328         subtype != PhotoAlbumSubType::GROUP_PHOTO && subtype != PhotoAlbumSubType::HIGHLIGHT &&
329         subtype != PhotoAlbumSubType::HIGHLIGHT_SUGGESTIONS) {
330         MEDIA_ERR_LOG("Invalid album subtype: %{public}d", subtype);
331         return E_INVALID_ARGUMENTS;
332     }
333 
334     vector<string> assetsArray;
335     for (size_t i = 1; i < whereArgsId.size() - 1; i++) {
336         assetsArray.push_back(whereArgsId[i]);
337     }
338 
339     int32_t deleteRow = DoDismissAssets(subtype, strAlbumId, assetsArray);
340     if (deleteRow > 0) {
341         auto watch = MediaLibraryNotify::GetInstance();
342         CHECK_AND_RETURN_RET_LOG(watch != nullptr, E_ERR, "Can not get MediaLibraryNotify Instance");
343         for (size_t i = 1; i < whereArgsUri.size() - 1; i++) {
344             watch->Notify(MediaFileUtils::Encode(whereArgsUri[i]), NotifyType::NOTIFY_ALBUM_DISMISS_ASSET, albumId);
345         }
346     }
347     return deleteRow;
348 }
349 
RemovePhotoAssets(RdbPredicates & predicates)350 int32_t PhotoMapOperations::RemovePhotoAssets(RdbPredicates &predicates)
351 {
352     vector<string> uriWhereArgs = predicates.GetWhereArgs();
353     int32_t deleteRow = 0;
354     CHECK_AND_RETURN_RET_LOG(!uriWhereArgs.empty(), deleteRow, "Remove photo assets failed: args is empty");
355     MediaLibraryRdbStore::ReplacePredicatesUriToId(predicates);
356     vector<string> idWhereArgs = predicates.GetWhereArgs();
357     string strAlbumId = idWhereArgs[0];
358     int32_t albumId = atoi(strAlbumId.c_str());
359     CHECK_AND_WARN_LOG(albumId > 0, "Invalid album Id: %{public}s", strAlbumId.c_str());
360     idWhereArgs.erase(idWhereArgs.begin());
361     if (idWhereArgs.empty()) {
362         MEDIA_WARN_LOG("No photo assets to remove");
363         return deleteRow;
364     }
365 
366     MEDIA_INFO_LOG("Remove %{public}zu photo assets from album %{public}d", idWhereArgs.size(), albumId);
367 
368     RdbPredicates predicatesPhotos(PhotoColumn::PHOTOS_TABLE);
369     predicatesPhotos.In(MediaColumn::MEDIA_ID, idWhereArgs);
370     AccurateRefresh::AssetAccurateRefresh assetRefresh(AccurateRefresh::REMOTE_ASSETS_BUSSINESS_NAME);
371     MediaLibraryPhotoOperations::UpdateSourcePath(idWhereArgs);
372     ValuesBucket values;
373     values.Put(MediaColumn::MEDIA_DATE_TRASHED, MediaFileUtils::UTCTimeMilliSeconds());
374     assetRefresh.Update(deleteRow, values, predicatesPhotos);
375     CHECK_AND_RETURN_RET_LOG(deleteRow > 0, E_HAS_DB_ERROR,
376         "Update Removed Asset to Trash failed, ret: %{public}d", deleteRow);
377 
378     assetRefresh.RefreshAlbum();
379 
380     uriWhereArgs.erase(uriWhereArgs.begin());
381     MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
382         static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), uriWhereArgs);
383 
384     auto watch = MediaLibraryNotify::GetInstance();
385     if (watch != nullptr) {
386         int trashAlbumId = watch->GetAlbumIdBySubType(PhotoAlbumSubType::TRASH);
387         CHECK_AND_PRINT_LOG(trashAlbumId > 0,
388             "Trash album id error: %{public}d, trash album notification unavailable", trashAlbumId);
389         for (size_t i = 0; i < uriWhereArgs.size(); i++) {
390             watch->Notify(MediaFileUtils::Encode(uriWhereArgs[i]), NotifyType::NOTIFY_REMOVE);
391             watch->Notify(MediaFileUtils::Encode(uriWhereArgs[i]), NotifyType::NOTIFY_ALBUM_REMOVE_ASSET, albumId);
392             watch->Notify(MediaFileUtils::Encode(uriWhereArgs[i]), NotifyType::NOTIFY_ALBUM_ADD_ASSET, trashAlbumId);
393         }
394     } else {
395         MEDIA_ERR_LOG("Failed to get notify instance, notification unavailable");
396     }
397     assetRefresh.Notify();
398 
399     DfxManager::GetInstance()->HandleDeleteBehavior(DfxType::ALBUM_REMOVE_PHOTOS, deleteRow, uriWhereArgs);
400     return deleteRow;
401 }
402 
IsQueryGroupPhotoAlbumAssets(const string & albumId,string & tagId,int32_t & isRemoved)403 bool IsQueryGroupPhotoAlbumAssets(const string &albumId, string &tagId, int32_t &isRemoved)
404 {
405     bool cond = (albumId.empty() || !MediaLibraryDataManagerUtils::IsNumber(albumId));
406     CHECK_AND_RETURN_RET(!cond, false);
407     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
408     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, albumId);
409     vector<string> columns = {PhotoAlbumColumns::ALBUM_TYPE, PhotoAlbumColumns::ALBUM_SUBTYPE, TAG_ID, IS_REMOVED};
410     auto resultSet = MediaLibraryRdbStore::QueryWithFilter(predicates, columns);
411     cond = (resultSet == nullptr || resultSet->GoToFirstRow() != E_OK);
412     CHECK_AND_RETURN_RET(!cond, false);
413 
414     int32_t albumType = GetInt32Val(PhotoAlbumColumns::ALBUM_TYPE, resultSet);
415     int32_t albumSubtype = GetInt32Val(PhotoAlbumColumns::ALBUM_SUBTYPE, resultSet);
416     tagId = GetStringVal(TAG_ID, resultSet);
417     isRemoved = GetInt32Val(IS_REMOVED, resultSet);
418     return albumType == PhotoAlbumType::SMART && albumSubtype == PhotoAlbumSubType::GROUP_PHOTO;
419 }
420 
QueryGroupPhotoAlbumAssets(const string & albumId,const string & tagId,const vector<string> & columns)421 shared_ptr<OHOS::NativeRdb::ResultSet> QueryGroupPhotoAlbumAssets(const string &albumId, const string &tagId,
422     const vector<string> &columns)
423 {
424     string strColumns;
425     for (size_t i = 0; i < columns.size(); i++) {
426         string column = columns[i];
427         if (dateTypeSecondsMap.find(column) != dateTypeSecondsMap.end()) {
428             strColumns.append(dateTypeSecondsMap[column]);
429         } else {
430             strColumns.append("P." + column);
431         }
432         if (i != columns.size() - 1) {
433             strColumns.append(", ");
434         }
435     }
436     string strTags = "'";
437     int32_t albumTagCount = 1;
438     for (char c : tagId) {
439         if (c == ',') {
440             strTags.append("', '");
441             albumTagCount++;
442         } else {
443             strTags.push_back(c);
444         }
445     }
446     strTags.append("'");
447     string sql = "SELECT " + strColumns + " FROM " + VISION_IMAGE_FACE_TABLE + " F INNER JOIN " +
448         ANALYSIS_ALBUM_TABLE + " AA ON F." + TAG_ID + " = AA." + TAG_ID + " AND AA." + GROUP_TAG + " IN (" + strTags +
449         ") INNER JOIN " + ANALYSIS_PHOTO_MAP_TABLE + " ON " + MAP_ALBUM + " = AA." + PhotoAlbumColumns::ALBUM_ID +
450         " AND " + MAP_ASSET + " = F." + MediaColumn::MEDIA_ID + " INNER JOIN " + PhotoColumn::PHOTOS_TABLE +
451         " P ON P." + MediaColumn::MEDIA_ID + " = F." + MediaColumn::MEDIA_ID + " AND " +
452         MediaColumn::MEDIA_DATE_TRASHED + " = 0 AND " + PhotoColumn::PHOTO_IS_TEMP + " = 0 AND " +
453         PhotoColumn::PHOTO_BURST_COVER_LEVEL + " = 1 AND " + MediaColumn::MEDIA_HIDDEN + " = 0 AND " +
454         MediaColumn::MEDIA_TIME_PENDING + " = 0 GROUP BY P." + MediaColumn::MEDIA_ID +
455         " HAVING COUNT(" + GROUP_TAG + ") = " + TOTAL_FACES + " AND " +
456         " COUNT(DISTINCT " + GROUP_TAG +") = " + to_string(albumTagCount) + ";";
457     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
458     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, nullptr, "rdbstore is nullptr");
459     return rdbStore->QuerySql(sql);
460 }
QueryPhotoAssets(const RdbPredicates & rdbPredicate,const vector<string> & columns)461 shared_ptr<OHOS::NativeRdb::ResultSet> PhotoMapOperations::QueryPhotoAssets(const RdbPredicates &rdbPredicate,
462     const vector<string> &columns)
463 {
464     if (rdbPredicate.GetWhereArgs().size() <= 0) {
465         return nullptr;
466     }
467     return MediaLibraryRdbStore::QueryWithFilter(rdbPredicate, columns);
468 }
469 } // namespace OHOS::Media