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