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