diff --git a/src/rust/lektor_db/src/connexion.rs b/src/rust/lektor_db/src/connexion.rs
index 26c30f7ba1beac6d1646d3ca9466846a9dddfc9e..943540e9b00986b4c36c2c314e7d19f937fda0ed 100644
--- a/src/rust/lektor_db/src/connexion.rs
+++ b/src/rust/lektor_db/src/connexion.rs
@@ -115,33 +115,24 @@ impl LktDatabaseConnection {
         })
     }
 
-    /// Delete a kara with its id in a repo.
-    pub fn delete_kara_by_repo(
-        &mut self,
-        arg_repo_id: i64,
-        arg_kara_id: i64,
-    ) -> LktDatabaseResult<()> {
-        self.sqlite.exclusive_transaction(|c| {
+    /// Delete a kara.
+    pub fn delete_kara(&mut self, filter: DeleteKaraFilter) -> LktDatabaseResult<()> {
+        self.sqlite.exclusive_transaction(|conn| {
             with_dsl!(repo_kara => {
-                let local_id = repo_kara
-                    .filter(repo_id.eq(arg_repo_id))
-                    .filter(repo_kara_id.eq(arg_kara_id))
-                    .first::<KaraId>(c)?
-                    .local_kara_id;
-                diesel::delete(repo_kara.filter(local_kara_id.eq(local_id))).execute(c)?;
+                let local_id = match filter {
+                    DeleteKaraFilter::ByLocalId(KaraFilterByLocalId { local_id }) => local_id,
+                    DeleteKaraFilter::ByRepoId(KaraFilterByRepoId { repo_id: rid, kara_id: kid }) => repo_kara
+                        .filter(repo_id.eq(rid))
+                        .filter(repo_kara_id.eq(kid))
+                        .first::<KaraId>(conn)?
+                        .local_kara_id
+                };
+                diesel::delete(repo_kara.filter(local_kara_id.eq(local_id))).execute(conn)?;
                 Ok(())
             })
         })
     }
 
-    /// Delete a kara by its local ID.
-    pub fn delete_kara_by_local_id(&mut self, local_id: i64) -> LktDatabaseResult<()> {
-        self.sqlite.exclusive_transaction(|c| {
-            with_dsl!(repo_kara => diesel::delete(repo_kara.filter(local_kara_id.eq(local_id))).execute(c)?);
-            Ok(())
-        })
-    }
-
     /// 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.
     fn ensure_languages_exist<'a>(&mut self, langs: &[NewLanguage<'a>]) -> LktDatabaseResult<()> {
@@ -169,18 +160,17 @@ impl LktDatabaseConnection {
         })
     }
 
