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