postgres_named_parameters_derive/
statement.rs1use attribute_derive::FromAttr;
2use quote::quote;
3use syn::DeriveInput;
4
5#[derive(FromAttr)]
6#[attribute(ident = statement)]
7struct StatementTraitHelperAttribute {
8 #[attribute(example = r#""DELETE FROM Person WHERE id = @id""#)]
9 sql: String,
10}
11
12pub fn derive_statement_impl(ast: DeriveInput) -> syn::Result<proc_macro2::TokenStream> {
13 let args = StatementTraitHelperAttribute::from_attributes(&ast.attrs)?;
14 let syn::Data::Struct(struct_ast) = ast.data else {
15 return Err(syn::Error::new(
16 ast.ident.span(),
17 "#[derive(Statement)] can only be used on structs",
18 ));
19 };
20
21 let named_parameters = crate::util::get_field_names(&struct_ast);
22 let parameter_list = crate::util::get_parameter_list(&struct_ast);
23 let transformed_sql = match crate::numberify::numberify(args.sql, named_parameters) {
24 Ok(sql) => sql,
25 Err(err) => {
26 let err = format!("Error with SQL provided to #[derive(Statement)]: {}", err);
27 return Err(syn::Error::new(ast.ident.span(), err));
28 }
29 };
30
31 let generics = ast.generics;
32 let ident = ast.ident;
33 let where_clause = &generics.where_clause;
34
35 let output = quote! {
36 #[automatically_derived]
37 impl #generics postgres_named_parameters::Statement for #ident #generics #where_clause {
38 fn execute_statement(&self, connection: &mut impl postgres_named_parameters::postgres::GenericClient) -> Result<u64, postgres_named_parameters::postgres::error::Error> {
39 connection.execute(#transformed_sql, #parameter_list)
40 }
41 }
42 };
43 Ok(output.into())
44}