db: Save Track data when deleting

This includes the favorite status, playcount, last played timestamp, and
last started timestamp. These values will be restored if a Track with
the same mbid is created at a later time.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2022-11-09 10:59:35 -05:00
parent 8a16b4e05f
commit ff835832c8
3 changed files with 95 additions and 7 deletions

View File

@ -395,6 +395,41 @@ CREATE TRIGGER tracks_active_trigger
END;
/****************************************************
* *
* Data saved when Tracks are deleted *
* *
****************************************************/
CREATE TABLE saved_track_data (
mbid TEXT PRIMARY KEY,
favorite BOOLEAN NOT NULL DEFAULT FALSE,
playcount INTEGER NOT NULL DEFAULT 0,
lastplayed TIMESTAMP DEFAULT NULL,
laststarted TIMESTAMP DEFAULT NULL
);
CREATE TRIGGER tracks_delete_save BEFORE DELETE ON tracks
WHEN OLD.mbid != "" BEGIN
INSERT INTO saved_track_data
(mbid, favorite, playcount, lastplayed, laststarted)
VALUES (OLD.mbid, OLD.favorite, OLD.playcount,
OLD.lastplayed, OLD.laststarted);
END;
CREATE TRIGGER tracks_insert_restore AFTER INSERT ON tracks
WHEN NEW.mbid != "" BEGIN
UPDATE tracks SET favorite = saved_track_data.favorite,
playcount = saved_track_data.playcount,
lastplayed = saved_track_data.lastplayed,
laststarted = saved_track_data.laststarted
FROM saved_track_data
WHERE tracks.mbid = saved_track_data.mbid AND
tracks.mbid = NEW.mbid;
DELETE FROM saved_track_data WHERE mbid = NEW.mbid;
END;
/******************************************
* *
* Create Default Playlists *

View File

@ -146,13 +146,15 @@ class Table(table.Table):
number: int = 0, length: float = 0.0, artist: str = "",
mbid: str = "", mtime: float = 0.0) -> sqlite3.Cursor:
"""Insert a new Track into the database."""
return self.sql("""INSERT INTO tracks
if cur := self.sql("""INSERT INTO tracks
(libraryid, mediumid, path, year, title,
number, length, artist, mbid, mtime)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING *""",
library.libraryid, medium.mediumid, path, year.year,
title, number, length, artist, mbid, mtime)
title, number, length, artist, mbid, mtime):
return self.sql("SELECT * FROM tracks WHERE trackid=?",
cur.lastrowid)
def do_sql_select_all(self) -> sqlite3.Cursor:
"""Load Tracks from the database."""

View File

@ -2,6 +2,7 @@
"""Tests our track Gio.ListModel."""
import datetime
import pathlib
import unittest
import emmental.db.tracks
import tests.util
import unittest.mock
@ -231,6 +232,33 @@ class TestTrackTable(tests.util.TestCase):
cur = self.sql("SELECT COUNT(*) FROM tracks")
self.assertEqual(cur.fetchone()["COUNT(*)"], 2)
def test_create_restore(self):
"""Test restoring saved track data."""
now = datetime.datetime.now()
self.sql("""INSERT INTO saved_track_data
(mbid, favorite, playcount, lastplayed, laststarted)
VALUES (?, ?, ?, ? , ?)""", "ab-cd-ef", True, 42, now, now)
track1 = self.tracks.create(self.library, pathlib.Path("/a/b/1.ogg"),
self.medium, self.year)
self.assertFalse(track1.favorite)
self.assertEqual(track1.playcount, 0)
self.assertIsNone(track1.lastplayed)
self.assertIsNone(track1.laststarted)
row = self.sql("SELECT COUNT(*) FROM saved_track_data").fetchone()
self.assertEqual(row["COUNT(*)"], 1)
track2 = self.tracks.create(self.library, pathlib.Path("/a/b/2.ogg"),
self.medium, self.year, mbid="ab-cd-ef")
self.assertTrue(track2.favorite)
self.assertEqual(track2.playcount, 42)
self.assertEqual(track2.lastplayed, now)
self.assertEqual(track2.laststarted, now)
row = self.sql("SELECT COUNT(*) FROM saved_track_data").fetchone()
self.assertEqual(row["COUNT(*)"], 0)
def test_delete(self):
"""Test deleting a Track."""
track = self.tracks.create(self.library, pathlib.Path("/a/b/c.ogg"),
@ -245,6 +273,29 @@ class TestTrackTable(tests.util.TestCase):
self.assertFalse(track.delete())
def test_delete_save(self):
"""Test saving track data when a track is deleted."""
now = datetime.datetime.now()
track1 = self.tracks.create(self.library, pathlib.Path("/a/b/1.ogg"),
self.medium, self.year, mbid="ab-cd-ef")
track2 = self.tracks.create(self.library, pathlib.Path("/a/b/2.ogg"),
self.medium, self.year)
self.sql("""UPDATE tracks
SET favorite=?, laststarted=?, lastplayed=?, playcount=?
WHERE trackid=?""", True, now, now, 42, track1.trackid)
track1.delete()
track2.delete()
rows = self.sql("SELECT * FROM saved_track_data").fetchall()
self.assertEqual(len(rows), 1)
self.assertEqual(rows[0]["mbid"], "ab-cd-ef")
self.assertEqual(rows[0]["favorite"], True)
self.assertEqual(rows[0]["laststarted"], now)
self.assertEqual(rows[0]["lastplayed"], now)
self.assertEqual(rows[0]["playcount"], 42)
def test_filter(self):
"""Test filtering the Track table."""
self.tracks.create(self.library, pathlib.Path("/a/b/1.ogg"),