diesel_derives/
valid_grouping.rs
1use proc_macro2::TokenStream;
2use quote::quote;
3use syn::parse_quote;
4use syn::DeriveInput;
5use syn::Result;
6
7use crate::model::Model;
8use crate::util::{ty_for_foreign_derive, wrap_in_dummy_mod};
9
10pub fn derive(mut item: DeriveInput) -> Result<TokenStream> {
11 let model = Model::from_item(&item, true, false)?;
12 let struct_ty = ty_for_foreign_derive(&item, &model)?;
13
14 let type_params = item
15 .generics
16 .type_params()
17 .map(|param| param.ident.clone())
18 .collect::<Vec<_>>();
19
20 for type_param in type_params {
21 let where_clause = item.generics.make_where_clause();
22 where_clause
23 .predicates
24 .push(parse_quote!(#type_param: ValidGrouping<__GroupByClause>));
25 }
26
27 if model.aggregate {
28 item.generics.params.push(parse_quote!(__GroupByClause));
29 let (impl_generics, _, where_clause) = item.generics.split_for_impl();
30
31 Ok(wrap_in_dummy_mod(quote! {
32 use diesel::expression::{ValidGrouping, MixedAggregates, is_aggregate};
33
34 impl #impl_generics ValidGrouping<__GroupByClause> for #struct_ty
35 #where_clause
36 {
37 type IsAggregate = is_aggregate::Yes;
38 }
39 }))
40 } else {
41 let mut aggregates = item
42 .generics
43 .type_params()
44 .map(|t| quote!(#t::IsAggregate))
45 .collect::<Vec<_>>()
46 .into_iter();
47
48 let is_aggregate = aggregates
49 .next()
50 .map(|first| {
51 let where_clause = item.generics.make_where_clause();
52 aggregates.fold(first, |left, right| {
53 where_clause.predicates.push(parse_quote!(
54 #left: MixedAggregates<#right>
55 ));
56 quote!(<#left as MixedAggregates<#right>>::Output)
57 })
58 })
59 .unwrap_or_else(|| quote!(is_aggregate::Never));
60
61 item.generics.params.push(parse_quote!(__GroupByClause));
62 let (impl_generics, _, where_clause) = item.generics.split_for_impl();
63
64 Ok(wrap_in_dummy_mod(quote! {
65 use diesel::expression::{ValidGrouping, MixedAggregates, is_aggregate};
66
67 impl #impl_generics ValidGrouping<__GroupByClause> for #struct_ty
68 #where_clause
69 {
70 type IsAggregate = #is_aggregate;
71 }
72 }))
73 }
74}