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(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&type_param, &mut _s);
        ::quote::__private::push_colon(&mut _s);
        ::quote::__private::push_ident(&mut _s, "diesel");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "expression");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "ValidGrouping");
        ::quote::__private::push_lt(&mut _s);
        ::quote::__private::push_ident(&mut _s, "__GroupByClause");
        ::quote::__private::push_gt(&mut _s);
        _s
    })parse_quote!(#type_param: diesel::expression::ValidGrouping<__GroupByClause>));
25    }
26
27    if model.aggregate {
28        item.generics.params.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_ident(&mut _s, "__GroupByClause");
        _s
    })parse_quote!(__GroupByClause));
29        let (impl_generics, _, where_clause) = item.generics.split_for_impl();
30
31        Ok(wrap_in_dummy_mod({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "expression");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ValidGrouping");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__GroupByClause");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&struct_ty, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "type");
            ::quote::__private::push_ident(&mut _s, "IsAggregate");
            ::quote::__private::push_eq(&mut _s);
            ::quote::__private::push_ident(&mut _s, "diesel");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "expression");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "is_aggregate");
            ::quote::__private::push_colon2(&mut _s);
            ::quote::__private::push_ident(&mut _s, "Yes");
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    _s
}quote! {
32            impl #impl_generics diesel::expression::ValidGrouping<__GroupByClause> for #struct_ty
33            #where_clause
34            {
35                type IsAggregate = diesel::expression::is_aggregate::Yes;
36            }
37        }))
38    } else {
39        let mut aggregates = item
40            .generics
41            .type_params()
42            .map(
43                |t| {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&t, &mut _s);
    ::quote::__private::push_ident(&mut _s, "as");
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "expression");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ValidGrouping");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__GroupByClause");
    ::quote::__private::push_shr(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "IsAggregate");
    _s
}quote!(<#t as diesel::expression::ValidGrouping<__GroupByClause>>::IsAggregate),
44            )
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(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::ToTokens::to_tokens(&left, &mut _s);
        ::quote::__private::push_colon(&mut _s);
        ::quote::__private::push_ident(&mut _s, "diesel");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "expression");
        ::quote::__private::push_colon2(&mut _s);
        ::quote::__private::push_ident(&mut _s, "MixedAggregates");
        ::quote::__private::push_lt(&mut _s);
        ::quote::ToTokens::to_tokens(&right, &mut _s);
        ::quote::__private::push_gt(&mut _s);
        _s
    })parse_quote!(
54                        #left: diesel::expression::MixedAggregates<#right>
55                    ));
56                    {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&left, &mut _s);
    ::quote::__private::push_ident(&mut _s, "as");
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "expression");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "MixedAggregates");
    ::quote::__private::push_lt(&mut _s);
    ::quote::ToTokens::to_tokens(&right, &mut _s);
    ::quote::__private::push_shr(&mut _s);
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Output");
    _s
}quote!(<#left as diesel::expression::MixedAggregates<#right>>::Output)
57                })
58            })
59            .unwrap_or_else(|| {
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "expression");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "is_aggregate");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "Never");
    _s
}quote!(diesel::expression::is_aggregate::Never));
60
61        item.generics.params.push(::syn::__private::parse_quote({
        let mut _s = ::quote::__private::TokenStream::new();
        ::quote::__private::push_ident(&mut _s, "__GroupByClause");
        _s
    })parse_quote!(__GroupByClause));
62        let (impl_generics, _, where_clause) = item.generics.split_for_impl();
63
64        Ok(wrap_in_dummy_mod({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_ident(&mut _s, "impl");
    ::quote::ToTokens::to_tokens(&impl_generics, &mut _s);
    ::quote::__private::push_ident(&mut _s, "diesel");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "expression");
    ::quote::__private::push_colon2(&mut _s);
    ::quote::__private::push_ident(&mut _s, "ValidGrouping");
    ::quote::__private::push_lt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "__GroupByClause");
    ::quote::__private::push_gt(&mut _s);
    ::quote::__private::push_ident(&mut _s, "for");
    ::quote::ToTokens::to_tokens(&struct_ty, &mut _s);
    ::quote::ToTokens::to_tokens(&where_clause, &mut _s);
    ::quote::__private::push_group(&mut _s,
        ::quote::__private::Delimiter::Brace,
        {
            let mut _s = ::quote::__private::TokenStream::new();
            ::quote::__private::push_ident(&mut _s, "type");
            ::quote::__private::push_ident(&mut _s, "IsAggregate");
            ::quote::__private::push_eq(&mut _s);
            ::quote::ToTokens::to_tokens(&is_aggregate, &mut _s);
            ::quote::__private::push_semi(&mut _s);
            _s
        });
    _s
}quote! {
65
66            impl #impl_generics diesel::expression::ValidGrouping<__GroupByClause> for #struct_ty
67            #where_clause
68            {
69                type IsAggregate = #is_aggregate;
70            }
71        }))
72    }
73}