1313#include " util/math.h"
1414
1515PlaylistDAO::PlaylistDAO ()
16- : m_pAutoDJProcessor(nullptr ) {
16+ : m_currentHistoryPlaylist(kInvalidPlaylistId ),
17+ m_pAutoDJProcessor(nullptr ) {
1718}
1819
1920void PlaylistDAO::initialize (const QSqlDatabase& database) {
@@ -277,19 +278,35 @@ bool PlaylistDAO::deleteUnlockedPlaylists(QStringList&& idStringList) {
277278}
278279
279280bool PlaylistDAO::deleteAllUnlockedPlaylistsWithFewerTracks (
280- PlaylistDAO::HiddenType type, int minNumberOfTracks) {
281+ PlaylistDAO::HiddenType type,
282+ int minNumberOfTracks,
283+ bool skipCurrHistory) {
284+ // Note: this slot is also called after purging tracks in order to delete
285+ // now empty history playlists.
286+ // Though, if the current History is now also empty, we must not delete that!
287+ // Else the following session log is lost -- or rather not recorded in the
288+ // first place since the id passed to appendTrackToPlaylist() does not exist
289+ // anymore.
290+ // skipCurrHistory prevents that.
281291 VERIFY_OR_DEBUG_ASSERT (minNumberOfTracks > 0 ) {
282292 return false ; // nothing to do, probably unintended invocation
283293 }
284294
285295 QSqlQuery query (m_database);
286- query. prepare ( QStringLiteral (
296+ QString queryString = QStringLiteral (
287297 " SELECT id FROM Playlists "
288298 " WHERE (SELECT count(playlist_id) FROM PlaylistTracks WHERE "
289299 " Playlists.ID = PlaylistTracks.playlist_id) < :length AND "
290- " Playlists.hidden = :hidden AND Playlists.locked = 0" ));
300+ " Playlists.hidden = :hidden AND Playlists.locked = 0" );
301+ if (skipCurrHistory) {
302+ queryString.append (QStringLiteral (" AND Playlists.ID != :currHistoryId" ));
303+ }
304+ query.prepare (queryString);
291305 query.bindValue (" :hidden" , static_cast <int >(type));
292306 query.bindValue (" :length" , minNumberOfTracks);
307+ if (skipCurrHistory) {
308+ query.bindValue (" :currHistoryId" , m_currentHistoryPlaylist);
309+ }
293310 if (!query.exec ()) {
294311 LOG_FAILED_QUERY (query);
295312 return false ;
@@ -299,6 +316,11 @@ bool PlaylistDAO::deleteAllUnlockedPlaylistsWithFewerTracks(
299316 while (query.next ()) {
300317 idStringList.append (query.value (0 ).toString ());
301318 }
319+
320+ if (idStringList.isEmpty ()) {
321+ return false ;
322+ }
323+
302324 qInfo () << " Prepared deletion of" << idStringList.size () << " playlists of type" << type
303325 << " that contain fewer than" << minNumberOfTracks << " tracks" ;
304326
@@ -405,9 +427,29 @@ bool PlaylistDAO::removeTracksFromPlaylist(int playlistId, int startIndex) {
405427 return true ;
406428}
407429
430+ bool PlaylistDAO::playlistExists (const int playlistId) const {
431+ ScopedTransaction transaction (m_database);
432+ QSqlQuery query (m_database);
433+ query.prepare (QStringLiteral (" SELECT id FROM Playlists WHERE id = :id" ));
434+ query.bindValue (" :id" , playlistId);
435+
436+ if (!query.exec ()) {
437+ LOG_FAILED_QUERY (query);
438+ return false ;
439+ }
440+
441+ if (query.next ()) {
442+ // id is guaranteed to be unique, so we can return here
443+ return true ;
444+ }
445+ // not found
446+ return false ;
447+ }
448+
408449bool PlaylistDAO::appendTracksToPlaylist (const QList<TrackId>& trackIds, const int playlistId) {
409450 // qDebug() << "PlaylistDAO::appendTracksToPlaylist"
410451 // << QThread::currentThread() << m_database.connectionName();
452+ DEBUG_ASSERT (playlistExists (playlistId));
411453
412454 // Start the transaction
413455 ScopedTransaction transaction (m_database);
@@ -991,7 +1033,8 @@ void PlaylistDAO::removeTracksFromPlaylists(const QList<TrackId>& trackIds, bool
9911033 transaction.commit ();
9921034
9931035 // We may now have empty history playlists. Remove them.
994- deleteAllUnlockedPlaylistsWithFewerTracks (PlaylistDAO::PLHT_SET_LOG , 1 );
1036+ // Note: does not delete current History playlist.
1037+ deleteAllUnlockedPlaylistsWithFewerTracks (PlaylistDAO::PLHT_SET_LOG , 1 , true );
9951038
9961039 // update the sidebar
9971040 emit playlistContentChanged (playlistIds);
0 commit comments