diesel_derives/
as_expression.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(item: DeriveInput) -> Result<TokenStream> {
11 let model = Model::from_item(&item, true, false)?;
12
13 if model.sql_types.is_empty() {
14 return Err(syn::Error::new(
15 proc_macro2::Span::call_site(),
16 "At least one `sql_type` is needed for deriving `AsExpression` on a structure.",
17 ));
18 }
19
20 let struct_ty = ty_for_foreign_derive(&item, &model)?;
21
22 let (impl_generics_plain, _, where_clause_plain) = item.generics.split_for_impl();
24
25 let mut generics = item.generics.clone();
26 generics.params.push(parse_quote!('__expr));
27
28 let (impl_generics, _, where_clause) = generics.split_for_impl();
29
30 let mut generics2 = generics.clone();
31 generics2.params.push(parse_quote!('__expr2));
32 let (impl_generics2, _, where_clause2) = generics2.split_for_impl();
33
34 let tokens = model.sql_types.iter().map(|sql_type| {
35
36 let mut to_sql_generics = item.generics.clone();
37 to_sql_generics.params.push(parse_quote!(__DB));
38 to_sql_generics.make_where_clause().predicates.push(parse_quote!(__DB: diesel::backend::Backend));
39 to_sql_generics.make_where_clause().predicates.push(parse_quote!(Self: diesel::serialize::ToSql<#sql_type, __DB>));
40 let (to_sql_impl_generics, _, to_sql_where_clause) = to_sql_generics.split_for_impl();
41
42 let tokens = quote!(
43 impl #impl_generics diesel::expression::AsExpression<#sql_type>
44 for &'__expr #struct_ty #where_clause
45 {
46 type Expression = diesel::internal::derives::as_expression::Bound<#sql_type, Self>;
47
48 fn as_expression(self) -> <Self as diesel::expression::AsExpression<#sql_type>>::Expression {
49 diesel::internal::derives::as_expression::Bound::new(self)
50 }
51 }
52
53 impl #impl_generics diesel::expression::AsExpression<diesel::sql_types::Nullable<#sql_type>>
54 for &'__expr #struct_ty #where_clause
55 {
56 type Expression = diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<#sql_type>, Self>;
57
58 fn as_expression(self) -> <Self as diesel::expression::AsExpression<diesel::sql_types::Nullable<#sql_type>>>::Expression {
59 diesel::internal::derives::as_expression::Bound::new(self)
60 }
61 }
62
63 impl #impl_generics2 diesel::expression::AsExpression<#sql_type>
64 for &'__expr2 &'__expr #struct_ty #where_clause2
65 {
66 type Expression = diesel::internal::derives::as_expression::Bound<#sql_type, Self>;
67
68 fn as_expression(self) -> <Self as diesel::expression::AsExpression<#sql_type>>::Expression {
69 diesel::internal::derives::as_expression::Bound::new(self)
70 }
71 }
72
73 impl #impl_generics2 diesel::expression::AsExpression<diesel::sql_types::Nullable<#sql_type>>
74 for &'__expr2 &'__expr #struct_ty #where_clause2
75 {
76 type Expression = diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<#sql_type>, Self>;
77
78 fn as_expression(self) -> <Self as diesel::expression::AsExpression<diesel::sql_types::Nullable<#sql_type>>>::Expression {
79 diesel::internal::derives::as_expression::Bound::new(self)
80 }
81 }
82
83 impl #to_sql_impl_generics diesel::serialize::ToSql<diesel::sql_types::Nullable<#sql_type>, __DB>
84 for #struct_ty #to_sql_where_clause
85 {
86 fn to_sql<'__b>(&'__b self, out: &mut diesel::serialize::Output<'__b, '_, __DB>) -> diesel::serialize::Result
87 {
88 diesel::serialize::ToSql::<#sql_type, __DB>::to_sql(self, out)
89 }
90 }
91 );
92
93 if model.not_sized {
94 tokens
95 } else {
96 quote!(
97 #tokens
98
99 impl #impl_generics_plain diesel::expression::AsExpression<#sql_type> for #struct_ty #where_clause_plain {
100 type Expression = diesel::internal::derives::as_expression::Bound<#sql_type, Self>;
101
102 fn as_expression(self) -> <Self as diesel::expression::AsExpression<#sql_type>>::Expression {
103 diesel::internal::derives::as_expression::Bound::new(self)
104 }
105 }
106
107 impl #impl_generics_plain diesel::expression::AsExpression<diesel::sql_types::Nullable<#sql_type>> for #struct_ty
108 #where_clause_plain
109 {
110 type Expression = diesel::internal::derives::as_expression::Bound<diesel::sql_types::Nullable<#sql_type>, Self>;
111
112 fn as_expression(self) -> <Self as diesel::expression::AsExpression<diesel::sql_types::Nullable<#sql_type>>>::Expression {
113 diesel::internal::derives::as_expression::Bound::new(self)
114 }
115 }
116 )
117 }
118 });
119
120 Ok(wrap_in_dummy_mod(quote! {
121 #(#tokens)*
122 }))
123}