sql-macros-derive 0.2.0

Auto generate sql queries for CRUD on sqlx
Documentation
use quote::quote;

use crate::model::{self, TableModel};

fn generate_method(
    method_name: &syn::Ident,
    table_name: &str,
    sql_filters: &str,
    choices: &[model::FilterChoice],
) -> proc_macro2::TokenStream {
    let params = model::params_tokens_for_choices(choices);
    let idents = model::idents_for_choices(choices);
    let query = format!("DELETE FROM {table_name} WHERE {sql_filters}");

    quote! {
        #[doc = #query]
        pub async fn #method_name(
            conn: &mut sqlx::PgConnection,
            #params
        ) -> Result<sqlx::any::AnyQueryResult, sqlx::Error> {
            let result = sqlx::query!(
                #query,
                #(#idents),*
            )
            .execute(&mut *conn)
            .await?;
            Ok(result.into())
        }
    }
}

pub fn expand(model: &TableModel) -> darling::Result<proc_macro2::TokenStream> {
    let struct_name = &model.struct_name;
    let mut methods = Vec::new();

    for column in model.columns.iter().filter(|c| c.is_delete_filter) {
        for &op in &column.ops {
            let method_name = if op == model::Operator::Eq {
                format!("delete_by_{}", column.ident)
            } else {
                format!("delete_by_{}_{}", column.ident, model::op_word(op))
            };
            let method_name = syn::Ident::new(&method_name, column.ident.span());
            let choices = vec![model::FilterChoice { column, op }];
            let sql_filters = model::sql_condition_for_choices(&choices, 0);
            methods.push(generate_method(
                &method_name,
                &model.table_name,
                &sql_filters,
                &choices,
            ));
        }
    }

    for custom in model.custom_delete_methods()? {
        let sql_filters = model::render_custom_where(&custom, 0);
        let choices: Vec<model::FilterChoice> = custom
            .filters
            .iter()
            .map(|&column| model::FilterChoice {
                column,
                op: model::Operator::Eq,
            })
            .collect();
        methods.push(generate_method(
            &custom.method_name,
            &model.table_name,
            &sql_filters,
            &choices,
        ));
    }

    Ok(quote! {
        impl #struct_name {
            #(#methods)*
        }
    })
}