diff --git a/inc/liblektor-rs/database.h b/inc/liblektor-rs/database.h
index b398c88f7452822301f8b3e1f8d1f418218cbe3d..23bab61ffc3d11dd96644f61aaa175106e6d540b 100644
--- a/inc/liblektor-rs/database.h
+++ b/inc/liblektor-rs/database.h
@@ -5,12 +5,17 @@
 extern "C" {
 #endif
 
+#include <stdint.h>
+
 struct lkt_sqlite_connection;
 typedef struct lkt_sqlite_connection lkt_sqlite_connection;
 
 lkt_sqlite_connection *lkt_database_establish_connection(const char *);
 void lkt_database_close_connection(lkt_sqlite_connection *const);
 
+bool lkt_database_delete_kara_by_repo(lkt_sqlite_connection *const, int64_t, int64_t);
+bool lkt_database_delete_kara_by_local_id(lkt_sqlite_connection *const, int64_t);
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/src/rust/liblektor-rs/src/database/error.rs b/src/rust/liblektor-rs/src/database/error.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d0fd2eb7d42e821e43a1a2c2bb38b3777fb35e03
--- /dev/null
+++ b/src/rust/liblektor-rs/src/database/error.rs
@@ -0,0 +1,40 @@
+use super::*;
+
+pub enum LktDatabaseError {
+    DieselConnection(diesel::ConnectionError),
+    DieselResult(diesel::result::Error),
+    IntegerOverflow,
+    String(String),
+}
+
+pub type LktDatabaseResult<T> = Result<T, LktDatabaseError>;
+
+impl From<diesel::ConnectionError> for LktDatabaseError {
+    fn from(err: diesel::ConnectionError) -> Self {
+        LktDatabaseError::DieselConnection(err)
+    }
+}
+
+impl From<diesel::result::Error> for LktDatabaseError {
+    fn from(err: diesel::result::Error) -> Self {
+        LktDatabaseError::DieselResult(err)
+    }
+}
+
+impl From<std::num::TryFromIntError> for LktDatabaseError {
+    fn from(_: std::num::TryFromIntError) -> Self {
+        LktDatabaseError::IntegerOverflow
+    }
+}
+
+impl std::fmt::Display for LktDatabaseError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        use LktDatabaseError::*;
+        match self {
+            DieselConnection(err) => write!(f, "diesel connection error: {err}"),
+            DieselResult(err) => write!(f, "diesel result error: {err}"),
+            IntegerOverflow => f.write_str("integer overflow when casting to i32"),
+            String(str) => f.write_str(str),
+        }
+    }
+}
diff --git a/src/rust/liblektor-rs/src/database/mod.rs b/src/rust/liblektor-rs/src/database/mod.rs
index 9b910e96103b7ab917dc03508637e7864351fbe7..28c83cbf62cd8033deb0cb21282394829b5ce337 100644
--- a/src/rust/liblektor-rs/src/database/mod.rs
+++ b/src/rust/liblektor-rs/src/database/mod.rs
@@ -2,15 +2,15 @@
 
 pub(self) use diesel::prelude::*;
 use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
+pub(self) use error::*;
 pub(self) use log::*;
 
+pub mod error;
 pub mod models;
 pub mod schema;
 pub mod unsafe_interface;
 
-use self::models::*;
-
-use crate::{database::schema::kara_tags, kurisu_api::v1 as api_v1};
+use crate::{database::models::*, kurisu_api::v1 as api_v1};
 
 /// The migrations!
 const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
@@ -32,10 +32,10 @@ pub fn establish_connection(path: impl AsRef<str>) -> Result<SqliteConnection, S
 
 /// All the information needed to add a kara recieved from a repo!
 pub type NewKaraRequest<'a> = (
-    models::NewKaraId,
+    models::KaraId,
     models::NewKara<'a>,
-    models::NewLanguage<'a>,
-    Vec<models::AddKaraMaker<'a>>,
+    models::Language<'a>,
+    Vec<models::KaraMaker<'a>>,
     Vec<models::AddKaraTag>,
 );
 
@@ -43,47 +43,119 @@ pub struct LktDatabaseConnection {
     sqlite: SqliteConnection,
 }
 
