1use std::collections::{HashMap, HashSet};
2
3use proc_macro2::{Span, TokenStream};
4use quote::{quote, quote_spanned};
5use syn::spanned::Spanned as _;
6use syn::{DeriveInput, Expr, Path, Result, Type, parse_quote};
7
8use crate::attrs::AttributeSpanWrapper;
9use crate::field::Field;
10use crate::model::Model;
11use crate::util::{inner_of_option_ty, is_option_ty, wrap_in_dummy_mod};
12
13pub fn derive(item: DeriveInput) -> Result<TokenStream> {
14 let model = Model::from_item(&item, false, false)?;
15
16 let struct_name = &item.ident;
17 let table_name = &model.table_names()[0];
18
19 let fields_for_update = model
20 .fields()
21 .iter()
22 .filter(|f| {
23 !model
24 .primary_key_names
25 .iter()
26 .any(|p| f.column_name().map(|f| f == *p).unwrap_or_default())
27 })
28 .collect::<Vec<_>>();
29
30 if fields_for_update.is_empty() {
31 return Err(syn::Error::new(
32 proc_macro2::Span::mixed_site(),
33 "deriving `AsChangeset` on a structure that only contains primary keys isn't supported.\n\
34 help: if you want to change the primary key of a row, you should do so with `.set(table::id.eq(new_id))`.\n\
35 note: `#[derive(AsChangeset)]` never changes the primary key of a row.",
36 ));
37 }
38
39 let treat_none_as_null = model.treat_none_as_null();
40
41 let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
42
43 let mut generate_borrowed_changeset = true;
44
45 let mut direct_field_ty = Vec::with_capacity(fields_for_update.len());
46 let mut direct_field_assign = Vec::with_capacity(fields_for_update.len());
47 let mut ref_field_ty = Vec::with_capacity(fields_for_update.len());
48 let mut ref_field_assign = Vec::with_capacity(fields_for_update.len());
49
50 let mut field_ty_bounds = Vec::with_capacity(model.fields().len());
52 let mut borrowed_field_ty_bounds = Vec::with_capacity(model.fields().len());
53 let mut field_ty_bounds_guard = HashMap::new();
54 let mut borrowed_field_ty_bounds_guard = HashMap::new();
55
56 for field in fields_for_update {
57 if field.skip_update() {
59 continue;
60 }
61 let treat_none_as_null = match &field.treat_none_as_null {
63 Some(attr) => {
64 if let Some(embed) = &field.embed {
65 return Err(syn::Error::new(
66 embed.attribute_span,
67 "`embed` and `treat_none_as_default_value` are mutually exclusive",
68 ));
69 }
70
71 if !is_option_ty(&field.ty) {
72 return Err(syn::Error::new(
73 field.ty.span(),
74 "expected `treat_none_as_null` field to be of type `Option<_>`",
75 ));
76 }
77
78 attr.item
79 }
80 None => treat_none_as_null,
81 };
82
83 match (field.serialize_as.as_ref(), field.embed()) {
84 (Some(AttributeSpanWrapper { item: ty, .. }), false) => {
85 direct_field_ty.push(field_changeset_ty_serialize_as(
86 field,
87 table_name,
88 ty,
89 treat_none_as_null,
90 )?);
91 direct_field_assign.push(field_changeset_expr_serialize_as(
92 field,
93 table_name,
94 ty,
95 treat_none_as_null,
96 )?);
97 field_ty_bounds.push(generate_field_bound(
98 field,
99 table_name,
100 Some(ty),
101 None,
102 &mut field_ty_bounds_guard,
103 treat_none_as_null,
104 )?);
105
106 generate_borrowed_changeset = false; }
108 (Some(AttributeSpanWrapper { attribute_span, .. }), true) => {
109 return Err(syn::Error::new(
110 *attribute_span,
111 "`#[diesel(embed)]` cannot be combined with `#[diesel(serialize_as)]`",
112 ));
113 }
114 (None, true) => {
115 direct_field_ty.push(field_changeset_ty_embed(field, None));
116 direct_field_assign.push(field_changeset_expr_embed(field, None));
117 ref_field_ty.push(field_changeset_ty_embed(field, Some({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'update");
_s
}quote!(&'update))));
118 ref_field_assign.push(field_changeset_expr_embed(field, Some({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
_s
}quote!(&))));
119 }
120 (None, false) => {
121 direct_field_ty.push(field_changeset_ty(
122 field,
123 table_name,
124 None,
125 treat_none_as_null,
126 )?);
127 direct_field_assign.push(field_changeset_expr(
128 field,
129 table_name,
130 None,
131 treat_none_as_null,
132 )?);
133 ref_field_ty.push(field_changeset_ty(
134 field,
135 table_name,
136 Some({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'update");
_s
}quote!(&'update)),
137 treat_none_as_null,
138 )?);
139 ref_field_assign.push(field_changeset_expr(
140 field,
141 table_name,
142 Some({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_and(&mut _s);
_s
}quote!(&)),
143 treat_none_as_null,
144 )?);
145
146 field_ty_bounds.push(generate_field_bound(
147 field,
148 table_name,
149 None,
150 None,
151 &mut field_ty_bounds_guard,
152 treat_none_as_null,
153 )?);
154
155 borrowed_field_ty_bounds.push(generate_field_bound(
156 field,
157 table_name,
158 None,
159 Some(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lifetime(&mut _s, "\'update");
_s
})parse_quote!('update)),
160 &mut borrowed_field_ty_bounds_guard,
161 treat_none_as_null,
162 )?);
163 }
164 }
165 }
166
167 let field_ty_bounds = field_ty_bounds
168 .into_iter()
169 .filter_map(|(type_to_check, bound)| {
170 super::insertable::filter_bounds(&field_ty_bounds_guard, type_to_check, bound)
171 });
172
173 let tpe_lifetimes = item.generics.lifetimes();
174
175 let changeset_owned = {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "_check_owned");
::quote::__private::push_lt(&mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut tpe_lifetimes, i) = tpe_lifetimes.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let tpe_lifetimes =
match tpe_lifetimes.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&tpe_lifetimes, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_ident(&mut _s, "where");
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut field_ty_bounds, i) = field_ty_bounds.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let field_ty_bounds =
match field_ty_bounds.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&field_ty_bounds, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
::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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&struct_name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &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, "Target");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "table");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "Changeset");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut direct_field_ty, i) =
direct_field_ty.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let direct_field_ty =
match direct_field_ty.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&direct_field_ty, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Changeset");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "as_changeset");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Changeset");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "as_changeset");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut direct_field_assign, i) =
direct_field_assign.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let direct_field_assign =
match direct_field_assign.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&direct_field_assign, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
_s
});
_s
});
_s
});
_s
}quote! {
176 fn _check_owned<#(#tpe_lifetimes,)*>()
177 where #(#field_ty_bounds,)*
178 {}
179
180 impl #impl_generics diesel::query_builder::AsChangeset for #struct_name #ty_generics
181 #where_clause
182 {
183 type Target = #table_name::table;
184 type Changeset = <(#(#direct_field_ty,)*) as diesel::query_builder::AsChangeset>::Changeset;
185
186 fn as_changeset(self) -> <Self as diesel::query_builder::AsChangeset>::Changeset {
187 diesel::query_builder::AsChangeset::as_changeset((#(#direct_field_assign,)*))
188 }
189 }
190 };
191
192 let changeset_borrowed = if generate_borrowed_changeset {
193 let mut impl_generics = item.generics.clone();
194 impl_generics.params.push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lifetime(&mut _s, "\'update");
_s
})parse_quote!('update));
195 let (impl_generics, _, _) = impl_generics.split_for_impl();
196 let borrowed_field_ty_bounds =
197 borrowed_field_ty_bounds
198 .into_iter()
199 .filter_map(|(type_to_check, bound)| {
200 super::insertable::filter_bounds(
201 &borrowed_field_ty_bounds_guard,
202 type_to_check,
203 bound,
204 )
205 });
206 let tpe_lifetimes = item.generics.lifetimes().map(|lp| {
207 let lt = &lp.lifetime;
208 let bound = lp.bounds.iter();
209 if lp.bounds.is_empty() {
210 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(<, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'update");
_s
}quote!(#lt: 'update)
211 } else {
212 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(<, &mut _s);
::quote::__private::push_colon(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'update");
::quote::__private::push_add(&mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut bound, i) = bound.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let bound =
match bound.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&bound, &mut _s);
::quote::__private::push_add(&mut _s);
}
}
_s
}quote!(#lt: 'update + #(#bound +)*)
213 }
214 });
215 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_pound(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Bracket,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "allow");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "clippy");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s,
"multiple_bound_locations");
_s
});
_s
});
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "_check_borrowed");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'update");
::quote::__private::push_comma(&mut _s);
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut tpe_lifetimes, i) = tpe_lifetimes.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let tpe_lifetimes =
match tpe_lifetimes.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&tpe_lifetimes, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_gt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_ident(&mut _s, "where");
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut borrowed_field_ty_bounds, i) =
borrowed_field_ty_bounds.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let borrowed_field_ty_bounds =
match borrowed_field_ty_bounds.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&borrowed_field_ty_bounds, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
::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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_ident(&mut _s, "for");
::quote::__private::push_and(&mut _s);
::quote::__private::push_lifetime(&mut _s, "\'update");
::quote::ToTokens::to_tokens(&struct_name, &mut _s);
::quote::ToTokens::to_tokens(&ty_generics, &mut _s);
::quote::__private::push_ident(&mut _s, "where");
::quote::ToTokens::to_tokens(&where_clause, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut ref_field_ty, i) = ref_field_ty.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let ref_field_ty =
match ref_field_ty.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&ref_field_ty, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_comma(&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, "Target");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "table");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "type");
::quote::__private::push_ident(&mut _s, "Changeset");
::quote::__private::push_eq(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut ref_field_ty, i) = ref_field_ty.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let ref_field_ty =
match ref_field_ty.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&ref_field_ty, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Changeset");
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "as_changeset");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
_s
});
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Changeset");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
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, "query_builder");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "AsChangeset");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "as_changeset");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut ref_field_assign, i) =
ref_field_assign.quote_into_iter();
let has_iter = has_iter | i;
<_ as
::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let ref_field_assign =
match ref_field_assign.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&ref_field_assign, &mut _s);
::quote::__private::push_comma(&mut _s);
}
}
_s
});
_s
});
_s
});
_s
});
_s
}quote! {
216 #[allow(clippy::multiple_bound_locations)]
217 fn _check_borrowed<'update, #(#tpe_lifetimes,)*>()
218 where
219 #(#borrowed_field_ty_bounds,)*
220 {}
221
222 impl #impl_generics diesel::query_builder::AsChangeset for &'update #struct_name #ty_generics
223 where
224 #where_clause
225 (#(#ref_field_ty,)*): diesel::query_builder::AsChangeset,
226 {
227 type Target = #table_name::table;
228 type Changeset = <(#(#ref_field_ty,)*) as diesel::query_builder::AsChangeset>::Changeset;
229
230 fn as_changeset(self) -> <Self as diesel::query_builder::AsChangeset>::Changeset {
231 diesel::query_builder::AsChangeset::as_changeset((#(#ref_field_assign,)*))
232 }
233 }
234 }
235 } else {
236 ::quote::__private::TokenStream::new();quote! {}
237 };
238
239 Ok(wrap_in_dummy_mod({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&changeset_owned, &mut _s);
::quote::ToTokens::to_tokens(&changeset_borrowed, &mut _s);
_s
}quote!(
240 #changeset_owned
241
242 #changeset_borrowed
243 )))
244}
245
246fn generate_field_bound(
247 field: &Field,
248 table_name: &Path,
249 ty: Option<&Type>,
250 borrowed: Option<syn::Lifetime>,
251 guard: &mut HashMap<Type, HashSet<Vec<syn::Lifetime>>>,
252 treat_none_as_null: bool,
253) -> Result<(Type, TokenStream)> {
254 let (ty_for_guard, as_expression_bound) = super::insertable::generate_field_bound(
255 field,
256 table_name,
257 ty.unwrap_or_else(|| field_changeset_actual_ty(field, treat_none_as_null)),
258 treat_none_as_null,
259 borrowed.clone(),
260 guard,
261 )?;
262 Ok((ty_for_guard, as_expression_bound))
263}
264
265fn field_changeset_actual_ty(field: &Field, treat_none_as_null: bool) -> &Type {
266 if !treat_none_as_null && is_option_ty(&field.ty) {
267 inner_of_option_ty(&field.ty)
268 } else {
269 &field.ty
270 }
271}
272
273fn field_changeset_ty_embed(field: &Field, lifetime: Option<TokenStream>) -> TokenStream {
274 let field_ty = &field.ty;
275 let span = Span::mixed_site().located_at(field.span);
276 {
let mut _s = ::quote::__private::TokenStream::new();
let _span: ::quote::__private::Span =
::quote::__private::get_span(span).__into_span();
::quote::ToTokens::to_tokens(&lifetime, &mut _s);
::quote::ToTokens::to_tokens(&field_ty, &mut _s);
_s
}quote_spanned!(span=> #lifetime #field_ty)
277}
278
279fn field_changeset_expr_embed(field: &Field, lifetime: Option<TokenStream>) -> TokenStream {
280 let field_name = &field.name;
281 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&lifetime, &mut _s);
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&field_name, &mut _s);
_s
}quote!(#lifetime self.#field_name)
282}
283
284fn field_changeset_ty(
285 field: &Field,
286 table_name: &Path,
287 lifetime: Option<TokenStream>,
288 treat_none_as_null: bool,
289) -> Result<TokenStream> {
290 let column_name = field.column_name()?.to_ident()?;
291 if !treat_none_as_null && is_option_ty(&field.ty) {
292 let field_ty = inner_of_option_ty(&field.ty);
293 Ok(
294 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "dsl");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Eq");
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&lifetime, &mut _s);
::quote::ToTokens::to_tokens(&field_ty, &mut _s);
::quote::__private::push_shr(&mut _s);
_s
}quote!(std::option::Option<diesel::dsl::Eq<#table_name::#column_name, #lifetime #field_ty>>),
295 )
296 } else {
297 let field_ty = &field.ty;
298 Ok({
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, "dsl");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Eq");
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&lifetime, &mut _s);
::quote::ToTokens::to_tokens(&field_ty, &mut _s);
::quote::__private::push_gt(&mut _s);
_s
}quote!(diesel::dsl::Eq<#table_name::#column_name, #lifetime #field_ty>))
299 }
300}
301
302fn field_changeset_expr(
303 field: &Field,
304 table_name: &Path,
305 lifetime: Option<TokenStream>,
306 treat_none_as_null: bool,
307) -> Result<TokenStream> {
308 let field_name = &field.name;
309 let column_name = field.column_name()?.to_ident()?;
310 if !treat_none_as_null && is_option_ty(&field.ty) {
311 if lifetime.is_some() {
312 Ok(
313 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&field_name, &mut _s);
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "as_ref");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "map");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "x");
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ExpressionMethods");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "eq");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "x");
_s
});
_s
});
_s
}quote!(self.#field_name.as_ref().map(|x| diesel::ExpressionMethods::eq(#table_name::#column_name, x))),
314 )
315 } else {
316 Ok(
317 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&field_name, &mut _s);
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "map");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "x");
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ExpressionMethods");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "eq");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_ident(&mut _s, "x");
_s
});
_s
});
_s
}quote!(self.#field_name.map(|x| diesel::ExpressionMethods::eq(#table_name::#column_name, x))),
318 )
319 }
320 } else {
321 Ok(
322 {
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, "ExpressionMethods");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "eq");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&lifetime, &mut _s);
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&field_name, &mut _s);
_s
});
_s
}quote!(diesel::ExpressionMethods::eq(#table_name::#column_name, #lifetime self.#field_name)),
323 )
324 }
325}
326
327fn field_changeset_ty_serialize_as(
328 field: &Field,
329 table_name: &Path,
330 ty: &Type,
331 treat_none_as_null: bool,
332) -> Result<TokenStream> {
333 let column_name = field.column_name()?.to_ident()?;
334 if !treat_none_as_null && is_option_ty(&field.ty) {
335 let inner_ty = inner_of_option_ty(ty);
336 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "option");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Option");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "dsl");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Eq");
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&inner_ty, &mut _s);
::quote::__private::push_shr(&mut _s);
_s
}quote!(std::option::Option<diesel::dsl::Eq<#table_name::#column_name, #inner_ty>>))
337 } else {
338 Ok({
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, "dsl");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Eq");
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::ToTokens::to_tokens(&ty, &mut _s);
::quote::__private::push_gt(&mut _s);
_s
}quote!(diesel::dsl::Eq<#table_name::#column_name, #ty>))
339 }
340}
341
342fn field_changeset_expr_serialize_as(
343 field: &Field,
344 table_name: &Path,
345 ty: &Type,
346 treat_none_as_null: bool,
347) -> Result<TokenStream> {
348 let field_name = &field.name;
349 let column_name = field.column_name()?.to_ident()?;
350 let column: Expr = ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&table_name, &mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::ToTokens::to_tokens(&column_name, &mut _s);
_s
})parse_quote!(#table_name::#column_name);
351 if !treat_none_as_null && is_option_ty(&field.ty) {
352 Ok(
353 {
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&field_name, &mut _s);
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "map");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "x");
::quote::__private::push_or(&mut _s);
::quote::__private::push_ident(&mut _s, "diesel");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "ExpressionMethods");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "eq");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&column, &mut _s);
::quote::__private::push_comma(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Into");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&ty, &mut _s);
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "into");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "x");
_s
});
_s
});
_s
});
_s
}quote!(self.#field_name.map(|x| diesel::ExpressionMethods::eq(#column, ::std::convert::Into::<#ty>::into(x)))),
354 )
355 } else {
356 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&column, &mut _s);
::quote::__private::push_dot(&mut _s);
::quote::__private::push_ident(&mut _s, "eq");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "std");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "convert");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Into");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_lt(&mut _s);
::quote::ToTokens::to_tokens(&ty, &mut _s);
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "into");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "self");
::quote::__private::push_dot(&mut _s);
::quote::ToTokens::to_tokens(&field_name, &mut _s);
_s
});
_s
});
_s
}quote!(#column.eq(::std::convert::Into::<#ty>::into(self.#field_name))))
357 }
358}