use proc_macro2::TokenStream;
use quote::quote;
use super::context::Context;
impl Context<'_> {
pub fn soft_delete_methods(&self) -> TokenStream {
if !self.soft_delete {
return TokenStream::new();
}
let hard_delete = self.hard_delete_method();
let restore = self.restore_method();
let find_with_deleted = self.find_by_id_with_deleted_method();
let list_with_deleted = self.list_with_deleted_method();
quote! {
#hard_delete
#restore
#find_with_deleted
#list_with_deleted
}
}
fn hard_delete_method(&self) -> TokenStream {
let Self {
table,
id_name,
id_type,
dialect,
..
} = self;
let placeholder = dialect.placeholder(1);
quote! {
async fn hard_delete(&self, id: #id_type) -> Result<bool, Self::Error> {
let result = sqlx::query(&format!(
"DELETE FROM {} WHERE {} = {}",
#table, stringify!(#id_name), #placeholder
)).bind(&id).execute(self).await?;
Ok(result.rows_affected() > 0)
}
}
}
fn restore_method(&self) -> TokenStream {
let Self {
table,
id_name,
id_type,
dialect,
..
} = self;
let placeholder = dialect.placeholder(1);
quote! {
async fn restore(&self, id: #id_type) -> Result<bool, Self::Error> {
let result = sqlx::query(&format!(
"UPDATE {} SET deleted_at = NULL WHERE {} = {} AND deleted_at IS NOT NULL",
#table, stringify!(#id_name), #placeholder
)).bind(&id).execute(self).await?;
Ok(result.rows_affected() > 0)
}
}
}
fn find_by_id_with_deleted_method(&self) -> TokenStream {
let Self {
entity_name,
row_name,
table,
columns_str,
id_name,
id_type,
dialect,
..
} = self;
let placeholder = dialect.placeholder(1);
quote! {
async fn find_by_id_with_deleted(&self, id: #id_type) -> Result<Option<#entity_name>, Self::Error> {
let row: Option<#row_name> = sqlx::query_as(
&format!("SELECT {} FROM {} WHERE {} = {}", #columns_str, #table, stringify!(#id_name), #placeholder)
).bind(&id).fetch_optional(self).await?;
Ok(row.map(#entity_name::from))
}
}
}
fn list_with_deleted_method(&self) -> TokenStream {
let Self {
entity_name,
row_name,
table,
columns_str,
id_name,
dialect,
..
} = self;
let limit_placeholder = dialect.placeholder(1);
let offset_placeholder = dialect.placeholder(2);
quote! {
async fn list_with_deleted(&self, limit: i64, offset: i64) -> Result<Vec<#entity_name>, Self::Error> {
let rows: Vec<#row_name> = sqlx::query_as(
&format!("SELECT {} FROM {} ORDER BY {} DESC LIMIT {} OFFSET {}",
#columns_str, #table, stringify!(#id_name), #limit_placeholder, #offset_placeholder)
).bind(limit).bind(offset).fetch_all(self).await?;
Ok(rows.into_iter().map(#entity_name::from).collect())
}
}
}
}