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