From d6b1da50fb61cde29144be4947e88934f8ecaeab Mon Sep 17 00:00:00 2001 From: Adrian Ulrich Date: Thu, 8 Jun 2017 11:18:02 +0200 Subject: [PATCH] Fix renames We failed to fully remove any orphaned artists, albums references, this could result in duplicate items showing up in the songs view. --- .../android/medialibrary/MediaLibrary.java | 2 +- .../medialibrary/MediaLibraryBackend.java | 18 ++++++++---------- .../android/medialibrary/MediaScanner.java | 9 ++++++--- .../android/medialibrary/MediaSchema.java | 7 +++++++ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/ch/blinkenlights/android/medialibrary/MediaLibrary.java b/src/ch/blinkenlights/android/medialibrary/MediaLibrary.java index 3f30cde9..b4f91d09 100644 --- a/src/ch/blinkenlights/android/medialibrary/MediaLibrary.java +++ b/src/ch/blinkenlights/android/medialibrary/MediaLibrary.java @@ -290,7 +290,7 @@ public class MediaLibrary { int rows = getBackend(context).delete(TABLE_SONGS, SongColumns._ID+"="+id, null); if (rows > 0) { - getBackend(context).cleanOrphanedEntries(); + getBackend(context).cleanOrphanedEntries(true); notifyObserver(); } return rows; diff --git a/src/ch/blinkenlights/android/medialibrary/MediaLibraryBackend.java b/src/ch/blinkenlights/android/medialibrary/MediaLibraryBackend.java index cba7e4b9..bc3d2f51 100644 --- a/src/ch/blinkenlights/android/medialibrary/MediaLibraryBackend.java +++ b/src/ch/blinkenlights/android/medialibrary/MediaLibraryBackend.java @@ -177,25 +177,23 @@ public class MediaLibraryBackend extends SQLiteOpenHelper { /** * Purges orphaned entries from the media library * + * @param fullCleanup also remove orphaned playlist entries and songs marked for deletion. */ - void cleanOrphanedEntries() { + void cleanOrphanedEntries(boolean fullCleanup) { SQLiteDatabase dbh = getWritableDatabase(); - // These are not orphaned, but corrupted entries: This song exists multiple times as we have - // multiple artist or album references. Just nuke it as we can't tell which entry is correct. - // A re-scan will re-add the song (once). - dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_SONGS+" WHERE "+MediaLibrary.SongColumns._ID+" IN ("+ - "SELECT "+MediaLibrary.SongColumns._ID+" FROM "+MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS+" GROUP BY "+ - MediaLibrary.SongColumns._ID+" HAVING count("+MediaLibrary.SongColumns._ID+") > 1)"); - // Remove all songs which are marked for deletion - dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_SONGS+" WHERE "+MediaLibrary.SongColumns.MTIME+"="+PENDING_DELETION_MTIME); + // Remove all songs which are marked for deletion and playlist orphaned playlist entries. + if (fullCleanup) { + dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_SONGS+" WHERE "+MediaLibrary.SongColumns.MTIME+"="+PENDING_DELETION_MTIME); + dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_PLAYLISTS_SONGS+" WHERE "+MediaLibrary.PlaylistSongColumns.SONG_ID+" NOT IN (SELECT "+MediaLibrary.SongColumns._ID+" FROM "+MediaLibrary.TABLE_SONGS+");"); + } + // And remove any orphaned references. dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_ALBUMS+" WHERE "+MediaLibrary.AlbumColumns._ID+" NOT IN (SELECT "+MediaLibrary.SongColumns.ALBUM_ID+" FROM "+MediaLibrary.TABLE_SONGS+");"); dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_GENRES_SONGS+" WHERE "+MediaLibrary.GenreSongColumns.SONG_ID+" NOT IN (SELECT "+MediaLibrary.SongColumns._ID+" FROM "+MediaLibrary.TABLE_SONGS+");"); dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_GENRES+" WHERE "+MediaLibrary.GenreColumns._ID+" NOT IN (SELECT "+MediaLibrary.GenreSongColumns._GENRE_ID+" FROM "+MediaLibrary.TABLE_GENRES_SONGS+");"); dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS+" WHERE "+MediaLibrary.ContributorSongColumns.SONG_ID+" NOT IN (SELECT "+MediaLibrary.SongColumns._ID+" FROM "+MediaLibrary.TABLE_SONGS+");"); dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_CONTRIBUTORS+" WHERE "+MediaLibrary.ContributorColumns._ID+" NOT IN (SELECT "+MediaLibrary.ContributorSongColumns._CONTRIBUTOR_ID+" FROM "+MediaLibrary.TABLE_CONTRIBUTORS_SONGS+");"); - dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_PLAYLISTS_SONGS+" WHERE "+MediaLibrary.PlaylistSongColumns.SONG_ID+" NOT IN (SELECT "+MediaLibrary.SongColumns._ID+" FROM "+MediaLibrary.TABLE_SONGS+");"); } /** diff --git a/src/ch/blinkenlights/android/medialibrary/MediaScanner.java b/src/ch/blinkenlights/android/medialibrary/MediaScanner.java index 94a44a86..41d30ef4 100644 --- a/src/ch/blinkenlights/android/medialibrary/MediaScanner.java +++ b/src/ch/blinkenlights/android/medialibrary/MediaScanner.java @@ -67,7 +67,7 @@ public class MediaScanner implements Handler.Callback { */ private boolean mIsInitialScan; /** - * True if we must cleanup orphaned entries after the scan finished. + * True if we must do a full cleanup of orphaned entries after the scan finished. */ private boolean mPendingCleanup; /** @@ -199,7 +199,7 @@ public class MediaScanner implements Handler.Callback { } if (mPendingCleanup) { mPendingCleanup = false; - mBackend.cleanOrphanedEntries(); + mBackend.cleanOrphanedEntries(true); } // make sure to notify about changes which cleanOrphanedEntries // might have caused @@ -443,8 +443,11 @@ public class MediaScanner implements Handler.Callback { // this tries to preserve play and skipcounts of the song playCount = mBackend.getColumnFromSongId(MediaLibrary.SongColumns.PLAYCOUNT, songId); skipCount = mBackend.getColumnFromSongId(MediaLibrary.SongColumns.SKIPCOUNT, songId); + // Remove the song from the database for now but do not delete any + // playlist references to it. mBackend.delete(MediaLibrary.TABLE_SONGS, MediaLibrary.SongColumns._ID+"="+songId, null); - mPendingCleanup = true; // we deleted an entry, so we must also cleanup playlists, artists, etc... + mBackend.cleanOrphanedEntries(false); + mPendingCleanup = true; // Ensure that we run a full cleanup after all scans finished, to get rid of orphaned playlist entries. hasChanged = true; // notify caller about change even if we are not going to re-insert this file. } diff --git a/src/ch/blinkenlights/android/medialibrary/MediaSchema.java b/src/ch/blinkenlights/android/medialibrary/MediaSchema.java index 934f45bf..aefa76ab 100644 --- a/src/ch/blinkenlights/android/medialibrary/MediaSchema.java +++ b/src/ch/blinkenlights/android/medialibrary/MediaSchema.java @@ -293,6 +293,13 @@ public class MediaSchema { dbh.execSQL("DROP TABLE preferences"); } + if (oldVersion >= 20170407 && oldVersion < 20170608) { + // renames were buggy for some time -> get rid of duplicates + dbh.execSQL("DELETE FROM "+MediaLibrary.TABLE_SONGS+" WHERE "+MediaLibrary.SongColumns._ID+" IN ("+ + "SELECT "+MediaLibrary.SongColumns._ID+" FROM "+MediaLibrary.VIEW_SONGS_ALBUMS_ARTISTS+" GROUP BY "+ + MediaLibrary.SongColumns._ID+" HAVING count("+MediaLibrary.SongColumns._ID+") > 1)"); + } + } }