+/// Load the diesel DSL for a given table. With the loaded dsl execute the
+/// expression...
+macro_rules! with_dsl {
+    ($table: ident => $expr: expr) => {{
+        use self::schema::$table::dsl::*;
+        use diesel::dsl::*;
+        $expr
+    }};
+}
+
 impl LktDatabaseConnection {
     /// Get a tag id by its name.
-    pub fn get_tag_id_by_name(&mut self, tag_name: impl AsRef<str>) -> i32 {
-        use self::schema::tag::dsl::*;
-        tag.filter(name.is(tag_name.as_ref()))
-            .first::<Tag>(&mut self.sqlite)
-            .unwrap()
-            .id
+    pub fn get_tag_id_by_name(&mut self, tag_name: impl AsRef<str>) -> LktDatabaseResult<i32> {
+        Ok(with_dsl!(tag => tag.filter(name.is(tag_name.as_ref()))
+            .first::<Tag>(&mut self.sqlite)?.id
+        ))
     }
 
-    /// Get a free local id for all karas.
-    pub fn get_kara_new_local_id(&mut self) -> i32 {
-        use self::schema::kara::dsl::*;
-        use diesel::dsl::*;
-        kara.select(max(id))
-            .first::<Option<i32>>(&mut self.sqlite)
-            .unwrap()
+    /// Get a free local id for all karas. Note that using this function might
+    /// be unsafe because there is no guarenties that the returned ID will be
+    /// free by the time a kara is inserted with the said id...
+    pub fn get_kara_new_local_id(&mut self) -> LktDatabaseResult<i32> {
+        let max = with_dsl!(kara => kara.select(max(id))
+            .first::<Option<i32>>(&mut self.sqlite)?
             .unwrap_or(0)
+        );
+        Ok(max + 1)
+    }
+
+    /// Delete a kara with its id in a repo.
+    pub fn delete_kara_by_repo(
+        &mut self,
+        arg_repo_id: u64,
+        arg_kara_id: u64,
+    ) -> LktDatabaseResult<()> {
+        let arg_repo_id = i32::try_from(arg_repo_id)?;
+        let arg_kara_id = i32::try_from(arg_kara_id)?;
+        self.sqlite.exclusive_transaction(|c| {
+            let local_id = with_dsl!(repo_kara => repo_kara
+                .filter(repo_id.eq(arg_repo_id))
+                .filter(repo_kara_id.eq(arg_kara_id))
+                .first::<KaraId>(c)?
+                .local_kara_id
+            );
+            with_dsl!(repo_kara => diesel::delete(repo_kara.filter(local_kara_id.eq(local_id))).execute(c)?);
+            with_dsl!(kara      => diesel::delete(kara.filter(id.eq(local_id))).execute(c)?);
+            Ok(())
+        })
+    }
+
+    /// Delete a kara by its local ID.
+    pub fn delete_kara_by_local_id(&mut self, kara_id: u64) -> LktDatabaseResult<()> {
+        let local_id = i32::try_from(kara_id)?;
+        self.sqlite.exclusive_transaction(|c| {
+            with_dsl!(repo_kara => diesel::delete(repo_kara.filter(local_kara_id.eq(local_id))).execute(c)?);
+            with_dsl!(kara      => diesel::delete(kara.filter(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.
+    pub fn ensure_language_exists(&mut self, lang: &Language) -> 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..."))),
+            })
+        })
+    }
+
+    /// Add a kara with a request.
+    pub fn add_kara_from_request<'a>(&mut self, kara: NewKaraRequest<'a>) -> LktDatabaseResult<()> {
+        let (id, new_kara, lang, karamakers, tags) = kara;
+        self.ensure_language_exists(&lang)?;
+        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_tags   => {
+                diesel::delete(kara_tags.filter(kara_id.eq(new_kara.id))).execute(c)?;
+                diesel::insert_into(kara_tags).values(tags).execute(c)?;
+            });
+            Ok(())
+        })
     }
 
     /// Create a series of models from a kara signature from Kurisu's V1 API.
-    pub fn new_kara<'a>(&mut self, repo_id: u64, kara: api_v1::Kara<'a>) -> NewKaraRequest<'a> {
-        error!("todo: query the database for a new local id");
-        let local_id = self.get_kara_new_local_id();
-        let id = NewKaraId {
-            repo_id: repo_id as i32,
-            local_kara_id: local_id as i32,
-            repo_kara_id: kara.id as i32,
+    pub fn new_kara_v1<'a>(
+        &mut self,
+        repo_id: u64,
+        kara: api_v1::Kara<'a>,
+    ) -> LktDatabaseResult<NewKaraRequest<'a>> {
+        let local_id = self.get_kara_new_local_id()?;
+        let repo_id = i32::try_from(repo_id)?;
+        let id = KaraId {
+            repo_id,
+            local_kara_id: local_id,
+            repo_kara_id: i32::try_from(kara.id)?,
         };
