Update code

This commit is contained in:
Wojciech Kozlowski 2025-01-12 11:55:56 +01:00
parent a5ea60cc98
commit 538368ec38
6 changed files with 48 additions and 68 deletions

View File

@ -35,8 +35,8 @@ impl From<DeserializeDatabase> for Collection {
#[derive(Clone, Debug, Deserialize)] #[derive(Clone, Debug, Deserialize)]
pub struct DeserializeArtist { pub struct DeserializeArtist {
pub name: String, pub name: String,
pub sort: Option<String>,
pub musicbrainz: DeserializeMbRefOption, pub musicbrainz: DeserializeMbRefOption,
pub sort: Option<String>,
pub properties: HashMap<String, Vec<String>>, pub properties: HashMap<String, Vec<String>>,
pub albums: Vec<DeserializeAlbum>, pub albums: Vec<DeserializeAlbum>,
} }
@ -45,9 +45,9 @@ pub struct DeserializeArtist {
pub struct DeserializeAlbum { pub struct DeserializeAlbum {
pub title: String, pub title: String,
pub lib_id: SerdeAlbumLibId, pub lib_id: SerdeAlbumLibId,
pub musicbrainz: DeserializeMbRefOption,
pub date: SerdeAlbumDate, pub date: SerdeAlbumDate,
pub seq: u8, pub seq: u8,
pub musicbrainz: DeserializeMbRefOption,
pub primary_type: Option<SerdeAlbumPrimaryType>, pub primary_type: Option<SerdeAlbumPrimaryType>,
pub secondary_types: Vec<SerdeAlbumSecondaryType>, pub secondary_types: Vec<SerdeAlbumSecondaryType>,
} }

View File

@ -1,4 +1,4 @@
use std::collections::BTreeMap; use std::collections::HashMap;
use serde::Serialize; use serde::Serialize;
@ -25,9 +25,9 @@ impl<'a> From<&'a Collection> for SerializeDatabase<'a> {
#[derive(Debug, Serialize, PartialEq, Eq)] #[derive(Debug, Serialize, PartialEq, Eq)]
pub struct SerializeArtist<'a> { pub struct SerializeArtist<'a> {
pub name: &'a str, pub name: &'a str,
pub sort: Option<&'a str>, pub sort: &'a Option<String>,
pub musicbrainz: SerializeMbRefOption<'a>, pub musicbrainz: SerializeMbRefOption<'a>,
pub properties: BTreeMap<&'a str, &'a Vec<String>>, pub properties: &'a HashMap<String, Vec<String>>,
pub albums: Vec<SerializeAlbum<'a>>, pub albums: Vec<SerializeAlbum<'a>>,
} }
@ -35,9 +35,9 @@ pub struct SerializeArtist<'a> {
pub struct SerializeAlbum<'a> { pub struct SerializeAlbum<'a> {
pub title: &'a str, pub title: &'a str,
pub lib_id: SerdeAlbumLibId, pub lib_id: SerdeAlbumLibId,
pub musicbrainz: SerializeMbRefOption<'a>,
pub date: SerdeAlbumDate, pub date: SerdeAlbumDate,
pub seq: u8, pub seq: u8,
pub musicbrainz: SerializeMbRefOption<'a>,
pub primary_type: Option<SerdeAlbumPrimaryType>, pub primary_type: Option<SerdeAlbumPrimaryType>,
pub secondary_types: Vec<SerdeAlbumSecondaryType>, pub secondary_types: Vec<SerdeAlbumSecondaryType>,
} }
@ -75,15 +75,9 @@ impl<'a> From<&'a Artist> for SerializeArtist<'a> {
fn from(artist: &'a Artist) -> Self { fn from(artist: &'a Artist) -> Self {
SerializeArtist { SerializeArtist {
name: &artist.meta.id.name, name: &artist.meta.id.name,
sort: artist.meta.sort.as_deref(),
musicbrainz: (&artist.meta.id.mb_ref).into(), musicbrainz: (&artist.meta.id.mb_ref).into(),
properties: artist sort: &artist.meta.sort,
.meta properties: &artist.meta.info.properties,
.info
.properties
.iter()
.map(|(k, v)| (k.as_ref(), v))
.collect(),
albums: artist.albums.iter().map(Into::into).collect(), albums: artist.albums.iter().map(Into::into).collect(),
} }
} }
@ -94,9 +88,9 @@ impl<'a> From<&'a Album> for SerializeAlbum<'a> {
SerializeAlbum { SerializeAlbum {
title: &album.meta.id.title, title: &album.meta.id.title,
lib_id: album.meta.id.lib_id.into(), lib_id: album.meta.id.lib_id.into(),
musicbrainz: (&album.meta.id.mb_ref).into(),
date: album.meta.date.into(), date: album.meta.date.into(),
seq: album.meta.seq.0, seq: album.meta.seq.0,
musicbrainz: (&album.meta.id.mb_ref).into(),
primary_type: album.meta.info.primary_type.map(Into::into), primary_type: album.meta.info.primary_type.map(Into::into),
secondary_types: album secondary_types: album
.meta .meta

View File

@ -105,9 +105,9 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> {
fn create_artists_table(&self) -> Result<(), Error> { fn create_artists_table(&self) -> Result<(), Error> {
let mut stmt = self.prepare( let mut stmt = self.prepare(
"CREATE TABLE IF NOT EXISTS artists ( "CREATE TABLE IF NOT EXISTS artists (
name TEXT NOT NULL PRIMARY KEY, name TEXT NOT NULL,
sort TEXT NULL,
mbid JSON NOT NULL DEFAULT '\"None\"', mbid JSON NOT NULL DEFAULT '\"None\"',
sort TEXT NULL,
properties JSON NOT NULL DEFAULT '{}' properties JSON NOT NULL DEFAULT '{}'
)", )",
); );
@ -131,8 +131,7 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> {
day INT NULL, day INT NULL,
seq INT NOT NULL, seq INT NOT NULL,
primary_type JSON NOT NULL DEFAULT 'null', primary_type JSON NOT NULL DEFAULT 'null',
secondary_types JSON NOT NULL DEFAULT '[]', secondary_types JSON NOT NULL DEFAULT '[]'
FOREIGN KEY (artist_name) REFERENCES artists(name) ON DELETE CASCADE ON UPDATE NO ACTION
)", )",
); );
Self::execute(&mut stmt, ()) Self::execute(&mut stmt, ())
@ -178,12 +177,18 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> {
} }
fn select_all_artists(&self) -> Result<Vec<DeserializeArtist>, Error> { fn select_all_artists(&self) -> Result<Vec<DeserializeArtist>, 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 rows = Self::query(&mut stmt, ())?;
let mut artists = vec![]; let mut artists = vec![];
while let Some(row) = Self::next_row(&mut rows)? { 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::<String>(row, 1)?)?,
sort: Self::get_value(row, 2)?,
properties: serde_json::from_str(&Self::get_value::<String>(row, 3)?)?,
albums: vec![],
});
} }
Ok(artists) Ok(artists)
@ -214,52 +219,28 @@ impl ISqlTransactionBackend for SqlTransactionSqliteBackend<'_> {
fn select_artist_albums(&self, artist_name: &str) -> Result<Vec<DeserializeAlbum>, Error> { fn select_artist_albums(&self, artist_name: &str) -> Result<Vec<DeserializeAlbum>, Error> {
let mut stmt = self.prepare_cached( 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", FROM albums WHERE artist_name = ?1",
); );
let mut rows = Self::query(&mut stmt, [artist_name])?; let mut rows = Self::query(&mut stmt, [artist_name])?;
let mut albums = vec![]; let mut albums = vec![];
while let Some(row) = Self::next_row(&mut rows)? { 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::<String>(row, 1)?)?,
musicbrainz: serde_json::from_str(&Self::get_value::<String>(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::<String>(row, 7)?)?,
secondary_types: serde_json::from_str(&Self::get_value::<String>(row, 8)?)?,
});
} }
Ok(albums) Ok(albums)
} }
} }
impl TryFrom<&Row<'_>> for DeserializeArtist {
type Error = Error;
fn try_from(row: &Row<'_>) -> Result<Self, Self::Error> {
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::<String>(row, 2)?)?,
properties: serde_json::from_str(&Backend::get_value::<String>(row, 3)?)?,
albums: vec![],
})
}
}
impl TryFrom<&Row<'_>> for DeserializeAlbum {
type Error = Error;
fn try_from(row: &Row<'_>) -> Result<Self, Self::Error> {
type Backend<'a> = SqlTransactionSqliteBackend<'a>;
Ok(DeserializeAlbum {
title: Backend::get_value(row, 0)?,
lib_id: serde_json::from_str(&Backend::get_value::<String>(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::<String>(row, 6)?)?,
primary_type: serde_json::from_str(&Backend::get_value::<String>(row, 7)?)?,
secondary_types: serde_json::from_str(&Backend::get_value::<String>(row, 8)?)?,
})
}
}

