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 30 private: 31 int32_t UpgradeAlbumPlugin(NativeRdb::RdbStore &store); 32 int32_t UpgradePhotoAlbum(NativeRdb::RdbStore &store); 33 int32_t UpgradePhotos(NativeRdb::RdbStore &store); 34 int32_t UpgradePhotoMap(NativeRdb::RdbStore &store); 35 int32_t MergeAlbumFromOldBundleNameToNewBundleName(NativeRdb::RdbStore &store); 36 int32_t UpgradePhotosBelongsToAlbum(NativeRdb::RdbStore &store); 37 38 private: 39 int32_t AddOwnerAlbumIdColumn(NativeRdb::RdbStore &store); 40 int32_t AddlPathColumn(NativeRdb::RdbStore &store); 41 int32_t MoveSingleRelationshipToPhotos(NativeRdb::RdbStore &store); 42 int32_t UpdatelPathColumn(NativeRdb::RdbStore &store); 43 int32_t ExecSqlWithRetry(std::function<int32_t()> execSql); 44 45 private: 46 DbUpgradeUtils dbUpgradeUtils_; 47 48 private: 49 const std::string SQL_PHOTO_ALBUM_TABLE_ADD_LPATH_COLUMN = "ALTER TABLE PhotoAlbum ADD COLUMN lpath TEXT;"; 50 const std::string SQL_PHOTO_ALBUM_TABLE_UPDATE_LPATH_COLUMN = "\ 51 UPDATE PhotoAlbum \ 52 SET lpath = \ 53 ( \ 54 SELECT \ 55 CASE \ 56 WHEN COALESCE(album_plugin.lpath, '') <> '' THEN album_plugin.lpath \ 57 WHEN COALESCE(plugin_v2.lpath, '') <> '' THEN plugin_v2.lpath \ 58 WHEN album_type = 2048 THEN '/Pictures/'||PA.album_name \ 59 WHEN album_type = 0 THEN '/Pictures/Users/'||PA.album_name \ 60 ELSE '/Pictures/其它' \ 61 END AS s_lpath \ 62 FROM PhotoAlbum AS PA \ 63 LEFT JOIN album_plugin \ 64 ON COALESCE(PA.bundle_name, '') <> '' AND PA.bundle_name = album_plugin.bundle_name \ 65 LEFT JOIN album_plugin AS plugin_v2 \ 66 ON PA.album_type = 2048 AND PA.album_name = plugin_v2.album_name \ 67 WHERE PhotoAlbum.album_id = PA.album_id \ 68 ORDER BY \ 69 ( \ 70 CASE \ 71 WHEN COALESCE(album_plugin.lpath, '') <> '' THEN album_plugin.priority \ 72 WHEN COALESCE(plugin_v2.lpath, '') <> '' THEN plugin_v2.priority \ 73 ELSE 1 \ 74 END \ 75 ) DESC, s_lpath ASC \ 76 LIMIT 1 \ 77 ) \ 78 WHERE COALESCE(PhotoAlbum.album_name, '') <> '' AND \ 79 PhotoAlbum.album_subtype != 1024 AND \ 80 COALESCE(PhotoAlbum.lpath, '') = '';"; 81 const std::string SQL_PHOTOS_TABLE_ADD_OWNER_ALBUM_ID = "\ 82 ALTER TABLE Photos ADD COLUMN owner_album_id INT DEFAULT 0;"; 83 const std::string SQL_TEMP_PHOTO_MAP_TABLE_DROP = "DROP TABLE IF EXISTS temp_photo_map;"; 84 // 使用 group 分组查找 Photos 的一条关联关系 85 const std::string SQL_TEMP_PHOTO_MAP_TABLE_CREATE = "\ 86 CREATE TABLE IF NOT EXISTS temp_photo_map \ 87 AS \ 88 SELECT MIN(map_album) AS map_album, \ 89 map_asset \ 90 FROM PhotoMap \ 91 INNER JOIN Photos \ 92 ON PhotoMap.map_asset=Photos.file_id \ 93 WHERE position IN (1, 3) AND \ 94 COALESCE(owner_album_id, 0) = 0 \ 95 GROUP BY map_asset;"; 96 const std::vector<std::string> SQL_TEMP_PHOTO_MAP_TABLE_CREATE_INDEX_ARRAY = { 97 "CREATE INDEX IF NOT EXISTS unique_index_temp_photo_map_map_asset ON temp_photo_map ( \ 98 map_asset \ 99 );", 100 "CREATE UNIQUE INDEX IF NOT EXISTS unique_index_temp_photo_map_all ON temp_photo_map ( \ 101 map_album, map_asset \ 102 );"}; 103 // owner_album_id 默认值是 0,使用 UNION 避免无查询结果时,被更新为 NULL 104 const std::string SQL_PHOTOS_TABLE_UPDATE_ALBUM_ID = "\ 105 UPDATE Photos SET owner_album_id = \ 106 ( \ 107 SELECT map_album \ 108 FROM temp_photo_map \ 109 WHERE file_id=map_asset \ 110 UNION \ 111 SELECT 0 AS map_album \ 112 ORDER BY map_album DESC \ 113 LIMIT 1 \ 114 ) \ 115 WHERE COALESCE(owner_album_id, 0)=0;"; 116 const std::string SQL_PHOTO_MAP_TABLE_DELETE_SINGLE_RELATIONSHIP = "\ 117 DELETE FROM PhotoMap \ 118 WHERE EXISTS \ 119 ( \ 120 SELECT 1 \ 121 FROM temp_photo_map \ 122 WHERE PhotoMap.map_album=temp_photo_map.map_album AND \ 123 PhotoMap.map_asset=temp_photo_map.map_asset \ 124 );"; 125 /* Clear the cache table. */ 126 const std::string SQL_TEMP_ALBUM_BUNDLE_NAME_DELETE = "\ 127 DROP TABLE IF EXISTS temp_album_bundle_name;"; 128 /* Cache the mapping of old to new bundle names */ 129 const std::string SQL_TEMP_ALBUM_BUNDLE_NAME_CREATE = "\ 130 CREATE TABLE IF NOT EXISTS temp_album_bundle_name \ 131 AS \ 132 SELECT \ 133 'com.huawei.ohos.screenrecorder' AS bundle_name_old, \ 134 'com.huawei.hmos.screenrecorder' AS bundle_name_new \ 135 UNION \ 136 SELECT \ 137 'com.huawei.ohos.screenshot' AS bundle_name_old, \ 138 'com.huawei.hmos.screenshot' AS bundle_name_new \ 139 ;"; 140 /* Create the Album if it doesn't exist */ 141 const std::string SQL_PHOTO_ALBUM_INSERT_NEW_ALBUM = "\ 142 INSERT INTO PhotoAlbum( \ 143 album_type, \ 144 album_subtype, \ 145 album_name, \ 146 bundle_name, \ 147 lpath, \ 148 date_modified, \ 149 date_added \ 150 ) \ 151 SELECT \ 152 PA1.album_type, \ 153 PA1.album_subtype, \ 154 PA1.album_name, \ 155 M.bundle_name_new AS bundle_name, \ 156 CASE \ 157 WHEN COALESCE(album_plugin.lpath,'') <> '' THEN album_plugin.lpath \ 158 ELSE '/Pictures/'||PA1.album_name \ 159 END AS lpath, \ 160 strftime('%s000', 'now') AS date_modified, \ 161 strftime('%s000', 'now') AS date_added \ 162 FROM PhotoAlbum AS PA1 \ 163 INNER JOIN temp_album_bundle_name AS M \ 164 ON PA1.bundle_name=M.bundle_name_old \ 165 LEFT JOIN PhotoAlbum AS PA2 \ 166 ON M.bundle_name_new=PA2.bundle_name \ 167 LEFT JOIN album_plugin \ 168 ON M.bundle_name_new=album_plugin.bundle_name \ 169 WHERE PA2.bundle_name IS NULL;"; 170 /* Add the relationship in PhotoMap for new Album and Photo */ 171 const std::string SQL_PHOTO_MAP_INSERT_NEW_ALBUM = "\ 172 INSERT INTO PhotoMap( \ 173 map_album, \ 174 map_asset \ 175 ) \ 176 SELECT \ 177 PA2.album_id AS album_id_new, \ 178 PM.map_asset \ 179 FROM PhotoAlbum AS PA1 \ 180 INNER JOIN temp_album_bundle_name AS M \ 181 ON PA1.bundle_name=M.bundle_name_old \ 182 INNER JOIN PhotoAlbum AS PA2 \ 183 ON M.bundle_name_new=PA2.bundle_name \ 184 INNER JOIN PhotoMap AS PM \ 185 ON PA1.album_id=PM.map_album \ 186 EXCEPT \ 187 SELECT PA.album_id, \ 188 PM.map_asset \ 189 FROM PhotoAlbum AS PA \ 190 INNER JOIN temp_album_bundle_name AS M \ 191 ON PA.bundle_name=M.bundle_name_new \ 192 INNER JOIN PhotoMap AS PM \ 193 ON PA.album_id=PM.map_album \ 194 ; "; 195 /* Remove the relationship in PhotoMap for old Album and Photo */ 196 const std::string SQL_PHOTO_MAP_DELETE_OLD_ALBUM = "\ 197 DELETE FROM PhotoMap \ 198 WHERE map_album IN \ 199 ( \ 200 SELECT \ 201 PA1.album_id \ 202 FROM PhotoAlbum AS PA1 \ 203 INNER JOIN temp_album_bundle_name AS M \ 204 ON PA1.bundle_name=M.bundle_name_old \ 205 );"; 206 /* Replace the relationship in Photos for new Album and Photo */ 207 const std::string SQL_PHOTOS_UPDATE_NEW_ALBUM = "\ 208 UPDATE Photos \ 209 SET owner_album_id=( \ 210 SELECT PA2.album_id \ 211 FROM PhotoAlbum AS PA1 \ 212 INNER JOIN temp_album_bundle_name AS M \ 213 ON PA1.bundle_name=M.bundle_name_old \ 214 INNER JOIN PhotoAlbum AS PA2 \ 215 ON M.bundle_name_new=PA2.bundle_name \ 216 WHERE Photos.owner_album_id=PA1.album_id \ 217 ) \ 218 WHERE owner_album_id IN \ 219 ( \ 220 SELECT \ 221 PA1.album_id \ 222 FROM PhotoAlbum AS PA1 \ 223 INNER JOIN temp_album_bundle_name AS M \ 224 ON PA1.bundle_name=M.bundle_name_old \ 225 ); "; 226 /* Remove the relationship in Photos for old Album and Photo */ 227 const std::string SQL_PHOTO_ALBUM_DELETE_OLD_ALBUM = "\ 228 DELETE FROM PhotoAlbum \ 229 WHERE album_id IN \ 230 ( \ 231 SELECT \ 232 PA.album_id \ 233 FROM PhotoAlbum AS PA \ 234 INNER JOIN temp_album_bundle_name AS M \ 235 ON PA.bundle_name=M.bundle_name_old \ 236 ); "; 237 const std::vector<std::string> SQL_MERGE_ALBUM_FROM_OLD_BUNDLE_NAME_TO_NEW_BUNDLE_NAME = { 238 SQL_TEMP_ALBUM_BUNDLE_NAME_DELETE, 239 SQL_TEMP_ALBUM_BUNDLE_NAME_CREATE, 240 SQL_PHOTO_ALBUM_INSERT_NEW_ALBUM, 241 SQL_PHOTO_MAP_INSERT_NEW_ALBUM, 242 SQL_PHOTO_MAP_DELETE_OLD_ALBUM, 243 SQL_PHOTOS_UPDATE_NEW_ALBUM, 244 SQL_PHOTO_ALBUM_DELETE_OLD_ALBUM, 245 SQL_TEMP_ALBUM_BUNDLE_NAME_DELETE, 246 }; 247 /* Create the Album if it doesn't exist */ 248 const std::string SQL_PHOTO_ALBUM_INSERT_OTHER_ALBUM = "\ 249 INSERT INTO PhotoAlbum( \ 250 album_type, \ 251 album_subtype, \ 252 album_name, \ 253 bundle_name, \ 254 lpath \ 255 ) \ 256 SELECT \ 257 2048 AS album_type, \ 258 2049 AS album_subtype, \ 259 '其它' AS album_name, \ 260 'com.other.album' AS bundle_name, \ 261 '/Pictures/其它' AS lpath \ 262 EXCEPT \ 263 SELECT \ 264 album_type, \ 265 album_subtype, \ 266 album_name, \ 267 bundle_name, \ 268 lpath \ 269 FROM PhotoAlbum ;"; 270 /* The Photo, doesn't belong to any album, should belongs to '其它' album */ 271 const std::string SQL_PHOTOS_UPDATE_OTHER_ALBUM = "\ 272 UPDATE Photos \ 273 SET owner_album_id=( \ 274 SELECT album_id \ 275 FROM PhotoAlbum \ 276 WHERE lpath='/Pictures/其它' \ 277 LIMIT 1 \ 278 ) \ 279 WHERE file_id IN \ 280 ( \ 281 SELECT file_id \ 282 FROM Photos \ 283 LEFT JOIN PhotoMap \ 284 ON Photos.file_id = PhotoMap.map_asset \ 285 WHERE PhotoMap.map_asset IS NULL AND \ 286 COALESCE(Photos.owner_album_id, 0) = 0 AND \ 287 Photos.position IN (1, 3) \ 288 );"; 289 const std::vector<std::string> SQL_PHOTOS_NEED_TO_BELONGS_TO_ALBUM = { 290 SQL_PHOTO_ALBUM_INSERT_OTHER_ALBUM, 291 SQL_PHOTOS_UPDATE_OTHER_ALBUM, 292 }; 293 }; 294 } // namespace DataTransfer 295 } // namespace OHOS::Media 296 #endif // OHOS_MEDIA_DATATRANSFER_MEDIA_LIBRARY_DB_UPGRADE_H