-        let lang = NewLanguage::from(kara.get_language());
-        let kara_makers = vec![AddKaraMaker {
-            id: local_id as i32,
+        let lang = Language::from(kara.get_language());
+        let kara_makers = vec![KaraMaker {
+            id: local_id,
             name: kara.author_name,
         }];
         let tags = vec![AddKaraTag {
-            kara_id: local_id as i32,
-            tag_id: self.get_tag_id_by_name("number"),
+            kara_id: local_id,
+            tag_id: self.get_tag_id_by_name("number")?,
             value: Some(format!("{}", kara.song_number)),
         }];
         let kara = NewKara {
-            id: local_id as i32,
+            id: local_id,
             song_title: kara.song_name,
             song_type: kara.song_type,
             song_origin: kara.category,
@@ -91,6 +163,6 @@ impl LktDatabaseConnection {
             language: lang.code,
             file_hash: format!("{}", kara.unix_timestamp),
         };
-        (id, kara, lang, kara_makers, tags)
+        Ok((id, kara, lang, kara_makers, tags))
     }
 }
diff --git a/src/rust/liblektor-rs/src/database/models.rs b/src/rust/liblektor-rs/src/database/models.rs
index 63914a8daefb3807def36e2997d147d9c8dfb004..b22a1be9756f5daa531e9cd4f386a09dde9c4f20 100644
--- a/src/rust/liblektor-rs/src/database/models.rs
+++ b/src/rust/liblektor-rs/src/database/models.rs
@@ -14,15 +14,15 @@ pub struct NewRepo<'a> {
     pub name: &'a str,
 }
 
-#[derive(Insertable)]
+#[derive(Debug, Insertable, Queryable, Selectable)]
 #[diesel(table_name = repo_kara)]
-pub struct NewKaraId {
+pub struct KaraId {
     pub repo_id: i32,
     pub repo_kara_id: i32,
     pub local_kara_id: i32,
 }
 
-#[derive(Insertable)]
+#[derive(Debug, Insertable)]
 #[diesel(table_name = kara)]
 pub struct NewKara<'a> {
     pub id: i32,
@@ -34,16 +34,16 @@ pub struct NewKara<'a> {
     pub file_hash: String,
 }
 
-#[derive(Insertable)]
+#[derive(Debug, Insertable, Queryable, Selectable)]
 #[diesel(table_name = kara_makers)]
-pub struct AddKaraMaker<'a> {
+pub struct KaraMaker<'a> {
     pub id: i32,
     pub name: &'a str,
 }
 
-#[derive(Insertable)]
+#[derive(Debug, Insertable, Queryable, Selectable)]
 #[diesel(table_name = iso_639_1)]
-pub struct NewLanguage<'a> {
+pub struct Language<'a> {
     pub code: &'a str,
     pub name_en: &'a str,
     pub is_iso: bool,
@@ -58,7 +58,7 @@ pub struct AddKaraTag {
     pub value: Option<String>,
 }
 
-impl<'a> From<api_v1::Language<'a>> for NewLanguage<'a> {
+impl<'a> From<api_v1::Language<'a>> for Language<'a> {
     fn from(lang: api_v1::Language<'a>) -> Self {
         Self {
             code: lang.code,
@@ -70,7 +70,8 @@ impl<'a> From<api_v1::Language<'a>> for NewLanguage<'a> {
 }
 
 // Then the queriable things
-#[derive(Queryable)]
+
+#[derive(Queryable, Selectable)]
 #[diesel(table_name = tag)]
 pub struct Tag {
     pub id: i32,
diff --git a/src/rust/liblektor-rs/src/database/unsafe_interface.rs b/src/rust/liblektor-rs/src/database/unsafe_interface.rs
index ebd5e1af6c7801fd31b1c69e6eb3c629972fe214..7b744d412cadee89b94c60ab6a3cca42b31df88b 100644
--- a/src/rust/liblektor-rs/src/database/unsafe_interface.rs
+++ b/src/rust/liblektor-rs/src/database/unsafe_interface.rs
@@ -41,3 +41,33 @@ pub unsafe extern "C" fn lkt_database_close_connection(db: *mut LktDatabaseConne
         drop(db);
     }
 }
+
+/// Delete a kara by its repo and id in the repo ids. The passed database
+/// pointer must be allocated by the [lkt_database_establish_connection]
+/// function. The function will return `true` on success, `false` otherwise. Any
+/// error will be logged.
+#[no_mangle]
+pub unsafe extern "C" fn lkt_database_delete_kara_by_repo(
+    db: *mut LktDatabaseConnection,
+    repo: u64,
+    kara: u64,
+) -> bool {
+    let db = db.as_mut().expect("passing a nullptr as db handle");
+    db.delete_kara_by_repo(repo, kara)
+        .map_err(|err| error!(target: "DB", "delete_kara_by_repo failed: {err}"))
+        .is_ok()
+}
+
+/// Delete a kara by its local id. The passed database pointer must be allocated
+/// by the [lkt_database_establish_connection] function. The function will
+/// return `true` on success, `false` otherwise. Any error will be logged.
+#[no_mangle]
+pub unsafe extern "C" fn lkt_database_delete_kara_by_local_id(
+    db: *mut LktDatabaseConnection,
+    local_id: u64,
+) -> bool {
+    let db = db.as_mut().expect("passing a nullptr as db handle");
+    db.delete_kara_by_local_id(local_id)
+        .map_err(|err| error!(target: "DB", "delete_kara_by_local_id failed: {err}"))
+        .is_ok()
+}