• 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 
16 #include "medialibrary_rdb_utils.h"
17 
18 #include <functional>
19 #include <iomanip>
20 #include <sstream>
21 #include <string>
22 
23 #include "datashare_values_bucket.h"
24 #include "media_analysis_helper.h"
25 #include "media_app_uri_permission_column.h"
26 #include "media_file_uri.h"
27 #include "media_file_utils.h"
28 #include "media_log.h"
29 #include "media_refresh_album_column.h"
30 #include "medialibrary_album_fusion_utils.h"
31 #include "medialibrary_async_worker.h"
32 #include "medialibrary_business_record_column.h"
33 #include "medialibrary_data_manager_utils.h"
34 #include "medialibrary_db_const.h"
35 #include "medialibrary_formmap_operations.h"
36 #include "medialibrary_notify.h"
37 #include "medialibrary_photo_operations.h"
38 #include "medialibrary_rdb_transaction.h"
39 #include "medialibrary_tracer.h"
40 #include "permission_utils.h"
41 #include "photo_album_column.h"
42 #include "photo_map_column.h"
43 #include "result_set.h"
44 #include "userfile_manager_types.h"
45 #include "vision_album_column.h"
46 #include "vision_column.h"
47 #include "vision_face_tag_column.h"
48 #include "vision_image_face_column.h"
49 #include "vision_photo_map_column.h"
50 #include "vision_total_column.h"
51 #include "location_column.h"
52 #include "search_column.h"
53 #include "story_cover_info_column.h"
54 #include "story_play_info_column.h"
55 #include "photo_query_filter.h"
56 #include "power_efficiency_manager.h"
57 #include "rdb_sql_utils.h"
58 #include "medialibrary_restore.h"
59 
60 namespace OHOS::Media {
61 using namespace std;
62 using namespace NativeRdb;
63 
64 constexpr int32_t E_EMPTY_ALBUM_ID = 1;
65 constexpr size_t ALBUM_UPDATE_THRESHOLD = 1000;
66 constexpr int32_t SINGLE_FACE = 1;
67 constexpr double LOCATION_DB_ZERO = 0;
68 constexpr double LOCATION_LATITUDE_MAX = 90.0;
69 constexpr double LOCATION_LATITUDE_MIN = -90.0;
70 constexpr double LOCATION_LONGITUDE_MAX = 180.0;
71 constexpr double LOCATION_LONGITUDE_MIN = -180.0;
72 constexpr int32_t SEARCH_UPDATE_STATUS = 2;
73 constexpr int32_t FACE_RECOGNITION = 1;
74 constexpr int32_t FACE_FEATURE = 2;
75 constexpr int32_t FACE_CLUSTERED = 3;
76 constexpr int32_t CLOUD_POSITION_STATUS = 2;
77 constexpr int32_t UPDATE_ALBUM_TIME_OUT = 1000;
78 constexpr int32_t PERSIST_READ_IMAGEVIDEO = 1;
79 constexpr int32_t PERSIST_READWRITE_IMAGEVIDEO = 4;
80 mutex MediaLibraryRdbUtils::sRefreshAlbumMutex_;
81 
82 // 注意,端云同步代码仓也有相同常量,添加新相册时,请通知端云同步进行相应修改
83 const std::vector<std::string> ALL_SYS_PHOTO_ALBUM = {
84     std::to_string(PhotoAlbumSubType::FAVORITE),
85     std::to_string(PhotoAlbumSubType::VIDEO),
86     std::to_string(PhotoAlbumSubType::HIDDEN),
87     std::to_string(PhotoAlbumSubType::TRASH),
88     std::to_string(PhotoAlbumSubType::SCREENSHOT),
89     std::to_string(PhotoAlbumSubType::CAMERA),
90     std::to_string(PhotoAlbumSubType::IMAGE),
91     std::to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
92     std::to_string(PhotoAlbumSubType::SOURCE_GENERIC),
93 };
94 
95 // 注意,端云同步代码仓也有相同常量,添加新相册时,请通知端云同步进行相应修改
96 const std::vector<std::string> ALL_ANALYSIS_ALBUM = {
97     std::to_string(PhotoAlbumSubType::CLASSIFY),
98     std::to_string(PhotoAlbumSubType::GEOGRAPHY_LOCATION),
99     std::to_string(PhotoAlbumSubType::GEOGRAPHY_CITY),
100     std::to_string(PhotoAlbumSubType::SHOOTING_MODE),
101     std::to_string(PhotoAlbumSubType::PORTRAIT),
102 };
103 
104 struct BussinessRecordValue {
105     string bussinessType;
106     string key;
107     string value;
108 };
109 
110 struct UpdateAlbumData {
111     int32_t albumId;
112     int32_t albumSubtype;
113     int32_t hiddenCount;
114     int32_t albumCount;
115     int32_t albumImageCount;
116     int32_t albumVideoCount;
117     string hiddenCover;
118     string  albumCoverUri;
119     uint8_t isCoverSatisfied;
120     int32_t newTotalCount { 0 };
121     bool shouldNotify { false };
122     bool hasChanged {false};
123 };
124 
125 struct RefreshAlbumData {
126     int32_t albumId;
127     int32_t albumSubtype;
128 };
129 
130 enum UpdateAlbumType {
131     UPDATE_SYSTEM_ALBUM = 400,
132     UPDATE_HIDDEN_ALBUM,
133     UPDATE_USER_ALBUM,
134     UPDATE_SOURCE_ALBUM,
135     UPDATE_ANALYSIS_ALBUM,
136 };
137 
138 using UpdateHandler = std::function<int32_t(
139     const shared_ptr<MediaLibraryRdbStore> &rdbStore,
140     UpdateAlbumData &data,
141     const bool hiddenState,
142     std::shared_ptr<TransactionOperations> trans)>;
143 
144 atomic<bool> MediaLibraryRdbUtils::isNeedRefreshAlbum = false;
145 atomic<bool> MediaLibraryRdbUtils::isInRefreshTask = false;
146 
147 const string ANALYSIS_REFRESH_BUSINESS_TYPE = "ANALYSIS_ALBUM_REFRESH";
148 
GetStringValFromColumn(const shared_ptr<ResultSet> & resultSet,const int index)149 static inline string GetStringValFromColumn(const shared_ptr<ResultSet> &resultSet, const int index)
150 {
151     string value;
152     if (resultSet->GetString(index, value)) {
153         return "";
154     }
155     return value;
156 }
157 
GetIntValFromColumn(const shared_ptr<ResultSet> & resultSet,const int index)158 static inline int32_t GetIntValFromColumn(const shared_ptr<ResultSet> &resultSet, const int index)
159 {
160     int32_t value = 0;
161     if (resultSet->GetInt(index, value)) {
162         return 0;
163     }
164     return value;
165 }
166 
GetStringValFromColumn(const shared_ptr<ResultSet> & resultSet,const string & columnName)167 static inline string GetStringValFromColumn(const shared_ptr<ResultSet> &resultSet, const string &columnName)
168 {
169     int32_t index = 0;
170     if (resultSet->GetColumnIndex(columnName, index)) {
171         return "";
172     }
173 
174     return GetStringValFromColumn(resultSet, index);
175 }
176 
GetIntValFromColumn(const shared_ptr<ResultSet> & resultSet,const string & columnName)177 static inline int32_t GetIntValFromColumn(const shared_ptr<ResultSet> &resultSet, const string &columnName)
178 {
179     int32_t index = 0;
180     if (resultSet->GetColumnIndex(columnName, index)) {
181         return 0;
182     }
183 
184     return GetIntValFromColumn(resultSet, index);
185 }
186 
GetTypeFromCountVariation(UpdateAlbumData & data)187 static NotifyType GetTypeFromCountVariation(UpdateAlbumData &data)
188 {
189     int oldCount = data.albumVideoCount + data.albumImageCount;
190     int newCount = data.newTotalCount;
191     if (oldCount < newCount) {
192         return NOTIFY_ALBUM_ADD_ASSET;
193     } else if (oldCount > newCount) {
194         return NOTIFY_ALBUM_REMOVE_ASSET;
195     } else {
196         return NOTIFY_UPDATE;
197     }
198 }
199 
SendAlbumIdNotify(UpdateAlbumData & data)200 static void SendAlbumIdNotify(UpdateAlbumData &data)
201 {
202     auto watch = MediaLibraryNotify::GetInstance();
203     if (watch != nullptr && data.shouldNotify && data.hasChanged && data.albumSubtype != PhotoAlbumSubType::TRASH &&
204         data.albumSubtype != PhotoAlbumSubType::HIDDEN) {
205         NotifyType type = GetTypeFromCountVariation(data);
206         watch->Notify(PhotoColumn::PHOTO_URI_PREFIX, type, data.albumId);
207         MEDIA_INFO_LOG("send notification albumId: %{public}d, type:%{public}d", data.albumId, type);
208     }
209 }
210 
GetUserAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & userAlbumIds,const vector<string> & columns)211 static inline shared_ptr<ResultSet> GetUserAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,
212     const vector<string> &userAlbumIds, const vector<string> &columns)
213 {
214     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
215     if (userAlbumIds.empty()) {
216         predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
217     } else {
218         predicates.In(PhotoAlbumColumns::ALBUM_ID, userAlbumIds);
219     }
220     CHECK_AND_RETURN_RET(rdbStore != nullptr, nullptr);
221     return rdbStore->Query(predicates, columns);
222 }
223 
GetAnalysisAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & analysisAlbumIds,const vector<string> & columns)224 static inline shared_ptr<ResultSet> GetAnalysisAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,
225     const vector<string> &analysisAlbumIds, const vector<string> &columns)
226 {
227     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
228     if (!analysisAlbumIds.empty()) {
229         predicates.In(PhotoAlbumColumns::ALBUM_ID, analysisAlbumIds);
230     }
231     CHECK_AND_RETURN_RET(rdbStore != nullptr, nullptr);
232     return rdbStore->Query(predicates, columns);
233 }
234 
GetSourceAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & sourceAlbumIds,const vector<string> & columns)235 static inline shared_ptr<ResultSet> GetSourceAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,
236     const vector<string> &sourceAlbumIds, const vector<string> &columns)
237 {
238     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
239     if (!sourceAlbumIds.empty()) {
240         predicates.In(PhotoAlbumColumns::ALBUM_ID, sourceAlbumIds);
241     } else {
242         predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::SOURCE_GENERIC));
243     }
244     CHECK_AND_RETURN_RET(rdbStore != nullptr, nullptr);
245     return rdbStore->Query(predicates, columns);
246 }
247 
GetCommonAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & albumIds,const vector<string> & columns)248 static shared_ptr<ResultSet> GetCommonAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,
249     const vector<string> &albumIds, const vector<string> &columns)
250 {
251     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
252     if (!albumIds.empty()) {
253         predicates.In(PhotoAlbumColumns::ALBUM_ID, albumIds);
254     } else {
255         predicates.BeginWrap();
256         predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::SOURCE_GENERIC));
257         predicates.Or();
258         predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
259         predicates.EndWrap();
260     }
261     CHECK_AND_RETURN_RET(rdbStore != nullptr, nullptr);
262     return rdbStore->Query(predicates, columns);
263 }
264 
GetAnalysisAlbumBySubtype(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & subtypes,const vector<string> & columns)265 static inline shared_ptr<ResultSet> GetAnalysisAlbumBySubtype(const shared_ptr<MediaLibraryRdbStore> rdbStore,
266     const vector<string> &subtypes, const vector<string> &columns)
267 {
268     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
269     if (!subtypes.empty()) {
270         predicates.In(ALBUM_SUBTYPE, subtypes);
271     } else {
272         predicates.In(ALBUM_SUBTYPE, ALL_ANALYSIS_ALBUM);
273     }
274 
275     CHECK_AND_RETURN_RET(rdbStore != nullptr, nullptr);
276     return rdbStore->Query(predicates, columns);
277 }
278 
GetQueryFilter(const string & tableName)279 static string GetQueryFilter(const string &tableName)
280 {
281     if (tableName == MEDIALIBRARY_TABLE) {
282         return MEDIALIBRARY_TABLE + "." + MEDIA_DATA_DB_SYNC_STATUS + " = " +
283             to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE));
284     }
285     if (tableName == PhotoColumn::PHOTOS_TABLE) {
286         return PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_SYNC_STATUS + " = " +
287             to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) + " AND " +
288             PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_CLEAN_FLAG + " = " +
289             to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN));
290     }
291     if (tableName == PhotoAlbumColumns::TABLE) {
292         return PhotoAlbumColumns::TABLE + "." + PhotoAlbumColumns::ALBUM_DIRTY + " != " +
293             to_string(static_cast<int32_t>(DirtyTypes::TYPE_DELETED));
294     }
295     if (tableName == PhotoMap::TABLE) {
296         return PhotoMap::TABLE + "." + PhotoMap::DIRTY + " != " + to_string(static_cast<int32_t>(
297             DirtyTypes::TYPE_DELETED));
298     }
299     return "";
300 }
301 
AddQueryFilter(AbsRdbPredicates & predicates)302 void MediaLibraryRdbUtils::AddQueryFilter(AbsRdbPredicates &predicates)
303 {
304     /* build all-table vector */
305     string tableName = predicates.GetTableName();
306     vector<string> joinTables = predicates.GetJoinTableNames();
307     joinTables.push_back(tableName);
308     /* add filters */
309     string filters;
310     for (auto &t : joinTables) {
311         string filter = GetQueryFilter(t);
312         if (filter.empty()) {
313             continue;
314         }
315         if (filters.empty()) {
316             filters += filter;
317         } else {
318             filters += " AND " + filter;
319         }
320     }
321     if (filters.empty()) {
322         return;
323     }
324 
325     /* rebuild */
326     string queryCondition = predicates.GetWhereClause();
327     queryCondition = queryCondition.empty() ? filters : filters + " AND " + queryCondition;
328     predicates.SetWhereClause(queryCondition);
329 }
330 
QueryGoToFirst(const shared_ptr<MediaLibraryRdbStore> rdbStore,const RdbPredicates & predicates,const vector<string> & columns)331 static shared_ptr<ResultSet> QueryGoToFirst(const shared_ptr<MediaLibraryRdbStore> rdbStore,
332     const RdbPredicates &predicates, const vector<string> &columns)
333 {
334     MediaLibraryTracer tracer;
335     tracer.Start("QueryGoToFirst");
336     auto resultSet = rdbStore->StepQueryWithoutCheck(predicates, columns);
337     CHECK_AND_RETURN_RET(resultSet != nullptr, nullptr);
338 
339     MediaLibraryTracer goToFirst;
340     goToFirst.Start("GoToFirstRow");
341     int32_t err = resultSet->GoToFirstRow();
342     MediaLibraryRestore::GetInstance().CheckRestore(err);
343     return resultSet;
344 }
345 
ForEachRow(const shared_ptr<MediaLibraryRdbStore> rdbStore,std::vector<UpdateAlbumData> & datas,const bool hiddenState,const UpdateHandler & func)346 static int32_t ForEachRow(const shared_ptr<MediaLibraryRdbStore> rdbStore, std::vector<UpdateAlbumData> &datas,
347     const bool hiddenState, const UpdateHandler &func)
348 {
349     int32_t err = NativeRdb::E_OK;
350     for (auto data : datas) {
351         std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
352         std::function<int(void)> transFunc = [&]()->int {
353             // Ignore failure here, try to iterate rows as much as possible.
354             func(rdbStore, data, hiddenState, trans);
355             return err;
356         };
357         err = trans->RetryTrans(transFunc);
358         CHECK_AND_PRINT_LOG(err == E_OK, "ForEachRow: trans retry fail!, ret:%{public}d", err);
359         SendAlbumIdNotify(data);
360     }
361     return E_SUCCESS;
362 }
363 
GetFileCount(const shared_ptr<ResultSet> & resultSet)364 static inline int32_t GetFileCount(const shared_ptr<ResultSet> &resultSet)
365 {
366     return GetIntValFromColumn(resultSet, MEDIA_COLUMN_COUNT_1);
367 }
368 
GetPortraitFileCount(const shared_ptr<ResultSet> & resultSet)369 static inline int32_t GetPortraitFileCount(const shared_ptr<ResultSet> &resultSet)
370 {
371     return GetIntValFromColumn(resultSet, MEDIA_COLUMN_COUNT_DISTINCT_FILE_ID);
372 }
373 
GetAlbumCount(const shared_ptr<ResultSet> & resultSet,const string & column)374 static inline int32_t GetAlbumCount(const shared_ptr<ResultSet> &resultSet, const string &column)
375 {
376     return GetIntValFromColumn(resultSet, column);
377 }
378 
GetAlbumCover(const shared_ptr<ResultSet> & resultSet,const string & column)379 static inline string GetAlbumCover(const shared_ptr<ResultSet> &resultSet, const string &column)
380 {
381     return GetStringValFromColumn(resultSet, column);
382 }
383 
GetAlbumId(const shared_ptr<ResultSet> & resultSet)384 static inline int32_t GetAlbumId(const shared_ptr<ResultSet> &resultSet)
385 {
386     return GetIntValFromColumn(resultSet, PhotoAlbumColumns::ALBUM_ID);
387 }
388 
GetAlbumSubType(const shared_ptr<ResultSet> & resultSet)389 static inline int32_t GetAlbumSubType(const shared_ptr<ResultSet> &resultSet)
390 {
391     return GetIntValFromColumn(resultSet, PhotoAlbumColumns::ALBUM_SUBTYPE);
392 }
393 
GetIsCoverSatisfied(const shared_ptr<ResultSet> & resultSet)394 static inline uint8_t GetIsCoverSatisfied(const shared_ptr<ResultSet> &resultSet)
395 {
396     return GetIntValFromColumn(resultSet, IS_COVER_SATISFIED);
397 }
398 
GetFileName(const string & filePath)399 static string GetFileName(const string &filePath)
400 {
401     string fileName;
402 
403     size_t lastSlash = filePath.rfind('/');
404     if (lastSlash == string::npos) {
405         return fileName;
406     }
407     if (filePath.size() > (lastSlash + 1)) {
408         fileName = filePath.substr(lastSlash + 1);
409     }
410     return fileName;
411 }
412 
GetTitleFromDisplayName(const string & displayName)413 static string GetTitleFromDisplayName(const string &displayName)
414 {
415     auto pos = displayName.find_last_of('.');
416     if (pos == string::npos) {
417         return "";
418     }
419     return displayName.substr(0, pos);
420 }
421 
GetExtraUri(const string & displayName,const string & path)422 static string GetExtraUri(const string &displayName, const string &path)
423 {
424     string extraUri = "/" + GetTitleFromDisplayName(GetFileName(path)) + "/" + displayName;
425     return MediaFileUtils::Encode(extraUri);
426 }
427 
GetUriByExtrConditions(const string & prefix,const string & fileId,const string & suffix)428 static string GetUriByExtrConditions(const string &prefix, const string &fileId, const string &suffix)
429 {
430     return prefix + fileId + suffix;
431 }
432 
GetCover(const shared_ptr<ResultSet> & resultSet)433 static inline string GetCover(const shared_ptr<ResultSet> &resultSet)
434 {
435     string coverUri;
436     int32_t fileId = GetIntValFromColumn(resultSet, PhotoColumn::MEDIA_ID);
437     if (fileId <= 0) {
438         return coverUri;
439     }
440 
441     string extrUri = GetExtraUri(GetStringValFromColumn(resultSet, PhotoColumn::MEDIA_NAME),
442         GetStringValFromColumn(resultSet, PhotoColumn::MEDIA_FILE_PATH));
443     return GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX, to_string(fileId), extrUri);
444 }
445 
SetCount(const shared_ptr<ResultSet> & fileResult,const UpdateAlbumData & data,ValuesBucket & values,const bool hiddenState,PhotoAlbumSubType subtype)446 static int32_t SetCount(const shared_ptr<ResultSet> &fileResult, const UpdateAlbumData &data,
447     ValuesBucket &values, const bool hiddenState, PhotoAlbumSubType subtype)
448 {
449     const string &targetColumn = hiddenState ? PhotoAlbumColumns::HIDDEN_COUNT : PhotoAlbumColumns::ALBUM_COUNT;
450     int32_t oldCount = hiddenState ? data.hiddenCount : data.albumCount;
451     int32_t newCount;
452     if (subtype == PORTRAIT) {
453         newCount = GetPortraitFileCount(fileResult);
454     } else {
455         newCount = GetFileCount(fileResult);
456     }
457     int32_t id = data.albumId;
458     if (oldCount != newCount) {
459         MEDIA_INFO_LOG("Album %{public}d Update %{public}s, oldCount: %{public}d, newCount: %{public}d", id,
460             targetColumn.c_str(), oldCount, newCount);
461         values.PutInt(targetColumn, newCount);
462         if (hiddenState) {
463             MEDIA_INFO_LOG("Update album contains hidden: %{public}d", newCount != 0);
464             values.PutInt(PhotoAlbumColumns::CONTAINS_HIDDEN, newCount != 0);
465         }
466     }
467     return newCount;
468 }
469 
SetPortraitCover(const shared_ptr<ResultSet> & fileResult,const UpdateAlbumData & data,ValuesBucket & values,int newCount)470 static void SetPortraitCover(const shared_ptr<ResultSet> &fileResult, const UpdateAlbumData &data,
471     ValuesBucket &values, int newCount)
472 {
473     string newCover;
474     if (newCount != 0) {
475         newCover = GetCover(fileResult);
476     }
477     string oldCover = data.albumCoverUri;
478     if (oldCover != newCover) {
479         values.PutInt(IS_COVER_SATISFIED, static_cast<uint8_t>(CoverSatisfiedType::DEFAULT_SETTING));
480         values.PutString(PhotoAlbumColumns::ALBUM_COVER_URI, newCover);
481         int32_t albumId = data.albumId;
482         MEDIA_INFO_LOG("Update portrait album %{public}d. oldCover: %{public}s, newCover: %{public}s",
483             albumId, MediaFileUtils::GetUriWithoutDisplayname(oldCover).c_str(),
484             MediaFileUtils::GetUriWithoutDisplayname(newCover).c_str());
485     }
486 }
487 
SetCover(const shared_ptr<ResultSet> & fileResult,const UpdateAlbumData & data,ValuesBucket & values,const bool hiddenState)488 static void SetCover(const shared_ptr<ResultSet> &fileResult, const UpdateAlbumData &data,
489     ValuesBucket &values, const bool hiddenState)
490 {
491     string newCover;
492     int32_t newCount = GetFileCount(fileResult);
493     if (newCount != 0) {
494         newCover = GetCover(fileResult);
495     }
496     const string &targetColumn = hiddenState ? PhotoAlbumColumns::HIDDEN_COVER : PhotoAlbumColumns::ALBUM_COVER_URI;
497     string oldCover = hiddenState ? data.hiddenCover : data.albumCoverUri;
498     if (oldCover != newCover) {
499         int32_t id = data.albumId;
500         MEDIA_INFO_LOG("Update album %{public}d %{public}s. oldCover: %{public}s, newCover: %{public}s",
501             id, targetColumn.c_str(), MediaFileUtils::GetUriWithoutDisplayname(oldCover).c_str(),
502             MediaFileUtils::GetUriWithoutDisplayname(newCover).c_str());
503         values.PutString(targetColumn, newCover);
504     }
505 }
506 
GetTrashAlbumHiddenPredicates(RdbPredicates & predicates)507 static void GetTrashAlbumHiddenPredicates(RdbPredicates &predicates)
508 {
509     PhotoQueryFilter::Config config {};
510     config.hiddenConfig = PhotoQueryFilter::ConfigType::INCLUDE;
511     config.trashedConfig = PhotoQueryFilter::ConfigType::INCLUDE;
512     PhotoQueryFilter::ModifyPredicate(config, predicates);
513     MEDIA_DEBUG_LOG("Query hidden asset in trash album, predicates statement is %{public}s",
514         predicates.GetStatement().c_str());
515 }
516 
GetAlbumCountAndCoverPredicates(PhotoAlbumSubType subtype,const int32_t albumId,NativeRdb::RdbPredicates & predicates,const bool hiddenState,const bool isUpdateAlbum=false)517 static void GetAlbumCountAndCoverPredicates(PhotoAlbumSubType subtype, const int32_t albumId,
518     NativeRdb::RdbPredicates &predicates, const bool hiddenState, const bool isUpdateAlbum = false)
519 {
520     static const string QUERY_ASSETS_FROM_ANALYSIS_ALBUM =
521         PhotoColumn::PHOTO_SYNC_STATUS + " = " + to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) +
522         " AND " + PhotoColumn::PHOTO_CLEAN_FLAG + " = " + to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) +
523         " AND " + MediaColumn::MEDIA_ID + " IN (SELECT " + PhotoMap::ASSET_ID + " FROM " + ANALYSIS_PHOTO_MAP_TABLE +
524         " WHERE " + PhotoMap::ALBUM_ID + " = ?) AND " + MediaColumn::MEDIA_DATE_TRASHED + " = 0 AND " +
525         MediaColumn::MEDIA_HIDDEN + " = ? AND " + MediaColumn::MEDIA_TIME_PENDING + " = 0 AND " +
526         PhotoColumn::PHOTO_IS_TEMP + " = 0 AND " + PhotoColumn::PHOTO_BURST_COVER_LEVEL + " = " +
527         to_string(static_cast<int32_t>(BurstCoverLevelType::COVER));
528 
529     bool isUserAlbum = subtype == PhotoAlbumSubType::USER_GENERIC;
530     bool isSourceAlbum = subtype == PhotoAlbumSubType::SOURCE_GENERIC;
531     bool isAnalysisAlbum = subtype >= PhotoAlbumSubType::ANALYSIS_START && subtype <= PhotoAlbumSubType::ANALYSIS_END;
532     bool isSystemAlbum = subtype >= PhotoAlbumSubType::SYSTEM_START && subtype <= PhotoAlbumSubType::SYSTEM_END;
533     if (isUpdateAlbum && isAnalysisAlbum) {
534         predicates.SetWhereClause(QUERY_ASSETS_FROM_ANALYSIS_ALBUM);
535         predicates.SetWhereArgs({ to_string(albumId), to_string(hiddenState) });
536         return;
537     }
538 
539     if (isUserAlbum) {
540         PhotoAlbumColumns::GetUserAlbumPredicates(albumId, predicates, hiddenState);
541     } else if (subtype == PhotoAlbumSubType::PORTRAIT) {
542         PhotoAlbumColumns::GetPortraitAlbumPredicates(albumId, predicates, hiddenState);
543     } else if (isAnalysisAlbum) {
544         PhotoAlbumColumns::GetAnalysisAlbumPredicates(albumId, predicates, hiddenState);
545     } else if (isSourceAlbum) {
546         PhotoAlbumColumns::GetSourceAlbumPredicates(albumId, predicates, hiddenState);
547     } else if (isSystemAlbum) {
548         if (hiddenState && subtype == PhotoAlbumSubType::TRASH) {
549             GetTrashAlbumHiddenPredicates(predicates);
550             return;
551         }
552         PhotoAlbumColumns::GetSystemAlbumPredicates(subtype, predicates, hiddenState);
553     } else {
554         MEDIA_ERR_LOG("Invalid album subtype %{public}d, will return nothing", subtype);
555         predicates.EqualTo(PhotoColumn::MEDIA_ID, to_string(0));
556     }
557 }
558 
SetImageVideoCount(int32_t newTotalCount,const shared_ptr<ResultSet> & fileResultVideo,const UpdateAlbumData & data,ValuesBucket & values)559 static void SetImageVideoCount(int32_t newTotalCount, const shared_ptr<ResultSet> &fileResultVideo,
560     const UpdateAlbumData &data, ValuesBucket &values)
561 {
562     int32_t oldVideoCount = data.albumVideoCount;
563     int32_t newVideoCount = GetFileCount(fileResultVideo);
564     if (oldVideoCount != newVideoCount) {
565         MEDIA_DEBUG_LOG("Update album %{public}s, oldCount: %{public}d, newCount: %{public}d",
566             PhotoAlbumColumns::ALBUM_VIDEO_COUNT.c_str(), oldVideoCount, newVideoCount);
567         values.PutInt(PhotoAlbumColumns::ALBUM_VIDEO_COUNT, newVideoCount);
568     }
569     int32_t oldImageCount = data.albumImageCount;
570     int32_t newImageCount = newTotalCount - newVideoCount;
571     if (oldImageCount != newImageCount) {
572         MEDIA_DEBUG_LOG("Update album %{public}s, oldCount: %{public}d, newCount: %{public}d",
573             PhotoAlbumColumns::ALBUM_IMAGE_COUNT.c_str(), oldImageCount, newImageCount);
574         values.PutInt(PhotoAlbumColumns::ALBUM_IMAGE_COUNT, newImageCount);
575     }
576 }
577 
QueryAlbumCount(const shared_ptr<MediaLibraryRdbStore> rdbStore,int32_t albumId,PhotoAlbumSubType subtype)578 static int32_t QueryAlbumCount(const shared_ptr<MediaLibraryRdbStore> rdbStore,
579     int32_t albumId, PhotoAlbumSubType subtype)
580 {
581     const vector<string> columns = { MEDIA_COLUMN_COUNT_1 };
582     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
583     GetAlbumCountAndCoverPredicates(subtype, albumId, predicates, false);
584     auto fetchResult = QueryGoToFirst(rdbStore, predicates, columns);
585     CHECK_AND_RETURN_RET(fetchResult != nullptr, E_HAS_DB_ERROR);
586     return GetFileCount(fetchResult);
587 }
588 
QueryAlbumVideoCount(const shared_ptr<MediaLibraryRdbStore> rdbStore,int32_t albumId,PhotoAlbumSubType subtype)589 static int32_t QueryAlbumVideoCount(const shared_ptr<MediaLibraryRdbStore> rdbStore,
590     int32_t albumId, PhotoAlbumSubType subtype)
591 {
592     const vector<string> columns = { MEDIA_COLUMN_COUNT_1 };
593     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
594     GetAlbumCountAndCoverPredicates(subtype, albumId, predicates, false);
595     predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_MEDIA_TYPE_INDEX);
596     predicates.EqualTo(MediaColumn::MEDIA_TYPE, to_string(MEDIA_TYPE_VIDEO));
597     auto fetchResult = QueryGoToFirst(rdbStore, predicates, columns);
598     CHECK_AND_RETURN_RET(fetchResult != nullptr, E_HAS_DB_ERROR);
599     return GetFileCount(fetchResult);
600 }
601 
QueryAlbumHiddenCount(const shared_ptr<MediaLibraryRdbStore> rdbStore,int32_t albumId,PhotoAlbumSubType subtype)602 static int32_t QueryAlbumHiddenCount(const shared_ptr<MediaLibraryRdbStore> rdbStore,
603     int32_t albumId, PhotoAlbumSubType subtype)
604 {
605     const vector<string> columns = { MEDIA_COLUMN_COUNT_1 };
606     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
607     GetAlbumCountAndCoverPredicates(subtype, albumId, predicates, true);
608     auto fetchResult = QueryGoToFirst(rdbStore, predicates, columns);
609     CHECK_AND_RETURN_RET(fetchResult != nullptr, E_HAS_DB_ERROR);
610     return GetFileCount(fetchResult);
611 }
612 
SetAlbumCounts(const shared_ptr<MediaLibraryRdbStore> rdbStore,int32_t albumId,PhotoAlbumSubType subtype,AlbumCounts & albumCounts)613 static int32_t SetAlbumCounts(const shared_ptr<MediaLibraryRdbStore> rdbStore,
614     int32_t albumId, PhotoAlbumSubType subtype, AlbumCounts &albumCounts)
615 {
616     int ret = QueryAlbumCount(rdbStore, albumId, subtype);
617     CHECK_AND_RETURN_RET_LOG(ret >= E_SUCCESS, ret,
618         "Failed to QueryAlbumCount, ret:%{public}d", ret);
619     albumCounts.count = ret;
620 
621     ret = QueryAlbumVideoCount(rdbStore, albumId, subtype);
622     CHECK_AND_RETURN_RET_LOG(ret >= E_SUCCESS, ret,
623         "Failed to QueryAlbumVideoCount, ret:%{public}d", ret);
624     albumCounts.videoCount = ret;
625     albumCounts.imageCount = albumCounts.count - albumCounts.videoCount;
626 
627     ret = QueryAlbumHiddenCount(rdbStore, albumId, subtype);
628     CHECK_AND_RETURN_RET_LOG(ret >= E_SUCCESS, ret,
629         "Failed to QueryAlbumCount, ret:%{public}d", ret);
630     albumCounts.hiddenCount = ret;
631     return E_SUCCESS;
632 }
633 
SetAlbumCoverUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,int32_t albumId,PhotoAlbumSubType subtype,string & uri)634 static int32_t SetAlbumCoverUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,
635     int32_t albumId, PhotoAlbumSubType subtype, string &uri)
636 {
637     const vector<string> columns = {
638         PhotoColumn::MEDIA_ID,
639         PhotoColumn::MEDIA_FILE_PATH,
640         PhotoColumn::MEDIA_NAME
641     };
642     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
643     GetAlbumCountAndCoverPredicates(subtype, albumId, predicates, false);
644     if (subtype == PhotoAlbumSubType::HIDDEN) {
645         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_HIDDEN_TIME_INDEX);
646     } else if (subtype == PhotoAlbumSubType::VIDEO || subtype == PhotoAlbumSubType::IMAGE) {
647         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_MEDIA_TYPE_INDEX);
648     } else if (subtype == PhotoAlbumSubType::FAVORITE) {
649         predicates.IndexedBy(PhotoColumn::PHOTO_FAVORITE_INDEX);
650     } else if (subtype == PhotoAlbumSubType::CLOUD_ENHANCEMENT) {
651         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_CLOUD_ENHANCEMENT_ALBUM_INDEX);
652     } else if (subtype == PhotoAlbumSubType::USER_GENERIC || subtype == PhotoAlbumSubType::SOURCE_GENERIC) {
653         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_ALBUM_INDEX);
654     } else {
655         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_ADDED_INDEX);
656     }
657     predicates.Limit(1);
658 
659     auto fetchResult = QueryGoToFirst(rdbStore, predicates, columns);
660     CHECK_AND_RETURN_RET_LOG(fetchResult != nullptr, E_HAS_DB_ERROR, "QueryGoToFirst failed");
661     uri = GetCover(fetchResult);
662     return E_SUCCESS;
663 }
664 
SetAlbumCoverHiddenUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,int32_t albumId,PhotoAlbumSubType subtype,string & uri)665 static int32_t SetAlbumCoverHiddenUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,
666     int32_t albumId, PhotoAlbumSubType subtype, string &uri)
667 {
668     const vector<string> columns = {
669         PhotoColumn::MEDIA_ID,
670         PhotoColumn::MEDIA_FILE_PATH,
671         PhotoColumn::MEDIA_NAME
672     };
673     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
674     GetAlbumCountAndCoverPredicates(subtype, albumId, predicates, true);
675     predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_HIDDEN_TIME_INDEX);
676     predicates.Limit(1);
677 
678     auto fetchResult = QueryGoToFirst(rdbStore, predicates, columns);
679     CHECK_AND_RETURN_RET_LOG(fetchResult != nullptr, E_HAS_DB_ERROR, "QueryGoToFirst failed");
680     uri = GetCover(fetchResult);
681     return E_SUCCESS;
682 }
683 
FillOneAlbumCountAndCoverUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,int32_t albumId,PhotoAlbumSubType subtype,string & sql)684 int32_t MediaLibraryRdbUtils::FillOneAlbumCountAndCoverUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,
685     int32_t albumId, PhotoAlbumSubType subtype, string &sql)
686 {
687     AlbumCounts albumCounts = { 0, 0, 0, 0 };
688     int32_t ret = SetAlbumCounts(rdbStore, albumId, subtype, albumCounts);
689     CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
690     string coverUri;
691     ret = SetAlbumCoverUri(rdbStore, albumId, subtype, coverUri);
692     CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
693     string coverHiddenUri;
694     if (albumCounts.hiddenCount != 0) {
695         ret = SetAlbumCoverHiddenUri(rdbStore, albumId, subtype, coverHiddenUri);
696         CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
697     }
698 
699     CHECK_AND_RETURN_RET_LOG(albumId >= 0, E_HAS_DB_ERROR,
700         "Can not get correct albumId, error albumId is %{public}d", albumId);
701     string coverUriSql = PhotoAlbumColumns::ALBUM_COVER_URI;
702     if (coverUri.empty()) {
703         coverUriSql += " = NULL";
704     } else {
705         coverUriSql += " = '" + coverUri + "'";
706     }
707     string coverHiddenUriSql = PhotoAlbumColumns::HIDDEN_COVER;
708     if (coverHiddenUri.empty()) {
709         coverHiddenUriSql += " = NULL";
710     } else {
711         coverHiddenUriSql += " = '" + coverHiddenUri + "'";
712     }
713 
714     sql = "UPDATE " + PhotoAlbumColumns::TABLE + " SET " +
715         PhotoAlbumColumns::ALBUM_COUNT + " = " + to_string(albumCounts.count) + ", " +
716         PhotoAlbumColumns::ALBUM_IMAGE_COUNT + " = " +  to_string(albumCounts.imageCount) + ", " +
717         PhotoAlbumColumns::ALBUM_VIDEO_COUNT + " = " + to_string(albumCounts.videoCount) + ", " +
718         PhotoAlbumColumns::HIDDEN_COUNT + " = " + to_string(albumCounts.hiddenCount) + ", " +
719         PhotoAlbumColumns::CONTAINS_HIDDEN + " = " + to_string((albumCounts.hiddenCount == 0) ? 0 : 1) + ", " +
720         coverUriSql + ", " + coverHiddenUriSql + " WHERE " +
721         PhotoAlbumColumns::ALBUM_ID + " = " + to_string(albumId) + ";";
722     return E_SUCCESS;
723 }
724 
GetPhotoId(const std::string & uri)725 static std::string GetPhotoId(const std::string &uri)
726 {
727     if (uri.compare(0, PhotoColumn::PHOTO_URI_PREFIX.size(),
728         PhotoColumn::PHOTO_URI_PREFIX) != 0) {
729         return "";
730     }
731     std::string tmp = uri.substr(PhotoColumn::PHOTO_URI_PREFIX.size());
732     return tmp.substr(0, tmp.find_first_of('/'));
733 }
734 
RefreshAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,const std::vector<RefreshAlbumData> & datas,function<void (PhotoAlbumType,PhotoAlbumSubType,int)> refreshProcessHandler)735 static int32_t RefreshAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,
736     const std::vector<RefreshAlbumData> &datas,
737     function<void(PhotoAlbumType, PhotoAlbumSubType, int)> refreshProcessHandler)
738 {
739     for (auto data : datas) {
740         auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
741         int32_t albumId = data.albumId;
742         string sql;
743         int32_t ret = MediaLibraryRdbUtils::FillOneAlbumCountAndCoverUri(rdbStore, albumId, subtype, sql);
744         CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
745 
746         ret = rdbStore->ExecuteSql(sql);
747         CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
748             "Failed to execute sql:%{private}s", sql.c_str());
749         MEDIA_DEBUG_LOG("Execute sql %{private}s success", sql.c_str());
750         refreshProcessHandler(PhotoAlbumType::SYSTEM, subtype, albumId);
751     }
752     return E_SUCCESS;
753 }
754 
DeleteAllAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore)755 static void DeleteAllAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore)
756 {
757     string updateRefreshTableSql = "DELETE FROM " + ALBUM_REFRESH_TABLE;
758     int32_t ret = rdbStore->ExecuteSql(updateRefreshTableSql);
759     CHECK_AND_RETURN_LOG(ret == NativeRdb::E_OK,
760         "Failed to execute sql:%{private}s", updateRefreshTableSql.c_str());
761     MEDIA_INFO_LOG("Delete AlbumRefreshTable success");
762 }
763 
GetSystemRefreshAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,std::vector<RefreshAlbumData> & systemAlbums)764 static int32_t GetSystemRefreshAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,
765     std::vector<RefreshAlbumData> &systemAlbums)
766 {
767     vector<string> columns = { PhotoAlbumColumns::ALBUM_ID, PhotoAlbumColumns::ALBUM_SUBTYPE };
768     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
769     predicates.SetWhereClause(PhotoAlbumColumns::ALBUM_ID + " IN (SELECT " + REFRESH_ALBUM_ID + " FROM " +
770         ALBUM_REFRESH_TABLE + ")");
771     auto resultSet = rdbStore->Query(predicates, columns);
772     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Can not query ALBUM_REFRESH_TABLE");
773     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
774         RefreshAlbumData data;
775         data.albumId = GetAlbumId(resultSet);
776         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(resultSet));
777         systemAlbums.push_back(data);
778     }
779     resultSet->Close();
780     return E_SUCCESS;
781 }
782 
GetIsUpdateAllAnalysis(const shared_ptr<MediaLibraryRdbStore> rdbStore,bool & isUpdateAllAnalysis)783 static int32_t GetIsUpdateAllAnalysis(const shared_ptr<MediaLibraryRdbStore> rdbStore, bool &isUpdateAllAnalysis)
784 {
785     vector<string> columns = { REFRESH_ALBUM_ID };
786     NativeRdb::RdbPredicates predicates(ALBUM_REFRESH_TABLE);
787     predicates.EqualTo(REFRESH_ALBUM_ID, -1);
788     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->Query(predicates, columns);
789     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Failed query RefreshAlbum.");
790     if (resultSet->GoToFirstRow() == NativeRdb::E_OK) {
791         isUpdateAllAnalysis = true;
792         MEDIA_INFO_LOG("isUpdateAllAnalysis is true.");
793     }
794     resultSet->Close();
795     return E_SUCCESS;
796 }
797 
GetAnalysisRefreshAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,vector<RefreshAlbumData> & analysisAlbums,bool & isUpdateAllAnalysis)798 static int32_t GetAnalysisRefreshAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,
799     vector<RefreshAlbumData> &analysisAlbums, bool &isUpdateAllAnalysis)
800 {
801     int ret = GetIsUpdateAllAnalysis(rdbStore, isUpdateAllAnalysis);
802     if (ret == E_HAS_DB_ERROR) {
803         return E_HAS_DB_ERROR;
804     } else if (isUpdateAllAnalysis) {
805         MEDIA_INFO_LOG("UpdateAllAnalysis.");
806         return E_SUCCESS;
807     }
808 
809     vector<string> columns = { PhotoAlbumColumns::ALBUM_ID, PhotoAlbumColumns::ALBUM_SUBTYPE };
810     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
811     predicates.SetWhereClause(PhotoAlbumColumns::ALBUM_ID + " IN (SELECT " + REFRESH_ALBUM_ID +
812         " - 100000000 FROM " + ALBUM_REFRESH_TABLE + " WHERE refresh_album_id > 100000000)");
813     auto resultSet = rdbStore->Query(predicates, columns);
814     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Can not query ALBUM_REFRESH_TABLE");
815     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
816         RefreshAlbumData data;
817         data.albumId = GetAlbumId(resultSet);
818         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(resultSet));
819         analysisAlbums.push_back(data);
820     }
821     resultSet->Close();
822     return E_SUCCESS;
823 }
824 
QueryAlbumById(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & albumIds)825 shared_ptr<ResultSet> QueryAlbumById(const shared_ptr<MediaLibraryRdbStore> rdbStore,
826     const vector<string> &albumIds)
827 {
828     vector<string> columns = {
829         PhotoAlbumColumns::ALBUM_ID,
830         PhotoAlbumColumns::ALBUM_SUBTYPE
831     };
832     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
833     predicates.In(PhotoAlbumColumns::ALBUM_ID, albumIds);
834     auto resultSet = rdbStore->Query(predicates, columns);
835     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, nullptr, "Can not Query from rdb");
836     return resultSet;
837 }
838 
IsNeedRefreshByCheckTable(const shared_ptr<MediaLibraryRdbStore> rdbStore,bool & signal)839 int32_t MediaLibraryRdbUtils::IsNeedRefreshByCheckTable(const shared_ptr<MediaLibraryRdbStore> rdbStore,
840     bool &signal)
841 {
842     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "rdb is nullptr");
843 
844     RdbPredicates predicates(ALBUM_REFRESH_TABLE);
845     vector<string> columns = { REFRESH_ALBUM_ID };
846     auto resultSet = rdbStore->Query(predicates, columns);
847     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Can not query ALBUM_REFRESH_TABLE");
848 
849     int32_t count = 0;
850     int32_t ret = resultSet->GetRowCount(count);
851     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
852         "GetRowCount failed ret:%{public}d", ret);
853     if (count == 0) {
854         MEDIA_DEBUG_LOG("count is zero, should not refresh");
855         signal = false;
856     } else {
857         MEDIA_DEBUG_LOG("count is %{public}d, should refresh", count);
858         signal = true;
859     }
860     return E_SUCCESS;
861 }
862 
IsNeedRefreshAlbum()863 bool MediaLibraryRdbUtils::IsNeedRefreshAlbum()
864 {
865     return isNeedRefreshAlbum.load();
866 }
867 
SetNeedRefreshAlbum(bool isNeedRefresh)868 void MediaLibraryRdbUtils::SetNeedRefreshAlbum(bool isNeedRefresh)
869 {
870     isNeedRefreshAlbum = isNeedRefresh;
871 }
872 
IsInRefreshTask()873 bool MediaLibraryRdbUtils::IsInRefreshTask()
874 {
875     return isInRefreshTask.load();
876 }
877 
GetPortraitAlbumCountPredicates(const string & albumId,RdbPredicates & predicates)878 static void GetPortraitAlbumCountPredicates(const string &albumId, RdbPredicates &predicates)
879 {
880     string anaAlbumGroupTag = ANALYSIS_ALBUM_TABLE + "." + GROUP_TAG;
881     string anaAlbumId = ANALYSIS_ALBUM_TABLE + "." + ALBUM_ID;
882     string anaPhotoMapAlbum = ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ALBUM;
883     string anaPhotoMapAsset = ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ASSET;
884     string photosDateTrashed = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_DATE_TRASHED;
885     string photosFileId = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID;
886     string photosHidden = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_HIDDEN;
887     string photosTimePending = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_TIME_PENDING;
888     string photosIsTemp = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_IS_TEMP;
889     string photoIsCover = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_BURST_COVER_LEVEL;
890 
891     string clause = anaPhotoMapAsset + " = " + photosFileId;
892     predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ clause });
893     clause = anaAlbumId + " = " + anaPhotoMapAlbum;
894     predicates.InnerJoin(ANALYSIS_ALBUM_TABLE)->On({ clause });
895 
896     clause = "( " + anaAlbumGroupTag + " IN ( SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE +
897         " WHERE " + ALBUM_ID + " = " + albumId + " ))";
898     predicates.SetWhereClause(clause + " AND ");
899     predicates.BeginWrap();
900     predicates.EqualTo(photosDateTrashed, to_string(0));
901     predicates.EqualTo(photosHidden, to_string(0));
902     predicates.EqualTo(photosTimePending, to_string(0));
903     predicates.EqualTo(photosIsTemp, to_string(0));
904     predicates.EqualTo(photoIsCover, to_string(static_cast<int32_t>(BurstCoverLevelType::COVER)));
905     predicates.EndWrap();
906     predicates.Distinct();
907 }
908 
IsCoverValid(const shared_ptr<MediaLibraryRdbStore> rdbStore,const string & albumId,const string & fileId)909 static bool IsCoverValid(const shared_ptr<MediaLibraryRdbStore> rdbStore, const string &albumId, const string &fileId)
910 {
911     if (fileId.empty()) {
912         MEDIA_WARN_LOG("Invalid cover: empty file_id");
913         return false;
914     }
915     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
916 
917     string anaPhotoMapAsset = ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ASSET;
918     string photosFileId = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_ID;
919     string clause = anaPhotoMapAsset + " = " + photosFileId;
920     predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ clause });
921 
922     string anaAlbumId = ANALYSIS_ALBUM_TABLE + "." + ALBUM_ID;
923     string anaPhotoMapAlbum = ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ALBUM;
924     clause = anaAlbumId + " = " + anaPhotoMapAlbum;
925     predicates.InnerJoin(ANALYSIS_ALBUM_TABLE)->On({ clause });
926 
927     string photoSyncStatus = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_SYNC_STATUS;
928     string photoCleanFlag = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_CLEAN_FLAG;
929     string photosDateTrashed = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_DATE_TRASHED;
930     string photosHidden = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_HIDDEN;
931     string photosTimePending = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_TIME_PENDING;
932     string photosIsTemp = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_IS_TEMP;
933     string photoIsCover = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_BURST_COVER_LEVEL;
934 
935     string whereClause = anaAlbumId + " = " + albumId + " AND " + photosFileId + " = " + fileId + " AND " +
936         photoSyncStatus + " = " + to_string(static_cast<int32_t>(SyncStatusType::TYPE_VISIBLE)) + " AND " +
937         photoCleanFlag + " = " + to_string(static_cast<int32_t>(CleanType::TYPE_NOT_CLEAN)) + " AND " +
938         photosDateTrashed + " = " + to_string(0) + " AND " + photosHidden + " = " + to_string(0) + " AND " +
939         photosTimePending + " = " + to_string(0) + " AND " + photosIsTemp + " = " + to_string(0) + " AND " +
940         photoIsCover + " = " + to_string(static_cast<int32_t>(BurstCoverLevelType::COVER));
941 
942     predicates.SetWhereClause(whereClause);
943     predicates.Limit(1);
944     vector<string> columns;
945     auto resultSet = rdbStore->Query(predicates, columns);
946     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, false,
947         "Can not query Photos, albumId: %{public}s, fileId: %{public}s", albumId.c_str(), fileId.c_str());
948     int32_t count = 0;
949     int32_t ret = resultSet->GetRowCount(count);
950     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, false,
951         "GetRowCount failed, albumId: %{public}s, fileId: %{public}s, ret:%{public}d", albumId.c_str(),
952         fileId.c_str(), ret);
953     if (count == 0) {
954         MEDIA_WARN_LOG("Invalid cover: albumId: %{public}s, fileId: %{public}s not exist", albumId.c_str(),
955             fileId.c_str());
956         return false;
957     }
958     return true;
959 }
960 
ShouldUpdatePortraitAlbumCover(const shared_ptr<MediaLibraryRdbStore> rdbStore,const string & albumId,const string & fileId,const uint8_t isCoverSatisfied)961 static inline bool ShouldUpdatePortraitAlbumCover(const shared_ptr<MediaLibraryRdbStore> rdbStore,
962     const string &albumId, const string &fileId, const uint8_t isCoverSatisfied)
963 {
964     return isCoverSatisfied == static_cast<uint8_t>(CoverSatisfiedType::NO_SETTING) ||
965         !IsCoverValid(rdbStore, albumId, fileId);
966 }
967 
QueryPortraitAlbumCover(const shared_ptr<MediaLibraryRdbStore> rdbStore,const string & albumId)968 static shared_ptr<ResultSet> QueryPortraitAlbumCover(const shared_ptr<MediaLibraryRdbStore> rdbStore,
969     const string &albumId)
970 {
971     MediaLibraryTracer tracer;
972     tracer.Start("QueryPortraitCover");
973     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
974 
975     // INNER JOIN AnalysisPhotoMap ON AnalysisPhotoMap.map_asset = Photos.file_id
976     string anaPhotoMapAsset = ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ASSET;
977     string photosFileId = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_ID;
978     string clause = anaPhotoMapAsset + " = " + photosFileId;
979     predicates.InnerJoin(ANALYSIS_PHOTO_MAP_TABLE)->On({ clause });
980 
981     // INNER JOIN AnalysisAlbum ON AnalysisAlbum.album_id = AnalysisPhotoMap.map_album
982     string anaAlbumId = ANALYSIS_ALBUM_TABLE + "." + ALBUM_ID;
983     string anaPhotoMapAlbum = ANALYSIS_PHOTO_MAP_TABLE + "." + MAP_ALBUM;
984     clause = anaAlbumId + " = " + anaPhotoMapAlbum;
985     predicates.InnerJoin(ANALYSIS_ALBUM_TABLE)->On({ clause });
986 
987     // INNER JOIN tab_analysis_image_face ON tab_analysis_image_face.file_id = Photos.file_id
988     string anaImageFaceFileId = VISION_IMAGE_FACE_TABLE + "." + MediaColumn::MEDIA_ID;
989     clause = anaImageFaceFileId + "=" + photosFileId;
990     predicates.InnerJoin(VISION_IMAGE_FACE_TABLE)->On({ clause });
991 
992     clause = "Photos.sync_status = 0 "
993         "AND Photos.clean_flag = 0 "
994         "AND Photos.date_trashed = 0 "
995         "AND Photos.hidden = 0 "
996         "AND Photos.time_pending = 0 "
997         "AND Photos.is_temp = 0 "
998         "AND Photos.burst_cover_level = 1 "
999         "AND AnalysisAlbum.group_tag IN (SELECT group_tag FROM AnalysisAlbum WHERE album_id = " +
1000         albumId +
1001         " LIMIT 1) ";
1002     predicates.SetWhereClause(clause);
1003 
1004     predicates.OrderByAsc(
1005         "CASE WHEN AnalysisAlbum.group_tag LIKE '%' || tab_analysis_image_face.tag_id || '%' THEN 0 ELSE 1 END");
1006     predicates.OrderByDesc(VISION_IMAGE_FACE_TABLE + "." + IS_EXCLUDED);
1007     predicates.OrderByDesc(VISION_IMAGE_FACE_TABLE + "." + FACE_AESTHETICS_SCORE);
1008     predicates.OrderByAsc("CASE WHEN tab_analysis_image_face.total_faces = 1 THEN 0 ELSE 1 END");
1009     predicates.OrderByDesc(PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_DATE_ADDED);
1010     predicates.Limit(1);
1011     const string columnFileId = PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_ID;
1012     const string columnDisplayName = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_NAME;
1013     const string columnData = PhotoColumn::PHOTOS_TABLE + "." + MediaColumn::MEDIA_FILE_PATH;
1014     const vector<string> columns = { columnFileId, columnDisplayName, columnData };
1015     auto resultSet = rdbStore->StepQueryWithoutCheck(predicates, columns);
1016     string sql = RdbSqlUtils::BuildQueryString(predicates, columns);
1017     CHECK_AND_RETURN_RET(resultSet != nullptr, nullptr);
1018     int32_t err = resultSet->GoToFirstRow();
1019     MediaLibraryRestore::GetInstance().CheckRestore(err);
1020     return resultSet;
1021 }
1022 
SetPortraitUpdateValues(const shared_ptr<MediaLibraryRdbStore> rdbStore,const UpdateAlbumData & data,const vector<string> & fileIds,ValuesBucket & values)1023 static int32_t SetPortraitUpdateValues(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1024     const UpdateAlbumData &data, const vector<string> &fileIds, ValuesBucket &values)
1025 {
1026     const vector<string> countColumns = {
1027         MEDIA_COLUMN_COUNT_DISTINCT_FILE_ID
1028     };
1029 
1030     string coverUri = data.albumCoverUri;
1031     string coverId = GetPhotoId(coverUri);
1032     uint8_t isCoverSatisfied = data.isCoverSatisfied;
1033 
1034     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1035     string albumId = to_string(data.albumId);
1036     GetPortraitAlbumCountPredicates(albumId, predicates);
1037     shared_ptr<ResultSet> countResult = QueryGoToFirst(rdbStore, predicates, countColumns);
1038     CHECK_AND_RETURN_RET_LOG(countResult != nullptr, E_HAS_DB_ERROR, "Failed to query Portrait Album Count");
1039 
1040     int32_t newCount = SetCount(countResult, data, values, false, PhotoAlbumSubType::PORTRAIT);
1041     if (!ShouldUpdatePortraitAlbumCover(rdbStore, albumId, coverId, isCoverSatisfied)) {
1042         return E_SUCCESS;
1043     }
1044     shared_ptr<ResultSet> coverResult = QueryPortraitAlbumCover(rdbStore, albumId);
1045     CHECK_AND_RETURN_RET_LOG(coverResult != nullptr, E_HAS_DB_ERROR,
1046         "Failed to query Portrait Album Cover");
1047     SetPortraitCover(coverResult, data, values, newCount);
1048     return E_SUCCESS;
1049 }
1050 
RefreshHighlightAlbum(int32_t albumId)1051 static void RefreshHighlightAlbum(int32_t albumId)
1052 {
1053     vector<string> albumIds;
1054     albumIds.push_back(to_string(albumId));
1055     MediaAnalysisHelper::AsyncStartMediaAnalysisService(
1056         static_cast<int32_t>(Media::MediaAnalysisProxy::ActivateServiceType::HIGHLIGHT_COVER_GENERATE), albumIds);
1057 }
1058 
SetUpdateValues(const shared_ptr<MediaLibraryRdbStore> rdbStore,UpdateAlbumData & data,ValuesBucket & values,PhotoAlbumSubType subtype,const bool hiddenState)1059 static int32_t SetUpdateValues(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1060     UpdateAlbumData &data, ValuesBucket &values, PhotoAlbumSubType subtype, const bool hiddenState)
1061 {
1062     const vector<string> columns = {
1063         MEDIA_COLUMN_COUNT_1, PhotoColumn::MEDIA_ID,
1064         PhotoColumn::MEDIA_FILE_PATH, PhotoColumn::MEDIA_NAME
1065     };
1066     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1067     GetAlbumCountAndCoverPredicates(subtype, data.albumId, predicates, hiddenState, true);
1068     if (subtype == PhotoAlbumSubType::HIDDEN || hiddenState) {
1069         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_HIDDEN_TIME_INDEX);
1070     } else if (subtype == PhotoAlbumSubType::VIDEO || subtype == PhotoAlbumSubType::IMAGE) {
1071         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_MEDIA_TYPE_INDEX);
1072     } else if (subtype == PhotoAlbumSubType::FAVORITE) {
1073         predicates.IndexedBy(PhotoColumn::PHOTO_FAVORITE_INDEX);
1074     } else if (subtype == PhotoAlbumSubType::CLOUD_ENHANCEMENT) {
1075         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_CLOUD_ENHANCEMENT_ALBUM_INDEX);
1076     } else if (subtype == PhotoAlbumSubType::USER_GENERIC || subtype == PhotoAlbumSubType::SOURCE_GENERIC) {
1077         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_ALBUM_INDEX);
1078     } else {
1079         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_ADDED_INDEX);
1080     }
1081     auto fileResult = QueryGoToFirst(rdbStore, predicates, columns);
1082     CHECK_AND_RETURN_RET_LOG(fileResult != nullptr, E_HAS_DB_ERROR, "Failed to query fileResult");
1083     int32_t newCount = SetCount(fileResult, data, values, hiddenState, subtype);
1084     data.newTotalCount = newCount;
1085     if (subtype != PhotoAlbumSubType::HIGHLIGHT && subtype != PhotoAlbumSubType::HIGHLIGHT_SUGGESTIONS) {
1086         SetCover(fileResult, data, values, hiddenState);
1087     }
1088     if (hiddenState == 0 && (subtype < PhotoAlbumSubType::ANALYSIS_START ||
1089         subtype > PhotoAlbumSubType::ANALYSIS_END)) {
1090         predicates.Clear();
1091         GetAlbumCountAndCoverPredicates(subtype, data.albumId, predicates, hiddenState, true);
1092         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_MEDIA_TYPE_INDEX);
1093         string queryCondition = predicates.GetWhereClause();
1094         if (queryCondition.empty()) {
1095             predicates.EqualTo(MediaColumn::MEDIA_TYPE, to_string(MEDIA_TYPE_VIDEO));
1096         } else {
1097             predicates.SetWhereClause(
1098                 "(" + queryCondition + ") AND " + MediaColumn::MEDIA_TYPE + " = " + to_string(MEDIA_TYPE_VIDEO));
1099         }
1100         auto fileResultVideo = QueryGoToFirst(rdbStore, predicates, columns);
1101         CHECK_AND_RETURN_RET_LOG(fileResultVideo != nullptr, E_HAS_DB_ERROR, "Failed to query fileResultVideo");
1102         SetImageVideoCount(newCount, fileResultVideo, data, values);
1103     }
1104     return E_SUCCESS;
1105 }
1106 
QueryAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris,PhotoAlbumType photoAlbumType)1107 static vector<string> QueryAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore, const vector<string> &uris,
1108     PhotoAlbumType photoAlbumType)
1109 {
1110     vector<string> albumIds;
1111     string idArgs;
1112     for (size_t i = 0; i < uris.size(); i++) {
1113         string fileId = GetPhotoId(uris[i]);
1114         if (fileId.size() > 0) {
1115             idArgs.append("'").append(fileId).append("'").append(",");
1116         }
1117         if ((i == 0 || i % ALBUM_UPDATE_THRESHOLD != 0) && i < uris.size() - 1) {
1118             continue;
1119         }
1120         if (idArgs.size() == 0) {
1121             continue;
1122         }
1123         idArgs = idArgs.substr(0, idArgs.size() - 1);
1124         const string sql = ""
1125             "WITH PhotoAlbumIds AS ( SELECT album_id FROM PhotoAlbum WHERE album_type = " +
1126             to_string(photoAlbumType) +
1127             " ) "
1128             "SELECT DISTINCT "
1129             "owner_album_id "
1130             "FROM"
1131             "  Photos"
1132             "  INNER JOIN PhotoAlbumIds ON Photos.owner_album_id = PhotoAlbumIds.album_id "
1133             "WHERE"
1134             "  file_id IN ( " +
1135             idArgs + " );";
1136         auto resultSet = rdbStore->QueryByStep(sql);
1137         if (resultSet == nullptr) {
1138             MEDIA_ERR_LOG("Failed to Query AlbumId");
1139             continue;
1140         }
1141         while (resultSet->GoToNextRow() == E_OK) {
1142             albumIds.push_back(to_string(GetIntValFromColumn(resultSet, 0)));
1143         }
1144         resultSet->Close();
1145         idArgs.clear();
1146     }
1147     return albumIds;
1148 }
1149 
QueryAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris)1150 static vector<string> QueryAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore, const vector<string> &uris)
1151 {
1152     vector<string> albumIds;
1153     string idArgs;
1154     for (size_t i = 0; i < uris.size(); i++) {
1155         string fileId = GetPhotoId(uris[i]);
1156         if (fileId.size() > 0) {
1157             idArgs.append("'").append(fileId).append("'").append(",");
1158         }
1159         if ((i == 0 || i % ALBUM_UPDATE_THRESHOLD != 0) && i < uris.size() - 1) {
1160             continue;
1161         }
1162         if (idArgs.size() == 0) {
1163             continue;
1164         }
1165         idArgs = idArgs.substr(0, idArgs.size() - 1);
1166         const string sql = ""
1167             "SELECT DISTINCT owner_album_id FROM Photos WHERE "
1168             "file_id IN ( " + idArgs + " ); ";
1169         auto resultSet = rdbStore->QueryByStep(sql);
1170         if (resultSet == nullptr) {
1171             MEDIA_ERR_LOG("Failed to Query AlbumId");
1172             continue;
1173         }
1174         while (resultSet->GoToNextRow() == E_OK) {
1175             albumIds.push_back(to_string(GetIntValFromColumn(resultSet, 0)));
1176         }
1177         resultSet->Close();
1178         idArgs.clear();
1179     }
1180     return albumIds;
1181 }
1182 
UpdateUserAlbumIfNeeded(const shared_ptr<MediaLibraryRdbStore> rdbStore,UpdateAlbumData & data,const bool hiddenState,std::shared_ptr<TransactionOperations> trans)1183 static int32_t UpdateUserAlbumIfNeeded(const shared_ptr<MediaLibraryRdbStore> rdbStore, UpdateAlbumData &data,
1184     const bool hiddenState, std::shared_ptr<TransactionOperations> trans)
1185 {
1186     MediaLibraryTracer tracer;
1187     tracer.Start("UpdateUserAlbumIfNeeded");
1188     CHECK_AND_RETURN_RET_LOG(trans != nullptr, E_HAS_DB_ERROR, "transactionOprn is null");
1189     ValuesBucket values;
1190     auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
1191     int err = SetUpdateValues(rdbStore, data, values, subtype, hiddenState);
1192     CHECK_AND_RETURN_RET_LOG(err >= 0, err,
1193         "Failed to set update values when updating albums, album id: %{public}d, hidden state: %{public}d",
1194         data.albumId, hiddenState ? 1 : 0);
1195     if (values.IsEmpty()) {
1196         return E_SUCCESS;
1197     }
1198 
1199     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
1200     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(data.albumId));
1201     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
1202     int32_t changedRows = 0;
1203     err = trans->Update(changedRows, values, predicates);
1204     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, err,
1205         "Failed to update album count and cover! album id: %{public}d, hidden state: %{public}d",
1206         data.albumId, hiddenState ? 1 : 0);
1207     data.hasChanged = true;
1208     return E_SUCCESS;
1209 }
1210 
UpdatePortraitAlbumIfNeeded(const shared_ptr<MediaLibraryRdbStore> rdbStore,const UpdateAlbumData & data,const vector<string> & fileIds,std::shared_ptr<TransactionOperations> trans)1211 static int32_t UpdatePortraitAlbumIfNeeded(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1212     const UpdateAlbumData &data, const vector<string> &fileIds, std::shared_ptr<TransactionOperations> trans)
1213 {
1214     MediaLibraryTracer tracer;
1215     tracer.Start("UpdatePortraitAlbumIfNeeded");
1216     CHECK_AND_RETURN_RET_LOG(trans != nullptr, E_HAS_DB_ERROR, "transactionOprn is null");
1217     auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
1218     CHECK_AND_RETURN_RET(subtype == PhotoAlbumSubType::PORTRAIT, E_SUCCESS);
1219 
1220     ValuesBucket values;
1221     int32_t albumId = data.albumId;
1222     int setRet = SetPortraitUpdateValues(rdbStore, data, fileIds, values);
1223     if (setRet != E_SUCCESS) {
1224         MEDIA_ERR_LOG("Failed to set portrait album update values! album id: %{public}d, err: %{public}d", albumId,
1225             setRet);
1226         return setRet;
1227     }
1228     if (values.IsEmpty()) {
1229         return E_SUCCESS;
1230     }
1231 
1232     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
1233     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(albumId));
1234     int32_t changedRows = 0;
1235     int updateRet = trans->Update(changedRows, values, predicates);
1236     CHECK_AND_RETURN_RET_LOG(updateRet == NativeRdb::E_OK, updateRet,
1237         "Failed to update album count and cover! album id: %{public}d, err: %{public}d", albumId, updateRet);
1238     return E_SUCCESS;
1239 }
1240 
UpdateAnalysisAlbumIfNeeded(const shared_ptr<MediaLibraryRdbStore> rdbStore,UpdateAlbumData & data,const bool hiddenState,std::shared_ptr<TransactionOperations> trans=nullptr)1241 static int32_t UpdateAnalysisAlbumIfNeeded(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1242     UpdateAlbumData &data, const bool hiddenState, std::shared_ptr<TransactionOperations> trans = nullptr)
1243 {
1244     MediaLibraryTracer tracer;
1245     tracer.Start("UpdateAnalysisAlbumIfNeeded");
1246     ValuesBucket values;
1247     auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
1248     int err = SetUpdateValues(rdbStore, data, values, subtype, hiddenState);
1249     CHECK_AND_RETURN_RET_LOG(err >= 0, err,
1250         "Failed to set update values when updating albums, album id: %{public}d, hidden state: %{public}d",
1251         data.albumId, hiddenState ? 1 : 0);
1252     if (values.IsEmpty()) {
1253         return E_SUCCESS;
1254     }
1255 
1256     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
1257     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(data.albumId));
1258     int32_t changedRows = 0;
1259     if (trans == nullptr) {
1260         err = rdbStore->Update(changedRows, values, predicates);
1261     } else {
1262         err = trans->Update(changedRows, values, predicates);
1263     }
1264 
1265     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, err,
1266         "Failed to update album count and cover! album id: %{public}d, hidden state: %{public}d",
1267         data.albumId, hiddenState ? 1 : 0);
1268     data.hasChanged = true;
1269     return E_SUCCESS;
1270 }
1271 
UpdateCommonAlbumIfNeeded(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,UpdateAlbumData & data,const bool hiddenState,std::shared_ptr<TransactionOperations> trans)1272 static int32_t UpdateCommonAlbumIfNeeded(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,
1273     UpdateAlbumData &data, const bool hiddenState, std::shared_ptr<TransactionOperations> trans)
1274 {
1275     CHECK_AND_RETURN_RET_LOG(trans != nullptr, E_HAS_DB_ERROR, "transactionOprn is null");
1276     MediaLibraryTracer tracer;
1277     tracer.Start("UpdateCommonAlbumIfNeeded");
1278     ValuesBucket values;
1279     auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
1280     int err = SetUpdateValues(rdbStore, data, values, subtype, hiddenState);
1281     CHECK_AND_RETURN_RET_LOG(err >= 0, err,
1282         "Failed to set update values when updating albums, album id: %{public}d, hidden state: %{public}d",
1283         data.albumId, hiddenState ? 1 : 0);
1284     if (values.IsEmpty()) {
1285         return E_SUCCESS;
1286     }
1287 
1288     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
1289     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(data.albumId));
1290     predicates.BeginWrap();
1291     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::USER_GENERIC));
1292     predicates.Or();
1293     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::SOURCE_GENERIC));
1294     predicates.EndWrap();
1295     int32_t changedRows = 0;
1296     err = trans->Update(changedRows, values, predicates);
1297     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, err,
1298         "Failed to update album count and cover! album id: %{public}d, hidden state: %{public}d",
1299         data.albumId, hiddenState ? 1 : 0);
1300     data.hasChanged = true;
1301     return E_SUCCESS;
1302 }
1303 
UpdateSourceAlbumIfNeeded(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,UpdateAlbumData & data,const bool hiddenState,std::shared_ptr<TransactionOperations> trans)1304 static int32_t UpdateSourceAlbumIfNeeded(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,
1305     UpdateAlbumData &data, const bool hiddenState, std::shared_ptr<TransactionOperations> trans)
1306 {
1307     CHECK_AND_RETURN_RET_LOG(trans != nullptr, E_HAS_DB_ERROR, "transactionOprn is null");
1308     MediaLibraryTracer tracer;
1309     tracer.Start("UpdateSourceAlbumIfNeeded");
1310     ValuesBucket values;
1311     auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
1312     int err = SetUpdateValues(rdbStore, data, values, subtype, hiddenState);
1313     CHECK_AND_RETURN_RET_LOG(err >= 0, err,
1314         "Failed to set update values when updating albums, album id: %{public}d, hidden state: %{public}d",
1315         data.albumId, hiddenState ? 1 : 0);
1316     if (values.IsEmpty()) {
1317         return E_SUCCESS;
1318     }
1319 
1320     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
1321     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(data.albumId));
1322     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::SOURCE_GENERIC));
1323     int32_t changedRows = 0;
1324     err = trans->Update(changedRows, values, predicates);
1325     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, err,
1326         "Failed to update album count and cover! album id: %{public}d, hidden state: %{public}d",
1327         data.albumId, hiddenState ? 1 : 0);
1328     data.hasChanged = true;
1329     return E_SUCCESS;
1330 }
1331 
UpdateSysAlbumIfNeeded(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,UpdateAlbumData & data,const bool hiddenState,std::shared_ptr<TransactionOperations> trans)1332 static int32_t UpdateSysAlbumIfNeeded(const std::shared_ptr<MediaLibraryRdbStore> rdbStore, UpdateAlbumData &data,
1333     const bool hiddenState, std::shared_ptr<TransactionOperations> trans)
1334 {
1335     CHECK_AND_RETURN_RET_LOG(trans != nullptr, E_HAS_DB_ERROR, "transactionOprn is null");
1336     auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
1337     MediaLibraryTracer tracer;
1338     tracer.Start("UpdateSysAlbum: " + to_string(subtype));
1339     ValuesBucket values;
1340     int err = SetUpdateValues(rdbStore, data, values, subtype, hiddenState);
1341     CHECK_AND_RETURN_RET_LOG(err >= 0, err,
1342         "Failed to set update values when updating albums, album id: %{public}d, hidden state: %{public}d",
1343         data.albumId, hiddenState ? 1 : 0);
1344     if (values.IsEmpty()) {
1345         return E_SUCCESS;
1346     }
1347 
1348     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
1349     predicates.EqualTo(PhotoAlbumColumns::ALBUM_SUBTYPE, to_string(subtype));
1350     predicates.EqualTo(PhotoAlbumColumns::ALBUM_ID, to_string(data.albumId));
1351     int32_t changedRows = 0;
1352     err = trans->Update(changedRows, values, predicates);
1353     CHECK_AND_RETURN_RET_LOG(err == NativeRdb::E_OK, err,
1354         "Failed to update album count and cover! album id: %{public}d, hidden state: %{public}d",
1355         data.albumId, hiddenState ? 1 : 0);
1356     data.hasChanged = true;
1357     return E_SUCCESS;
1358 }
1359 
UpdateUserAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & userAlbumIds={})1360 static void UpdateUserAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1361     const vector<string> &userAlbumIds = {})
1362 {
1363     MediaLibraryTracer tracer;
1364     tracer.Start("UpdateUserAlbumHiddenState");
1365     auto albumResult = GetUserAlbum(rdbStore, userAlbumIds, {
1366         PhotoAlbumColumns::ALBUM_ID,
1367         PhotoAlbumColumns::CONTAINS_HIDDEN,
1368         PhotoAlbumColumns::HIDDEN_COUNT,
1369         PhotoAlbumColumns::HIDDEN_COVER,
1370     });
1371     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
1372     std::vector<UpdateAlbumData> datas;
1373     while (albumResult->GoToNextRow() == E_OK) {
1374         UpdateAlbumData data;
1375         data.albumId = GetAlbumId(albumResult);
1376         data.albumSubtype = PhotoAlbumSubType::USER_GENERIC;
1377         data.hiddenCount = GetAlbumCount(albumResult, PhotoAlbumColumns::HIDDEN_COUNT);
1378         data.hiddenCover = GetAlbumCover(albumResult, PhotoAlbumColumns::HIDDEN_COVER);
1379         datas.push_back(data);
1380     }
1381     albumResult->Close();
1382 
1383     ForEachRow(rdbStore, datas, true, UpdateUserAlbumIfNeeded);
1384 }
1385 
CopyAssetIfNeed(int32_t fileId,int32_t albumId,const shared_ptr<MediaLibraryRdbStore> rdbStore,vector<int32_t> & updateIds)1386 static bool CopyAssetIfNeed(int32_t fileId, int32_t albumId,
1387     const shared_ptr<MediaLibraryRdbStore> rdbStore, vector<int32_t> &updateIds)
1388 {
1389     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
1390     predicates.EqualTo(PhotoColumn::MEDIA_ID, fileId);
1391     vector<string> columns;
1392     shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->Query(predicates, columns);
1393     CHECK_AND_RETURN_RET(resultSet != nullptr, false);
1394     bool needCopy = true;
1395     int64_t newAssetId = -1;
1396     if (resultSet->GoToFirstRow() == NativeRdb::E_OK) {
1397         auto albumIdQuery = GetIntValFromColumn(resultSet, PhotoColumn::PHOTO_OWNER_ALBUM_ID);
1398         if (albumIdQuery == albumId) {
1399             needCopy = false;
1400             updateIds.push_back(fileId);
1401         } else {
1402             needCopy = true;
1403             MEDIA_DEBUG_LOG("add assets: need copy assets id is: %{public}s", to_string(fileId).c_str());
1404             MediaLibraryAlbumFusionUtils::HandleSingleFileCopy(rdbStore, fileId, albumId, newAssetId);
1405             updateIds.push_back(newAssetId);
1406         }
1407     }
1408     return needCopy;
1409 }
1410 
UpdateUserAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris,bool shouldNotify)1411 void MediaLibraryRdbUtils::UpdateUserAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1412     const vector<string> &uris, bool shouldNotify)
1413 {
1414     MediaLibraryTracer tracer;
1415     tracer.Start("UpdateUserAlbumByUri");
1416 
1417     if (uris.size() == 0) {
1418         UpdateUserAlbumInternal(rdbStore);
1419         UpdateUserAlbumHiddenState(rdbStore);
1420     }
1421 
1422     vector<string> albumIds = QueryAlbumId(rdbStore, uris, PhotoAlbumType::USER);
1423     if (albumIds.size() > 0) {
1424         UpdateUserAlbumInternal(rdbStore, albumIds, shouldNotify);
1425         UpdateUserAlbumHiddenState(rdbStore, albumIds);
1426     }
1427 }
1428 
UpdateUserAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & userAlbumIds,bool shouldNotify)1429 void MediaLibraryRdbUtils::UpdateUserAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1430     const vector<string> &userAlbumIds, bool shouldNotify)
1431 {
1432     MediaLibraryTracer tracer;
1433     tracer.Start("UpdateUserAlbumInternal");
1434 
1435     vector<string> columns = {
1436         PhotoAlbumColumns::ALBUM_ID,
1437         PhotoAlbumColumns::ALBUM_COVER_URI,
1438         PhotoAlbumColumns::ALBUM_COUNT,
1439         PhotoAlbumColumns::ALBUM_IMAGE_COUNT,
1440         PhotoAlbumColumns::ALBUM_VIDEO_COUNT,
1441     };
1442     auto albumResult = GetUserAlbum(rdbStore, userAlbumIds, columns);
1443     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
1444 
1445     std::vector<UpdateAlbumData> datas;
1446     while (albumResult->GoToNextRow() == E_OK) {
1447         UpdateAlbumData data;
1448         data.albumId = GetAlbumId(albumResult);
1449         data.albumSubtype = PhotoAlbumSubType::USER_GENERIC;
1450         data.albumCoverUri = GetAlbumCover(albumResult, PhotoAlbumColumns::ALBUM_COVER_URI);
1451         data.albumCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_COUNT);
1452         data.albumImageCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_IMAGE_COUNT);
1453         data.albumVideoCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_VIDEO_COUNT);
1454         data.shouldNotify = shouldNotify;
1455         datas.push_back(data);
1456     }
1457     albumResult->Close();
1458     ForEachRow(rdbStore, datas, false, UpdateUserAlbumIfNeeded);
1459 }
1460 
GetIntFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,int & value)1461 static int32_t GetIntFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, int &value)
1462 {
1463     CHECK_AND_RETURN_RET(resultSet != nullptr, E_HAS_DB_ERROR);
1464     int index = -1;
1465     resultSet->GetColumnIndex(column, index);
1466     CHECK_AND_RETURN_RET(index != -1, E_HAS_DB_ERROR);
1467     CHECK_AND_RETURN_RET(resultSet->GetInt(index, value) == NativeRdb::E_OK, E_HAS_DB_ERROR);
1468     return E_OK;
1469 }
1470 
GetStringFromResultSet(shared_ptr<ResultSet> resultSet,const string & column,string & value)1471 static int32_t GetStringFromResultSet(shared_ptr<ResultSet> resultSet, const string &column, string &value)
1472 {
1473     CHECK_AND_RETURN_RET(resultSet != nullptr, E_HAS_DB_ERROR);
1474     int index = -1;
1475     resultSet->GetColumnIndex(column, index);
1476     CHECK_AND_RETURN_RET(index != -1, E_HAS_DB_ERROR);
1477     CHECK_AND_RETURN_RET(resultSet->GetString(index, value) == NativeRdb::E_OK, E_HAS_DB_ERROR);
1478     return E_OK;
1479 }
1480 
UpdateTrashedAssetOnAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,RdbPredicates & predicates)1481 int32_t MediaLibraryRdbUtils::UpdateTrashedAssetOnAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1482     RdbPredicates &predicates)
1483 {
1484     vector<string> newWhereIdArgs;
1485     for (auto albumId: predicates.GetWhereArgs()) {
1486         MEDIA_INFO_LOG("Start trashed album, album id is: %{public}s", albumId.c_str());
1487         const std::string QUERY_FILE_ASSET_INFO = "SELECT file_id, data, display_name FROM"
1488             " Photos WHERE owner_album_id = " + albumId + " AND clean_flag = 0 AND hidden = 0";
1489         shared_ptr<NativeRdb::ResultSet> resultSet = rdbStore->QuerySql(QUERY_FILE_ASSET_INFO);
1490         vector<string> fileAssetsIds, fileAssetsUri;
1491         while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1492             int32_t fileId = -1;
1493             string assetData;
1494             string displayName;
1495             GetIntFromResultSet(resultSet, MediaColumn::MEDIA_ID, fileId);
1496             GetStringFromResultSet(resultSet, MediaColumn::MEDIA_FILE_PATH, assetData);
1497             GetStringFromResultSet(resultSet, MediaColumn::MEDIA_NAME, displayName);
1498             fileAssetsIds.push_back(to_string(fileId));
1499             string extraUri = MediaFileUtils::GetExtraUri(displayName, assetData);
1500             string uri = MediaFileUtils::GetUriByExtrConditions(PhotoColumn::PHOTO_URI_PREFIX,
1501                 to_string(fileId), extraUri);
1502             fileAssetsUri.push_back(uri);
1503         }
1504         newWhereIdArgs.push_back(albumId);
1505         if (fileAssetsUri.empty()) {
1506             continue;
1507         }
1508         MediaLibraryPhotoOperations::UpdateSourcePath(fileAssetsIds);
1509         RdbPredicates predicatesPhotos(PhotoColumn::PHOTOS_TABLE);
1510         predicatesPhotos.EqualTo(PhotoColumn::PHOTO_OWNER_ALBUM_ID, albumId);
1511         predicatesPhotos.And()->In(MediaColumn::MEDIA_ID, fileAssetsIds);
1512         ValuesBucket values;
1513         values.Put(MediaColumn::MEDIA_DATE_TRASHED, MediaFileUtils::UTCTimeMilliSeconds());
1514         int32_t updateRow = -1;
1515         int ret = rdbStore->Update(updateRow, values, predicatesPhotos);
1516         if (ret != NativeRdb::E_OK) {
1517             MEDIA_ERR_LOG("Update failed on trashed, album id is: %{public}s", albumId.c_str());
1518             continue;
1519         }
1520         MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, {
1521             to_string(PhotoAlbumSubType::IMAGE), to_string(PhotoAlbumSubType::VIDEO),
1522             to_string(PhotoAlbumSubType::FAVORITE), to_string(PhotoAlbumSubType::TRASH),
1523             to_string(PhotoAlbumSubType::HIDDEN), to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT)
1524         });
1525         MediaLibraryRdbUtils::UpdateAnalysisAlbumByUri(rdbStore, fileAssetsUri);
1526         MediaAnalysisHelper::StartMediaAnalysisServiceAsync(
1527             static_cast<int32_t>(MediaAnalysisProxy::ActivateServiceType::START_UPDATE_INDEX), fileAssetsUri);
1528         MediaLibraryPhotoOperations::TrashPhotosSendNotify(fileAssetsUri);
1529     }
1530     predicates.SetWhereArgs(newWhereIdArgs);
1531     return newWhereIdArgs.size();
1532 }
1533 
UpdateRemovedAssetToTrash(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & whereIdArgs)1534 int32_t MediaLibraryRdbUtils::UpdateRemovedAssetToTrash(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1535     const vector<string> &whereIdArgs)
1536 {
1537     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "rdbStore is null");
1538     int32_t updateRows = 0;
1539     RdbPredicates predicatesPhotos(PhotoColumn::PHOTOS_TABLE);
1540     predicatesPhotos.In(MediaColumn::MEDIA_ID, whereIdArgs);
1541     ValuesBucket values;
1542     values.Put(MediaColumn::MEDIA_DATE_TRASHED, MediaFileUtils::UTCTimeMilliSeconds());
1543     rdbStore->Update(updateRows, values, predicatesPhotos);
1544     CHECK_AND_RETURN_RET_LOG(updateRows > 0, E_HAS_DB_ERROR,
1545         "Failed to remove assets, updateRows: %{public}d", updateRows);
1546     return updateRows;
1547 }
1548 
UpdateHighlightPlayInfo(const shared_ptr<MediaLibraryRdbStore> rdbStore,const string & albumId)1549 int32_t MediaLibraryRdbUtils::UpdateHighlightPlayInfo(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1550     const string &albumId)
1551 {
1552     MEDIA_INFO_LOG("Start update highlight play info on dismiss highlight asset");
1553     const std::string UPDATE_HIGHLIGHT_PLAY_INFO = "UPDATE tab_highlight_play_info SET status = 1 "
1554         "WHERE album_id = (SELECT id FROM tab_highlight_album WHERE album_id = " + albumId + " LIMIT 1)";
1555 
1556     int32_t ret = rdbStore->ExecuteSql(UPDATE_HIGHLIGHT_PLAY_INFO);
1557     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, ret, "Failed to execute sql:%{public}s",
1558         UPDATE_HIGHLIGHT_PLAY_INFO.c_str());
1559     return ret;
1560 }
1561 
UpdateOwnerAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<DataShare::DataShareValuesBucket> & values,vector<int32_t> & updateIds)1562 int32_t MediaLibraryRdbUtils::UpdateOwnerAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1563     const vector<DataShare::DataShareValuesBucket> &values, vector<int32_t> &updateIds)
1564 {
1565     vector<string> whereIdArgs;
1566     int32_t updateRows = 0;
1567     bool isValid = false;
1568     int32_t albumId = values[0].Get(PhotoColumn::PHOTO_OWNER_ALBUM_ID, isValid);
1569     for (const auto &value : values) {
1570         bool isValidNew = false;
1571         std::string assetUri = value.Get(MediaColumn::MEDIA_ID, isValidNew);
1572         if (!MediaFileUtils::StartsWith(assetUri, PhotoColumn::PHOTO_URI_PREFIX)) {
1573             continue;
1574         }
1575         auto photoId = std::stoi(MediaFileUri::GetPhotoId(assetUri));
1576         if (CopyAssetIfNeed(photoId, albumId, rdbStore, updateIds)) {
1577             updateRows++;
1578             continue;
1579         }
1580         whereIdArgs.push_back(MediaFileUri::GetPhotoId(assetUri));
1581     }
1582     if (whereIdArgs.empty()) {
1583         MEDIA_INFO_LOG("add assets: no need copy assets is 0 for update owner album id");
1584         return updateRows;
1585     }
1586     RdbPredicates updatePredicates(PhotoColumn::PHOTOS_TABLE);
1587     updatePredicates.In(MediaColumn::MEDIA_ID, whereIdArgs);
1588     ValuesBucket updateValues;
1589     updateValues.PutString(PhotoColumn::PHOTO_OWNER_ALBUM_ID, to_string(albumId));
1590     int32_t changedRowsNoNeedCopy = 0;
1591     int err = rdbStore->Update(changedRowsNoNeedCopy, updateValues, updatePredicates);
1592     CHECK_AND_PRINT_LOG(err == NativeRdb::E_OK, "Failed to update owner album id");
1593     return updateRows + changedRowsNoNeedCopy;
1594 }
1595 
QueryAnalysisAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore,const RdbPredicates predicates,vector<string> & albumId)1596 static void QueryAnalysisAlbumId(const shared_ptr<MediaLibraryRdbStore> rdbStore, const RdbPredicates predicates,
1597     vector<string> &albumId)
1598 {
1599     const vector<string> columns = {
1600         "Distinct " + PhotoMap::ALBUM_ID
1601     };
1602     auto resultSet = rdbStore->Query(predicates, columns);
1603     CHECK_AND_RETURN_LOG(resultSet != nullptr, "Failed to Query Analysis Album ID");
1604     while (resultSet->GoToNextRow() == E_OK) {
1605         albumId.push_back(to_string(GetIntValFromColumn(resultSet, 0)));
1606     }
1607 }
1608 
UpdateAnalysisAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris)1609 void MediaLibraryRdbUtils::UpdateAnalysisAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1610     const vector<string> &uris)
1611 {
1612     MediaLibraryTracer tracer;
1613     tracer.Start("UpdateAnalysisAlbumByUri");
1614 
1615     if (uris.size() == 0) {
1616         UpdateAnalysisAlbumInternal(rdbStore);
1617     }
1618     vector<string> albumIds;
1619     vector<string> idArgs;
1620     vector<string> fileIds;
1621     for (size_t i = 0; i < uris.size(); i++) {
1622         string fileId = GetPhotoId(uris[i]);
1623         if (fileId.size() > 0) {
1624             idArgs.push_back(fileId);
1625             fileIds.push_back(fileId);
1626         }
1627         if (idArgs.size() == ALBUM_UPDATE_THRESHOLD || i == uris.size() - 1) {
1628             RdbPredicates predicates(ANALYSIS_PHOTO_MAP_TABLE);
1629             predicates.In(PhotoMap::ASSET_ID, idArgs);
1630             QueryAnalysisAlbumId(rdbStore, predicates, albumIds);
1631             idArgs.clear();
1632         }
1633     }
1634     if (albumIds.size() > 0) {
1635         UpdateAnalysisAlbumInternal(rdbStore, albumIds, fileIds);
1636     }
1637 }
1638 
GetAlbumIdsForPortrait(const shared_ptr<MediaLibraryRdbStore> rdbStore,vector<string> & portraitAlbumIds)1639 int32_t MediaLibraryRdbUtils::GetAlbumIdsForPortrait(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1640     vector<string> &portraitAlbumIds)
1641 {
1642     std::stringstream labelIds;
1643     unordered_set<string> resultAlbumIds;
1644     for (size_t i = 0; i < portraitAlbumIds.size(); i++) {
1645         labelIds << portraitAlbumIds[i];
1646         if (i != portraitAlbumIds.size() - 1) {
1647             labelIds << ",";
1648         }
1649         resultAlbumIds.insert(portraitAlbumIds[i]);
1650     }
1651 
1652     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
1653     predicates.SetWhereClause(GROUP_TAG + " IN(SELECT " + GROUP_TAG + " FROM " + ANALYSIS_ALBUM_TABLE +
1654         " WHERE " + ALBUM_ID + " IN (" + labelIds.str() + ") AND " + ALBUM_SUBTYPE + " = " + to_string(PORTRAIT) +")");
1655     vector<string> columns = {
1656         ALBUM_ID,
1657     };
1658     auto resultSet = rdbStore->Query(predicates, columns);
1659     CHECK_AND_RETURN_RET(resultSet != nullptr, E_HAS_DB_ERROR);
1660     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
1661         string albumId = to_string(GetIntValFromColumn(resultSet, ALBUM_ID));
1662         if (resultAlbumIds.find(albumId) == resultAlbumIds.end()) {
1663             resultAlbumIds.insert(albumId);
1664             portraitAlbumIds.push_back(albumId);
1665         }
1666     }
1667     return E_OK;
1668 }
1669 
GetAlbumSubtypeArgument(const RdbPredicates & predicates)1670 int32_t MediaLibraryRdbUtils::GetAlbumSubtypeArgument(const RdbPredicates &predicates)
1671 {
1672     string whereClause = predicates.GetWhereClause();
1673     vector<string> whereArgs = predicates.GetWhereArgs();
1674     size_t subtypePos = whereClause.find(PhotoAlbumColumns::ALBUM_SUBTYPE + " = ?");
1675     if (subtypePos == string::npos) {
1676         return E_ERR;
1677     }
1678     size_t argsIndex = 0;
1679     for (size_t i = 0; i < subtypePos; i++) {
1680         if (whereClause[i] == '?') {
1681             argsIndex++;
1682         }
1683     }
1684     CHECK_AND_RETURN_RET(argsIndex <= whereArgs.size() - 1, E_ERR);
1685     const string &subtype = whereArgs[argsIndex];
1686     bool cond = subtype.empty() || !MediaLibraryDataManagerUtils::IsNumber(subtype);
1687     CHECK_AND_RETURN_RET(!cond, E_ERR);
1688     return std::stoi(subtype);
1689 }
1690 
GetUpdateAlbumDataInfo(shared_ptr<ResultSet> albumResult,std::vector<UpdateAlbumData> & datas)1691 static void GetUpdateAlbumDataInfo(shared_ptr<ResultSet> albumResult, std::vector<UpdateAlbumData> &datas)
1692 {
1693     CHECK_AND_RETURN_LOG(albumResult != nullptr, "albumResult is nullptr");
1694     while (albumResult->GoToNextRow() == E_OK) {
1695         UpdateAlbumData data;
1696         data.albumId = GetAlbumId(albumResult);
1697         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(albumResult));
1698         data.albumCoverUri = GetAlbumCover(albumResult, PhotoAlbumColumns::ALBUM_COVER_URI);
1699         data.albumCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_COUNT);
1700         data.isCoverSatisfied = GetIsCoverSatisfied(albumResult);
1701         datas.push_back(data);
1702     }
1703 }
1704 
UpdateAnalysisAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & anaAlbumAlbumIds,const vector<string> & fileIds)1705 void MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1706     const vector<string> &anaAlbumAlbumIds, const vector<string> &fileIds)
1707 {
1708     MediaLibraryTracer tracer;
1709     tracer.Start("UpdateAnalysisAlbumInternal");
1710     vector<string> columns = {
1711         PhotoAlbumColumns::ALBUM_ID, PhotoAlbumColumns::ALBUM_SUBTYPE,
1712         PhotoAlbumColumns::ALBUM_COVER_URI, PhotoAlbumColumns::ALBUM_COUNT,
1713         IS_COVER_SATISFIED };
1714     vector<string> tempAlbumId = anaAlbumAlbumIds;
1715     if (tempAlbumId.size() > 0) {
1716         GetAlbumIdsForPortrait(rdbStore, tempAlbumId);
1717     }
1718     auto albumResult = GetAnalysisAlbum(rdbStore, tempAlbumId, columns);
1719     CHECK_AND_RETURN_LOG(albumResult != nullptr, "Failed to get Analysis Album");
1720     std::vector<UpdateAlbumData> datas;
1721     GetUpdateAlbumDataInfo(albumResult, datas);
1722     albumResult->Close();
1723 
1724     // For each row
1725     int32_t err = NativeRdb::E_OK;
1726     for (auto data : datas) {
1727         int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
1728         std::shared_ptr<TransactionOperations> trans = make_shared<TransactionOperations>(__func__);
1729         std::function<int(void)> func = [&]()->int {
1730             auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
1731             if (subtype == PhotoAlbumSubType::PORTRAIT) {
1732                 UpdatePortraitAlbumIfNeeded(rdbStore, data, fileIds, trans);
1733             } else if (subtype == PhotoAlbumSubType::GROUP_PHOTO) {
1734                 MEDIA_INFO_LOG("No need to update group photo");
1735             } else {
1736                 UpdateAnalysisAlbumIfNeeded(rdbStore, data, false, trans);
1737             }
1738             return err;
1739         };
1740         err = trans->RetryTrans(func);
1741         CHECK_AND_PRINT_LOG(err == E_OK, "UpdateAnalysisAlbumInternal: tans finish fail!, ret:%{public}d", err);
1742         int32_t costTime = static_cast<int32_t>(MediaFileUtils::UTCTimeMilliSeconds() - start);
1743         if (costTime > UPDATE_ALBUM_TIME_OUT) {
1744             MEDIA_INFO_LOG("udpate analysis album: %{public}d cost %{public}d", data.albumId, costTime);
1745         }
1746     }
1747 }
1748 
UpdateAnalysisAlbumByFile(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & fileIds,const vector<int> & albumTypes)1749 void MediaLibraryRdbUtils::UpdateAnalysisAlbumByFile(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1750     const vector<string> &fileIds, const vector<int> &albumTypes)
1751 {
1752     CHECK_AND_RETURN_LOG(!fileIds.empty(), "Failed to UpdateAnalysisAlbumByFile cause fileIds empty");
1753     MediaLibraryTracer tracer;
1754     tracer.Start("UpdateAnalysisAlbumByFile");
1755     vector<string> columns = {
1756         PhotoMap::ALBUM_ID,
1757     };
1758     RdbPredicates predicates(ANALYSIS_PHOTO_MAP_TABLE);
1759     if (!albumTypes.empty()) {
1760         std::string files;
1761         for (std::string fileId : fileIds) {
1762             files.append("'").append(fileId).append("'").append(",");
1763         }
1764         files = files.substr(0, files.length() - 1);
1765         std::string subTypes;
1766         for (int subtype : albumTypes) {
1767             subTypes.append(to_string(subtype)).append(",");
1768         }
1769         subTypes = subTypes.substr(0, subTypes.length() - 1);
1770         predicates.SetWhereClause(PhotoMap::ASSET_ID + " in(" + files + ") and " + PhotoMap::ALBUM_ID +
1771             " in(select album_id from AnalysisAlbum where album_subtype in(" + subTypes + "))");
1772     } else {
1773         predicates.In(PhotoMap::ASSET_ID, fileIds);
1774     }
1775     shared_ptr<ResultSet> mapResult = rdbStore->Query(predicates, columns);
1776     CHECK_AND_RETURN_LOG(mapResult != nullptr, "Failed query AnalysisAlbum");
1777     vector<string> albumIds;
1778     while (mapResult->GoToNextRow() == E_OK) {
1779         albumIds.push_back(to_string(GetIntValFromColumn(mapResult, PhotoMap::ALBUM_ID)));
1780     }
1781     int err = E_HAS_DB_ERROR;
1782     int32_t deletedRows = 0;
1783     err = rdbStore->Delete(deletedRows, predicates);
1784 
1785     bool cond = (err != E_OK || deletedRows <= 0);
1786     CHECK_AND_RETURN_LOG(!cond, "Failed Delete AnalysisPhotoMap");
1787     UpdateAnalysisAlbumInternal(rdbStore, albumIds, fileIds);
1788 }
1789 
UpdateCommonAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & albumIds={})1790 static void UpdateCommonAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1791     const vector<string> &albumIds = {})
1792 {
1793     MediaLibraryTracer tracer;
1794     tracer.Start("UpdateCommonAlbumHiddenState");
1795 
1796     auto albumResult = GetCommonAlbum(rdbStore, albumIds, {
1797         PhotoAlbumColumns::ALBUM_ID,
1798         PhotoAlbumColumns::ALBUM_SUBTYPE,
1799         PhotoAlbumColumns::HIDDEN_COUNT,
1800         PhotoAlbumColumns::HIDDEN_COVER,
1801     });
1802     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
1803     std::vector<UpdateAlbumData> datas;
1804     while (albumResult->GoToNextRow() == E_OK) {
1805         UpdateAlbumData data;
1806         data.albumId = GetAlbumId(albumResult);
1807         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(albumResult));
1808         data.hiddenCount = GetAlbumCount(albumResult, PhotoAlbumColumns::HIDDEN_COUNT);
1809         data.hiddenCover = GetAlbumCover(albumResult, PhotoAlbumColumns::HIDDEN_COVER);
1810         datas.push_back(data);
1811     }
1812     albumResult->Close();
1813     ForEachRow(rdbStore, datas, true, UpdateCommonAlbumIfNeeded);
1814 }
1815 
UpdateSourceAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & sourceAlbumIds={})1816 static void UpdateSourceAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1817     const vector<string> &sourceAlbumIds = {})
1818 {
1819     MediaLibraryTracer tracer;
1820     tracer.Start("UpdateSourceAlbumHiddenState");
1821 
1822     auto albumResult = GetSourceAlbum(rdbStore, sourceAlbumIds, {
1823         PhotoAlbumColumns::ALBUM_ID,
1824         PhotoAlbumColumns::ALBUM_SUBTYPE,
1825         PhotoAlbumColumns::HIDDEN_COUNT,
1826         PhotoAlbumColumns::HIDDEN_COVER,
1827     });
1828     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
1829     std::vector<UpdateAlbumData> datas;
1830     while (albumResult->GoToNextRow() == E_OK) {
1831         UpdateAlbumData data;
1832         data.albumId = GetAlbumId(albumResult);
1833         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(albumResult));
1834         data.hiddenCount = GetAlbumCount(albumResult, PhotoAlbumColumns::HIDDEN_COUNT);
1835         data.hiddenCover = GetAlbumCover(albumResult, PhotoAlbumColumns::HIDDEN_COVER);
1836         datas.push_back(data);
1837     }
1838     albumResult->Close();
1839     ForEachRow(rdbStore, datas, true, UpdateSourceAlbumIfNeeded);
1840 }
1841 
UpdateCommonAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris,bool shouldNotify)1842 void MediaLibraryRdbUtils::UpdateCommonAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1843     const vector<string> &uris, bool shouldNotify)
1844 {
1845     if (uris.size() == 0) {
1846         // it will be update all later
1847         return;
1848     }
1849     MediaLibraryTracer tracer;
1850     tracer.Start("UpdateCommonAlbumByUri");
1851     vector<string> albumIds = QueryAlbumId(rdbStore, uris);
1852     if (albumIds.size() > 0) {
1853         UpdateCommonAlbumInternal(rdbStore, albumIds, shouldNotify);
1854         UpdateCommonAlbumHiddenState(rdbStore, albumIds);
1855     }
1856 }
1857 
UpdateSourceAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris,bool shouldNotify)1858 void MediaLibraryRdbUtils::UpdateSourceAlbumByUri(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1859     const vector<string> &uris, bool shouldNotify)
1860 {
1861     MediaLibraryTracer tracer;
1862     tracer.Start("UpdateSourceAlbumByUri");
1863 
1864     if (uris.size() == 0) {
1865         UpdateSourceAlbumInternal(rdbStore);
1866         UpdateSourceAlbumHiddenState(rdbStore);
1867     }
1868 
1869     vector<string> albumIds = QueryAlbumId(rdbStore, uris, PhotoAlbumType::SOURCE);
1870     if (albumIds.size() > 0) {
1871         UpdateSourceAlbumInternal(rdbStore, albumIds, shouldNotify);
1872         UpdateSourceAlbumHiddenState(rdbStore, albumIds);
1873     }
1874 }
1875 
UpdateCommonAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & albumIds,bool shouldNotify)1876 void MediaLibraryRdbUtils::UpdateCommonAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1877     const vector<string> &albumIds, bool shouldNotify)
1878 {
1879     MediaLibraryTracer tracer;
1880     tracer.Start("UpdateCommonAlbumInternal");
1881 
1882     vector<string> columns = {
1883         PhotoAlbumColumns::ALBUM_ID,
1884         PhotoAlbumColumns::ALBUM_SUBTYPE,
1885         PhotoAlbumColumns::ALBUM_COVER_URI,
1886         PhotoAlbumColumns::ALBUM_COUNT,
1887         PhotoAlbumColumns::ALBUM_IMAGE_COUNT,
1888         PhotoAlbumColumns::ALBUM_VIDEO_COUNT,
1889     };
1890     auto albumResult = GetCommonAlbum(rdbStore, albumIds, columns);
1891     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
1892     std::vector<UpdateAlbumData> datas;
1893     while (albumResult->GoToNextRow() == E_OK) {
1894         UpdateAlbumData data;
1895         data.albumId = GetAlbumId(albumResult);
1896         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(albumResult));
1897         data.albumCoverUri = GetAlbumCover(albumResult, PhotoAlbumColumns::ALBUM_COVER_URI);
1898         data.albumCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_COUNT);
1899         data.albumImageCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_IMAGE_COUNT);
1900         data.albumVideoCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_VIDEO_COUNT);
1901         data.shouldNotify = shouldNotify;
1902         datas.push_back(data);
1903     }
1904     albumResult->Close();
1905 
1906     ForEachRow(rdbStore, datas, false, UpdateCommonAlbumIfNeeded);
1907 }
1908 
UpdateSourceAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & sourceAlbumIds,bool shouldNotify)1909 void MediaLibraryRdbUtils::UpdateSourceAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1910     const vector<string> &sourceAlbumIds, bool shouldNotify)
1911 {
1912     MediaLibraryTracer tracer;
1913     tracer.Start("UpdateSourceAlbumInternal");
1914 
1915     vector<string> columns = {
1916         PhotoAlbumColumns::ALBUM_ID,
1917         PhotoAlbumColumns::ALBUM_SUBTYPE,
1918         PhotoAlbumColumns::ALBUM_COVER_URI,
1919         PhotoAlbumColumns::ALBUM_COUNT,
1920         PhotoAlbumColumns::ALBUM_IMAGE_COUNT,
1921         PhotoAlbumColumns::ALBUM_VIDEO_COUNT,
1922     };
1923     auto albumResult = GetSourceAlbum(rdbStore, sourceAlbumIds, columns);
1924     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
1925     std::vector<UpdateAlbumData> datas;
1926     while (albumResult->GoToNextRow() == E_OK) {
1927         UpdateAlbumData data;
1928         data.albumId = GetAlbumId(albumResult);
1929         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(albumResult));
1930         data.albumCoverUri = GetAlbumCover(albumResult, PhotoAlbumColumns::ALBUM_COVER_URI);
1931         data.albumCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_COUNT);
1932         data.albumImageCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_IMAGE_COUNT);
1933         data.albumVideoCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_VIDEO_COUNT);
1934         data.shouldNotify = shouldNotify;
1935         datas.push_back(data);
1936     }
1937     albumResult->Close();
1938 
1939     ForEachRow(rdbStore, datas, false, UpdateSourceAlbumIfNeeded);
1940 }
1941 
GetSystemAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & subtypes,const vector<string> & columns)1942 static inline shared_ptr<ResultSet> GetSystemAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1943     const vector<string> &subtypes, const vector<string> &columns)
1944 {
1945     RdbPredicates predicates(PhotoAlbumColumns::TABLE);
1946     if (subtypes.empty()) {
1947         predicates.In(PhotoAlbumColumns::ALBUM_SUBTYPE, ALL_SYS_PHOTO_ALBUM);
1948     } else {
1949         predicates.In(PhotoAlbumColumns::ALBUM_SUBTYPE, subtypes);
1950     }
1951     return rdbStore->QueryWithFilter(predicates, columns);
1952 }
1953 
UpdateSystemAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & subtypes,bool shouldNotify)1954 void MediaLibraryRdbUtils::UpdateSystemAlbumInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1955     const vector<string> &subtypes, bool shouldNotify)
1956 {
1957     MediaLibraryTracer tracer;
1958     tracer.Start("UpdateSystemAlbumInternal");
1959 
1960     vector<string> columns = {
1961         PhotoAlbumColumns::ALBUM_ID,
1962         PhotoAlbumColumns::ALBUM_SUBTYPE,
1963         PhotoAlbumColumns::ALBUM_COVER_URI,
1964         PhotoAlbumColumns::ALBUM_COUNT,
1965         PhotoAlbumColumns::ALBUM_IMAGE_COUNT,
1966         PhotoAlbumColumns::ALBUM_VIDEO_COUNT,
1967     };
1968     auto albumResult = GetSystemAlbum(rdbStore, subtypes, columns);
1969     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
1970     std::vector<UpdateAlbumData> datas;
1971     while (albumResult->GoToNextRow() == E_OK) {
1972         UpdateAlbumData data;
1973         data.albumId = GetAlbumId(albumResult);
1974         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(albumResult));
1975         data.albumCoverUri = GetAlbumCover(albumResult, PhotoAlbumColumns::ALBUM_COVER_URI);
1976         data.albumCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_COUNT);
1977         data.albumImageCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_IMAGE_COUNT);
1978         data.albumVideoCount = GetAlbumCount(albumResult, PhotoAlbumColumns::ALBUM_VIDEO_COUNT);
1979         data.shouldNotify = shouldNotify;
1980         datas.push_back(data);
1981     }
1982     albumResult->Close();
1983     ForEachRow(rdbStore, datas, false, UpdateSysAlbumIfNeeded);
1984 }
1985 
UpdateSysAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & subtypes)1986 void MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(const shared_ptr<MediaLibraryRdbStore> rdbStore,
1987     const vector<string> &subtypes)
1988 {
1989     MediaLibraryTracer tracer;
1990     tracer.Start("UpdateSysAlbumHiddenState");
1991 
1992     shared_ptr<ResultSet> albumResult = nullptr;
1993 
1994     const vector<string> columns = {
1995         PhotoAlbumColumns::ALBUM_ID,
1996         PhotoAlbumColumns::ALBUM_SUBTYPE,
1997         PhotoAlbumColumns::HIDDEN_COUNT,
1998         PhotoAlbumColumns::HIDDEN_COVER,
1999     };
2000 
2001     if (subtypes.empty()) {
2002         albumResult = GetSystemAlbum(rdbStore, {
2003             to_string(PhotoAlbumSubType::IMAGE),
2004             to_string(PhotoAlbumSubType::VIDEO),
2005             to_string(PhotoAlbumSubType::HIDDEN),
2006             to_string(PhotoAlbumSubType::TRASH),
2007             to_string(PhotoAlbumSubType::FAVORITE),
2008             to_string(PhotoAlbumSubType::SCREENSHOT),
2009             to_string(PhotoAlbumSubType::CAMERA),
2010             to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
2011         }, columns);
2012     } else {
2013         albumResult = GetSystemAlbum(rdbStore, subtypes, columns);
2014     }
2015 
2016     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
2017     std::vector<UpdateAlbumData> datas;
2018     while (albumResult->GoToNextRow() == E_OK) {
2019         UpdateAlbumData data;
2020         data.albumId = GetAlbumId(albumResult);
2021         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(albumResult));
2022         data.hiddenCount = GetAlbumCount(albumResult, PhotoAlbumColumns::HIDDEN_COUNT);
2023         data.hiddenCover = GetAlbumCover(albumResult, PhotoAlbumColumns::HIDDEN_COVER);
2024         datas.push_back(data);
2025     }
2026     albumResult->Close();
2027 
2028     ForEachRow(rdbStore, datas, true, UpdateSysAlbumIfNeeded);
2029 }
2030 
AddSystemAlbum(set<string> & systemAlbum,shared_ptr<NativeRdb::ResultSet> resultSet)2031 static void AddSystemAlbum(set<string> &systemAlbum, shared_ptr<NativeRdb::ResultSet> resultSet)
2032 {
2033     int minMediaType = GetIntValFromColumn(resultSet, "Min(" + MediaColumn::MEDIA_TYPE + ")");
2034     int maxMediaType = GetIntValFromColumn(resultSet, "Max(" + MediaColumn::MEDIA_TYPE + ")");
2035     int favorite = GetIntValFromColumn(resultSet, "Max(" + MediaColumn::MEDIA_IS_FAV + ")");
2036     int cloudAssociate = GetIntValFromColumn(resultSet, "Max(" + PhotoColumn::PHOTO_STRONG_ASSOCIATION + ")");
2037     if (minMediaType == MEDIA_TYPE_IMAGE) {
2038         systemAlbum.insert(to_string(PhotoAlbumSubType::IMAGE));
2039     }
2040     if (maxMediaType == MEDIA_TYPE_VIDEO) {
2041         systemAlbum.insert(to_string(PhotoAlbumSubType::VIDEO));
2042     }
2043     if (favorite > 0) {
2044         systemAlbum.insert(to_string(PhotoAlbumSubType::FAVORITE));
2045     }
2046     if (cloudAssociate > 0) {
2047         systemAlbum.insert(to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT));
2048     }
2049     MEDIA_INFO_LOG("AddSystemAlbum minMediaType:%{public}d, maxMediaType:%{public}d, favorite:%{public}d,"
2050         " cloudAssociate:%{public}d,", minMediaType, maxMediaType, favorite, cloudAssociate);
2051 }
2052 
GetUpdateAlbumByOperationType(set<string> & systemAlbum,set<string> & hiddenSystemAlbum,AlbumOperationType albumOperationType,int32_t hidden)2053 static void GetUpdateAlbumByOperationType(set<string> &systemAlbum, set<string> &hiddenSystemAlbum,
2054     AlbumOperationType albumOperationType, int32_t hidden)
2055 {
2056     if (albumOperationType == AlbumOperationType::DELETE_PHOTO ||
2057         albumOperationType == AlbumOperationType::RECOVER_PHOTO) {
2058         systemAlbum.insert(to_string(PhotoAlbumSubType::TRASH));
2059         if (hidden > 0) {
2060             hiddenSystemAlbum.insert(to_string(PhotoAlbumSubType::TRASH));
2061         }
2062     }
2063     if (albumOperationType == UNHIDE_PHOTO || hidden > 0) {
2064         systemAlbum.insert(to_string(PhotoAlbumSubType::HIDDEN));
2065         hiddenSystemAlbum.insert(to_string(PhotoAlbumSubType::HIDDEN));
2066     }
2067 }
2068 
GetSystemAlbumByUris(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris,AlbumOperationType albumOperationType,set<string> & systemAlbum,set<string> & hiddenSystemAlbum)2069 static void GetSystemAlbumByUris(const shared_ptr<MediaLibraryRdbStore> rdbStore, const vector<string> &uris,
2070     AlbumOperationType albumOperationType, set<string> &systemAlbum, set<string> &hiddenSystemAlbum)
2071 {
2072     MediaLibraryTracer tracer;
2073     tracer.Start("GetSystemAlbumByUris");
2074     vector<string> fileIds;
2075     for (auto uri : uris) {
2076         string fileId = GetPhotoId(uri);
2077         fileIds.push_back(fileId);
2078     }
2079     size_t queryTime = (fileIds.size() + ALBUM_UPDATE_THRESHOLD -1) / ALBUM_UPDATE_THRESHOLD;
2080     for (size_t i = 0; i < queryTime; i++) {
2081         size_t start = i * ALBUM_UPDATE_THRESHOLD;
2082         size_t end = (start + ALBUM_UPDATE_THRESHOLD) < fileIds.size() ?
2083             (start + ALBUM_UPDATE_THRESHOLD) : fileIds.size();
2084         std::vector<string> childVector(fileIds.begin() + start, fileIds.begin() + end);
2085         RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2086         predicates.In(PhotoColumn::MEDIA_ID, childVector);
2087         predicates.GroupBy({MediaColumn::MEDIA_HIDDEN});
2088         const vector<string> columns = {
2089             MediaColumn::MEDIA_HIDDEN,
2090             "Min(" + MediaColumn::MEDIA_TYPE + ")",
2091             "Max(" + MediaColumn::MEDIA_TYPE + ")",
2092             "Max(" + MediaColumn::MEDIA_IS_FAV + ")",
2093             "Max(" + PhotoColumn::PHOTO_STRONG_ASSOCIATION + ")",
2094         };
2095         auto resultSet = rdbStore->Query(predicates, columns);
2096         if (resultSet == nullptr) {
2097             MEDIA_ERR_LOG("Failed to query Systemalbum info!");
2098             continue;
2099         }
2100         while (resultSet->GoToNextRow() == E_OK) {
2101             int32_t hidden = GetIntValFromColumn(resultSet, 0);
2102             AddSystemAlbum(systemAlbum, resultSet);
2103             AddSystemAlbum(hiddenSystemAlbum, resultSet);
2104             GetUpdateAlbumByOperationType(systemAlbum, hiddenSystemAlbum, albumOperationType, hidden);
2105         }
2106         resultSet->Close();
2107     }
2108 }
2109 
UpdateSystemAlbumsByUris(const shared_ptr<MediaLibraryRdbStore> rdbStore,AlbumOperationType albumOperationType,const vector<string> & uris,NotifyAlbumType type)2110 void MediaLibraryRdbUtils::UpdateSystemAlbumsByUris(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2111     AlbumOperationType albumOperationType, const vector<string> &uris, NotifyAlbumType type)
2112 {
2113     if (uris.empty() || albumOperationType == AlbumOperationType::DEFAULT) {
2114         vector<string> systemAlbumsExcludeSource = {
2115             to_string(PhotoAlbumSubType::FAVORITE),
2116             to_string(PhotoAlbumSubType::VIDEO),
2117             to_string(PhotoAlbumSubType::HIDDEN),
2118             to_string(PhotoAlbumSubType::TRASH),
2119             to_string(PhotoAlbumSubType::IMAGE),
2120             to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
2121         };
2122         MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, systemAlbumsExcludeSource,
2123             type & NotifyAlbumType::SYS_ALBUM);
2124         MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(rdbStore);
2125     } else {
2126         set<string> systemAlbumSet;
2127         set<string> hiddenSystemAlbumSet;
2128         GetSystemAlbumByUris(rdbStore, uris, albumOperationType, systemAlbumSet, hiddenSystemAlbumSet);
2129         vector<string> systemAlbum;
2130         vector<string> hiddenSystemAlbum;
2131         systemAlbum.assign(systemAlbumSet.begin(), systemAlbumSet.end());
2132         hiddenSystemAlbum.assign(hiddenSystemAlbumSet.begin(), hiddenSystemAlbumSet.end());
2133         MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore, systemAlbum,
2134             type & NotifyAlbumType::SYS_ALBUM);
2135         if (!hiddenSystemAlbum.empty()) {
2136             MediaLibraryRdbUtils::UpdateSysAlbumHiddenState(rdbStore, hiddenSystemAlbum);
2137         }
2138     }
2139 }
2140 
UpdateAllAlbums(shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & uris,NotifyAlbumType type,bool isBackUpAndRestore,AlbumOperationType albumOperationType)2141 void MediaLibraryRdbUtils::UpdateAllAlbums(shared_ptr<MediaLibraryRdbStore> rdbStore, const vector<string> &uris,
2142     NotifyAlbumType type, bool isBackUpAndRestore, AlbumOperationType albumOperationType)
2143 {
2144     MediaLibraryTracer tracer;
2145     tracer.Start("UpdateAllAlbums");
2146     if (rdbStore == nullptr) {
2147         MEDIA_ERR_LOG("Failed to get rdbstore, try again!");
2148         rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2149         CHECK_AND_RETURN_LOG(rdbStore != nullptr,
2150             "Fatal error! Failed to get rdbstore, new cloud data is not processed!!");
2151     }
2152 
2153     MediaLibraryRdbUtils::UpdateSystemAlbumsByUris(rdbStore, albumOperationType, uris, type);
2154     MediaLibraryRdbUtils::UpdateUserAlbumByUri(rdbStore, uris);
2155     MediaLibraryRdbUtils::UpdateSourceAlbumByUri(rdbStore, uris);
2156     if (!isBackUpAndRestore) {
2157         std::thread([rdbStore, uris]() { MediaLibraryRdbUtils::UpdateAnalysisAlbumByUri(rdbStore, uris); }).detach();
2158     } else {
2159         MediaLibraryRdbUtils::UpdateAnalysisAlbumByUri(rdbStore, uris);
2160     }
2161 }
2162 
UpdateAlbumReplacedSignal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & albumIdVector)2163 static int32_t UpdateAlbumReplacedSignal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2164     const vector<string> &albumIdVector)
2165 {
2166     CHECK_AND_RETURN_RET(!albumIdVector.empty(), E_SUCCESS);
2167 
2168     ValuesBucket refreshValues;
2169     string insertRefreshTableSql = "INSERT OR IGNORE INTO " + ALBUM_REFRESH_TABLE + " VALUES ";
2170     for (size_t i = 0; i < albumIdVector.size(); ++i) {
2171         if (i != albumIdVector.size() - 1) {
2172             insertRefreshTableSql += "(" + albumIdVector[i] + "), ";
2173         } else {
2174             insertRefreshTableSql += "(" + albumIdVector[i] + ");";
2175         }
2176     }
2177     MEDIA_DEBUG_LOG("output insertRefreshTableSql:%{public}s", insertRefreshTableSql.c_str());
2178 
2179     int32_t ret = rdbStore->ExecuteSql(insertRefreshTableSql);
2180     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
2181         "Can not insert refreshed table, ret:%{public}d", ret);
2182     return E_SUCCESS;
2183 }
2184 
UpdateBussinessRecord(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<BussinessRecordValue> & updateValue)2185 static int32_t UpdateBussinessRecord(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2186     const vector<BussinessRecordValue> &updateValue)
2187 {
2188     CHECK_AND_RETURN_RET(!updateValue.empty(), E_SUCCESS);
2189 
2190     ValuesBucket refreshValues;
2191     string insertTableSql = "INSERT OR IGNORE INTO " + MedialibraryBusinessRecordColumn::TABLE + "(" +
2192         MedialibraryBusinessRecordColumn::BUSINESS_TYPE + "," + MedialibraryBusinessRecordColumn::KEY + "," +
2193         MedialibraryBusinessRecordColumn::VALUE + ") VALUES ";
2194     for (size_t i = 0; i < updateValue.size(); ++i) {
2195         if (i != updateValue.size() - 1) {
2196             insertTableSql += "('" + updateValue[i].bussinessType + "', '" + updateValue[i].key + "', '" +
2197                 updateValue[i].value + "'), ";
2198         } else {
2199             insertTableSql += "('" + updateValue[i].bussinessType + "', '" + updateValue[i].key + "', '" +
2200                 updateValue[i].value + "');";
2201         }
2202     }
2203     MEDIA_DEBUG_LOG("output insertTableSql:%{public}s", insertTableSql.c_str());
2204 
2205     int32_t ret = rdbStore->ExecuteSql(insertTableSql);
2206     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
2207         "Can not insert bussinessRecord table, ret:%{public}d", ret);
2208     return E_SUCCESS;
2209 }
2210 
UpdateSystemAlbumCountInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & subtypes)2211 void MediaLibraryRdbUtils::UpdateSystemAlbumCountInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2212     const vector<string> &subtypes)
2213 {
2214     // Only use in dfs
2215     MediaLibraryTracer tracer;
2216     tracer.Start("UpdateSystemAlbumCountInternal");
2217 
2218     vector<string> columns = { PhotoAlbumColumns::ALBUM_ID };
2219     auto albumResult = GetSystemAlbum(rdbStore, subtypes, columns);
2220     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
2221 
2222     vector<string> replaceSignalAlbumVector;
2223     while (albumResult->GoToNextRow() == NativeRdb::E_OK) {
2224         int32_t ret = GetIntValFromColumn(albumResult, PhotoAlbumColumns::ALBUM_ID);
2225         if (ret <= 0) {
2226             MEDIA_WARN_LOG("Can not get ret:%{public}d", ret);
2227         } else {
2228             replaceSignalAlbumVector.push_back(to_string(ret));
2229         }
2230     }
2231     if (!replaceSignalAlbumVector.empty()) {
2232         int32_t ret = UpdateAlbumReplacedSignal(rdbStore, replaceSignalAlbumVector);
2233         CHECK_AND_WARN_LOG(ret == E_OK, "Update sysalbum replaced signal failed ret:%{public}d", ret);
2234     }
2235     // Do not call SetNeedRefreshAlbum in this function
2236     // This is set by the notification from dfs
2237     // and is set by the media library observer after receiving the notification
2238 }
2239 
UpdateUserAlbumCountInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & userAlbumIds)2240 void MediaLibraryRdbUtils::UpdateUserAlbumCountInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2241     const vector<string> &userAlbumIds)
2242 {
2243     // only use in dfs
2244     MediaLibraryTracer tracer;
2245     tracer.Start("UpdateUserAlbumCountInternal");
2246 
2247     vector<string> columns = { PhotoAlbumColumns::ALBUM_ID };
2248     auto albumResult = GetUserAlbum(rdbStore, userAlbumIds, columns);
2249     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
2250 
2251     vector<string> replaceSignalAlbumVector;
2252     while (albumResult->GoToNextRow() == NativeRdb::E_OK) {
2253         int32_t ret = GetIntValFromColumn(albumResult, PhotoAlbumColumns::ALBUM_ID);
2254         if (ret <= 0) {
2255             MEDIA_WARN_LOG("Can not get ret:%{public}d", ret);
2256         } else {
2257             replaceSignalAlbumVector.push_back(to_string(ret));
2258         }
2259     }
2260     if (!replaceSignalAlbumVector.empty()) {
2261         int32_t ret = UpdateAlbumReplacedSignal(rdbStore, replaceSignalAlbumVector);
2262         CHECK_AND_WARN_LOG(ret == E_OK, "Update user album replaced signal failed ret:%{public}d", ret);
2263     }
2264     // Do not call SetNeedRefreshAlbum in this function
2265     // This is set by the notification from dfs
2266     // and is set by the media library observer after receiving the notification
2267 }
2268 
UpdateAnalysisAlbumCountInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,const vector<string> & subtypes)2269 void MediaLibraryRdbUtils::UpdateAnalysisAlbumCountInternal(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2270     const vector<string> &subtypes)
2271 {
2272     // only use in dfs
2273     MediaLibraryTracer tracer;
2274     tracer.Start("UpdateAnalysisAlbumCountInternal");
2275 
2276     vector<string> columns = { ALBUM_ID, ALBUM_SUBTYPE };
2277     auto albumResult = GetAnalysisAlbumBySubtype(rdbStore, subtypes, columns);
2278     CHECK_AND_RETURN_LOG(albumResult != nullptr, "album result is null");
2279 
2280     vector<BussinessRecordValue> updateAlbumIdList;
2281     while (albumResult->GoToNextRow() == NativeRdb::E_OK) {
2282         int32_t albumId = GetIntValFromColumn(albumResult, ALBUM_ID);
2283         int32_t subtype = GetIntValFromColumn(albumResult, ALBUM_SUBTYPE);
2284         if (albumId <= 0) {
2285             MEDIA_WARN_LOG("Can not get ret:%{public}d", albumId);
2286         } else {
2287             updateAlbumIdList.push_back({ ANALYSIS_REFRESH_BUSINESS_TYPE, to_string(subtype), to_string(albumId) });
2288         }
2289     }
2290     if (!updateAlbumIdList.empty()) {
2291         int32_t ret = UpdateBussinessRecord(rdbStore, updateAlbumIdList);
2292         CHECK_AND_WARN_LOG(ret == E_OK, "Update sysalbum replaced signal failed ret:%{public}d", ret);
2293     }
2294     // Do not call SetNeedRefreshAlbum in this function
2295     // This is set by the notification from dfs
2296     // and is set by the media library observer after receiving the notification
2297 }
2298 
HandleAnalysisAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore,vector<RefreshAlbumData> & albums,bool isUpdateAllAnalysis)2299 static void HandleAnalysisAlbum(const shared_ptr<MediaLibraryRdbStore> rdbStore, vector<RefreshAlbumData> &albums,
2300     bool isUpdateAllAnalysis)
2301 {
2302     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2303     int32_t count = -1;
2304     if (isUpdateAllAnalysis) {
2305         MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(rdbStore);
2306     } else {
2307         CHECK_AND_RETURN_LOG(!albums.empty(), "no album");
2308         count = static_cast<int32_t>(albums.size());
2309         std::vector<std::string> albumIds(count);
2310         for (int32_t i = 0; i < count; i++) {
2311             albumIds[i] = to_string(albums[i].albumId);
2312             MEDIA_DEBUG_LOG("analysis: %{public}s", albumIds[i].c_str());
2313         }
2314         MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(rdbStore, albumIds);
2315     }
2316     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2317     MEDIA_INFO_LOG("%{public}d analysis albums update cost %{public}ld", count,
2318         static_cast<long>(end - start));
2319 }
2320 
RefreshPhotoAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,function<void (PhotoAlbumType,PhotoAlbumSubType,int)> refreshProcessHandler)2321 int RefreshPhotoAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2322     function<void(PhotoAlbumType, PhotoAlbumSubType, int)> refreshProcessHandler)
2323 {
2324     std::vector<RefreshAlbumData> systeAlbums;
2325     std::vector<RefreshAlbumData> analysisAlbums;
2326     bool isUpdateAllAnalysis = false;
2327     int ret = GetSystemRefreshAlbums(rdbStore, systeAlbums);
2328     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret, "failed to get system album id from refresh album");
2329     ret = GetAnalysisRefreshAlbums(rdbStore, analysisAlbums, isUpdateAllAnalysis);
2330     DeleteAllAlbumId(rdbStore);
2331     CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, ret, "failed to get analysis album id from refresh album");
2332     if (systeAlbums.empty() && analysisAlbums.empty()) {
2333         MEDIA_INFO_LOG("all album are empty");
2334         return E_EMPTY_ALBUM_ID;
2335     }
2336     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2337     ret = RefreshAlbums(rdbStore, systeAlbums, refreshProcessHandler);
2338     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2339     MEDIA_INFO_LOG("%{public}d system albums update cost %{public}ld", (int)systeAlbums.size(), (long)(end - start));
2340     HandleAnalysisAlbum(rdbStore, analysisAlbums, isUpdateAllAnalysis);
2341     return ret;
2342 }
2343 
RefreshAnalysisAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,const std::vector<UpdateAlbumData> & datas,function<void (PhotoAlbumType,PhotoAlbumSubType,int)> refreshProcessHandler,const vector<string> & subtypes)2344 static int32_t RefreshAnalysisAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2345     const std::vector<UpdateAlbumData> &datas,
2346     function<void(PhotoAlbumType, PhotoAlbumSubType, int)> refreshProcessHandler,
2347     const vector<string> &subtypes)
2348 {
2349     for (auto data : datas) {
2350         int ret = UpdateAnalysisAlbumIfNeeded(rdbStore, data, false);
2351         CHECK_AND_RETURN_RET_LOG(ret == E_SUCCESS, E_HAS_DB_ERROR, "UpdateAnalysisAlbumIfNeeded fail");
2352         auto subtype = static_cast<PhotoAlbumSubType>(data.albumSubtype);
2353         int32_t albumId = data.albumId;
2354         refreshProcessHandler(PhotoAlbumType::SMART, subtype, albumId);
2355     }
2356 
2357     string deleteRefreshTableSql = "DELETE FROM " + MedialibraryBusinessRecordColumn::TABLE + " WHERE " +
2358         MedialibraryBusinessRecordColumn::BUSINESS_TYPE + " = '" + ANALYSIS_REFRESH_BUSINESS_TYPE + "'";
2359     int32_t ret = rdbStore->ExecuteSql(deleteRefreshTableSql);
2360     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
2361         "Failed to execute sql:%{private}s", deleteRefreshTableSql.c_str());
2362     MEDIA_DEBUG_LOG("Delete RefreshAnalysisAlbums success");
2363     return E_SUCCESS;
2364 }
2365 
GetRefreshAnalysisAlbumIds(const shared_ptr<MediaLibraryRdbStore> rdbStore,vector<string> & albumIds,const vector<string> & subtypes)2366 static int32_t GetRefreshAnalysisAlbumIds(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2367     vector<string> &albumIds, const vector<string> &subtypes)
2368 {
2369     RdbPredicates predicates(MedialibraryBusinessRecordColumn::TABLE);
2370     if (!subtypes.empty()) {
2371         predicates.In(MedialibraryBusinessRecordColumn::KEY, subtypes);
2372     } else {
2373         predicates.In(MedialibraryBusinessRecordColumn::KEY, ALL_ANALYSIS_ALBUM);
2374     }
2375     predicates.EqualTo(MedialibraryBusinessRecordColumn::BUSINESS_TYPE, ANALYSIS_REFRESH_BUSINESS_TYPE);
2376 
2377     vector<string> columns = { MedialibraryBusinessRecordColumn::VALUE };
2378     auto resultSet = rdbStore->Query(predicates, columns);
2379     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, E_HAS_DB_ERROR, "Can not query ALBUM_REFRESH_TABLE");
2380 
2381     int32_t count = 0;
2382     int32_t ret = resultSet->GetRowCount(count);
2383     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
2384         "GetRowCount failed ret:%{public}d", ret);
2385     if (count == 0) {
2386         MEDIA_DEBUG_LOG("count is zero, break");
2387         return E_SUCCESS;
2388     }
2389 
2390     while (resultSet->GoToNextRow() == NativeRdb::E_OK) {
2391         int32_t columnIndex = 0;
2392         ret = resultSet->GetColumnIndex(MedialibraryBusinessRecordColumn::VALUE, columnIndex);
2393         CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
2394             "GetColumnIndex failed ret:%{public}d", ret);
2395         string refreshAlbumId;
2396         ret = resultSet->GetString(columnIndex, refreshAlbumId);
2397         CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, E_HAS_DB_ERROR,
2398             "GetString failed ret:%{public}d", ret);
2399         albumIds.push_back(refreshAlbumId);
2400     }
2401     return E_SUCCESS;
2402 }
2403 
RefreshAnalysisPhotoAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,function<void (PhotoAlbumType,PhotoAlbumSubType,int)> refreshProcessHandler,const vector<string> & subtypes)2404 int RefreshAnalysisPhotoAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2405     function<void(PhotoAlbumType, PhotoAlbumSubType, int)> refreshProcessHandler, const vector<string> &subtypes)
2406 {
2407     int64_t start = MediaFileUtils::UTCTimeMilliSeconds();
2408     vector<string> albumIds;
2409     int ret = GetRefreshAnalysisAlbumIds(rdbStore, albumIds, subtypes);
2410     CHECK_AND_RETURN_RET(ret == E_SUCCESS, ret);
2411     if (albumIds.empty()) {
2412         MEDIA_DEBUG_LOG("albumIds is empty");
2413         return E_EMPTY_ALBUM_ID;
2414     }
2415     vector<string> columns = {
2416         PhotoAlbumColumns::ALBUM_ID,
2417         PhotoAlbumColumns::ALBUM_SUBTYPE,
2418         PhotoAlbumColumns::ALBUM_COVER_URI,
2419         PhotoAlbumColumns::ALBUM_COUNT,
2420     };
2421     auto resultSet = GetAnalysisAlbum(rdbStore, albumIds, columns);
2422     CHECK_AND_RETURN_RET(resultSet != nullptr, E_HAS_DB_ERROR);
2423 
2424     std::vector<UpdateAlbumData> datas;
2425     while (resultSet->GoToNextRow() == E_OK) {
2426         UpdateAlbumData data;
2427         data.albumId = GetAlbumId(resultSet);
2428         data.albumSubtype = static_cast<PhotoAlbumSubType>(GetAlbumSubType(resultSet));
2429         data.albumCoverUri = GetAlbumCover(resultSet, PhotoAlbumColumns::ALBUM_COVER_URI);
2430         data.albumCount = GetAlbumCount(resultSet, PhotoAlbumColumns::ALBUM_COUNT);
2431         datas.push_back(data);
2432     }
2433     resultSet->Close();
2434 
2435     ret = RefreshAnalysisAlbums(rdbStore, datas, refreshProcessHandler, subtypes);
2436     int64_t end = MediaFileUtils::UTCTimeMilliSeconds();
2437     MEDIA_INFO_LOG("%{public}d analysis albums update cost %{public}ld", (int)albumIds.size(), (long)(end - start));
2438     return ret;
2439 }
2440 
IsRefreshAlbumEmpty(const shared_ptr<MediaLibraryRdbStore> rdbStore)2441 static bool IsRefreshAlbumEmpty(const shared_ptr<MediaLibraryRdbStore> rdbStore)
2442 {
2443     RdbPredicates predicates(ALBUM_REFRESH_TABLE);
2444     vector<string> columns = { MEDIA_COLUMN_COUNT_1 };
2445     auto resultSet = rdbStore->Query(predicates, columns);
2446     CHECK_AND_RETURN_RET_LOG(resultSet != nullptr, true, "Can not query ALBUM_REFRESH_TABLE");
2447     int32_t count = GetFileCount(resultSet);
2448     MEDIA_DEBUG_LOG("RefreshAllAlbuming remain count:%{public}d", count);
2449     return count <= 0;
2450 }
2451 
RefreshAllAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,function<void (PhotoAlbumType,PhotoAlbumSubType,int)> refreshProcessHandler,function<void ()> refreshCallback)2452 int32_t MediaLibraryRdbUtils::RefreshAllAlbums(const shared_ptr<MediaLibraryRdbStore> rdbStore,
2453     function<void(PhotoAlbumType, PhotoAlbumSubType, int)> refreshProcessHandler, function<void()> refreshCallback)
2454 {
2455     unique_lock<mutex> lock(sRefreshAlbumMutex_);
2456     if (IsInRefreshTask()) {
2457         lock.unlock();
2458         MEDIA_DEBUG_LOG("RefreshAllAlbuming, quit");
2459         return E_OK;
2460     }
2461     isInRefreshTask = true;
2462     lock.unlock();
2463 
2464     MediaLibraryTracer tracer;
2465     tracer.Start("RefreshAllAlbums");
2466 
2467     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, E_HAS_DB_ERROR, "Can not get rdb");
2468 
2469     int ret = E_SUCCESS;
2470     bool isRefresh = false;
2471     while (IsNeedRefreshAlbum() || !IsRefreshAlbumEmpty(rdbStore)) {
2472         SetNeedRefreshAlbum(false);
2473         ret = RefreshPhotoAlbums(rdbStore, refreshProcessHandler);
2474         if (ret == E_EMPTY_ALBUM_ID) {
2475             ret = E_SUCCESS;
2476             continue;
2477         }
2478         if (ret != E_SUCCESS) {
2479             break;
2480         }
2481         this_thread::sleep_for(chrono::milliseconds(PowerEfficiencyManager::GetAlbumUpdateInterval()));
2482         isRefresh = true;
2483     }
2484     // update SHOOTING_MODE album
2485     vector<string> subtype = { std::to_string(PhotoAlbumSubType::SHOOTING_MODE) };
2486     ret = RefreshAnalysisPhotoAlbums(rdbStore, refreshProcessHandler, subtype);
2487     if (ret == E_EMPTY_ALBUM_ID) {
2488         ret = E_SUCCESS;
2489     }
2490 
2491     if (ret != E_SUCCESS) {
2492         // refresh failed and set flag, try to refresh next time
2493         SetNeedRefreshAlbum(true);
2494     } else {
2495         // refresh task is successful
2496         SetNeedRefreshAlbum(false);
2497     }
2498     isInRefreshTask = false;
2499     if (isRefresh) {
2500         refreshCallback();
2501     }
2502 
2503     return ret;
2504 }
2505 
UpdateAllAlbumsForCloud(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2506 void MediaLibraryRdbUtils::UpdateAllAlbumsForCloud(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2507 {
2508     // 注意,端云同步代码仓也有相同函数,添加新相册时,请通知端云同步进行相应修改
2509     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore);
2510     MediaLibraryRdbUtils::UpdateUserAlbumInternal(rdbStore);
2511     MediaLibraryRdbUtils::UpdateAnalysisAlbumInternal(rdbStore);
2512 }
2513 
UpdateAllAlbumsCountForCloud(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2514 void MediaLibraryRdbUtils::UpdateAllAlbumsCountForCloud(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2515 {
2516     // 注意,端云同步代码仓也有相同函数,添加新相册时,请通知端云同步进行相应修改
2517     MediaLibraryRdbUtils::UpdateSystemAlbumCountInternal(rdbStore);
2518     MediaLibraryRdbUtils::UpdateUserAlbumCountInternal(rdbStore);
2519     vector<string> subtype = { "4101" };
2520     MediaLibraryRdbUtils::UpdateAnalysisAlbumCountInternal(rdbStore, subtype);
2521 }
2522 
AddQueryIndex(AbsPredicates & predicates,const vector<string> & columns)2523 void MediaLibraryRdbUtils::AddQueryIndex(AbsPredicates& predicates, const vector<string>& columns)
2524 {
2525     auto it = find(columns.begin(), columns.end(), MEDIA_COLUMN_COUNT);
2526     if (it == columns.end()) {
2527         return;
2528     }
2529     const string &group = predicates.GetGroup();
2530     if (group.empty()) {
2531         predicates.GroupBy({ PhotoColumn::PHOTO_DATE_DAY });
2532         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_DAY_INDEX);
2533         return;
2534     }
2535     if (group == PhotoColumn::MEDIA_TYPE) {
2536         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_MEDIA_TYPE_INDEX);
2537         return;
2538     }
2539     if (group == PhotoColumn::PHOTO_DATE_DAY) {
2540         predicates.IndexedBy(PhotoColumn::PHOTO_SCHPT_DAY_INDEX);
2541         return;
2542     }
2543 }
2544 
AddVirtualColumnsOfDateType(vector<string> & columns)2545 void MediaLibraryRdbUtils::AddVirtualColumnsOfDateType(vector<string>& columns)
2546 {
2547     vector<string> dateTypes = { MEDIA_DATA_DB_DATE_ADDED, MEDIA_DATA_DB_DATE_TRASHED, MEDIA_DATA_DB_DATE_MODIFIED,
2548             MEDIA_DATA_DB_DATE_TAKEN };
2549     vector<string> dateTypeSeconds = { MEDIA_DATA_DB_DATE_ADDED_TO_SECOND,
2550             MEDIA_DATA_DB_DATE_TRASHED_TO_SECOND, MEDIA_DATA_DB_DATE_MODIFIED_TO_SECOND,
2551             MEDIA_DATA_DB_DATE_TAKEN_TO_SECOND };
2552     for (size_t i = 0; i < dateTypes.size(); i++) {
2553         auto it = find(columns.begin(), columns.end(), dateTypes[i]);
2554         if (it != columns.end()) {
2555             columns.push_back(dateTypeSeconds[i]);
2556         }
2557     }
2558 }
2559 
GetPhotoAndKnowledgeConnection()2560 vector<string> GetPhotoAndKnowledgeConnection()
2561 {
2562     vector<string> clauses;
2563     clauses.push_back(
2564         PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LATITUDE + " = " + GEO_KNOWLEDGE_TABLE + "." + LATITUDE);
2565     clauses.push_back(
2566         PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LONGITUDE + " = " + GEO_KNOWLEDGE_TABLE + "." + LONGITUDE);
2567     return clauses;
2568 }
2569 
QueryCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,const RdbPredicates & predicates)2570 int QueryCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore, const RdbPredicates &predicates)
2571 {
2572     const vector<string> columns = { MEDIA_COLUMN_COUNT_1 };
2573     auto fetchResult = QueryGoToFirst(rdbStore, predicates, columns);
2574     CHECK_AND_RETURN_RET(fetchResult != nullptr, 0);
2575     return GetFileCount(fetchResult);
2576 }
2577 
GetNewKnowledgeDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2578 int GetNewKnowledgeDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2579 {
2580     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2581     predicates.BeginWrap()->BeginWrap()
2582         ->LessThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LATITUDE, LOCATION_LATITUDE_MAX)
2583         ->And()->GreaterThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LATITUDE, LOCATION_DB_ZERO)
2584         ->EndWrap()->Or()->BeginWrap()
2585         ->LessThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LATITUDE, LOCATION_DB_ZERO)
2586         ->And()->GreaterThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LATITUDE, LOCATION_LATITUDE_MIN)
2587         ->EndWrap()->EndWrap()->And()->BeginWrap()->BeginWrap()
2588         ->LessThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LONGITUDE, LOCATION_LONGITUDE_MAX)->And()
2589         ->GreaterThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LONGITUDE, LOCATION_DB_ZERO)->EndWrap()
2590         ->Or()->BeginWrap()->LessThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LONGITUDE, LOCATION_DB_ZERO)
2591         ->And()->GreaterThan(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_LONGITUDE, LOCATION_LONGITUDE_MIN)
2592         ->EndWrap()->EndWrap();
2593     auto clauses = GetPhotoAndKnowledgeConnection();
2594     predicates.LeftOuterJoin(GEO_KNOWLEDGE_TABLE)->On(clauses);
2595     predicates.And()->BeginWrap()
2596         ->IsNull(GEO_KNOWLEDGE_TABLE + "." + LATITUDE)
2597         ->Or()->IsNull(GEO_KNOWLEDGE_TABLE + "." + LONGITUDE)
2598         ->Or()->IsNull(GEO_KNOWLEDGE_TABLE + "." + LANGUAGE)
2599         ->EndWrap();
2600 
2601     return QueryCount(rdbStore, predicates);
2602 }
2603 
GetUpdateKnowledgeDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2604 int GetUpdateKnowledgeDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2605 {
2606     RdbPredicates predicates(GEO_KNOWLEDGE_TABLE);
2607     predicates.LessThan(GEO_KNOWLEDGE_TABLE + "." + LOCATION_KEY, 0);
2608     return QueryCount(rdbStore, predicates);
2609 }
2610 
GetNewDictionaryDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2611 int GetNewDictionaryDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2612 {
2613     RdbPredicates predicates(GEO_KNOWLEDGE_TABLE);
2614     vector<string> clauses;
2615     clauses.push_back(GEO_KNOWLEDGE_TABLE + "." + CITY_ID + " = " + GEO_DICTIONARY_TABLE + "." + CITY_ID);
2616     clauses.push_back(GEO_KNOWLEDGE_TABLE + "." + LANGUAGE + " = " + GEO_DICTIONARY_TABLE + "." + LANGUAGE);
2617     predicates.LeftOuterJoin(GEO_DICTIONARY_TABLE)->On(clauses);
2618     predicates.BeginWrap()->IsNull(GEO_DICTIONARY_TABLE + "." + CITY_ID)
2619         ->And()->IsNotNull(GEO_KNOWLEDGE_TABLE + "." + COUNTRY)->EndWrap();
2620     vector<string> columns;
2621     auto resultSet = QueryGoToFirst(rdbStore, predicates, columns);
2622     CHECK_AND_RETURN_RET(resultSet != nullptr, 0);
2623     set<string> citySet;
2624     do {
2625         string cityId = GetStringValFromColumn(resultSet, CITY_ID);
2626         string cityName = GetStringValFromColumn(resultSet, CITY_NAME);
2627         if (cityId == "" || cityName == "") {
2628             continue;
2629         }
2630         citySet.insert(cityId);
2631     } while (!resultSet->GoToNextRow());
2632     return citySet.size();
2633 }
2634 
HasLocationData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2635 bool HasLocationData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2636 {
2637     int newDataCount = GetNewKnowledgeDataCount(rdbStore);
2638     int updateDataCount = GetUpdateKnowledgeDataCount(rdbStore);
2639     MEDIA_INFO_LOG("loc newDataCount:%{public}d, updateDataCount:%{public}d", newDataCount, updateDataCount);
2640 
2641     int newDictionaryCount = GetNewDictionaryDataCount(rdbStore);
2642     MEDIA_INFO_LOG("newDictionaryCount:%{public}d", newDictionaryCount);
2643     return (newDataCount + updateDataCount + newDictionaryCount) > 0;
2644 }
2645 
GetCvDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2646 int GetCvDataCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2647 {
2648     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2649     vector<string> clauses;
2650     clauses.push_back(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_ID  + " = " +
2651         VISION_TOTAL_TABLE + "." + PhotoColumn::MEDIA_ID);
2652     predicates.InnerJoin(VISION_TOTAL_TABLE)->On(clauses);
2653     predicates.BeginWrap()->EqualTo(VISION_TOTAL_TABLE + "." + STATUS, 0)->And()
2654         ->BeginWrap()->EqualTo(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_TIME_PENDING, 0)->And()
2655         ->EqualTo(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_DATE_TRASHED, 0)->And()
2656         ->BeginWrap()->NotEqualTo(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_POSITION, CLOUD_POSITION_STATUS)
2657         ->Or()->BeginWrap()
2658         ->EqualTo(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_POSITION, CLOUD_POSITION_STATUS)->And()
2659         ->EqualTo(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::PHOTO_THUMB_STATUS, 0)
2660         ->EndWrap()->EndWrap()->EndWrap()->EndWrap();
2661     return QueryCount(rdbStore, predicates);
2662 }
2663 
HasCvData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2664 bool HasCvData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2665 {
2666     int count = GetCvDataCount(rdbStore);
2667     MEDIA_INFO_LOG("cv count:%{public}d", count);
2668     return count > 0;
2669 }
2670 
GetSearchBaseCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2671 int GetSearchBaseCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2672 {
2673     RdbPredicates predicates(SEARCH_TOTAL_TABLE);
2674     vector<string> clasues;
2675     clasues.push_back(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_FILE_ID + " = " +
2676         PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_ID);
2677     predicates.InnerJoin(PhotoColumn::PHOTOS_TABLE)->On(clasues);
2678     predicates.EqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_PHOTO_STATUS, 0)
2679         ->And()
2680         ->EqualTo(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_TIME_PENDING, 0)
2681         ->And()
2682         ->GreaterThanOrEqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_FILE_ID, 0);
2683     return QueryCount(rdbStore, predicates);
2684 }
2685 
GetSearchUpdateCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2686 int GetSearchUpdateCount(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2687 {
2688     RdbPredicates predicates(SEARCH_TOTAL_TABLE);
2689     vector<string> clauses;
2690     clauses.push_back(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_FILE_ID + " = " +
2691         PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_ID);
2692     vector<string> clausesTotal;
2693     clausesTotal.push_back(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_FILE_ID + " = " +
2694         VISION_TOTAL_TABLE + "." + PhotoColumn::MEDIA_ID);
2695     vector<string> clausesGeo;
2696     clausesGeo.push_back(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_LATITUDE + " = " + GEO_KNOWLEDGE_TABLE + "." + LATITUDE);
2697     clausesGeo.push_back(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_LONGITUDE +
2698         " = " + GEO_KNOWLEDGE_TABLE + "." + LONGITUDE);
2699     predicates.InnerJoin(PhotoColumn::PHOTOS_TABLE)->On(clauses);
2700     predicates.InnerJoin(VISION_TOTAL_TABLE)->On(clausesTotal);
2701     predicates.LeftOuterJoin(GEO_KNOWLEDGE_TABLE)->On(clausesGeo);
2702     predicates.GreaterThanOrEqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_FILE_ID, 0)->And()
2703         ->EqualTo(PhotoColumn::PHOTOS_TABLE + "." + PhotoColumn::MEDIA_TIME_PENDING, 0)->And()
2704         ->GreaterThan(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_PHOTO_STATUS, 0)->And()
2705         ->BeginWrap()->EqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_PHOTO_STATUS, SEARCH_UPDATE_STATUS)->Or()
2706         ->BeginWrap()->EqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_CV_STATUS, SEARCH_UPDATE_STATUS)->And()
2707         ->EqualTo(VISION_TOTAL_TABLE + "." + FACE, FACE_CLUSTERED)->EndWrap()->Or()
2708         ->BeginWrap()->EqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_CV_STATUS, 0)->And()
2709         ->BeginWrap()->NotEqualTo(VISION_TOTAL_TABLE + "." + OCR, 0)->Or()
2710         ->NotEqualTo(VISION_TOTAL_TABLE + "." + LABEL, 0)->Or()
2711         ->BeginWrap()->NotEqualTo(VISION_TOTAL_TABLE + "." + FACE, 0)->And()
2712         ->NotEqualTo(VISION_TOTAL_TABLE + "." + FACE, FACE_RECOGNITION)->And()
2713         ->NotEqualTo(VISION_TOTAL_TABLE + "." + FACE, FACE_FEATURE)->EndWrap()->EndWrap()->EndWrap()->Or()
2714         ->BeginWrap()->EqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_GEO_STATUS, 0)->And()
2715         ->BeginWrap()->NotEqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_LATITUDE, 0)->Or()
2716         ->NotEqualTo(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_LONGITUDE, 0)->EndWrap()->And()
2717         ->IsNotNull(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_LATITUDE)->And()
2718         ->IsNotNull(SEARCH_TOTAL_TABLE + "." + TBL_SEARCH_LONGITUDE)->And()
2719         ->BeginWrap()->IsNotNull(GEO_KNOWLEDGE_TABLE + "." + LATITUDE)->And()
2720         ->IsNotNull(GEO_KNOWLEDGE_TABLE + "." + LONGITUDE)->EndWrap()->EndWrap()->EndWrap();
2721     return QueryCount(rdbStore, predicates);
2722 }
2723 
HasSearchData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2724 bool HasSearchData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2725 {
2726     int baseCount = GetSearchBaseCount(rdbStore);
2727     int upateCount = GetSearchUpdateCount(rdbStore);
2728     MEDIA_INFO_LOG("baseCount:%{public}d, upateCount:%{public}d", baseCount, upateCount);
2729     return (baseCount + upateCount) > 0;
2730 }
2731 
HasHighLightData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2732 bool HasHighLightData(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2733 {
2734     RdbPredicates predicates(ANALYSIS_ALBUM_TABLE);
2735     vector<string> clauses;
2736     clauses.push_back(ANALYSIS_ALBUM_TABLE + "." + ALBUM_ID + " = " +
2737         HIGHLIGHT_COVER_INFO_TABLE + "." + ALBUM_ID);
2738     predicates.InnerJoin(HIGHLIGHT_COVER_INFO_TABLE)->On(clauses);
2739     predicates.EqualTo(ANALYSIS_ALBUM_TABLE + "." + ALBUM_SUBTYPE, to_string(PhotoAlbumSubType::HIGHLIGHT))->And()
2740         ->NotEqualTo(ANALYSIS_ALBUM_TABLE + "." + PhotoAlbumColumns::ALBUM_COVER_URI,
2741         HIGHLIGHT_COVER_INFO_TABLE + "." + COVER_KEY);
2742     int count = QueryCount(rdbStore, predicates);
2743     MEDIA_INFO_LOG("highligh count:%{public}d", count);
2744     return (count > 0);
2745 }
2746 
HasDataToAnalysis(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)2747 bool MediaLibraryRdbUtils::HasDataToAnalysis(const std::shared_ptr<MediaLibraryRdbStore> rdbStore)
2748 {
2749     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "HasDataToAnalysis rdbstore is null");
2750     bool loc = HasLocationData(rdbStore);
2751     bool cv = HasCvData(rdbStore);
2752     bool search = HasSearchData(rdbStore);
2753     bool highlight = HasHighLightData(rdbStore);
2754     return (loc || cv || search || highlight);
2755 }
2756 
UpdateThumbnailRelatedDataToDefault(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,const int64_t fileId)2757 int32_t MediaLibraryRdbUtils::UpdateThumbnailRelatedDataToDefault(const std::shared_ptr<MediaLibraryRdbStore> rdbStore,
2758     const int64_t fileId)
2759 {
2760     int32_t err = -1;
2761     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, err, "RdbStore is null!");
2762 
2763     ValuesBucket values;
2764     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_READY, 0);
2765     values.PutLong(PhotoColumn::PHOTO_THUMBNAIL_VISIBLE, 0);
2766     values.PutLong(PhotoColumn::PHOTO_LCD_VISIT_TIME, 0);
2767 
2768     RdbPredicates predicates(PhotoColumn::PHOTOS_TABLE);
2769     predicates.EqualTo(MediaColumn::MEDIA_ID, fileId);
2770     int32_t changedRows = 0;
2771     err = rdbStore->Update(changedRows, values, predicates);
2772     CHECK_AND_PRINT_LOG(err == NativeRdb::E_OK, "RdbStore Update failed! err: %{public}d", err);
2773     return err;
2774 }
2775 
QueryNeedTransformPermission(const shared_ptr<MediaLibraryRdbStore> & store)2776 static shared_ptr<NativeRdb::ResultSet> QueryNeedTransformPermission(const shared_ptr<MediaLibraryRdbStore> &store)
2777 {
2778     NativeRdb::RdbPredicates rdbPredicate(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
2779     vector<string> permissionTypes;
2780     permissionTypes.emplace_back(to_string(PERSIST_READ_IMAGEVIDEO));
2781     permissionTypes.emplace_back(to_string(PERSIST_READWRITE_IMAGEVIDEO));
2782     rdbPredicate.In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
2783     rdbPredicate.BeginWrap();
2784     rdbPredicate.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, "");
2785     rdbPredicate.Or();
2786     rdbPredicate.IsNull(AppUriPermissionColumn::TARGET_TOKENID);
2787     rdbPredicate.EndWrap();
2788     vector<string> columns{
2789         AppUriPermissionColumn::APP_ID
2790     };
2791     rdbPredicate.GroupBy(columns);
2792     return store->Query(rdbPredicate, columns);
2793 }
2794 
QueryTokenIdMap(const shared_ptr<NativeRdb::ResultSet> & resultSet)2795 static std::map<std::string, int64_t> QueryTokenIdMap(const shared_ptr<NativeRdb::ResultSet> &resultSet)
2796 {
2797     std::map<std::string, int64_t> appIdTokenIdMap;
2798     while (resultSet->GoToNextRow() == E_OK) {
2799         string appId;
2800         GetStringFromResultSet(resultSet, AppUriPermissionColumn::APP_ID, appId);
2801         int64_t tokenId;
2802         if (PermissionUtils::GetMainTokenId(appId, tokenId)) {
2803             appIdTokenIdMap.emplace(appId, tokenId);
2804         }
2805     }
2806     return appIdTokenIdMap;
2807 }
2808 
TransformAppId2TokenId(const shared_ptr<MediaLibraryRdbStore> & store)2809 void MediaLibraryRdbUtils::TransformAppId2TokenId(const shared_ptr<MediaLibraryRdbStore> &store)
2810 {
2811     MEDIA_INFO_LOG("TransformAppId2TokenId start!");
2812     auto resultSet = QueryNeedTransformPermission(store);
2813     CHECK_AND_RETURN_LOG(resultSet != nullptr, "TransformAppId2TokenId failed");
2814 
2815     std::map<std::string, int64_t> tokenIdMap = QueryTokenIdMap(resultSet);
2816     resultSet->Close();
2817     if (tokenIdMap.size() == 0) {
2818         MEDIA_WARN_LOG("TransformAppId2TokenId tokenIdMap empty");
2819         return;
2820     }
2821     int32_t successCount = 0;
2822     for (auto &pair : tokenIdMap) {
2823         NativeRdb::RdbPredicates rdbPredicate(AppUriPermissionColumn::APP_URI_PERMISSION_TABLE);
2824         vector<string> permissionTypes;
2825         permissionTypes.emplace_back(to_string(PERSIST_READ_IMAGEVIDEO));
2826         permissionTypes.emplace_back(to_string(PERSIST_READWRITE_IMAGEVIDEO));
2827         rdbPredicate.In(AppUriPermissionColumn::PERMISSION_TYPE, permissionTypes);
2828         rdbPredicate.EqualTo(AppUriPermissionColumn::APP_ID, pair.first);
2829         rdbPredicate.BeginWrap();
2830         rdbPredicate.EqualTo(AppUriPermissionColumn::TARGET_TOKENID, "");
2831         rdbPredicate.Or();
2832         rdbPredicate.IsNull(AppUriPermissionColumn::TARGET_TOKENID);
2833         rdbPredicate.EndWrap();
2834         ValuesBucket refreshValues;
2835         refreshValues.PutLong(AppUriPermissionColumn::TARGET_TOKENID, pair.second);
2836         refreshValues.PutLong(AppUriPermissionColumn::SOURCE_TOKENID, pair.second);
2837         int changeRows = 0;
2838         if (store->Update(changeRows, refreshValues, rdbPredicate) == E_OK) {
2839             successCount++;
2840         }
2841     }
2842     MEDIA_INFO_LOG("TransformAppId2TokenId updatecount:%{public}zu, successcount:%{public}d",
2843         tokenIdMap.size(), successCount);
2844 }
2845 
UpdateSystemAlbumExcludeSource(bool shouldNotify)2846 void MediaLibraryRdbUtils::UpdateSystemAlbumExcludeSource(bool shouldNotify)
2847 {
2848     vector<string> systemAlbumsExcludeSource = {
2849         to_string(PhotoAlbumSubType::FAVORITE),
2850         to_string(PhotoAlbumSubType::VIDEO),
2851         to_string(PhotoAlbumSubType::HIDDEN),
2852         to_string(PhotoAlbumSubType::TRASH),
2853         to_string(PhotoAlbumSubType::IMAGE),
2854         to_string(PhotoAlbumSubType::CLOUD_ENHANCEMENT),
2855     };
2856     auto rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2857     CHECK_AND_RETURN_LOG(rdbStore != nullptr, "Failed to get rdbStore.");
2858     MediaLibraryRdbUtils::UpdateSystemAlbumInternal(rdbStore,
2859         systemAlbumsExcludeSource, shouldNotify);
2860 }
2861 
AnalyzePhotosData()2862 bool MediaLibraryRdbUtils::AnalyzePhotosData()
2863 {
2864     shared_ptr<MediaLibraryRdbStore> rdbStore = MediaLibraryUnistoreManager::GetInstance().GetRdbStore();
2865     CHECK_AND_RETURN_RET_LOG(rdbStore != nullptr, false, "can not get rdb store, failed to analyze photos data");
2866     const string analyzeSql = "ANALYZE " + PhotoColumn::PHOTOS_TABLE;
2867     MEDIA_INFO_LOG("start analyze photos data");
2868     int32_t ret = rdbStore->ExecuteSql(analyzeSql);
2869     CHECK_AND_RETURN_RET_LOG(ret == NativeRdb::E_OK, false, "Failed to execute sql, analyze photos data failed");
2870     MEDIA_INFO_LOG("end analyze photos data");
2871     return true;
2872 }
2873 
AnalyzePhotosDataAsync()2874 bool MediaLibraryRdbUtils::AnalyzePhotosDataAsync()
2875 {
2876     shared_ptr<MediaLibraryAsyncWorker> asyncWorker = MediaLibraryAsyncWorker::GetInstance();
2877     CHECK_AND_RETURN_RET_LOG(asyncWorker != nullptr, false, "can not get async worker, failed to analyze photos data");
2878     shared_ptr<MediaLibraryAsyncTask> asyncTask = make_shared<MediaLibraryAsyncTask>(
2879         [](AsyncTaskData *data) { MediaLibraryRdbUtils::AnalyzePhotosData(); }, nullptr);
2880     CHECK_AND_RETURN_RET_LOG(asyncTask != nullptr, false, "Analyze Photos Data create task fail");
2881     asyncWorker->AddTask(asyncTask, false);
2882     MEDIA_INFO_LOG("Analyze Photos Data create task success");
2883     return true;
2884 }
2885 } // namespace OHOS::Media
2886