• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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_DATATRANSFER_MEDIA_LIBRARY_DB_UPGRADE_H
17 #define OHOS_MEDIA_DATATRANSFER_MEDIA_LIBRARY_DB_UPGRADE_H
18 
19 #include <string>
20 
21 #include "rdb_store.h"
22 #include "db_upgrade_utils.h"
23 
24 namespace OHOS::Media {
25 namespace DataTransfer {
26 class MediaLibraryDbUpgrade {
27 public:
28     int32_t OnUpgrade(NativeRdb::RdbStore &store);
29     int32_t CreateClassifyAlbum(const std::string &newAlbumName, NativeRdb::RdbStore &store);
30     bool CheckClassifyAlbumExist(const std::string &newAlbumName, NativeRdb::RdbStore &store);
31 
32 private:
33     int32_t UpgradeAlbumPlugin(NativeRdb::RdbStore &store);
34     int32_t UpgradePhotoAlbum(NativeRdb::RdbStore &store);
35     int32_t UpgradePhotos(NativeRdb::RdbStore &store);
36     int32_t UpgradePhotoMap(NativeRdb::RdbStore &store);
37     int32_t MergeAlbumFromOldBundleNameToNewBundleName(NativeRdb::RdbStore &store);
38     int32_t UpgradePhotosBelongsToAlbum(NativeRdb::RdbStore &store);
39     void AggregateClassifyAlbum(NativeRdb::RdbStore &store);
40 
41 private:
42     int32_t AddOwnerAlbumIdColumn(NativeRdb::RdbStore &store);
43     int32_t AddlPathColumn(NativeRdb::RdbStore &store);
44     int32_t MoveSingleRelationshipToPhotos(NativeRdb::RdbStore &store);
45     int32_t UpdatelPathColumn(NativeRdb::RdbStore &store);
46     int32_t ExecSqlWithRetry(std::function<int32_t()> execSql);
47     void ProcessClassifyAlbum(const std::string &newAlbumName, const std::vector<std::string> &oriAlbumNames,
48         NativeRdb::RdbStore &store);
49     void ProcessOcrClassifyAlbum(const std::string &newAlbumName, const std::vector<std::string> &ocrText,
50         NativeRdb::RdbStore &store);
51 
52 private:
53     DbUpgradeUtils dbUpgradeUtils_;
54 
55 private:
56     const std::string SQL_PHOTO_ALBUM_TABLE_ADD_LPATH_COLUMN = "ALTER TABLE PhotoAlbum ADD COLUMN lpath TEXT;";
57     const std::string SQL_PHOTO_ALBUM_TABLE_UPDATE_LPATH_COLUMN = "\
58         UPDATE PhotoAlbum \
59         SET lpath = \
60         ( \
61             SELECT \
62                 CASE \
63                     WHEN COALESCE(album_plugin.lpath, '') <> '' THEN album_plugin.lpath \
64                     WHEN COALESCE(plugin_v2.lpath, '') <> '' THEN plugin_v2.lpath \
65                     WHEN album_type = 2048 THEN '/Pictures/'||PA.album_name \
66                     WHEN album_type = 0 THEN '/Pictures/Users/'||PA.album_name \
67                     ELSE '/Pictures/其它' \
68                 END AS s_lpath \
69             FROM PhotoAlbum AS PA \
70                 LEFT JOIN album_plugin \
71                 ON COALESCE(PA.bundle_name, '') <> '' AND PA.bundle_name = album_plugin.bundle_name \
72                 LEFT JOIN album_plugin AS plugin_v2 \
73                 ON PA.album_type = 2048 AND PA.album_name = plugin_v2.album_name \
74             WHERE PhotoAlbum.album_id = PA.album_id \
75             ORDER BY \
76                 ( \
77                 CASE \
78                     WHEN COALESCE(album_plugin.lpath, '') <> '' THEN album_plugin.priority \
79                     WHEN COALESCE(plugin_v2.lpath, '') <> '' THEN plugin_v2.priority \
80                     ELSE 1 \
81                 END \
82                 ) DESC, s_lpath ASC \
83             LIMIT 1 \
84         ) \
85         WHERE COALESCE(PhotoAlbum.album_name, '') <> '' AND \
86             PhotoAlbum.album_subtype != 1024 AND \
87             COALESCE(PhotoAlbum.lpath, '') = '';";
88     const std::string SQL_PHOTOS_TABLE_ADD_OWNER_ALBUM_ID = "\
89         ALTER TABLE Photos ADD COLUMN owner_album_id INT DEFAULT 0;";
90     const std::string SQL_TEMP_PHOTO_MAP_TABLE_DROP = "DROP TABLE IF EXISTS temp_photo_map;";
91     // 使用 group 分组查找 Photos 的一条关联关系
92     const std::string SQL_TEMP_PHOTO_MAP_TABLE_CREATE = "\
93         CREATE TABLE IF NOT EXISTS temp_photo_map \
94         AS \
95         SELECT MIN(map_album) AS map_album, \
96             map_asset \
97         FROM PhotoMap \
98             INNER JOIN Photos \
99             ON PhotoMap.map_asset=Photos.file_id \
100         WHERE position IN (1, 3) AND \
101             COALESCE(owner_album_id, 0) = 0 \
102         GROUP BY map_asset;";
103     const std::vector<std::string> SQL_TEMP_PHOTO_MAP_TABLE_CREATE_INDEX_ARRAY = {
104         "CREATE INDEX IF NOT EXISTS unique_index_temp_photo_map_map_asset ON temp_photo_map ( \
105             map_asset \
106         );",
107         "CREATE UNIQUE INDEX IF NOT EXISTS unique_index_temp_photo_map_all ON temp_photo_map ( \
108             map_album, map_asset \
109         );"};
110     // owner_album_id 默认值是 0,使用 UNION 避免无查询结果时,被更新为 NULL
111     const std::string SQL_PHOTOS_TABLE_UPDATE_ALBUM_ID = "\
112         UPDATE Photos SET owner_album_id = \
113         ( \
114             SELECT map_album \
115             FROM temp_photo_map \
116             WHERE file_id=map_asset \
117             UNION \
118             SELECT 0 AS map_album \
119             ORDER BY map_album DESC \
120             LIMIT 1 \
121         ) \
122         WHERE COALESCE(owner_album_id, 0)=0;";
123     const std::string SQL_PHOTO_MAP_TABLE_DELETE_SINGLE_RELATIONSHIP = "\
124         DELETE FROM PhotoMap \
125         WHERE EXISTS \
126         ( \
127             SELECT 1 \
128             FROM temp_photo_map \
129             WHERE PhotoMap.map_album=temp_photo_map.map_album AND \
130                 PhotoMap.map_asset=temp_photo_map.map_asset \
131         );";
132     /* Clear the cache table. */
133     const std::string SQL_TEMP_ALBUM_BUNDLE_NAME_DELETE = "\
134         DROP TABLE IF EXISTS temp_album_bundle_name;";
135 
136     /* Cache the mapping of old to new bundle names */
137     const std::string SQL_TEMP_ALBUM_BUNDLE_NAME_CREATE =
138         "CREATE TABLE IF NOT EXISTS temp_album_bundle_name ("
139         "bundle_name_old TEXT,"
140         "bundle_name_new TEXT"
141         ");";
142 
143     const std::string SQL_TEMP_ALBUM_BUNDLE_NAME_INSERT =
144         "INSERT INTO temp_album_bundle_name (bundle_name_old, bundle_name_new) VALUES "
145         "('com.huawei.ohos.screenrecorder', 'com.huawei.hmos.screenrecorder'),"
146         "('com.huawei.ohos.screenshot', 'com.huawei.hmos.screenshot');";
147 
148     /* Create the Album if it doesn't exist */
149     const std::string SQL_PHOTO_ALBUM_INSERT_NEW_ALBUM = "\
150         INSERT INTO PhotoAlbum( \
151             album_type, \
152             album_subtype, \
153             album_name, \
154             bundle_name, \
155             lpath, \
156             date_modified, \
157             date_added \
158         ) \
159         SELECT \
160             PA1.album_type, \
161             PA1.album_subtype, \
162             PA1.album_name, \
163             M.bundle_name_new AS bundle_name, \
164             CASE \
165                 WHEN COALESCE(album_plugin.lpath,'') <> '' THEN album_plugin.lpath \
166                 ELSE '/Pictures/'||PA1.album_name \
167             END AS lpath, \
168             strftime('%s000', 'now') AS date_modified, \
169             strftime('%s000', 'now') AS date_added \
170         FROM PhotoAlbum AS PA1 \
171             INNER JOIN temp_album_bundle_name AS M \
172             ON PA1.bundle_name=M.bundle_name_old \
173             LEFT JOIN PhotoAlbum AS PA2 \
174             ON M.bundle_name_new=PA2.bundle_name \
175             LEFT JOIN album_plugin \
176             ON M.bundle_name_new=album_plugin.bundle_name \
177         WHERE PA2.bundle_name IS NULL;";
178     /* Add the relationship in PhotoMap for new Album and Photo */
179     const std::string SQL_PHOTO_MAP_INSERT_NEW_ALBUM = "\
180         INSERT INTO PhotoMap( \
181             map_album, \
182             map_asset \
183         ) \
184         SELECT \
185             PA2.album_id AS album_id_new, \
186             PM.map_asset \
187         FROM PhotoAlbum AS PA1 \
188             INNER JOIN temp_album_bundle_name AS M \
189             ON PA1.bundle_name=M.bundle_name_old \
190             INNER JOIN PhotoAlbum AS PA2 \
191             ON M.bundle_name_new=PA2.bundle_name \
192             INNER JOIN PhotoMap AS PM \
193             ON PA1.album_id=PM.map_album \
194         EXCEPT \
195         SELECT PA.album_id, \
196             PM.map_asset \
197         FROM PhotoAlbum AS PA \
198             INNER JOIN temp_album_bundle_name AS M \
199             ON PA.bundle_name=M.bundle_name_new \
200             INNER JOIN PhotoMap AS PM \
201             ON PA.album_id=PM.map_album \
202         ; ";
203     /* Remove the relationship in PhotoMap for old Album and Photo */
204     const std::string SQL_PHOTO_MAP_DELETE_OLD_ALBUM = "\
205         DELETE FROM PhotoMap \
206         WHERE map_album IN \
207         ( \
208             SELECT \
209                 PA1.album_id \
210             FROM PhotoAlbum AS PA1 \
211                 INNER JOIN temp_album_bundle_name AS M \
212                 ON PA1.bundle_name=M.bundle_name_old \
213         );";
214     /* Replace the relationship in Photos for new Album and Photo */
215     const std::string SQL_PHOTOS_UPDATE_NEW_ALBUM = "\
216         UPDATE Photos \
217         SET owner_album_id=( \
218             SELECT PA2.album_id \
219             FROM PhotoAlbum AS PA1 \
220                 INNER JOIN temp_album_bundle_name AS M \
221                 ON PA1.bundle_name=M.bundle_name_old \
222                 INNER JOIN PhotoAlbum AS PA2 \
223                 ON M.bundle_name_new=PA2.bundle_name \
224             WHERE Photos.owner_album_id=PA1.album_id \
225         ) \
226         WHERE owner_album_id IN \
227         ( \
228             SELECT \
229                 PA1.album_id \
230             FROM PhotoAlbum AS PA1 \
231                 INNER JOIN temp_album_bundle_name AS M \
232                 ON PA1.bundle_name=M.bundle_name_old \
233         ); ";
234     /* Remove the relationship in Photos for old Album and Photo */
235     const std::string SQL_PHOTO_ALBUM_DELETE_OLD_ALBUM = "\
236         DELETE FROM PhotoAlbum \
237         WHERE album_id IN \
238         ( \
239             SELECT \
240                 PA.album_id \
241             FROM PhotoAlbum AS PA \
242                 INNER JOIN temp_album_bundle_name AS M \
243                 ON PA.bundle_name=M.bundle_name_old \
244         ); ";
245     const std::vector<std::string> SQL_MERGE_ALBUM_FROM_OLD_BUNDLE_NAME_TO_NEW_BUNDLE_NAME = {
246         SQL_TEMP_ALBUM_BUNDLE_NAME_DELETE,
247         SQL_TEMP_ALBUM_BUNDLE_NAME_CREATE,
248         SQL_TEMP_ALBUM_BUNDLE_NAME_INSERT,
249         SQL_PHOTO_ALBUM_INSERT_NEW_ALBUM,
250         SQL_PHOTO_MAP_INSERT_NEW_ALBUM,
251         SQL_PHOTO_MAP_DELETE_OLD_ALBUM,
252         SQL_PHOTOS_UPDATE_NEW_ALBUM,
253         SQL_PHOTO_ALBUM_DELETE_OLD_ALBUM,
254         SQL_TEMP_ALBUM_BUNDLE_NAME_DELETE,
255     };
256     /* Create the Album if it doesn't exist */
257     const std::string SQL_PHOTO_ALBUM_INSERT_OTHER_ALBUM = "\
258         INSERT INTO PhotoAlbum( \
259             album_type, \
260             album_subtype, \
261             album_name, \
262             bundle_name, \
263             lpath \
264             ) \
265         SELECT \
266             2048 AS album_type, \
267             2049 AS album_subtype, \
268             '其它' AS album_name, \
269             'com.other.album' AS bundle_name, \
270             '/Pictures/其它' AS lpath \
271         EXCEPT \
272         SELECT \
273             album_type, \
274             album_subtype, \
275             album_name, \
276             bundle_name, \
277             lpath \
278         FROM PhotoAlbum ;";
279     /* The Photo, doesn't belong to any album, should belongs to '其它' album */
280     const std::string SQL_PHOTOS_UPDATE_OTHER_ALBUM = "\
281         UPDATE Photos \
282         SET owner_album_id=( \
283             SELECT album_id \
284             FROM PhotoAlbum \
285             WHERE lpath='/Pictures/其它' \
286             LIMIT 1 \
287         ) \
288         WHERE file_id IN \
289         ( \
290             SELECT file_id \
291             FROM Photos \
292                 LEFT JOIN PhotoMap \
293                 ON Photos.file_id = PhotoMap.map_asset \
294             WHERE PhotoMap.map_asset IS NULL AND \
295                 COALESCE(Photos.owner_album_id, 0) = 0 AND \
296                 Photos.position IN (1, 3) \
297         );";
298     const std::vector<std::string> SQL_PHOTOS_NEED_TO_BELONGS_TO_ALBUM = {
299         SQL_PHOTO_ALBUM_INSERT_OTHER_ALBUM,
300         SQL_PHOTOS_UPDATE_OTHER_ALBUM,
301     };
302     const std::string SQL_QUERY_CLASSIFY_ALBUM_EXIST = " \
303         SELECT \
304             count(1) AS count \
305         FROM AnalysisAlbum \
306         WHERE \
307             album_type = ? \
308         AND \
309             album_subtype = ? \
310         AND \
311             album_name = ?;";
312     const std::string SQL_CREATE_CLASSIFY_ALBUM = " \
313         INSERT INTO AnalysisAlbum( \
314             album_type, \
315             album_subtype, \
316             album_name, \
317             is_local, \
318             date_modified, \
319             count \
320             ) \
321         VALUES( \
322             ?, \
323             ?, \
324             ?, \
325             1, \
326             0, \
327             0 \
328         );";
329     const std::string SQL_INSERT_MAPPING_RESULT = " \
330         INSERT INTO AnalysisPhotoMap( \
331             map_album, \
332             map_asset \
333             ) \
334         SELECT DISTINCT ( \
335             SELECT \
336                 album_id \
337             FROM AnalysisAlbum \
338             WHERE album_name = ? \
339             ) AS album_id, \
340             AnalysisPhotoMap.map_asset \
341         FROM AnalysisAlbum \
342         INNER JOIN AnalysisPhotoMap \
343             ON AnalysisAlbum.album_id = AnalysisPhotoMap.map_album \
344             AND AnalysisAlbum.album_type = ? \
345             AND AnalysisAlbum.album_subtype = ? \
346             AND AnalysisAlbum.album_name IN ";
347     const std::string SQL_SELECT_CLASSIFY_OCR = " \
348         WITH TempResult AS ( \
349             SELECT DISTINCT ( \
350                 SELECT \
351                     album_id \
352                 FROM AnalysisAlbum \
353                 WHERE album_name = ? \
354                 ) AS album_id, \
355                 AnalysisPhotoMap.map_asset as map_asset \
356             FROM AnalysisAlbum \
357             INNER JOIN AnalysisPhotoMap \
358             ON AnalysisAlbum.album_id = AnalysisPhotoMap.map_album \
359             AND AnalysisAlbum.album_type = ? \
360             AND AnalysisAlbum.album_subtype = ? \
361             AND AnalysisAlbum.album_name = ? \
362             INNER JOIN tab_analysis_ocr \
363             ON AnalysisPhotoMap.map_asset = tab_analysis_ocr.file_id \
364             AND (";
365 };
366 }  // namespace DataTransfer
367 }  // namespace OHOS::Media
368 #endif  // OHOS_MEDIA_DATATRANSFER_MEDIA_LIBRARY_DB_UPGRADE_H