View File

@ -11,7 +11,7 @@ use musichoard::{
track::TrackFormat, track::TrackFormat,
}, },
external::{ external::{
database::json::{backend::JsonDatabaseFileBackend, JsonDatabase}, database::sql::{backend::SqlDatabaseSqliteBackend, SqlDatabase},
library::beets::{ library::beets::{
executor::{ssh::BeetsLibrarySshExecutor, BeetsLibraryProcessExecutor}, executor::{ssh::BeetsLibrarySshExecutor, BeetsLibraryProcessExecutor},
BeetsLibrary, BeetsLibrary,
@ -141,7 +141,10 @@ fn with_database<Library: ILibrary + 'static>(
{ {
Ok(f) => { Ok(f) => {
drop(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![]) .save(&vec![])
.expect("failed to create empty database"); .expect("failed to create empty database");
} }
@ -151,8 +154,10 @@ fn with_database<Library: ILibrary + 'static>(
}, },
} }
let db_exec = JsonDatabaseFileBackend::new(&db_opt.database_file_path); let db_exec = SqlDatabaseSqliteBackend::new(&db_opt.database_file_path)
with(builder.set_database(JsonDatabase::new(db_exec))); .expect("failed to initialise SQLite database backend");
let db = SqlDatabase::new(db_exec).expect("failed to open database");
with(builder.set_database(db));
}; };
} }

