diff --git a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java index 4da1c63f2..15d9cf389 100644 --- a/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java +++ b/app/src/main/java/org/schabi/newpipe/NewPipeDatabase.java @@ -7,6 +7,7 @@ import android.support.annotation.NonNull; import org.schabi.newpipe.database.AppDatabase; import static org.schabi.newpipe.database.AppDatabase.DATABASE_NAME; +import static org.schabi.newpipe.database.Migrations.MIGRATION_11_12; public final class NewPipeDatabase { @@ -17,9 +18,10 @@ public final class NewPipeDatabase { } public static void init(Context context) { - databaseInstance = Room.databaseBuilder(context.getApplicationContext(), - AppDatabase.class, DATABASE_NAME - ).build(); + databaseInstance = Room + .databaseBuilder(context.getApplicationContext(), AppDatabase.class, DATABASE_NAME) + .addMigrations(MIGRATION_11_12) + .build(); } @NonNull diff --git a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java index dedbfbf68..d5a9164dc 100644 --- a/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java +++ b/app/src/main/java/org/schabi/newpipe/database/AppDatabase.java @@ -10,17 +10,19 @@ import org.schabi.newpipe.database.history.model.SearchHistoryEntry; import org.schabi.newpipe.database.history.model.WatchHistoryEntry; import org.schabi.newpipe.database.playlist.dao.PlaylistDAO; import org.schabi.newpipe.database.playlist.dao.PlaylistStreamDAO; -import org.schabi.newpipe.database.stream.dao.StreamHistoryDAO; -import org.schabi.newpipe.database.stream.dao.StreamDAO; import org.schabi.newpipe.database.playlist.model.PlaylistEntity; import org.schabi.newpipe.database.playlist.model.PlaylistStreamEntity; +import org.schabi.newpipe.database.stream.dao.StreamDAO; +import org.schabi.newpipe.database.stream.dao.StreamHistoryDAO; import org.schabi.newpipe.database.stream.dao.StreamStateDAO; -import org.schabi.newpipe.database.stream.model.StreamHistoryEntity; import org.schabi.newpipe.database.stream.model.StreamEntity; +import org.schabi.newpipe.database.stream.model.StreamHistoryEntity; import org.schabi.newpipe.database.stream.model.StreamStateEntity; import org.schabi.newpipe.database.subscription.SubscriptionDAO; import org.schabi.newpipe.database.subscription.SubscriptionEntity; +import static org.schabi.newpipe.database.Migrations.DB_VER_12_0; + @TypeConverters({Converters.class}) @Database( entities = { @@ -28,7 +30,7 @@ import org.schabi.newpipe.database.subscription.SubscriptionEntity; StreamEntity.class, StreamHistoryEntity.class, StreamStateEntity.class, PlaylistEntity.class, PlaylistStreamEntity.class }, - version = 1, + version = DB_VER_12_0, exportSchema = false ) public abstract class AppDatabase extends RoomDatabase { diff --git a/app/src/main/java/org/schabi/newpipe/database/Migrations.java b/app/src/main/java/org/schabi/newpipe/database/Migrations.java new file mode 100644 index 000000000..f1aa52392 --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/database/Migrations.java @@ -0,0 +1,47 @@ +package org.schabi.newpipe.database; + +import android.arch.persistence.db.SupportSQLiteDatabase; +import android.arch.persistence.room.migration.Migration; +import android.support.annotation.NonNull; + +public class Migrations { + + public static final int DB_VER_11_0 = 1; + public static final int DB_VER_12_0 = 2; + + public static final Migration MIGRATION_11_12 = new Migration(DB_VER_11_0, DB_VER_12_0) { + @Override + public void migrate(@NonNull SupportSQLiteDatabase database) { + database.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)"); + database.execSQL("CREATE UNIQUE INDEX `index_streams_service_id_url` ON `streams` (`service_id`, `url`)"); + database.execSQL("CREATE TABLE IF NOT EXISTS `stream_history` (`stream_id` INTEGER NOT NULL, `access_date` INTEGER NOT NULL, PRIMARY KEY(`stream_id`, `access_date`), FOREIGN KEY(`stream_id`) REFERENCES `streams`(`uid`) ON UPDATE CASCADE ON DELETE CASCADE )"); + database.execSQL("CREATE INDEX `index_stream_history_stream_id` ON `stream_history` (`stream_id`)"); + database.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 )"); + database.execSQL("CREATE TABLE IF NOT EXISTS `playlists` (`uid` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT, `thumbnail_url` TEXT)"); + database.execSQL("CREATE INDEX `index_playlists_name` ON `playlists` (`name`)"); + database.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`, `stream_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)"); + database.execSQL("CREATE UNIQUE INDEX `index_playlist_stream_join_playlist_id_join_index` ON `playlist_stream_join` (`playlist_id`, `join_index`)"); + database.execSQL("CREATE INDEX `index_playlist_stream_join_stream_id` ON `playlist_stream_join` (`stream_id`)"); + + // Populate streams table with existing entries in watch history + // Latest data first, thus ignoring older entries with the same indices + database.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 + database.execSQL("INSERT INTO stream_history (stream_id, access_date)" + + "SELECT uid, creation_date " + + "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"); + } + }; +} diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamHistoryDAO.java b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamHistoryDAO.java index 522c03522..527d151ea 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamHistoryDAO.java +++ b/app/src/main/java/org/schabi/newpipe/database/stream/dao/StreamHistoryDAO.java @@ -37,7 +37,7 @@ public abstract class StreamHistoryDAO implements BasicDAO } @Query("DELETE FROM " + STREAM_HISTORY_TABLE + " WHERE " + JOIN_STREAM_ID + " = :streamId") - public abstract int deleteHistory(final long streamId); + public abstract int deleteStreamHistory(final long streamId); @Query("SELECT * FROM " + STREAM_TABLE + diff --git a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.java b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.java index 27d0aa7e1..c7ef889b9 100644 --- a/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.java +++ b/app/src/main/java/org/schabi/newpipe/database/stream/model/StreamEntity.java @@ -24,9 +24,9 @@ public class StreamEntity { final public static String STREAM_SERVICE_ID = "service_id"; final public static String STREAM_URL = "url"; final public static String STREAM_TITLE = "title"; - final public static String STREAM_TYPE = "streamType"; - final public static String STREAM_UPLOADER = "uploader"; + final public static String STREAM_TYPE = "stream_type"; final public static String STREAM_DURATION = "duration"; + final public static String STREAM_UPLOADER = "uploader"; final public static String STREAM_THUMBNAIL_URL = "thumbnail_url"; @PrimaryKey(autoGenerate = true) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/local/StreamRecordManager.java b/app/src/main/java/org/schabi/newpipe/fragments/local/StreamRecordManager.java index 458ec4da2..993ed58da 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/local/StreamRecordManager.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/local/StreamRecordManager.java @@ -35,7 +35,7 @@ public class StreamRecordManager { } public int removeHistory(final long streamId) { - return historyTable.deleteHistory(streamId); + return historyTable.deleteStreamHistory(streamId); } public Flowable> getStatistics() {