use std::ops::DerefMut; use serde_derive::Serialize; use sqlx::pool::PoolConnection; use sqlx::Sqlite; use crate::errors::DatabaseError; #[derive(Debug, Serialize, Clone)] pub struct DbTag { pub id: i64, pub tag: String, } impl DbTag { pub async fn create( conn: &mut PoolConnection<Sqlite>, new_tag: &str, ) -> Result<DbTag, DatabaseError> { if new_tag.is_empty() { return Err(DatabaseError::EmptyDataInsert); } sqlx::query_as!( DbTag, "INSERT INTO tags (tag) VALUES (?) RETURNING *", new_tag ) .fetch_optional(conn.deref_mut()) .await? .ok_or(DatabaseError::InsertGetError) } pub async fn get_all(conn: &mut PoolConnection<Sqlite>) -> Result<Vec<DbTag>, DatabaseError> { sqlx::query_as!(DbTag, "SELECT * FROM tags") .fetch_all(conn.deref_mut()) .await .map_err(DatabaseError::from) } pub async fn get( conn: &mut PoolConnection<Sqlite>, id: i64, ) -> Result<Option<DbTag>, DatabaseError> { sqlx::query_as!(DbTag, "SELECT * FROM tags WHERE id = ?", id) .fetch_optional(conn.deref_mut()) .await .map_err(DatabaseError::from) } pub async fn get_by_tag_or_create( conn: &mut PoolConnection<Sqlite>, target_tag: &str, ) -> Result<DbTag, DatabaseError> { match DbTag::get_by_tag(conn, target_tag).await? { Some(tag) => Ok(tag), None => DbTag::create(conn, target_tag).await, } } pub async fn get_by_tag( conn: &mut PoolConnection<Sqlite>, target_tag: &str, ) -> Result<Option<DbTag>, DatabaseError> { sqlx::query_as!(DbTag, "SELECT * FROM tags WHERE tag = ?", target_tag) .fetch_optional(conn.deref_mut()) .await .map_err(DatabaseError::from) } pub async fn delete_by_tag( conn: &mut PoolConnection<Sqlite>, filter_tag: &str, ) -> Result<(), DatabaseError> { if sqlx::query_scalar!("SELECT 1 FROM tags WHERE tag = ?", filter_tag) .fetch_optional(conn.deref_mut()) .await? .is_none() { return Err(DatabaseError::NotFound); } sqlx::query!("DELETE FROM tags WHERE tag = ?", filter_tag) .execute(conn.deref_mut()) .await .map(|res| match res.rows_affected() { 0 => Err(DatabaseError::DeleteError), _ => Ok(()), })? } }