-    /// Add a kara with a request.
+    /// Add a kara with a request. At this point any tag and language and
+    /// karamaker must exist in the database.
     pub fn add_kara_from_request(&mut self, kara: NewKaraRequest) -> LktDatabaseResult<()> {
         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_maker => diesel::insert_or_ignore_into(kara_maker).values(karamakers).execute(c)?);
             with_dsl!(kara_lang  => {
-                let langs = langs.into_iter().map(|NewLanguage { code: lang, .. }| NewKaraLanguage { id: new_kara.id, code: lang } );
                 diesel::delete(kara_lang.filter(id.eq(new_kara.id))).execute(c)?;
-                diesel::insert_into(kara_lang).values(langs.collect::<Vec<_>>()).execute(c)?;
+                diesel::insert_into(kara_lang).values(langs).execute(c)?;
             });
             with_dsl!(kara_tag => {
                 diesel::delete(kara_tag.filter(kara_id.eq(new_kara.id))).execute(c)?;
@@ -202,7 +192,13 @@ impl LktDatabaseConnection {
             local_kara_id: local_id,
             repo_kara_id: kara.id,
         };
-        let lang = NewLanguage::from(kara.get_language());
+        let lang = {
+            self.ensure_languages_exist(&[NewLanguage::from(kara.get_language())])?;
+            AddKaraLanguage {
+                id: kara.id,
+                code: kara.language,
+            }
+        };
         let kara_maker = vec![NewKaraMaker {
             id: local_id,
             name: kara.author_name,
diff --git a/src/rust/lektor_db/src/lib.rs b/src/rust/lektor_db/src/lib.rs
index 9767296a3514c3d536855b90563d8e995ca8caf1..379f5329c9d53ac8348bb8509318ea15c304bb3c 100644
--- a/src/rust/lektor_db/src/lib.rs
+++ b/src/rust/lektor_db/src/lib.rs
@@ -4,9 +4,9 @@
 
 pub mod connexion;
 pub mod error;
+pub mod models;
 pub mod queue;
 
-pub(self) mod models;
 pub(self) mod schema;
 
 pub(self) use diesel::prelude::*;
@@ -14,10 +14,10 @@ pub(self) use error::*;
 pub(self) use std::{collections::VecDeque, ops::Range, path::Path};
 
 /// All the information needed to add a kara recieved from a repo!
-pub(self) type NewKaraRequest<'a> = (
+pub type NewKaraRequest<'a> = (
     models::KaraId,
     models::NewKara<'a>,
     Vec<models::NewKaraMaker<'a>>,
-    Vec<models::NewLanguage<'a>>,
+    Vec<models::AddKaraLanguage<'a>>,
     Vec<models::AddKaraTag<'a>>,
 );
diff --git a/src/rust/lektor_db/src/models.rs b/src/rust/lektor_db/src/models.rs
index c4b5305218d9900b161f95d151d635885e56fa41..b42f25edebc82387fb70732815dc6d20747e5065 100644
--- a/src/rust/lektor_db/src/models.rs
+++ b/src/rust/lektor_db/src/models.rs
@@ -1,7 +1,13 @@
 //! Models used for querying, inserting or updating the database.
 
 use crate::{schema::*, *};
-use diesel::{deserialize::FromSqlRow, expression::AsExpression, sql_types};
+use diesel::{
+    deserialize::{self, FromSqlRow},
+    expression::AsExpression,
+    serialize::{self, ToSql},
+    sql_types,
+    sqlite::Sqlite,
+};
 use kurisu_api::v1 as api_v1;
 
 #[derive(Debug, Insertable, Queryable, Selectable)]
@@ -24,7 +30,7 @@ pub struct HistoryRecord {
 
 #[derive(Insertable)]
 #[diesel(table_name = repo)]
-pub struct NewRepo<'a> {
+pub(crate) struct NewRepo<'a> {
     pub id: i64,
     pub name: &'a str,
 }
@@ -50,7 +56,7 @@ pub struct NewKaraMaker<'a> {
 /// Add a new language to a kara. The language must exists in the database.
 #[derive(Debug, Insertable)]
 #[diesel(table_name = kara_lang)]
-pub struct NewKaraLanguage<'a> {
+pub struct AddKaraLanguage<'a> {
     pub id: i64,
     pub code: &'a str,
 }
@@ -58,7 +64,7 @@ pub struct NewKaraLanguage<'a> {
 /// Add a new language to the database. Will be deprecated.
 #[derive(Debug, Insertable)]
 #[diesel(table_name = iso_639_1)]
-pub struct NewLanguage<'a> {
+pub(crate) struct NewLanguage<'a> {
     pub code: &'a str,
     pub name_en: &'a str,
     pub is_iso: bool,
@@ -92,25 +98,28 @@ pub struct AddKaraTag<'a> {
 
 #[derive(Debug, Insertable)]
 #[diesel(table_name = tag)]
-pub struct NewTag<'a> {
+pub(crate) struct NewTag<'a> {
     pub id: i64,
     pub name: &'a str,
 }
 
-impl<'a> diesel::serialize::ToSql<sql_types::Nullable<sql_types::Text>, diesel::sqlite::Sqlite>
-    for KaraTagValue<'a>
-{
-    fn to_sql<'b>(
-        &'b self,
-        out: &mut diesel::serialize::Output<'b, '_, diesel::sqlite::Sqlite>,
-    ) -> diesel::serialize::Result {
+impl<'a> ToSql<sql_types::Nullable<sql_types::Text>, Sqlite> for KaraTagValue<'a> {
+    fn to_sql<'b>(&'b self, out: &mut serialize::Output<'b, '_, Sqlite>) -> serialize::Result {
         match self {
-            KaraTagValue::None => return Ok(diesel::serialize::IsNull::Yes),
+            KaraTagValue::None => return Ok(serialize::IsNull::Yes),
             KaraTagValue::Str(str) => out.set_value(*str),
             KaraTagValue::String(str) => out.set_value(str.as_str()),
             KaraTagValue::Integer(int) => out.set_value(format!("{int}")),
         };
-        Ok(diesel::serialize::IsNull::No)
+        Ok(serialize::IsNull::No)
+    }
+}
+
+impl<'a> FromSqlRow<sql_types::Nullable<sql_types::Text>, Sqlite> for KaraTagValue<'a> {
+    fn build_from_row<'b>(row: &impl diesel::row::Row<'b, Sqlite>) -> deserialize::Result<Self> {
+        Ok(row
+            .get_value::<sql_types::Nullable<sql_types::Text>, Option<String>, usize>(0)?
+            .map_or(KaraTagValue::None, KaraTagValue::String))
     }
 }
 
