Fix renames

We failed to fully remove any orphaned artists, albums references, this could result in duplicate items showing up in the songs view.
This commit is contained in:
Adrian Ulrich 2017-06-08 11:18:02 +02:00
parent 981b22764f
commit d6b1da50fb
4 changed files with 22 additions and 14 deletions

View File

@ -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;

View File

@ -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+");");
}
/**

View File

@ -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.
}

View File

@ -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)");
}
}
}