use proc_macro2::TokenStream;
use quote::quote;
use syn::{Ident, Type};
pub fn emit(
model_name: &Ident,
scalar_fields: &[(Ident, Type, String)],
relation_fields: &[Ident],
aggregate_fields: &[(Ident, Type, String, String)],
) -> TokenStream {
let rows = scalar_fields.iter().map(|(field, ty, col)| {
quote! {
#field: <#ty as prax_query::row::FromColumn>::from_column(row, #col)?,
}
});
let agg_rows = aggregate_fields.iter().map(|(field, ty, col, kind)| {
if kind == "count" {
quote! {
#field: row.get_i64_opt(#col)
.or_else(|e| {
if matches!(e, prax_query::row::RowError::ColumnNotFound(_)) {
Ok(None)
} else {
Err(e)
}
})?
.unwrap_or(0),
}
} else {
quote! {
#field: <#ty as prax_query::row::FromColumn>::from_column(row, #col)
.or_else(|e| {
if matches!(e, prax_query::row::RowError::ColumnNotFound(_)) {
Ok(<#ty as ::core::default::Default>::default())
} else {
Err(e)
}
})?,
}
}
});
let relation_defaults = relation_fields.iter().map(|field| {
quote! { #field: ::core::default::Default::default(), }
});
quote! {
impl prax_query::row::FromRow for #model_name {
fn from_row(row: &impl prax_query::row::RowRef)
-> Result<Self, prax_query::row::RowError>
{
Ok(Self {
#(#rows)*
#(#agg_rows)*
#(#relation_defaults)*
})
}
}
}
}