diff --git a/app/src/main/java/org/schabi/newpipe/database/Migrations.kt b/app/src/main/java/org/schabi/newpipe/database/Migrations.kt index 8988708e679..6566f7e6a26 100644 --- a/app/src/main/java/org/schabi/newpipe/database/Migrations.kt +++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.kt @@ -34,335 +34,319 @@ object Migrations { private val TAG = Migrations::class.java.getName() private val isDebug = MainActivity.DEBUG - val MIGRATION_1_2 = object : Migration(DB_VER_1, DB_VER_2) { - override fun migrate(db: SupportSQLiteDatabase) { - if (isDebug) { - Log.d(TAG, "Start migrating database") - } - - /* - * Unfortunately these queries must be hardcoded due to the possibility of - * schema and names changing at a later date, thus invalidating the older migration - * scripts if they are not hardcoded. - * */ - - // Not much we can do about this, since room doesn't create tables before migration. - // It's either this or blasting the entire database anew. - db.execSQL( - "CREATE INDEX `index_search_history_search` " + - "ON `search_history` (`search`)" - ) - db.execSQL( - "CREATE TABLE IF NOT EXISTS `streams` " + - "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + - "`service_id` INTEGER NOT NULL, `url` TEXT, `title` TEXT, " + - "`stream_type` TEXT, `duration` INTEGER, `uploader` TEXT, " + - "`thumbnail_url` TEXT)" - ) - db.execSQL( - "CREATE UNIQUE INDEX `index_streams_service_id_url` " + - "ON `streams` (`service_id`, `url`)" - ) - db.execSQL( - "CREATE TABLE IF NOT EXISTS `stream_history` " + - "(`stream_id` INTEGER NOT NULL, `access_date` INTEGER NOT NULL, " + - "`repeat_count` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `access_date`), " + - "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " + - "ON UPDATE CASCADE ON DELETE CASCADE )" - ) - db.execSQL( - "CREATE INDEX `index_stream_history_stream_id` " + - "ON `stream_history` (`stream_id`)" - ) - db.execSQL( - "CREATE TABLE IF NOT EXISTS `stream_state` " + - "(`stream_id` INTEGER NOT NULL, `progress_time` INTEGER NOT NULL, " + - "PRIMARY KEY(`stream_id`), FOREIGN KEY(`stream_id`) " + - "REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )" - ) - db.execSQL( - "CREATE TABLE IF NOT EXISTS `playlists` " + - "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + - "`name` TEXT, `thumbnail_url` TEXT)" - ) - db.execSQL("CREATE INDEX `index_playlists_name` ON `playlists` (`name`)") - db.execSQL( - "CREATE TABLE IF NOT EXISTS `playlist_stream_join` " + - "(`playlist_id` INTEGER NOT NULL, `stream_id` INTEGER NOT NULL, " + - "`join_index` INTEGER NOT NULL, PRIMARY KEY(`playlist_id`, `join_index`), " + - "FOREIGN KEY(`playlist_id`) REFERENCES `playlists`(`uid`) " + - "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + - "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " + - "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" - ) - db.execSQL( - "CREATE UNIQUE INDEX " + - "`index_playlist_stream_join_playlist_id_join_index` " + - "ON `playlist_stream_join` (`playlist_id`, `join_index`)" - ) - db.execSQL( - "CREATE INDEX `index_playlist_stream_join_stream_id` " + - "ON `playlist_stream_join` (`stream_id`)" - ) - db.execSQL( - "CREATE TABLE IF NOT EXISTS `remote_playlists` " + - "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + - "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " + - "`thumbnail_url` TEXT, `uploader` TEXT, `stream_count` INTEGER)" - ) - db.execSQL( - "CREATE INDEX `index_remote_playlists_name` " + - "ON `remote_playlists` (`name`)" - ) - db.execSQL( - "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " + - "ON `remote_playlists` (`service_id`, `url`)" - ) - - // Populate streams table with existing entries in watch history - // Latest data first, thus ignoring older entries with the same indices - db.execSQL( - "INSERT OR IGNORE INTO streams (service_id, url, title, " + - "stream_type, duration, uploader, thumbnail_url) " + - - "SELECT service_id, url, title, 'VIDEO_STREAM', duration, " + - "uploader, thumbnail_url " + - - "FROM watch_history " + - "ORDER BY creation_date DESC" - ) - - // Once the streams have PKs, join them with the normalized history table - // and populate it with the remaining data from watch history - db.execSQL( - "INSERT INTO stream_history (stream_id, access_date, repeat_count)" + - "SELECT uid, creation_date, 1 " + - "FROM watch_history INNER JOIN streams " + - "ON watch_history.service_id == streams.service_id " + - "AND watch_history.url == streams.url " + - "ORDER BY creation_date DESC" - ) - - db.execSQL("DROP TABLE IF EXISTS watch_history") + val MIGRATION_1_2 = Migration(DB_VER_1, DB_VER_2) { db -> + if (isDebug) { + Log.d(TAG, "Start migrating database") + } - if (isDebug) { - Log.d(TAG, "Stop migrating database") - } + /* + * Unfortunately these queries must be hardcoded due to the possibility of + * schema and names changing at a later date, thus invalidating the older migration + * scripts if they are not hardcoded. + * */ + + // Not much we can do about this, since room doesn't create tables before migration. + // It's either this or blasting the entire database anew. + db.execSQL( + "CREATE INDEX `index_search_history_search` " + + "ON `search_history` (`search`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `streams` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`service_id` INTEGER NOT NULL, `url` TEXT, `title` TEXT, " + + "`stream_type` TEXT, `duration` INTEGER, `uploader` TEXT, " + + "`thumbnail_url` TEXT)" + ) + db.execSQL( + "CREATE UNIQUE INDEX `index_streams_service_id_url` " + + "ON `streams` (`service_id`, `url`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `stream_history` " + + "(`stream_id` INTEGER NOT NULL, `access_date` INTEGER NOT NULL, " + + "`repeat_count` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `access_date`), " + + "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " + + "ON UPDATE CASCADE ON DELETE CASCADE )" + ) + db.execSQL( + "CREATE INDEX `index_stream_history_stream_id` " + + "ON `stream_history` (`stream_id`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `stream_state` " + + "(`stream_id` INTEGER NOT NULL, `progress_time` INTEGER NOT NULL, " + + "PRIMARY KEY(`stream_id`), FOREIGN KEY(`stream_id`) " + + "REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `playlists` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`name` TEXT, `thumbnail_url` TEXT)" + ) + db.execSQL("CREATE INDEX `index_playlists_name` ON `playlists` (`name`)") + db.execSQL( + "CREATE TABLE IF NOT EXISTS `playlist_stream_join` " + + "(`playlist_id` INTEGER NOT NULL, `stream_id` INTEGER NOT NULL, " + + "`join_index` INTEGER NOT NULL, PRIMARY KEY(`playlist_id`, `join_index`), " + + "FOREIGN KEY(`playlist_id`) REFERENCES `playlists`(`uid`) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + + "FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + db.execSQL( + "CREATE UNIQUE INDEX " + + "`index_playlist_stream_join_playlist_id_join_index` " + + "ON `playlist_stream_join` (`playlist_id`, `join_index`)" + ) + db.execSQL( + "CREATE INDEX `index_playlist_stream_join_stream_id` " + + "ON `playlist_stream_join` (`stream_id`)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS `remote_playlists` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " + + "`thumbnail_url` TEXT, `uploader` TEXT, `stream_count` INTEGER)" + ) + db.execSQL( + "CREATE INDEX `index_remote_playlists_name` " + + "ON `remote_playlists` (`name`)" + ) + db.execSQL( + "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " + + "ON `remote_playlists` (`service_id`, `url`)" + ) + + // Populate streams table with existing entries in watch history + // Latest data first, thus ignoring older entries with the same indices + db.execSQL( + "INSERT OR IGNORE INTO streams (service_id, url, title, " + + "stream_type, duration, uploader, thumbnail_url) " + + + "SELECT service_id, url, title, 'VIDEO_STREAM', duration, " + + "uploader, thumbnail_url " + + + "FROM watch_history " + + "ORDER BY creation_date DESC" + ) + + // Once the streams have PKs, join them with the normalized history table + // and populate it with the remaining data from watch history + db.execSQL( + "INSERT INTO stream_history (stream_id, access_date, repeat_count)" + + "SELECT uid, creation_date, 1 " + + "FROM watch_history INNER JOIN streams " + + "ON watch_history.service_id == streams.service_id " + + "AND watch_history.url == streams.url " + + "ORDER BY creation_date DESC" + ) + + db.execSQL("DROP TABLE IF EXISTS watch_history") + + if (isDebug) { + Log.d(TAG, "Stop migrating database") } } - val MIGRATION_2_3 = object : Migration(DB_VER_2, DB_VER_3) { - override fun migrate(db: SupportSQLiteDatabase) { - // Add NOT NULLs and new fields - db.execSQL( - "CREATE TABLE IF NOT EXISTS streams_new " + - "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + - "service_id INTEGER NOT NULL, url TEXT NOT NULL, title TEXT NOT NULL, " + - "stream_type TEXT NOT NULL, duration INTEGER NOT NULL, " + - "uploader TEXT NOT NULL, thumbnail_url TEXT, view_count INTEGER, " + - "textual_upload_date TEXT, upload_date INTEGER, " + - "is_upload_date_approximation INTEGER)" - ) - - db.execSQL( - "INSERT INTO streams_new (uid, service_id, url, title, stream_type, " + - "duration, uploader, thumbnail_url, view_count, textual_upload_date, " + - "upload_date, is_upload_date_approximation) " + - - "SELECT uid, service_id, url, ifnull(title, ''), " + - "ifnull(stream_type, 'VIDEO_STREAM'), ifnull(duration, 0), " + - "ifnull(uploader, ''), ifnull(thumbnail_url, ''), NULL, NULL, NULL, NULL " + - - "FROM streams WHERE url IS NOT NULL" - ) + val MIGRATION_2_3 = Migration(DB_VER_2, DB_VER_3) { db -> + // Add NOT NULLs and new fields + db.execSQL( + "CREATE TABLE IF NOT EXISTS streams_new " + + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "service_id INTEGER NOT NULL, url TEXT NOT NULL, title TEXT NOT NULL, " + + "stream_type TEXT NOT NULL, duration INTEGER NOT NULL, " + + "uploader TEXT NOT NULL, thumbnail_url TEXT, view_count INTEGER, " + + "textual_upload_date TEXT, upload_date INTEGER, " + + "is_upload_date_approximation INTEGER)" + ) + + db.execSQL( + "INSERT INTO streams_new (uid, service_id, url, title, stream_type, " + + "duration, uploader, thumbnail_url, view_count, textual_upload_date, " + + "upload_date, is_upload_date_approximation) " + + + "SELECT uid, service_id, url, ifnull(title, ''), " + + "ifnull(stream_type, 'VIDEO_STREAM'), ifnull(duration, 0), " + + "ifnull(uploader, ''), ifnull(thumbnail_url, ''), NULL, NULL, NULL, NULL " + + + "FROM streams WHERE url IS NOT NULL" + ) + + db.execSQL("DROP TABLE streams") + db.execSQL("ALTER TABLE streams_new RENAME TO streams") + db.execSQL( + "CREATE UNIQUE INDEX index_streams_service_id_url " + + "ON streams (service_id, url)" + ) + + // Tables for feed feature + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed " + + "(stream_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " + + "PRIMARY KEY(stream_id, subscription_id), " + + "FOREIGN KEY(stream_id) REFERENCES streams(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + db.execSQL("CREATE INDEX index_feed_subscription_id ON feed (subscription_id)") + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed_group " + + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, " + + "icon_id INTEGER NOT NULL, sort_order INTEGER NOT NULL)" + ) + db.execSQL("CREATE INDEX index_feed_group_sort_order ON feed_group (sort_order)") + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed_group_subscription_join " + + "(group_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " + + "PRIMARY KEY(group_id, subscription_id), " + + "FOREIGN KEY(group_id) REFERENCES feed_group(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + db.execSQL( + "CREATE INDEX index_feed_group_subscription_join_subscription_id " + + "ON feed_group_subscription_join (subscription_id)" + ) + db.execSQL( + "CREATE TABLE IF NOT EXISTS feed_last_updated " + + "(subscription_id INTEGER NOT NULL, last_updated INTEGER, " + + "PRIMARY KEY(subscription_id), " + + "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + + "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" + ) + } - db.execSQL("DROP TABLE streams") - db.execSQL("ALTER TABLE streams_new RENAME TO streams") - db.execSQL( - "CREATE UNIQUE INDEX index_streams_service_id_url " + - "ON streams (service_id, url)" - ) + val MIGRATION_3_4 = Migration(DB_VER_3, DB_VER_4) { db -> + db.execSQL("ALTER TABLE streams ADD COLUMN uploader_url TEXT") + } - // Tables for feed feature - db.execSQL( - "CREATE TABLE IF NOT EXISTS feed " + - "(stream_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " + - "PRIMARY KEY(stream_id, subscription_id), " + - "FOREIGN KEY(stream_id) REFERENCES streams(uid) " + - "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + - "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + - "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" - ) - db.execSQL("CREATE INDEX index_feed_subscription_id ON feed (subscription_id)") - db.execSQL( - "CREATE TABLE IF NOT EXISTS feed_group " + - "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, name TEXT NOT NULL, " + - "icon_id INTEGER NOT NULL, sort_order INTEGER NOT NULL)" - ) - db.execSQL("CREATE INDEX index_feed_group_sort_order ON feed_group (sort_order)") - db.execSQL( - "CREATE TABLE IF NOT EXISTS feed_group_subscription_join " + - "(group_id INTEGER NOT NULL, subscription_id INTEGER NOT NULL, " + - "PRIMARY KEY(group_id, subscription_id), " + - "FOREIGN KEY(group_id) REFERENCES feed_group(uid) " + - "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED, " + - "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + - "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" - ) - db.execSQL( - "CREATE INDEX index_feed_group_subscription_join_subscription_id " + - "ON feed_group_subscription_join (subscription_id)" - ) - db.execSQL( - "CREATE TABLE IF NOT EXISTS feed_last_updated " + - "(subscription_id INTEGER NOT NULL, last_updated INTEGER, " + - "PRIMARY KEY(subscription_id), " + - "FOREIGN KEY(subscription_id) REFERENCES subscriptions(uid) " + - "ON UPDATE CASCADE ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED)" - ) - } + val MIGRATION_4_5 = Migration(DB_VER_4, DB_VER_5) { db -> + db.execSQL( + "ALTER TABLE `subscriptions` ADD COLUMN `notification_mode` " + + "INTEGER NOT NULL DEFAULT 0" + ) } - val MIGRATION_3_4 = object : Migration(DB_VER_3, DB_VER_4) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL("ALTER TABLE streams ADD COLUMN uploader_url TEXT") - } + val MIGRATION_5_6 = Migration(DB_VER_5, DB_VER_6) { db -> + db.execSQL( + "ALTER TABLE `playlists` ADD COLUMN `is_thumbnail_permanent` " + + "INTEGER NOT NULL DEFAULT 0" + ) } - val MIGRATION_4_5 = object : Migration(DB_VER_4, DB_VER_5) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - "ALTER TABLE `subscriptions` ADD COLUMN `notification_mode` " + - "INTEGER NOT NULL DEFAULT 0" - ) - } + val MIGRATION_6_7 = Migration(DB_VER_6, DB_VER_7) { db -> + // Create a new column thumbnail_stream_id + db.execSQL( + "ALTER TABLE `playlists` ADD COLUMN `thumbnail_stream_id` " + + "INTEGER NOT NULL DEFAULT -1" + ) + + // Migrate the thumbnail_url to the thumbnail_stream_id + db.execSQL( + "UPDATE playlists SET thumbnail_stream_id = (" + + " SELECT CASE WHEN COUNT(*) != 0 then stream_uid ELSE -1 END" + + " FROM (" + + " SELECT p.uid AS playlist_uid, s.uid AS stream_uid" + + " FROM playlists p" + + " LEFT JOIN playlist_stream_join ps ON p.uid = ps.playlist_id" + + " LEFT JOIN streams s ON s.uid = ps.stream_id" + + " WHERE s.thumbnail_url = p.thumbnail_url) AS temporary_table" + + " WHERE playlist_uid = playlists.uid)" + ) + + // Remove the thumbnail_url field in the playlist table + db.execSQL( + "CREATE TABLE IF NOT EXISTS `playlists_new`" + + "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "name TEXT, " + + "is_thumbnail_permanent INTEGER NOT NULL, " + + "thumbnail_stream_id INTEGER NOT NULL)" + ) + + db.execSQL( + "INSERT INTO playlists_new" + + " SELECT uid, name, is_thumbnail_permanent, thumbnail_stream_id " + + " FROM playlists" + ) + + db.execSQL("DROP TABLE playlists") + db.execSQL("ALTER TABLE playlists_new RENAME TO playlists") + db.execSQL( + "CREATE INDEX IF NOT EXISTS " + + "`index_playlists_name` ON `playlists` (`name`)" + ) } - val MIGRATION_5_6 = object : Migration(DB_VER_5, DB_VER_6) { - override fun migrate(db: SupportSQLiteDatabase) { - db.execSQL( - "ALTER TABLE `playlists` ADD COLUMN `is_thumbnail_permanent` " + - "INTEGER NOT NULL DEFAULT 0" - ) - } + val MIGRATION_7_8 = Migration(DB_VER_7, DB_VER_8) { db -> + db.execSQL( + "DELETE FROM search_history WHERE id NOT IN (SELECT id FROM (SELECT " + + "MIN(id) as id FROM search_history GROUP BY trim(search), service_id ) tmp)" + ) + db.execSQL("UPDATE search_history SET search = trim(search)") } - val MIGRATION_6_7 = object : Migration(DB_VER_6, DB_VER_7) { - override fun migrate(db: SupportSQLiteDatabase) { - // Create a new column thumbnail_stream_id - db.execSQL( - "ALTER TABLE `playlists` ADD COLUMN `thumbnail_stream_id` " + - "INTEGER NOT NULL DEFAULT -1" - ) + val MIGRATION_8_9 = Migration(DB_VER_8, DB_VER_9) { db -> + try { + db.beginTransaction() - // Migrate the thumbnail_url to the thumbnail_stream_id + // Update playlists. + // Create a temp table to initialize display_index. db.execSQL( - "UPDATE playlists SET thumbnail_stream_id = (" + - " SELECT CASE WHEN COUNT(*) != 0 then stream_uid ELSE -1 END" + - " FROM (" + - " SELECT p.uid AS playlist_uid, s.uid AS stream_uid" + - " FROM playlists p" + - " LEFT JOIN playlist_stream_join ps ON p.uid = ps.playlist_id" + - " LEFT JOIN streams s ON s.uid = ps.stream_id" + - " WHERE s.thumbnail_url = p.thumbnail_url) AS temporary_table" + - " WHERE playlist_uid = playlists.uid)" + "CREATE TABLE `playlists_tmp` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`name` TEXT, `is_thumbnail_permanent` INTEGER NOT NULL, " + + "`thumbnail_stream_id` INTEGER NOT NULL, " + + "`display_index` INTEGER NOT NULL)" ) - - // Remove the thumbnail_url field in the playlist table db.execSQL( - "CREATE TABLE IF NOT EXISTS `playlists_new`" + - "(uid INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + - "name TEXT, " + - "is_thumbnail_permanent INTEGER NOT NULL, " + - "thumbnail_stream_id INTEGER NOT NULL)" + "INSERT INTO `playlists_tmp` " + + "(`uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " + + "`display_index`) " + + "SELECT `uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " + + "-1 " + + "FROM `playlists`" ) + // Replace the old table, note that this also removes the index on the name which + // we don't need anymore. + db.execSQL("DROP TABLE `playlists`") + db.execSQL("ALTER TABLE `playlists_tmp` RENAME TO `playlists`") + + // Update remote_playlists. + // Create a temp table to initialize display_index. db.execSQL( - "INSERT INTO playlists_new" + - " SELECT uid, name, is_thumbnail_permanent, thumbnail_stream_id " + - " FROM playlists" + "CREATE TABLE `remote_playlists_tmp` " + + "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + + "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " + + "`thumbnail_url` TEXT, `uploader` TEXT, " + + "`display_index` INTEGER NOT NULL," + + "`stream_count` INTEGER)" ) - - db.execSQL("DROP TABLE playlists") - db.execSQL("ALTER TABLE playlists_new RENAME TO playlists") db.execSQL( - "CREATE INDEX IF NOT EXISTS " + - "`index_playlists_name` ON `playlists` (`name`)" + "INSERT INTO `remote_playlists_tmp` (`uid`, `service_id`, " + + "`name`, `url`, `thumbnail_url`, `uploader`, `display_index`, " + + "`stream_count`)" + + "SELECT `uid`, `service_id`, `name`, `url`, `thumbnail_url`, `uploader`, " + + "-1, `stream_count` FROM `remote_playlists`" ) - } - } - val MIGRATION_7_8 = object : Migration(DB_VER_7, DB_VER_8) { - override fun migrate(db: SupportSQLiteDatabase) { + // Replace the old table, note that this also removes the index on the name which + // we don't need anymore. + db.execSQL("DROP TABLE `remote_playlists`") + db.execSQL("ALTER TABLE `remote_playlists_tmp` RENAME TO `remote_playlists`") + + // Create index on the new table. db.execSQL( - "DELETE FROM search_history WHERE id NOT IN (SELECT id FROM (SELECT " + - "MIN(id) as id FROM search_history GROUP BY trim(search), service_id ) tmp)" + "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " + + "ON `remote_playlists` (`service_id`, `url`)" ) - db.execSQL("UPDATE search_history SET search = trim(search)") - } - } - val MIGRATION_8_9 = object : Migration(DB_VER_8, DB_VER_9) { - override fun migrate(db: SupportSQLiteDatabase) { - try { - db.beginTransaction() - - // Update playlists. - // Create a temp table to initialize display_index. - db.execSQL( - "CREATE TABLE `playlists_tmp` " + - "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + - "`name` TEXT, `is_thumbnail_permanent` INTEGER NOT NULL, " + - "`thumbnail_stream_id` INTEGER NOT NULL, " + - "`display_index` INTEGER NOT NULL)" - ) - db.execSQL( - "INSERT INTO `playlists_tmp` " + - "(`uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " + - "`display_index`) " + - "SELECT `uid`, `name`, `is_thumbnail_permanent`, `thumbnail_stream_id`, " + - "-1 " + - "FROM `playlists`" - ) - - // Replace the old table, note that this also removes the index on the name which - // we don't need anymore. - db.execSQL("DROP TABLE `playlists`") - db.execSQL("ALTER TABLE `playlists_tmp` RENAME TO `playlists`") - - // Update remote_playlists. - // Create a temp table to initialize display_index. - db.execSQL( - "CREATE TABLE `remote_playlists_tmp` " + - "(`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, " + - "`service_id` INTEGER NOT NULL, `name` TEXT, `url` TEXT, " + - "`thumbnail_url` TEXT, `uploader` TEXT, " + - "`display_index` INTEGER NOT NULL," + - "`stream_count` INTEGER)" - ) - db.execSQL( - "INSERT INTO `remote_playlists_tmp` (`uid`, `service_id`, " + - "`name`, `url`, `thumbnail_url`, `uploader`, `display_index`, " + - "`stream_count`)" + - "SELECT `uid`, `service_id`, `name`, `url`, `thumbnail_url`, `uploader`, " + - "-1, `stream_count` FROM `remote_playlists`" - ) - - // Replace the old table, note that this also removes the index on the name which - // we don't need anymore. - db.execSQL("DROP TABLE `remote_playlists`") - db.execSQL("ALTER TABLE `remote_playlists_tmp` RENAME TO `remote_playlists`") - - // Create index on the new table. - db.execSQL( - "CREATE UNIQUE INDEX `index_remote_playlists_service_id_url` " + - "ON `remote_playlists` (`service_id`, `url`)" - ) - - db.setTransactionSuccessful() - } finally { - db.endTransaction() - } + db.setTransactionSuccessful() + } finally { + db.endTransaction() } } }