diesel_derives/
as_changeset.rs

1use proc_macro2::{Span, TokenStream};
2use quote::{quote, quote_spanned};
3use syn::spanned::Spanned as _;
4use syn::{parse_quote, DeriveInput, Expr, Path, Result, Type};
5
6use crate::attrs::AttributeSpanWrapper;
7use crate::field::Field;
8use crate::model::Model;
9use crate::util::{inner_of_option_ty, is_option_ty, wrap_in_dummy_mod};
10
11pub fn derive(item: DeriveInput) -> Result<TokenStream> {
12    let model = Model::from_item(&item, false, false)?;
13
14    let struct_name = &item.ident;
15    let table_name = &model.table_names()[0];
16
17    let fields_for_update = model
18        .fields()
19        .iter()
20        .filter(|f| {
21            !model
22                .primary_key_names
23                .iter()
24                .any(|p| f.column_name().map(|f| f == *p).unwrap_or_default())
25        })
26        .collect::<Vec<_>>();
27
28    if fields_for_update.is_empty() {
29        return Err(syn::Error::new(
30            proc_macro2::Span::mixed_site(),
31            "deriving `AsChangeset` on a structure that only contains primary keys isn't supported.\n\
32             help: if you want to change the primary key of a row, you should do so with `.set(table::id.eq(new_id))`.\n\
33             note: `#[derive(AsChangeset)]` never changes the primary key of a row."
34        ));
35    }
36
37    let treat_none_as_null = model.treat_none_as_null();
38
39    let (impl_generics, ty_generics, where_clause) = item.generics.split_for_impl();
40
41    let mut generate_borrowed_changeset = true;
42
43    let mut direct_field_ty = Vec::with_capacity(fields_for_update.len());
44    let mut direct_field_assign = Vec::with_capacity(fields_for_update.len());
45    let mut ref_field_ty = Vec::with_capacity(fields_for_update.len());
46    let mut ref_field_assign = Vec::with_capacity(fields_for_update.len());
47
48    for field in fields_for_update {
49        // skip this field while generating the update
50        if field.skip_update() {
51            continue;
52        }
53        // Use field-level attr. with fallback to the struct-level one.
54        let treat_none_as_null = match &field.treat_none_as_null {
55            Some(attr) => {
56                if let Some(embed) = &field.embed {
57                    return Err(syn::Error::new(
58                        embed.attribute_span,
59                        "`embed` and `treat_none_as_default_value` are mutually exclusive",
60                    ));
61                }
62
63                if !is_option_ty(&field.ty) {
64                    return Err(syn::Error::new(
65                        field.ty.span(),
66                        "expected `treat_none_as_null` field to be of type `Option<_>`",
67                    ));
68                }
69
70                attr.item
71            }
72            None => treat_none_as_null,
73        };
74
75        match (field.serialize_as.as_ref(), field.embed()) {
76            (Some(AttributeSpanWrapper { item: ty, .. }), false) => {
77                direct_field_ty.push(field_changeset_ty_serialize_as(
78                    field,
79                    table_name,
80                    ty,
81                    treat_none_as_null,
82                )?);
83                direct_field_assign.push(field_changeset_expr_serialize_as(
84                    field,
85                    table_name,
86                    ty,
87                    treat_none_as_null,
88                )?);
89
90                generate_borrowed_changeset = false; // as soon as we hit one field with #[diesel(serialize_as)] there is no point in generating the impl of AsChangeset for borrowed structs
91            }
92            (Some(AttributeSpanWrapper { attribute_span, .. }), true) => {
93                return Err(syn::Error::new(
94                    *attribute_span,
95                    "`#[diesel(embed)]` cannot be combined with `#[diesel(serialize_as)]`",
96                ));
97            }
98            (None, true) => {
99                direct_field_ty.push(field_changeset_ty_embed(field, None));
100                direct_field_assign.push(field_changeset_expr_embed(field, None));
101                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))));
102                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!(&))));
103            }
104            (None, false) => {
105                direct_field_ty.push(field_changeset_ty(
106                    field,
107                    table_name,
108                    None,
109                    treat_none_as_null,
110                )?);
111                direct_field_assign.push(field_changeset_expr(
112                    field,
113                    table_name,
114                    None,
115                    treat_none_as_null,
116                )?);
117                ref_field_ty.push(field_changeset_ty(
118                    field,
119                    table_name,
120                    Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and(&mut _s);
    ::quote::__private::push_lifetime(&mut _s, "\'update");
    _s
}quote!(&'update)),
121                    treat_none_as_null,
122                )?);
123                ref_field_assign.push(field_changeset_expr(
124                    field,
125                    table_name,
126                    Some({
    let mut _s = ::quote::__private::TokenStream::new();
    ::quote::__private::push_and(&mut _s);
    _s
}quote!(&)),
127                    treat_none_as_null,
128                )?);
129            }
130        }
131    }
132
133    let changeset_owned = {
    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, "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! {
134        impl #impl_generics diesel::query_builder::AsChangeset for #struct_name #ty_generics
135        #where_clause
136        {
137            type Target = #table_name::table;
138            type Changeset = <(#(#direct_field_ty,)*) as diesel::query_builder::AsChangeset>::Changeset;
139
140            fn as_changeset(self) -> <Self as diesel::query_builder::AsChangeset>::Changeset {
141                diesel::query_builder::AsChangeset::as_changeset((#(#direct_field_assign,)*))
142            }
143        }
144    };
145
146    let changeset_borrowed = if generate_borrowed_changeset {
147        let mut impl_generics = item.generics.clone();
148        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));
149        let (impl_generics, _, _) = impl_generics.split_for_impl();
150
151        {
    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, "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::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 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! {
152            impl #impl_generics diesel::query_builder::AsChangeset for &'update #struct_name #ty_generics
153            #where_clause
154            {
155                type Target = #table_name::table;
156                type Changeset = <(#(#ref_field_ty,)*) as diesel::query_builder::AsChangeset>::Changeset;
157
158                fn as_changeset(self) -> <Self as diesel::query_builder::AsChangeset>::Changeset {
159                    diesel::query_builder::AsChangeset::as_changeset((#(#ref_field_assign,)*))
160                }
161            }
162        }
163    } else {
164        ::quote::__private::TokenStream::new();quote! {}
165    };
166
167    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!(
168        #changeset_owned
169
170        #changeset_borrowed
171    )))
172}
173
174fn field_changeset_ty_embed(field: &Field, lifetime: Option<TokenStream>) -> TokenStream {
175    let field_ty = &field.ty;
176    let span = Span::mixed_site().located_at(field.span);
177    {
    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)
178}
179
180fn field_changeset_expr_embed(field: &Field, lifetime: Option<TokenStream>) -> TokenStream {
181    let field_name = &field.name;
182    {
    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)
183}
184
185fn field_changeset_ty(
186    field: &Field,
187    table_name: &Path,
188    lifetime: Option<TokenStream>,
189    treat_none_as_null: bool,
190) -> Result<TokenStream> {
191    let column_name = field.column_name()?.to_ident()?;
192    if !treat_none_as_null && is_option_ty(&field.ty) {
193        let field_ty = inner_of_option_ty(&field.ty);
194        Ok(
195            {
    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>>),
196        )
197    } else {
198        let field_ty = &field.ty;
199        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>))
200    }
201}
202
203fn field_changeset_expr(
204    field: &Field,
205    table_name: &Path,
206    lifetime: Option<TokenStream>,
207    treat_none_as_null: bool,
208) -> Result<TokenStream> {
209    let field_name = &field.name;
210    let column_name = field.column_name()?.to_ident()?;
211    if !treat_none_as_null && is_option_ty(&field.ty) {
212        if lifetime.is_some() {
213            Ok(
214                {
    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))),
215            )
216        } else {
217            Ok(
218                {
    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))),
219            )
220        }
221    } else {
222        Ok(
223            {
    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)),
224        )
225    }
226}
227
228fn field_changeset_ty_serialize_as(
229    field: &Field,
230    table_name: &Path,
231    ty: &Type,
232    treat_none_as_null: bool,
233) -> Result<TokenStream> {
234    let column_name = field.column_name()?.to_ident()?;
235    if !treat_none_as_null && is_option_ty(&field.ty) {
236        let inner_ty = inner_of_option_ty(ty);
237        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>>))
238    } else {
239        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>))
240    }
241}
242
243fn field_changeset_expr_serialize_as(
244    field: &Field,
245    table_name: &Path,
246    ty: &Type,
247    treat_none_as_null: bool,
248) -> Result<TokenStream> {
249    let field_name = &field.name;
250    let column_name = field.column_name()?.to_ident()?;
251    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);
252    if !treat_none_as_null && is_option_ty(&field.ty) {
253        Ok(
254            {
    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)))),
255        )
256    } else {
257        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))))
258    }
259}