From 99dc27da1650a6fd45ac7fce6eeba8d65aa3ed37 Mon Sep 17 00:00:00 2001 From: Kubat <mael.martin31@gmail.com> Date: Thu, 5 Jan 2023 21:54:26 +0100 Subject: [PATCH] LIBLEKTOR-RS: DB now supports multiple languages per kara --- .../2022-09-30-204512_initial/down.sql | 3 +- .../2022-09-30-204512_initial/up.sql | 7 ++++- .../liblektor-rs/lektor_db/src/connexion.rs | 28 ++++++++++++------- src/rust/liblektor-rs/lektor_db/src/lib.rs | 2 +- src/rust/liblektor-rs/lektor_db/src/models.rs | 8 +++++- src/rust/liblektor-rs/lektor_db/src/schema.rs | 12 ++++++-- 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/down.sql b/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/down.sql index cee1b6a5..b24c8023 100644 --- a/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/down.sql +++ b/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/down.sql @@ -6,4 +6,5 @@ DROP TABLE kara_tag; DROP TABLE tag; DROP TABLE kara_tags; DROP TABLE history; -DROP TABLE iso_639_1; \ No newline at end of file +DROP TABLE iso_639_1; +DROP TABLE kara_langs; \ No newline at end of file diff --git a/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/up.sql b/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/up.sql index dd9b2691..dcd18261 100644 --- a/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/up.sql +++ b/src/rust/liblektor-rs/lektor_db/migrations/2022-09-30-204512_initial/up.sql @@ -23,7 +23,6 @@ CREATE TABLE kara , song_type TEXT NOT NULL , song_origin TEXT NOT NULL , source_name TEXT NOT NULL - , language TEXT NOT NULL REFERENCES iso_639_1(code) , file_hash TEXT NOT NULL UNIQUE ); @@ -65,6 +64,12 @@ CREATE TABLE iso_639_1 , is_macro BOOLEAN NOT NULL DEFAULT false ); +CREATE TABLE kara_langs + ( id INTEGER NOT NULL REFERENCES kara ON DELETE CASCADE + , code TEXT NOT NULL REFERENCES iso_639_1 ON DELETE CASCADE + , PRIMARY KEY (id, code) + ); + -- As defined in ISO 639-1: -- https://archive.wikiwix.com/cache/index2.php?url=http%3A%2F%2Fwww.sil.org%2Fiso639-3%2Fcodes.asp%3Forder%3D639_1%26letter%3D%2525#federation=archive.wikiwix.com&tab=url INSERT OR REPLACE INTO iso_639_1 (is_macro, is_iso, code, name_en) VALUES diff --git a/src/rust/liblektor-rs/lektor_db/src/connexion.rs b/src/rust/liblektor-rs/lektor_db/src/connexion.rs index 68047761..75907ae3 100644 --- a/src/rust/liblektor-rs/lektor_db/src/connexion.rs +++ b/src/rust/liblektor-rs/lektor_db/src/connexion.rs @@ -98,24 +98,33 @@ impl LktDatabaseConnection { /// Ensure that a given language is present in the database. If it's not /// insert it. Existence test is done on the code of the language. - pub fn ensure_language_exists(&mut self, lang: &Language) -> LktDatabaseResult<()> { + pub fn ensure_languages_exist<'a>(&mut self, langs: &[Language<'a>]) -> LktDatabaseResult<()> { self.sqlite.exclusive_transaction(|c| { - with_dsl!(iso_639_1 => match iso_639_1.filter(code.eq(lang.code)).count().get_result(c)? { - 1 => Ok(()), - 0 => { diesel::insert_into(iso_639_1).values(lang).execute(c)?; Ok(()) } - count => Err(LktDatabaseError::String(format!("language `{lang:?}` has {count} occurences in the database..."))), - }) + for lang in langs { + with_dsl!(iso_639_1 => match iso_639_1.filter(code.eq(lang.code)).count().get_result(c)? { + 1 => {}, + 0 => { diesel::insert_into(iso_639_1).values(langs).execute(c)?; } + count => return Err(LktDatabaseError::String(format!("language `{lang:?}` has {count} occurences in the database..."))), + }) + } + Ok(()) }) } /// Add a kara with a request. pub fn add_kara_from_request(&mut self, kara: NewKaraRequest) -> LktDatabaseResult<()> { - let (id, new_kara, lang, karamakers, tags) = kara; - self.ensure_language_exists(&lang)?; + let (id, new_kara, karamakers, langs, tags) = kara; + self.ensure_languages_exist(&langs)?; self.sqlite.exclusive_transaction(|c| { with_dsl!(kara => diesel::insert_into(kara).values(&new_kara).execute(c)?); with_dsl!(repo_kara => diesel::insert_into(repo_kara).values(id).execute(c)?); with_dsl!(kara_makers => diesel::insert_or_ignore_into(kara_makers).values(karamakers).execute(c)?); + with_dsl!(kara_langs => { + use models::{Language, KaraLanguage}; + let langs = langs.into_iter().map(|Language { code: lang, .. }| KaraLanguage { id: new_kara.id, code: lang } ); + diesel::delete(kara_langs.filter(id.eq(new_kara.id))).execute(c)?; + diesel::insert_into(kara_langs).values(langs.collect::<Vec<_>>()).execute(c)?; + }); with_dsl!(kara_tags => { diesel::delete(kara_tags.filter(kara_id.eq(new_kara.id))).execute(c)?; diesel::insert_into(kara_tags).values(tags).execute(c)?; @@ -153,10 +162,9 @@ impl LktDatabaseConnection { song_type: kara.song_type, song_origin: kara.category, source_name: kara.source_name, - language: lang.code, file_hash: format!("{}", kara.unix_timestamp), }; - Ok((id, kara, lang, kara_makers, tags)) + Ok((id, kara, kara_makers, vec![lang], tags)) } /// Peek the next kara to play diff --git a/src/rust/liblektor-rs/lektor_db/src/lib.rs b/src/rust/liblektor-rs/lektor_db/src/lib.rs index 8f8e39f1..4043328d 100644 --- a/src/rust/liblektor-rs/lektor_db/src/lib.rs +++ b/src/rust/liblektor-rs/lektor_db/src/lib.rs @@ -14,7 +14,7 @@ pub(self) use std::{collections::VecDeque, ops::Range, path::Path}; pub type NewKaraRequest<'a> = ( models::KaraId, models::NewKara<'a>, - models::Language<'a>, Vec<models::KaraMaker<'a>>, + Vec<models::Language<'a>>, Vec<models::AddKaraTag>, ); diff --git a/src/rust/liblektor-rs/lektor_db/src/models.rs b/src/rust/liblektor-rs/lektor_db/src/models.rs index c8c2b21c..60940e02 100644 --- a/src/rust/liblektor-rs/lektor_db/src/models.rs +++ b/src/rust/liblektor-rs/lektor_db/src/models.rs @@ -28,7 +28,6 @@ pub struct NewKara<'a> { pub song_type: &'a str, pub song_origin: &'a str, pub source_name: &'a str, - pub language: &'a str, pub file_hash: String, } @@ -39,6 +38,13 @@ pub struct KaraMaker<'a> { pub name: &'a str, } +#[derive(Debug, Insertable, Queryable, Selectable)] +#[diesel(table_name = kara_langs)] +pub struct KaraLanguage<'a> { + pub id: i32, + pub code: &'a str, +} + #[derive(Debug, Insertable, Queryable, Selectable)] #[diesel(table_name = iso_639_1)] pub struct Language<'a> { diff --git a/src/rust/liblektor-rs/lektor_db/src/schema.rs b/src/rust/liblektor-rs/lektor_db/src/schema.rs index d45ece40..48a94b8b 100644 --- a/src/rust/liblektor-rs/lektor_db/src/schema.rs +++ b/src/rust/liblektor-rs/lektor_db/src/schema.rs @@ -24,11 +24,17 @@ diesel::table! { song_type -> Text, song_origin -> Text, source_name -> Text, - language -> Text, file_hash -> Text, } } +diesel::table! { + kara_langs (id, code) { + id -> Integer, + code -> Text, + } +} + diesel::table! { kara_makers (id, name) { id -> Integer, @@ -67,7 +73,8 @@ diesel::table! { } diesel::joinable!(history -> kara (id)); -diesel::joinable!(kara -> iso_639_1 (language)); +diesel::joinable!(kara_langs -> iso_639_1 (code)); +diesel::joinable!(kara_langs -> kara (id)); diesel::joinable!(kara_makers -> kara (id)); diesel::joinable!(kara_tags -> kara (kara_id)); diesel::joinable!(kara_tags -> tag (tag_id)); @@ -78,6 +85,7 @@ diesel::allow_tables_to_appear_in_same_query!( history, iso_639_1, kara, + kara_langs, kara_makers, kara_tags, repo, -- GitLab