From e23547d7ae2996f66025dc92f44d4290ddedbc57 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 12 Jan 2025 11:30:10 +0100 Subject: [PATCH 1/7] Album title cannot be primary key --- src/external/database/sql/backend.rs | 2 +- tests/files/database/database.db | Bin 28672 -> 24576 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/external/database/sql/backend.rs b/src/external/database/sql/backend.rs index 3bc9cb6..f7af8fe 100644 --- a/src/external/database/sql/backend.rs +++ b/src/external/database/sql/backend.rs @@ -122,7 +122,7 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { fn create_albums_table(&self) -> Result<(), Error> { let mut stmt = self.prepare( "CREATE TABLE IF NOT EXISTS albums ( - title TEXT NOT NULL PRIMARY KEY, + title TEXT NOT NULL, lib_id JSON NOT NULL DEFAULT '\"None\"', mbid JSON NOT NULL DEFAULT '\"None\"', artist_name TEXT NOT NULL, diff --git a/tests/files/database/database.db b/tests/files/database/database.db index 9fe47ada8d16334914faad64d9c5f70de30597aa..bf7a0cbf4438fa9acd90b0d2e2f8a1ed4c9811c6 100644 GIT binary patch delta 121 zcmZp8z}Rqrae}lU69WSS8xX?)=R_T2aV7@6ssdjA9}KMA=?r}T__y+&`7Ez2BkShZyh4nOY@7e_F)2!L0bRwxAI`wv z#vjig&VQNzJAWDfJ^tyN1qJN+UD%n08H3e)ImDO^8G|xYQWZ)vQWbnM(=$r)GV{{e z`I(g&L-Ue~QWLX5&SVo{R%HxGEJ!U<2*^oHFHL2&X0B$O{65ZHfQ5@$k})_ZF)uTb bS%TS=aq@(C5iTYUW^vBoocyx Date: Sun, 12 Jan 2025 11:33:57 +0100 Subject: [PATCH 2/7] Remove database-json files and featurs - non-working --- Cargo.toml | 5 +- src/external/database/json/backend.rs | 30 ----- src/external/database/json/mod.rs | 168 -------------------------- src/external/database/json/testmod.rs | 107 ---------------- src/external/database/mod.rs | 4 +- tests/database/json.rs | 68 ----------- tests/database/mod.rs | 2 - tests/files/database/database.json | 1 - tests/lib.rs | 2 +- 9 files changed, 4 insertions(+), 383 deletions(-) delete mode 100644 src/external/database/json/backend.rs delete mode 100644 src/external/database/json/mod.rs delete mode 100644 src/external/database/json/testmod.rs delete mode 100644 tests/database/json.rs delete mode 100644 tests/files/database/database.json diff --git a/Cargo.toml b/Cargo.toml index 86338aa..6d6d373 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,11 +31,10 @@ mockall = "0.13.1" tempfile = "3.15.0" [features] -default = ["database-json", "library-beets"] +default = ["database-sqlite", "library-beets"] bin = ["structopt"] database-sqlite = ["rusqlite", "serde", "serde_json"] database-sqlite-bundled = ["rusqlite/bundled"] -database-json = ["serde", "serde_json"] library-beets = [] library-beets-ssh = ["openssh", "tokio"] musicbrainz = ["paste", "reqwest", "serde", "serde_json"] @@ -43,7 +42,7 @@ tui = ["crossterm", "ratatui", "tui-input"] [[bin]] name = "musichoard" -required-features = ["bin", "database-json", "library-beets", "library-beets-ssh", "musicbrainz", "tui"] +required-features = ["bin", "database-sqlite", "database-sqlite-bundled", "library-beets", "library-beets-ssh", "musicbrainz", "tui"] [[example]] name = "musicbrainz-api---browse" diff --git a/src/external/database/json/backend.rs b/src/external/database/json/backend.rs deleted file mode 100644 index 76a190c..0000000 --- a/src/external/database/json/backend.rs +++ /dev/null @@ -1,30 +0,0 @@ -//! Module for storing MusicHoard data in a JSON file database. - -use std::fs; -use std::path::PathBuf; - -use crate::external::database::json::IJsonDatabaseBackend; - -/// JSON database backend that uses a local file for persistent storage. -pub struct JsonDatabaseFileBackend { - path: PathBuf, -} - -impl JsonDatabaseFileBackend { - /// Create a [`JsonDatabaseFileBackend`] that will read/write to the provided path. - pub fn new>(path: P) -> Self { - JsonDatabaseFileBackend { path: path.into() } - } -} - -impl IJsonDatabaseBackend for JsonDatabaseFileBackend { - fn read(&self) -> Result { - // Read entire file to memory as for now this is faster than a buffered read from disk: - // https://github.com/serde-rs/json/issues/160 - fs::read_to_string(&self.path) - } - - fn write(&mut self, json: &str) -> Result<(), std::io::Error> { - fs::write(&self.path, json) - } -} diff --git a/src/external/database/json/mod.rs b/src/external/database/json/mod.rs deleted file mode 100644 index 3d4709b..0000000 --- a/src/external/database/json/mod.rs +++ /dev/null @@ -1,168 +0,0 @@ -//! Module for storing MusicHoard data in a JSON file database. - -pub mod backend; - -#[cfg(test)] -use mockall::automock; - -use crate::{ - core::{ - collection::Collection, - interface::database::{IDatabase, LoadError, SaveError}, - }, - external::database::serde::{deserialize::DeserializeDatabase, serialize::SerializeDatabase}, -}; - -impl From for LoadError { - fn from(err: serde_json::Error) -> LoadError { - LoadError::SerDeError(err.to_string()) - } -} - -impl From for SaveError { - fn from(err: serde_json::Error) -> SaveError { - SaveError::SerDeError(err.to_string()) - } -} - -/// Trait for the JSON database backend. -#[cfg_attr(test, automock)] -pub trait IJsonDatabaseBackend { - /// Read the JSON string from the backend. - fn read(&self) -> Result; - - /// Write the JSON string to the backend. - fn write(&mut self, json: &str) -> Result<(), std::io::Error>; -} - -/// JSON database. -pub struct JsonDatabase { - backend: JDB, -} - -impl JsonDatabase { - /// Create a new JSON database with the provided backend, e.g. - /// [`backend::JsonDatabaseFileBackend`]. - pub fn new(backend: JDB) -> Self { - JsonDatabase { backend } - } -} - -impl IDatabase for JsonDatabase { - fn load(&mut self) -> Result { - let serialized = self.backend.read()?; - let database: DeserializeDatabase = serde_json::from_str(&serialized)?; - Ok(database.into()) - } - - fn save(&mut self, collection: &Collection) -> Result<(), SaveError> { - let database: SerializeDatabase = collection.into(); - let serialized = serde_json::to_string(&database)?; - self.backend.write(&serialized)?; - Ok(()) - } -} - -#[cfg(test)] -pub mod testmod; - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - - use mockall::predicate; - - use crate::core::{ - collection::{artist::Artist, Collection}, - testmod::FULL_COLLECTION, - }; - - use super::*; - use testmod::DATABASE_JSON; - - fn expected() -> Collection { - let mut expected = FULL_COLLECTION.to_owned(); - for artist in expected.iter_mut() { - for album in artist.albums.iter_mut() { - album.tracks.clear(); - } - } - expected - } - - #[test] - fn save() { - let write_data = FULL_COLLECTION.to_owned(); - let input = DATABASE_JSON.to_owned(); - - let mut backend = MockIJsonDatabaseBackend::new(); - backend - .expect_write() - .with(predicate::eq(input)) - .times(1) - .return_once(|_| Ok(())); - - JsonDatabase::new(backend).save(&write_data).unwrap(); - } - - #[test] - fn load() { - let expected = expected(); - let result = Ok(DATABASE_JSON.to_owned()); - eprintln!("{DATABASE_JSON}"); - - let mut backend = MockIJsonDatabaseBackend::new(); - backend.expect_read().times(1).return_once(|| result); - - let read_data: Vec = JsonDatabase::new(backend).load().unwrap(); - - assert_eq!(read_data, expected); - } - - #[test] - fn reverse() { - let input = DATABASE_JSON.to_owned(); - let result = Ok(input.clone()); - - let mut backend = MockIJsonDatabaseBackend::new(); - backend - .expect_write() - .with(predicate::eq(input)) - .times(1) - .return_once(|_| Ok(())); - backend.expect_read().times(1).return_once(|| result); - let mut database = JsonDatabase::new(backend); - - let write_data = FULL_COLLECTION.to_owned(); - database.save(&write_data).unwrap(); - let read_data: Vec = database.load().unwrap(); - - // Album information is not saved to disk. - let expected = expected(); - assert_eq!(read_data, expected); - } - - #[test] - fn load_errors() { - let json = String::from(""); - let serde_err = serde_json::from_str::(&json); - assert!(serde_err.is_err()); - - let serde_err: LoadError = serde_err.unwrap_err().into(); - assert!(!serde_err.to_string().is_empty()); - assert!(!format!("{:?}", serde_err).is_empty()); - } - - #[test] - fn save_errors() { - // serde_json will raise an error as it has certain requirements on keys. - let mut object = HashMap::, String>::new(); - object.insert(Ok(()), String::from("string")); - let serde_err = serde_json::to_string(&object); - assert!(serde_err.is_err()); - - let serde_err: SaveError = serde_err.unwrap_err().into(); - assert!(!serde_err.to_string().is_empty()); - assert!(!format!("{:?}", serde_err).is_empty()); - } -} diff --git a/src/external/database/json/testmod.rs b/src/external/database/json/testmod.rs deleted file mode 100644 index 04fd2b1..0000000 --- a/src/external/database/json/testmod.rs +++ /dev/null @@ -1,107 +0,0 @@ -pub static DATABASE_JSON: &str = "{\ - \"V20250103\":\ - [\ - {\ - \"name\":\"Album_Artist ‘A’\",\ - \"sort\":null,\ - \"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\ - \"properties\":{\ - \"MusicButler\":[\"https://www.musicbutler.io/artist-page/000000000\"],\ - \"Qobuz\":[\"https://www.qobuz.com/nl-nl/interpreter/artist-a/download-streaming-albums\"]\ - },\ - \"albums\":[\ - {\ - \"title\":\"album_title a.a\",\"lib_id\":{\"Value\":1},\ - \"date\":{\"year\":1998,\"month\":null,\"day\":null},\"seq\":1,\ - \"musicbrainz\":{\"Some\":\"00000000-0000-0000-0000-000000000000\"},\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - },\ - {\ - \"title\":\"album_title a.b\",\"lib_id\":{\"Value\":2},\ - \"date\":{\"year\":2015,\"month\":4,\"day\":null},\"seq\":1,\ - \"musicbrainz\":\"None\",\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - }\ - ]\ - },\ - {\ - \"name\":\"Album_Artist ‘B’\",\ - \"sort\":null,\ - \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\ - \"properties\":{\ - \"Bandcamp\":[\"https://artist-b.bandcamp.com/\"],\ - \"MusicButler\":[\ - \"https://www.musicbutler.io/artist-page/111111111\",\ - \"https://www.musicbutler.io/artist-page/111111112\"\ - ],\ - \"Qobuz\":[\"https://www.qobuz.com/nl-nl/interpreter/artist-b/download-streaming-albums\"]\ - },\ - \"albums\":[\ - {\ - \"title\":\"album_title b.a\",\"lib_id\":{\"Value\":3},\ - \"date\":{\"year\":2003,\"month\":6,\"day\":6},\"seq\":1,\ - \"musicbrainz\":\"None\",\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - },\ - {\ - \"title\":\"album_title b.b\",\"lib_id\":{\"Value\":4},\ - \"date\":{\"year\":2008,\"month\":null,\"day\":null},\"seq\":3,\ - \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111111\"},\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - },\ - {\ - \"title\":\"album_title b.c\",\"lib_id\":{\"Value\":5},\ - \"date\":{\"year\":2009,\"month\":null,\"day\":null},\"seq\":2,\ - \"musicbrainz\":{\"Some\":\"11111111-1111-1111-1111-111111111112\"},\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - },\ - {\ - \"title\":\"album_title b.d\",\"lib_id\":{\"Value\":6},\ - \"date\":{\"year\":2015,\"month\":null,\"day\":null},\"seq\":4,\ - \"musicbrainz\":\"None\",\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - }\ - ]\ - },\ - {\ - \"name\":\"The Album_Artist ‘C’\",\ - \"sort\":\"Album_Artist ‘C’, The\",\ - \"musicbrainz\":\"CannotHaveMbid\",\ - \"properties\":{},\ - \"albums\":[\ - {\ - \"title\":\"album_title c.a\",\"lib_id\":{\"Value\":7},\ - \"date\":{\"year\":1985,\"month\":null,\"day\":null},\"seq\":0,\ - \"musicbrainz\":\"None\",\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - },\ - {\ - \"title\":\"album_title c.b\",\"lib_id\":{\"Value\":8},\ - \"date\":{\"year\":2018,\"month\":null,\"day\":null},\"seq\":0,\ - \"musicbrainz\":\"None\",\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - }\ - ]\ - },\ - {\ - \"name\":\"Album_Artist ‘D’\",\ - \"sort\":null,\ - \"musicbrainz\":\"None\",\ - \"properties\":{},\ - \"albums\":[\ - {\ - \"title\":\"album_title d.a\",\"lib_id\":{\"Value\":9},\ - \"date\":{\"year\":1995,\"month\":null,\"day\":null},\"seq\":0,\ - \"musicbrainz\":\"None\",\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - },\ - {\ - \"title\":\"album_title d.b\",\"lib_id\":{\"Value\":10},\ - \"date\":{\"year\":2028,\"month\":null,\"day\":null},\"seq\":0,\ - \"musicbrainz\":\"None\",\ - \"primary_type\":\"Album\",\"secondary_types\":[]\ - }\ - ]\ - }\ - ]\ - }"; diff --git a/src/external/database/mod.rs b/src/external/database/mod.rs index ceca477..7c046e0 100644 --- a/src/external/database/mod.rs +++ b/src/external/database/mod.rs @@ -1,7 +1,5 @@ -#[cfg(feature = "database-json")] -pub mod json; #[cfg(feature = "database-sqlite")] pub mod sql; -#[cfg(any(feature = "database-json", feature = "database-sqlite"))] +#[cfg(any(feature = "database-sqlite"))] mod serde; diff --git a/tests/database/json.rs b/tests/database/json.rs deleted file mode 100644 index 9e13334..0000000 --- a/tests/database/json.rs +++ /dev/null @@ -1,68 +0,0 @@ -use std::{fs, path::PathBuf}; - -use once_cell::sync::Lazy; -use tempfile::NamedTempFile; - -use musichoard::{ - collection::{artist::Artist, Collection}, - external::database::json::{backend::JsonDatabaseFileBackend, JsonDatabase}, - interface::database::IDatabase, -}; - -use crate::testlib::COLLECTION; - -pub static DATABASE_TEST_FILE: Lazy = - Lazy::new(|| fs::canonicalize("./tests/files/database/database.json").unwrap()); - -fn expected() -> Collection { - let mut expected = COLLECTION.to_owned(); - for artist in expected.iter_mut() { - for album in artist.albums.iter_mut() { - album.tracks.clear(); - } - } - expected -} - -#[test] -fn save() { - let file = NamedTempFile::new().unwrap(); - - let backend = JsonDatabaseFileBackend::new(file.path()); - let mut database = JsonDatabase::new(backend); - - let write_data = COLLECTION.to_owned(); - database.save(&write_data).unwrap(); - - let expected = fs::read_to_string(&*DATABASE_TEST_FILE).unwrap(); - let actual = fs::read_to_string(file.path()).unwrap(); - - assert_eq!(actual, expected); -} - -#[test] -fn load() { - let backend = JsonDatabaseFileBackend::new(&*DATABASE_TEST_FILE); - let mut database = JsonDatabase::new(backend); - - let read_data: Vec = database.load().unwrap(); - - let expected = expected(); - assert_eq!(read_data, expected); -} - -#[test] -fn reverse() { - let file = NamedTempFile::new().unwrap(); - - let backend = JsonDatabaseFileBackend::new(file.path()); - let mut database = JsonDatabase::new(backend); - - let write_data = COLLECTION.to_owned(); - database.save(&write_data).unwrap(); - let read_data: Vec = database.load().unwrap(); - - // Album data is not saved into database. - let expected = expected(); - assert_eq!(read_data, expected); -} diff --git a/tests/database/mod.rs b/tests/database/mod.rs index c088ad8..024c321 100644 --- a/tests/database/mod.rs +++ b/tests/database/mod.rs @@ -1,4 +1,2 @@ -#[cfg(feature = "database-json")] -pub mod json; #[cfg(feature = "database-sqlite")] pub mod sql; diff --git a/tests/files/database/database.json b/tests/files/database/database.json deleted file mode 100644 index ccce86d..0000000 --- a/tests/files/database/database.json +++ /dev/null @@ -1 +0,0 @@ -{"V20250103":[{"name":"Аркона","sort":"Arkona","musicbrainz":{"Some":"baad262d-55ef-427a-83c7-f7530964f212"},"properties":{"Bandcamp":["https://arkonamoscow.bandcamp.com/"],"MusicButler":["https://www.musicbutler.io/artist-page/283448581"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/arkona/download-streaming-albums"]},"albums":[{"title":"Slovo","lib_id":{"Value":7},"date":{"year":2011,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Eluveitie","sort":null,"musicbrainz":{"Some":"8000598a-5edb-401c-8e6d-36b167feaf38"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/269358403"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/eluveitie/download-streaming-albums"]},"albums":[{"title":"Vên [re‐recorded]","lib_id":{"Value":1},"date":{"year":2004,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Ep","secondary_types":[]},{"title":"Slania","lib_id":{"Value":2},"date":{"year":2008,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Frontside","sort":null,"musicbrainz":{"Some":"3a901353-fccd-4afd-ad01-9c03f451b490"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/826588800"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/frontside/download-streaming-albums"]},"albums":[{"title":"…nasze jest królestwo, potęga i chwała na wieki…","lib_id":{"Value":3},"date":{"year":2001,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Heaven’s Basement","sort":"Heaven’s Basement","musicbrainz":{"Some":"c2c4d56a-d599-4a18-bd2f-ae644e2198cc"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/291158685"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/heaven-s-basement/download-streaming-albums"]},"albums":[{"title":"Paper Plague","lib_id":"Singleton","date":{"year":2011,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":null,"secondary_types":[]},{"title":"Unbreakable","lib_id":{"Value":4},"date":{"year":2011,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]}]},{"name":"Metallica","sort":null,"musicbrainz":{"Some":"65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab"},"properties":{"MusicButler":["https://www.musicbutler.io/artist-page/3996865"],"Qobuz":["https://www.qobuz.com/nl-nl/interpreter/metallica/download-streaming-albums"]},"albums":[{"title":"Ride the Lightning","lib_id":{"Value":5},"date":{"year":1984,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":[]},{"title":"S&M","lib_id":{"Value":6},"date":{"year":1999,"month":null,"day":null},"seq":0,"musicbrainz":"None","primary_type":"Album","secondary_types":["Live"]}]}]} \ No newline at end of file diff --git a/tests/lib.rs b/tests/lib.rs index 3ae0b9e..fbcc6e9 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "database-json")] +#![cfg(feature = "database-sqlite")] #![cfg(feature = "library-beets")] mod database; -- 2.47.1 From 538368ec38edbd7b5457ca52518c617969443375 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 12 Jan 2025 11:55:56 +0100 Subject: [PATCH 3/7] Update code --- src/external/database/serde/deserialize.rs | 4 +- src/external/database/serde/serialize.rs | 20 +++--- src/external/database/sql/backend.rs | 69 ++++++++------------- src/main.rs | 13 ++-- tests/files/database/database.db | Bin 24576 -> 20480 bytes tests/lib.rs | 10 +-- 6 files changed, 48 insertions(+), 68 deletions(-) diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index 007099e..89b8ef2 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -35,8 +35,8 @@ impl From for Collection { #[derive(Clone, Debug, Deserialize)] pub struct DeserializeArtist { pub name: String, - pub sort: Option, pub musicbrainz: DeserializeMbRefOption, + pub sort: Option, pub properties: HashMap>, pub albums: Vec, } @@ -45,9 +45,9 @@ pub struct DeserializeArtist { pub struct DeserializeAlbum { pub title: String, pub lib_id: SerdeAlbumLibId, + pub musicbrainz: DeserializeMbRefOption, pub date: SerdeAlbumDate, pub seq: u8, - pub musicbrainz: DeserializeMbRefOption, pub primary_type: Option, pub secondary_types: Vec, } diff --git a/src/external/database/serde/serialize.rs b/src/external/database/serde/serialize.rs index 197fc71..16d6dbb 100644 --- a/src/external/database/serde/serialize.rs +++ b/src/external/database/serde/serialize.rs @@ -1,4 +1,4 @@ -use std::collections::BTreeMap; +use std::collections::HashMap; use serde::Serialize; @@ -25,9 +25,9 @@ impl<'a> From<&'a Collection> for SerializeDatabase<'a> { #[derive(Debug, Serialize, PartialEq, Eq)] pub struct SerializeArtist<'a> { pub name: &'a str, - pub sort: Option<&'a str>, + pub sort: &'a Option, pub musicbrainz: SerializeMbRefOption<'a>, - pub properties: BTreeMap<&'a str, &'a Vec>, + pub properties: &'a HashMap>, pub albums: Vec>, } @@ -35,9 +35,9 @@ pub struct SerializeArtist<'a> { pub struct SerializeAlbum<'a> { pub title: &'a str, pub lib_id: SerdeAlbumLibId, + pub musicbrainz: SerializeMbRefOption<'a>, pub date: SerdeAlbumDate, pub seq: u8, - pub musicbrainz: SerializeMbRefOption<'a>, pub primary_type: Option, pub secondary_types: Vec, } @@ -75,15 +75,9 @@ impl<'a> From<&'a Artist> for SerializeArtist<'a> { fn from(artist: &'a Artist) -> Self { SerializeArtist { name: &artist.meta.id.name, - sort: artist.meta.sort.as_deref(), musicbrainz: (&artist.meta.id.mb_ref).into(), - properties: artist - .meta - .info - .properties - .iter() - .map(|(k, v)| (k.as_ref(), v)) - .collect(), + sort: &artist.meta.sort, + properties: &artist.meta.info.properties, albums: artist.albums.iter().map(Into::into).collect(), } } @@ -94,9 +88,9 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> { SerializeAlbum { title: &album.meta.id.title, lib_id: album.meta.id.lib_id.into(), + musicbrainz: (&album.meta.id.mb_ref).into(), date: album.meta.date.into(), seq: album.meta.seq.0, - musicbrainz: (&album.meta.id.mb_ref).into(), primary_type: album.meta.info.primary_type.map(Into::into), secondary_types: album .meta diff --git a/src/external/database/sql/backend.rs b/src/external/database/sql/backend.rs index f7af8fe..7d1b00a 100644 --- a/src/external/database/sql/backend.rs +++ b/src/external/database/sql/backend.rs @@ -105,9 +105,9 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { fn create_artists_table(&self) -> Result<(), Error> { let mut stmt = self.prepare( "CREATE TABLE IF NOT EXISTS artists ( - name TEXT NOT NULL PRIMARY KEY, - sort TEXT NULL, + name TEXT NOT NULL, mbid JSON NOT NULL DEFAULT '\"None\"', + sort TEXT NULL, properties JSON NOT NULL DEFAULT '{}' )", ); @@ -131,8 +131,7 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { day INT NULL, seq INT NOT NULL, primary_type JSON NOT NULL DEFAULT 'null', - secondary_types JSON NOT NULL DEFAULT '[]', - FOREIGN KEY (artist_name) REFERENCES artists(name) ON DELETE CASCADE ON UPDATE NO ACTION + secondary_types JSON NOT NULL DEFAULT '[]' )", ); Self::execute(&mut stmt, ()) @@ -178,12 +177,18 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { } fn select_all_artists(&self) -> Result, Error> { - let mut stmt = self.prepare_cached("SELECT name, sort, mbid, properties FROM artists"); + let mut stmt = self.prepare_cached("SELECT name, mbid, sort, properties FROM artists"); let mut rows = Self::query(&mut stmt, ())?; let mut artists = vec![]; while let Some(row) = Self::next_row(&mut rows)? { - artists.push(row.try_into()?); + artists.push(DeserializeArtist { + name: Self::get_value(row, 0)?, + musicbrainz: serde_json::from_str(&Self::get_value::(row, 1)?)?, + sort: Self::get_value(row, 2)?, + properties: serde_json::from_str(&Self::get_value::(row, 3)?)?, + albums: vec![], + }); } Ok(artists) @@ -214,52 +219,28 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { fn select_artist_albums(&self, artist_name: &str) -> Result, Error> { let mut stmt = self.prepare_cached( - "SELECT title, lib_id, year, month, day, seq, mbid, primary_type, secondary_types + "SELECT title, lib_id, mbid, year, month, day, seq, primary_type, secondary_types FROM albums WHERE artist_name = ?1", ); let mut rows = Self::query(&mut stmt, [artist_name])?; let mut albums = vec![]; while let Some(row) = Self::next_row(&mut rows)? { - albums.push(row.try_into()?); + albums.push(DeserializeAlbum { + title: Self::get_value(row, 0)?, + lib_id: serde_json::from_str(&Self::get_value::(row, 1)?)?, + musicbrainz: serde_json::from_str(&Self::get_value::(row, 2)?)?, + date: SerdeAlbumDate(AlbumDate::new( + Self::get_value(row, 3)?, + Self::get_value(row, 4)?, + Self::get_value(row, 5)?, + )), + seq: Self::get_value(row, 6)?, + primary_type: serde_json::from_str(&Self::get_value::(row, 7)?)?, + secondary_types: serde_json::from_str(&Self::get_value::(row, 8)?)?, + }); } Ok(albums) } } - -impl TryFrom<&Row<'_>> for DeserializeArtist { - type Error = Error; - - fn try_from(row: &Row<'_>) -> Result { - type Backend<'a> = SqlTransactionSqliteBackend<'a>; - Ok(DeserializeArtist { - name: Backend::get_value(row, 0)?, - sort: Backend::get_value(row, 1)?, - musicbrainz: serde_json::from_str(&Backend::get_value::(row, 2)?)?, - properties: serde_json::from_str(&Backend::get_value::(row, 3)?)?, - albums: vec![], - }) - } -} - -impl TryFrom<&Row<'_>> for DeserializeAlbum { - type Error = Error; - - fn try_from(row: &Row<'_>) -> Result { - type Backend<'a> = SqlTransactionSqliteBackend<'a>; - Ok(DeserializeAlbum { - title: Backend::get_value(row, 0)?, - lib_id: serde_json::from_str(&Backend::get_value::(row, 1)?)?, - date: SerdeAlbumDate(AlbumDate::new( - Backend::get_value(row, 2)?, - Backend::get_value(row, 3)?, - Backend::get_value(row, 4)?, - )), - seq: Backend::get_value(row, 5)?, - musicbrainz: serde_json::from_str(&Backend::get_value::(row, 6)?)?, - primary_type: serde_json::from_str(&Backend::get_value::(row, 7)?)?, - secondary_types: serde_json::from_str(&Backend::get_value::(row, 8)?)?, - }) - } -} diff --git a/src/main.rs b/src/main.rs index b7efbfa..655c47b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,7 +11,7 @@ use musichoard::{ track::TrackFormat, }, external::{ - database::json::{backend::JsonDatabaseFileBackend, JsonDatabase}, + database::sql::{backend::SqlDatabaseSqliteBackend, SqlDatabase}, library::beets::{ executor::{ssh::BeetsLibrarySshExecutor, BeetsLibraryProcessExecutor}, BeetsLibrary, @@ -141,7 +141,10 @@ fn with_database( { Ok(f) => { drop(f); - JsonDatabase::new(JsonDatabaseFileBackend::new(&db_opt.database_file_path)) + let db_exec = SqlDatabaseSqliteBackend::new(&db_opt.database_file_path) + .expect("failed to initialise SQLite database backend"); + SqlDatabase::new(db_exec) + .expect("failed to open new database") .save(&vec![]) .expect("failed to create empty database"); } @@ -151,8 +154,10 @@ fn with_database( }, } - let db_exec = JsonDatabaseFileBackend::new(&db_opt.database_file_path); - with(builder.set_database(JsonDatabase::new(db_exec))); + let db_exec = SqlDatabaseSqliteBackend::new(&db_opt.database_file_path) + .expect("failed to initialise SQLite database backend"); + let db = SqlDatabase::new(db_exec).expect("failed to open database"); + with(builder.set_database(db)); }; } diff --git a/tests/files/database/database.db b/tests/files/database/database.db index bf7a0cbf4438fa9acd90b0d2e2f8a1ed4c9811c6..d61193509f0fd6070ba013057c4233f9e4f96025 100644 GIT binary patch delta 253 zcmZoTz}T>Wae_P}>qG?)9u^*62EKp%TlqM6csC0Q%;c77u3%vomy~2|_by3H%1KSk zNh-}PhLEhAo4GGAN^&V61I@-_W_EFDX~t&T$=7-PChz4Ip3K2xHra(waq?_Flg=;`$7~8fYAtMS zCSS5KoczL8l~HGMfSvi|Rkqw5wT)3sZ1O;9QM=m$*^=^9q=;EpX6bTJ*aRiF^`71a&hj{w?aVa1J&Bl6W zc5!KG#^z9nW55;_Cl*as;B%N$0$kJ4!P$Wag!$RumWJ zWR|4HCzh7vgZc4L$HW^#8LXTC@kQ$}F=S7Uw!SHDoZS@ak(yYRn)j$-X0d`(VsUD2 zYF^1?3md1&{&tp=kJ%J}lv>!@Ob)a&lG)A57baY6xUlQOz6*OVY;Y{f&d*DnWUoKj)ZPSWfH{YSv5AR=sf8g}|15hY z;aV;R1_oCCbqxHE_^6)RM%UoXq4zR&i!yMl9}R0jY8; i%Fin)&P+*V2Ju{TO3P9+OEOcL_?cBXkzKRMK>z@i#jGCy diff --git a/tests/lib.rs b/tests/lib.rs index fbcc6e9..ab9c7bb 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -8,7 +8,7 @@ mod testlib; use musichoard::{ external::{ - database::json::{backend::JsonDatabaseFileBackend, JsonDatabase}, + database::sql::{backend::SqlDatabaseSqliteBackend, SqlDatabase}, library::beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary}, }, IMusicHoardBase, IMusicHoardDatabase, IMusicHoardLibrary, MusicHoard, @@ -28,8 +28,8 @@ fn merge_library_then_database() { .config(Some(&*library::beets::BEETS_TEST_CONFIG_PATH)); let library = BeetsLibrary::new(executor); - let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE); - let database = JsonDatabase::new(backend); + let backend = SqlDatabaseSqliteBackend::new(&*database::sql::DATABASE_TEST_FILE).unwrap(); + let database = SqlDatabase::new(backend).unwrap(); let mut music_hoard = MusicHoard::new(database, library); @@ -51,8 +51,8 @@ fn merge_database_then_library() { .config(Some(&*library::beets::BEETS_TEST_CONFIG_PATH)); let library = BeetsLibrary::new(executor); - let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE); - let database = JsonDatabase::new(backend); + let backend = SqlDatabaseSqliteBackend::new(&*database::sql::DATABASE_TEST_FILE).unwrap(); + let database = SqlDatabase::new(backend).unwrap(); let mut music_hoard = MusicHoard::new(database, library); -- 2.47.1 From 6238d533b1f8cb9460e958332d50077d81215078 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 12 Jan 2025 12:01:16 +0100 Subject: [PATCH 4/7] Avoid modifying test files --- tests/lib.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/tests/lib.rs b/tests/lib.rs index ab9c7bb..551af37 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -6,6 +6,8 @@ mod library; mod testlib; +use std::{fs, path::PathBuf}; + use musichoard::{ external::{ database::sql::{backend::SqlDatabaseSqliteBackend, SqlDatabase}, @@ -13,9 +15,16 @@ use musichoard::{ }, IMusicHoardBase, IMusicHoardDatabase, IMusicHoardLibrary, MusicHoard, }; +use tempfile::NamedTempFile; use crate::testlib::COLLECTION; +fn copy_file_into_temp>(path: P) -> NamedTempFile { + let temp = NamedTempFile::new().unwrap(); + fs::copy(path.into(), temp.path()).unwrap(); + temp +} + #[test] fn merge_library_then_database() { // Acquired the lock on the beets config file. We need to own the underlying object so later we @@ -28,7 +37,8 @@ fn merge_library_then_database() { .config(Some(&*library::beets::BEETS_TEST_CONFIG_PATH)); let library = BeetsLibrary::new(executor); - let backend = SqlDatabaseSqliteBackend::new(&*database::sql::DATABASE_TEST_FILE).unwrap(); + let file = copy_file_into_temp(&*database::sql::DATABASE_TEST_FILE); + let backend = SqlDatabaseSqliteBackend::new(file.path()).unwrap(); let database = SqlDatabase::new(backend).unwrap(); let mut music_hoard = MusicHoard::new(database, library); @@ -51,7 +61,8 @@ fn merge_database_then_library() { .config(Some(&*library::beets::BEETS_TEST_CONFIG_PATH)); let library = BeetsLibrary::new(executor); - let backend = SqlDatabaseSqliteBackend::new(&*database::sql::DATABASE_TEST_FILE).unwrap(); + let file = copy_file_into_temp(&*database::sql::DATABASE_TEST_FILE); + let backend = SqlDatabaseSqliteBackend::new(file.path()).unwrap(); let database = SqlDatabase::new(backend).unwrap(); let mut music_hoard = MusicHoard::new(database, library); -- 2.47.1 From 74b12e2ed0291fddd235493253cae15c0aaac5bc Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 12 Jan 2025 12:02:12 +0100 Subject: [PATCH 5/7] Fix lint --- src/external/database/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/external/database/mod.rs b/src/external/database/mod.rs index 7c046e0..3a2a7fa 100644 --- a/src/external/database/mod.rs +++ b/src/external/database/mod.rs @@ -1,5 +1,5 @@ #[cfg(feature = "database-sqlite")] pub mod sql; -#[cfg(any(feature = "database-sqlite"))] +#[cfg(feature = "database-sqlite")] mod serde; -- 2.47.1 From 88c4d1b55583b0632d814d2f135b6657324d9b6b Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 12 Jan 2025 12:08:19 +0100 Subject: [PATCH 6/7] Some renaming for consistency --- src/external/database/serde/deserialize.rs | 8 ++-- src/external/database/serde/serialize.rs | 8 ++-- src/external/database/sql/backend.rs | 10 ++--- src/external/database/sql/testmod.rs | 44 +++++++++++----------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/external/database/serde/deserialize.rs b/src/external/database/serde/deserialize.rs index 89b8ef2..0f4eb09 100644 --- a/src/external/database/serde/deserialize.rs +++ b/src/external/database/serde/deserialize.rs @@ -35,7 +35,7 @@ impl From for Collection { #[derive(Clone, Debug, Deserialize)] pub struct DeserializeArtist { pub name: String, - pub musicbrainz: DeserializeMbRefOption, + pub mb_ref: DeserializeMbRefOption, pub sort: Option, pub properties: HashMap>, pub albums: Vec, @@ -45,7 +45,7 @@ pub struct DeserializeArtist { pub struct DeserializeAlbum { pub title: String, pub lib_id: SerdeAlbumLibId, - pub musicbrainz: DeserializeMbRefOption, + pub mb_ref: DeserializeMbRefOption, pub date: SerdeAlbumDate, pub seq: u8, pub primary_type: Option, @@ -120,7 +120,7 @@ impl From for Artist { meta: ArtistMeta { id: ArtistId { name: artist.name, - mb_ref: artist.musicbrainz.into(), + mb_ref: artist.mb_ref.into(), }, sort: artist.sort, info: ArtistInfo { @@ -139,7 +139,7 @@ impl From for Album { id: AlbumId { title: album.title, lib_id: album.lib_id.into(), - mb_ref: album.musicbrainz.into(), + mb_ref: album.mb_ref.into(), }, date: album.date.into(), seq: AlbumSeq(album.seq), diff --git a/src/external/database/serde/serialize.rs b/src/external/database/serde/serialize.rs index 16d6dbb..dbb4145 100644 --- a/src/external/database/serde/serialize.rs +++ b/src/external/database/serde/serialize.rs @@ -25,8 +25,8 @@ impl<'a> From<&'a Collection> for SerializeDatabase<'a> { #[derive(Debug, Serialize, PartialEq, Eq)] pub struct SerializeArtist<'a> { pub name: &'a str, + pub mb_ref: SerializeMbRefOption<'a>, pub sort: &'a Option, - pub musicbrainz: SerializeMbRefOption<'a>, pub properties: &'a HashMap>, pub albums: Vec>, } @@ -35,7 +35,7 @@ pub struct SerializeArtist<'a> { pub struct SerializeAlbum<'a> { pub title: &'a str, pub lib_id: SerdeAlbumLibId, - pub musicbrainz: SerializeMbRefOption<'a>, + pub mb_ref: SerializeMbRefOption<'a>, pub date: SerdeAlbumDate, pub seq: u8, pub primary_type: Option, @@ -75,7 +75,7 @@ impl<'a> From<&'a Artist> for SerializeArtist<'a> { fn from(artist: &'a Artist) -> Self { SerializeArtist { name: &artist.meta.id.name, - musicbrainz: (&artist.meta.id.mb_ref).into(), + mb_ref: (&artist.meta.id.mb_ref).into(), sort: &artist.meta.sort, properties: &artist.meta.info.properties, albums: artist.albums.iter().map(Into::into).collect(), @@ -88,7 +88,7 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> { SerializeAlbum { title: &album.meta.id.title, lib_id: album.meta.id.lib_id.into(), - musicbrainz: (&album.meta.id.mb_ref).into(), + mb_ref: (&album.meta.id.mb_ref).into(), date: album.meta.date.into(), seq: album.meta.seq.0, primary_type: album.meta.info.primary_type.map(Into::into), diff --git a/src/external/database/sql/backend.rs b/src/external/database/sql/backend.rs index 7d1b00a..3ad96db 100644 --- a/src/external/database/sql/backend.rs +++ b/src/external/database/sql/backend.rs @@ -162,15 +162,15 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { fn insert_artist(&self, artist: &SerializeArtist<'_>) -> Result<(), Error> { let mut stmt = self.prepare_cached( - "INSERT INTO artists (name, sort, mbid, properties) + "INSERT INTO artists (name, mbid, sort, properties) VALUES (?1, ?2, ?3, ?4)", ); Self::execute( &mut stmt, ( artist.name, + serde_json::to_string(&artist.mb_ref)?, artist.sort, - serde_json::to_string(&artist.musicbrainz)?, serde_json::to_string(&artist.properties)?, ), ) @@ -184,7 +184,7 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { while let Some(row) = Self::next_row(&mut rows)? { artists.push(DeserializeArtist { name: Self::get_value(row, 0)?, - musicbrainz: serde_json::from_str(&Self::get_value::(row, 1)?)?, + mb_ref: serde_json::from_str(&Self::get_value::(row, 1)?)?, sort: Self::get_value(row, 2)?, properties: serde_json::from_str(&Self::get_value::(row, 3)?)?, albums: vec![], @@ -205,7 +205,7 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { ( album.title, serde_json::to_string(&album.lib_id)?, - serde_json::to_string(&album.musicbrainz)?, + serde_json::to_string(&album.mb_ref)?, artist_name, album.date.0.year, album.date.0.month, @@ -229,7 +229,7 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> { albums.push(DeserializeAlbum { title: Self::get_value(row, 0)?, lib_id: serde_json::from_str(&Self::get_value::(row, 1)?)?, - musicbrainz: serde_json::from_str(&Self::get_value::(row, 2)?)?, + mb_ref: serde_json::from_str(&Self::get_value::(row, 2)?)?, date: SerdeAlbumDate(AlbumDate::new( Self::get_value(row, 3)?, Self::get_value(row, 4)?, diff --git a/src/external/database/sql/testmod.rs b/src/external/database/sql/testmod.rs index c03a880..94046ad 100644 --- a/src/external/database/sql/testmod.rs +++ b/src/external/database/sql/testmod.rs @@ -21,10 +21,10 @@ pub static DATABASE_SQL_ARTISTS: Lazy> = Lazy::new(|| { vec![ DeserializeArtist { name: String::from("Album_Artist ‘A’"), - sort: None, - musicbrainz: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( + mb_ref: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( "00000000-0000-0000-0000-000000000000".try_into().unwrap(), ))), + sort: None, properties: HashMap::from([ ( String::from("MusicButler"), @@ -43,10 +43,10 @@ pub static DATABASE_SQL_ARTISTS: Lazy> = Lazy::new(|| { }, DeserializeArtist { name: String::from("Album_Artist ‘B’"), - sort: None, - musicbrainz: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( + mb_ref: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( "11111111-1111-1111-1111-111111111111".try_into().unwrap(), ))), + sort: None, properties: HashMap::from([ (String::from("MusicButler"), vec![ String::from("https://www.musicbutler.io/artist-page/111111111"), @@ -65,15 +65,15 @@ pub static DATABASE_SQL_ARTISTS: Lazy> = Lazy::new(|| { }, DeserializeArtist { name: String::from("The Album_Artist ‘C’"), + mb_ref: DeserializeMbRefOption(MbRefOption::CannotHaveMbid), sort: Some(String::from("Album_Artist ‘C’, The")), - musicbrainz: DeserializeMbRefOption(MbRefOption::CannotHaveMbid), properties: HashMap::new(), albums: vec![], }, DeserializeArtist { name: String::from("Album_Artist ‘D’"), + mb_ref: DeserializeMbRefOption(MbRefOption::None), sort: None, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), properties: HashMap::new(), albums: vec![], }, @@ -88,20 +88,20 @@ pub static DATABASE_SQL_ALBUMS: Lazy>> = L DeserializeAlbum { title: String::from("album_title a.a"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(1)), - date: SerdeAlbumDate(AlbumDate::new(Some(1998), None, None)), - seq: 1, - musicbrainz: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( + mb_ref: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( "00000000-0000-0000-0000-000000000000".try_into().unwrap(), ))), + date: SerdeAlbumDate(AlbumDate::new(Some(1998), None, None)), + seq: 1, primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, DeserializeAlbum { title: String::from("album_title a.b"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(2)), + mb_ref: DeserializeMbRefOption(MbRefOption::None), date: SerdeAlbumDate(AlbumDate::new(Some(2015), Some(4), None)), seq: 1, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, @@ -113,40 +113,40 @@ pub static DATABASE_SQL_ALBUMS: Lazy>> = L DeserializeAlbum { title: String::from("album_title b.a"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(3)), + mb_ref: DeserializeMbRefOption(MbRefOption::None), date: SerdeAlbumDate(AlbumDate::new(Some(2003), Some(6), Some(6))), seq: 1, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, DeserializeAlbum { title: String::from("album_title b.b"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(4)), - date: SerdeAlbumDate(AlbumDate::new(Some(2008), None, None)), - seq: 3, - musicbrainz: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( + mb_ref: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( "11111111-1111-1111-1111-111111111111".try_into().unwrap(), ))), + date: SerdeAlbumDate(AlbumDate::new(Some(2008), None, None)), + seq: 3, primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, DeserializeAlbum { title: String::from("album_title b.c"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(5)), - date: SerdeAlbumDate(AlbumDate::new(Some(2009), None, None)), - seq: 2, - musicbrainz: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( + mb_ref: DeserializeMbRefOption(MbRefOption::Some(DeserializeMbid( "11111111-1111-1111-1111-111111111112".try_into().unwrap(), ))), + date: SerdeAlbumDate(AlbumDate::new(Some(2009), None, None)), + seq: 2, primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, DeserializeAlbum { title: String::from("album_title b.d"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(6)), + mb_ref: DeserializeMbRefOption(MbRefOption::None), date: SerdeAlbumDate(AlbumDate::new(Some(2015), None, None)), seq: 4, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, @@ -158,18 +158,18 @@ pub static DATABASE_SQL_ALBUMS: Lazy>> = L DeserializeAlbum { title: String::from("album_title c.a"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(7)), + mb_ref: DeserializeMbRefOption(MbRefOption::None), date: SerdeAlbumDate(AlbumDate::new(Some(1985), None, None)), seq: 0, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, DeserializeAlbum { title: String::from("album_title c.b"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(8)), + mb_ref: DeserializeMbRefOption(MbRefOption::None), date: SerdeAlbumDate(AlbumDate::new(Some(2018), None, None)), seq: 0, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, @@ -181,9 +181,9 @@ pub static DATABASE_SQL_ALBUMS: Lazy>> = L DeserializeAlbum { title: String::from("album_title d.a"), lib_id: SerdeAlbumLibId(AlbumLibId::Value(9)), + mb_ref: DeserializeMbRefOption(MbRefOption::None), date: SerdeAlbumDate(AlbumDate::new(Some(1995), None, None)), seq: 0, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, @@ -192,7 +192,7 @@ pub static DATABASE_SQL_ALBUMS: Lazy>> = L lib_id: SerdeAlbumLibId(AlbumLibId::Value(10)), date: SerdeAlbumDate(AlbumDate::new(Some(2028), None, None)), seq: 0, - musicbrainz: DeserializeMbRefOption(MbRefOption::None), + mb_ref: DeserializeMbRefOption(MbRefOption::None), primary_type: Some(SerdeAlbumPrimaryType(AlbumPrimaryType::Album)), secondary_types: vec![], }, -- 2.47.1 From 35524336bbc45d099ed842d7ed14367c9bd9381b Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 12 Jan 2025 12:13:02 +0100 Subject: [PATCH 7/7] Fix coverage --- src/core/interface/database/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/core/interface/database/mod.rs b/src/core/interface/database/mod.rs index 3f9ab5f..27293d0 100644 --- a/src/core/interface/database/mod.rs +++ b/src/core/interface/database/mod.rs @@ -123,5 +123,9 @@ mod tests { let io_err: SaveError = io::Error::new(io::ErrorKind::Interrupted, "error").into(); assert!(!io_err.to_string().is_empty()); assert!(!format!("{:?}", io_err).is_empty()); + + let sd_err: SaveError = SaveError::SerDeError(String::from("serde")); + assert!(!sd_err.to_string().is_empty()); + assert!(!format!("{:?}", sd_err).is_empty()); } } -- 2.47.1