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
(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)
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):
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"),