1 /*
2  * Copyright (C) 2024-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 #ifndef OHOS_MEDIA_PHOTO_ALBUM_LPATH_OPERATION_H
17 #define OHOS_MEDIA_PHOTO_ALBUM_LPATH_OPERATION_H
18 
19 #include <string>
20 #include <vector>
21 
22 #include "medialibrary_rdbstore.h"
23 #include "photo_album_info_po.h"
24 
25 namespace OHOS::Media {
26 class PhotoAlbumLPathOperation {
27 public:
28     static PhotoAlbumLPathOperation &GetInstance();
29     PhotoAlbumLPathOperation &SetRdbStore(const std::shared_ptr<MediaLibraryRdbStore> &rdbStorePtr);
30     PhotoAlbumLPathOperation &CleanInvalidPhotoAlbums();
31     PhotoAlbumLPathOperation &CleanDuplicatePhotoAlbums();
32     PhotoAlbumLPathOperation &CleanEmptylPathPhotoAlbums();
33     int32_t GetAlbumAffectedCount() const;
34     PhotoAlbumLPathOperation &Start();
35     void Stop();
36 
37 private:
38     std::string ToString(const std::vector<NativeRdb::ValueObject> &values);
39     std::vector<PhotoAlbumInfoPo> GetInvalidPhotoAlbums();
40     std::vector<PhotoAlbumInfoPo> GetDuplicatelPathAlbumInfoMain();
41     std::vector<PhotoAlbumInfoPo> GetDuplicatelPathAlbumInfoSub(const PhotoAlbumInfoPo &albumInfo);
42     int32_t MergePhotoAlbum(const PhotoAlbumInfoPo &mainAlbumInfo, const PhotoAlbumInfoPo &subAlbumInfo);
43     std::vector<PhotoAlbumInfoPo> GetEmptylPathAlbumInfo();
44     int32_t CleanDuplicatePhotoAlbum(const PhotoAlbumInfoPo &mainAlbumInfo);
45     int32_t CleanEmptylPathPhotoAlbum(const PhotoAlbumInfoPo &subAlbumInfo);
46     PhotoAlbumInfoPo GetLatestAlbumInfoBylPath(const std::string &lPath);
47     int32_t UpdateAlbumInfoFromAlbumPluginByAlbumId(const PhotoAlbumInfoPo &albumInfo);
48     int32_t UpdateAlbumLPathByAlbumId(const PhotoAlbumInfoPo &albumInfo);
49 
50 private:
51     std::shared_ptr<MediaLibraryRdbStore> rdbStorePtr_;
52     int32_t albumAffectedCount_;
53     std::atomic<bool> isContinue_{true};
54     static std::shared_ptr<PhotoAlbumLPathOperation> instance_;
55     static std::mutex objMutex_;
56 
57 private:
58     const std::string SQL_PHOTO_ALBUM_EMPTY_QUERY = "\
59         SELECT \
60             album_id, \
61             album_name, \
62             album_type, \
63             album_subtype, \
64             lpath, \
65             bundle_name, \
66             dirty, \
67             count, \
68             cloud_id, \
69             priority \
70         FROM PhotoAlbum \
71         WHERE COALESCE(lpath, '') = '' AND \
72             album_type = 2048 AND \
73             COALESCE(PhotoAlbum.dirty, 1) <> 4 AND \
74             album_id NOT IN ( \
75                 SELECT DISTINCT owner_album_id \
76                 FROM Photos \
77             ) AND \
78             album_id NOT IN ( \
79                 SELECT DISTINCT map_album \
80                 FROM PhotoMap \
81                     INNER JOIN Photos \
82                     ON PhotoMap.map_asset = Photos.file_id \
83             );";
84     const std::string SQL_PHOTO_ALBUM_EMPTY_DELETE = "\
85         DELETE FROM PhotoAlbum \
86         WHERE COALESCE(lpath, '') = '' AND \
87             album_type = 2048 AND \
88             COALESCE(PhotoAlbum.dirty, 1) <> 4 AND \
89             album_id NOT IN ( \
90                 SELECT DISTINCT owner_album_id \
91                 FROM Photos \
92             ) AND \
93             album_id NOT IN ( \
94                 SELECT DISTINCT map_album \
95                 FROM PhotoMap \
96                     INNER JOIN Photos \
97                     ON PhotoMap.map_asset = Photos.file_id \
98             ) ;";
99     const std::string SQL_PHOTO_ALBUM_DUPLICATE_LPATH_MAIN_QUERY = "\
100         SELECT \
101             album_id, \
102             album_name, \
103             album_type, \
104             album_subtype, \
105             lpath, \
106             bundle_name, \
107             dirty, \
108             count, \
109             cloud_id, \
110             priority \
111         FROM PhotoAlbum \
112         WHERE album_id IN \
113         ( \
114             SELECT \
115                 MAX(album_id) AS album_id \
116             FROM PhotoAlbum \
117             WHERE album_type IN (0, 2048) AND \
118                 COALESCE(lpath, '') <> '' \
119             GROUP BY LOWER(lpath) \
120             HAVING COUNT(1) > 1 \
121         ) \
122         ORDER BY album_id;";
123     const std::string SQL_PHOTO_ALBUM_DUPLICATE_LPATH_SUB_QUERY = "\
124         SELECT \
125             PhotoAlbum.album_id, \
126             album_name, \
127             album_type, \
128             album_subtype, \
129             PhotoAlbum.lpath, \
130             bundle_name, \
131             dirty, \
132             count, \
133             cloud_id, \
134             priority \
135         FROM PhotoAlbum \
136             LEFT JOIN \
137             ( \
138                 SELECT \
139                     ? AS album_id, \
140                     ? AS lpath \
141             ) AS INPUT \
142             ON 1 = 1 \
143         WHERE album_type IN (0, 2048) AND \
144             LOWER(COALESCE(PhotoAlbum.lpath, '')) = LOWER(INPUT.lpath) AND \
145             PhotoAlbum.album_id <> INPUT.album_id \
146         ORDER BY PhotoAlbum.album_id;";
147     const std::string SQL_PHOTO_ALBUM_FIX_LPATH_QUERY = "\
148         SELECT \
149             album_id, \
150             album_name, \
151             album_type, \
152             album_subtype, \
153             lpath, \
154             bundle_name, \
155             dirty, \
156             count, \
157             cloud_id, \
158             priority \
159         FROM \
160         ( \
161             SELECT \
162                 album_id, \
163                 EMPTY.album_name, \
164                 album_type, \
165                 album_subtype, \
166                 CASE WHEN COALESCE(BUNDLE.bundle_name, '') <> '' THEN BUNDLE.lpath \
167                     WHEN COALESCE(cloud_id, '') <> '' THEN '' \
168                     WHEN COALESCE(NAME.album_name, '') <> '' THEN NAME.lpath \
169                     ELSE '/Pictures/'||EMPTY.album_name \
170                 END AS lpath, \
171                 EMPTY.bundle_name, \
172                 dirty, \
173                 count, \
174                 cloud_id, \
175                 priority \
176             FROM \
177             ( \
178                 SELECT \
179                     album_id, \
180                     album_name, \
181                     album_type, \
182                     album_subtype, \
183                     lpath, \
184                     bundle_name, \
185                     dirty, \
186                     count, \
187                     cloud_id, \
188                     priority \
189                 FROM PhotoAlbum \
190                 WHERE COALESCE(lPath, '') = '' AND \
191                     album_type = 2048 \
192             ) AS EMPTY \
193             LEFT JOIN \
194             ( \
195                 SELECT DISTINCT \
196                     bundle_name, \
197                     lpath \
198                 FROM album_plugin \
199                 WHERE COALESCE(bundle_name, '') <> '' AND \
200                     COALESCE(priority, 1) = 1 \
201             ) AS BUNDLE \
202             ON COALESCE(EMPTY.bundle_name, '') = COALESCE(BUNDLE.bundle_name, '') \
203             LEFT JOIN \
204             ( \
205                 SELECT DISTINCT album_name, \
206                     album_name_en, \
207                     lpath \
208                 FROM album_plugin \
209                 WHERE COALESCE(album_name, '') <> '' AND \
210                     COALESCE(priority, 1) = 1 \
211             ) AS NAME \
212             ON COALESCE(EMPTY.album_name, '') = COALESCE(NAME.album_name, '') OR \
213                 COALESCE(EMPTY.album_name, '') = COALESCE(NAME.album_name_en, '') \
214         ) \
215         WHERE COALESCE(lpath, '') <> '' \
216         ORDER BY album_id; ";
217     const std::string SQL_PHOTO_ALBUM_SYNC_BUNDLE_NAME_UPDATE = "\
218         UPDATE PhotoAlbum \
219         SET \
220             album_name = COALESCE( \
221                                 ( \
222                                     SELECT album_name \
223                                     FROM album_plugin \
224                                     WHERE LOWER(lpath) = LOWER(?) \
225                                     LIMIT 1 \
226                                 ), album_name), \
227             bundle_name = COALESCE( \
228                                 ( \
229                                     SELECT bundle_name \
230                                     FROM album_plugin \
231                                     WHERE LOWER(lpath) = LOWER(?) \
232                                     LIMIT 1 \
233                                 ), bundle_name), \
234             priority = COALESCE( \
235                                 ( \
236                                     SELECT priority \
237                                     FROM album_plugin \
238                                     WHERE LOWER(lpath) = LOWER(?) \
239                                     LIMIT 1 \
240                                 ), priority) \
241         WHERE album_id = ? AND \
242             LOWER(lpath) = LOWER(?) AND \
243             LOWER(lpath) IN ( \
244                 SELECT DISTINCT LOWER(lpath) \
245                 FROM album_plugin \
246                 WHERE COALESCE(lpath,'') <> '' \
247             );";
248     const std::string SQL_PHOTO_ALBUM_QUERY_BY_LPATH = "\
249         SELECT \
250             album_id, \
251             album_name, \
252             album_type, \
253             album_subtype, \
254             lpath, \
255             bundle_name, \
256             dirty, \
257             count, \
258             cloud_id, \
259             priority \
260         FROM PhotoAlbum \
261         WHERE LOWER(COALESCE(lpath, '')) = LOWER(?) \
262         ORDER BY album_id DESC \
263         LIMIT 1;";
264     const std::string SQL_PHOTO_ALBUM_UPDATE_LPATH_BY_ALBUM_ID = "\
265         UPDATE PhotoAlbum \
266         SET lpath = ? \
267         WHERE album_id = ? AND \
268             album_type = 2048 AND \
269             COALESCE(lpath, '') = '' AND \
270             LOWER(?) NOT IN ( \
271                 SELECT DISTINCT LOWER(PA.lpath) \
272                 FROM PhotoAlbum AS PA \
273                 WHERE COALESCE(PA.lpath, '') <> '' \
274             );";
275 };
276 }  // namespace OHOS::Media
277 #endif  // OHOS_MEDIA_PHOTO_ALBUM_LPATH_OPERATION_H