Binary file not shown.

View File

@ -8,7 +8,7 @@ mod testlib;
use musichoard::{ use musichoard::{
external::{ external::{
database::json::{backend::JsonDatabaseFileBackend, JsonDatabase}, database::sql::{backend::SqlDatabaseSqliteBackend, SqlDatabase},
library::beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary}, library::beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary},
}, },
IMusicHoardBase, IMusicHoardDatabase, IMusicHoardLibrary, MusicHoard, IMusicHoardBase, IMusicHoardDatabase, IMusicHoardLibrary, MusicHoard,
@ -28,8 +28,8 @@ fn merge_library_then_database() {
.config(Some(&*library::beets::BEETS_TEST_CONFIG_PATH)); .config(Some(&*library::beets::BEETS_TEST_CONFIG_PATH));
let library = BeetsLibrary::new(executor); let library = BeetsLibrary::new(executor);
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE); let backend = SqlDatabaseSqliteBackend::new(&*database::sql::DATABASE_TEST_FILE).unwrap();
let database = JsonDatabase::new(backend); let database = SqlDatabase::new(backend).unwrap();
let mut music_hoard = MusicHoard::new(database, library); 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)); .config(Some(&*library::beets::BEETS_TEST_CONFIG_PATH));
let library = BeetsLibrary::new(executor); let library = BeetsLibrary::new(executor);
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE); let backend = SqlDatabaseSqliteBackend::new(&*database::sql::DATABASE_TEST_FILE).unwrap();
let database = JsonDatabase::new(backend); let database = SqlDatabase::new(backend).unwrap();
let mut music_hoard = MusicHoard::new(database, library); let mut music_hoard = MusicHoard::new(database, library);