@@ -129,14 +138,14 @@ impl<'a> From<api_v1::Language<'a>> for NewLanguage<'a> {
 
 #[derive(Queryable, Selectable)]
 #[diesel(table_name = tag)]
-pub struct Tag {
+pub(crate) struct Tag {
     pub id: i64,
     pub name: String,
 }
 
 #[derive(Queryable, Selectable)]
 #[diesel(table_name = kara)]
-pub struct Kara {
+pub(crate) struct Kara {
     pub id: i64,
     pub is_dl: bool,
     pub song_title: String,
@@ -145,3 +154,25 @@ pub struct Kara {
     pub source_name: String,
     pub file_hash: String,
 }
+
+#[derive(Debug, Queryable)]
+#[diesel(table_name = repo_kara)]
+pub struct KaraFilterByRepoId {
+    pub repo_id: i64,
+
+    #[diesel(column_name = "repo_kara_id")]
+    pub kara_id: i64,
+}
+
+#[derive(Debug, Queryable)]
+#[diesel(table_name = repo_kara)]
+pub struct KaraFilterByLocalId {
+    #[diesel(column_name = "local_kara_id")]
+    pub local_id: i64,
+}
+
+#[derive(Debug)]
+pub enum DeleteKaraFilter {
+    ByLocalId(KaraFilterByLocalId),
+    ByRepoId(KaraFilterByRepoId),
+}
diff --git a/src/rust/lektor_unsafe/src/db.rs b/src/rust/lektor_unsafe/src/db.rs
index a17a4fe57014f00724296483cd1e700182d5a663..7ad17c31a04db81b26cba305c40e2a2b5ed2961d 100644
--- a/src/rust/lektor_unsafe/src/db.rs
+++ b/src/rust/lektor_unsafe/src/db.rs
@@ -5,7 +5,10 @@
 //! defined in lektor's C code...
 
 use crate::*;
-use lektor_db::connexion::LktDatabaseConnection;
+use lektor_db::{
+    connexion::LktDatabaseConnection,
+    models::{DeleteKaraFilter, KaraFilterByLocalId, KaraFilterByRepoId},
+};
 
 /// Wrap the [`establish_connection`] function. On error log the message and
 /// return a [`std::ptr::null_mut`].
@@ -60,8 +63,12 @@ pub unsafe extern "C" fn lkt_database_delete_kara_by_repo(
     repo: i64,
     kara: i64,
 ) -> bool {
-    let db = db.as_mut().expect("passing a nullptr as db handle");
-    db.delete_kara_by_repo(repo, kara)
+    db.as_mut()
+        .expect("passing a nullptr as db handle")
+        .delete_kara(DeleteKaraFilter::ByRepoId(KaraFilterByRepoId {
+            repo_id: repo,
+            kara_id: kara,
+        }))
         .map_err(|err| error!(target: "DB", "delete_kara_by_repo failed: {err}"))
         .is_ok()
 }
@@ -77,8 +84,11 @@ pub unsafe extern "C" fn lkt_database_delete_kara_by_local_id(
     db: *mut LktDatabaseConnection,
     local_id: i64,
 ) -> bool {
-    let db = db.as_mut().expect("passing a nullptr as db handle");
-    db.delete_kara_by_local_id(local_id)
+    db.as_mut()
+        .expect("passing a nullptr as db handle")
+        .delete_kara(DeleteKaraFilter::ByLocalId(KaraFilterByLocalId {
+            local_id,
+        }))
         .map_err(|err| error!(target: "DB", "delete_kara_by_local_id failed: {err}"))
         .is_ok()
 }