1use proc_macro2::TokenStream;
2use syn::punctuated::Punctuated;
3use syn::{DeriveInput, parse_quote};
4
5use crate::model::Model;
6use crate::selectable::FieldSelectExpressionTyBuilder;
7
8fn generate_default_checks(
9 model: &Model,
10 original_impl_generics: &syn::ImplGenerics<'_>,
11 original_where_clause: Option<&syn::WhereClause>,
12 field_select_expression_type_builders: &[FieldSelectExpressionTyBuilder<'_>],
13) -> syn::Result<TokenStream> {
14 let checks = [
15 (
16 {
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, "internal");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "derives");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "has_query");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "expand_pg");
::quote::__private::push_bang(&mut _s);
_s
}quote::quote! {
17 diesel::internal::derives::has_query::expand_pg!
18 },
19 ::syn::__private::parse_quote({
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, "pg");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Pg");
_s
})parse_quote! {diesel::pg::Pg},
20 ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"_check_field_compatibility_pg");
_s
})parse_quote! {_check_field_compatibility_pg},
21 ),
22 (
23 {
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, "internal");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "derives");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "has_query");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "expand_sqlite");
::quote::__private::push_bang(&mut _s);
_s
}quote::quote! {
24 diesel::internal::derives::has_query::expand_sqlite!
25 },
26 ::syn::__private::parse_quote({
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, "sqlite");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Sqlite");
_s
})parse_quote! {diesel::sqlite::Sqlite},
27 ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"_check_field_compatibility_sqlite");
_s
})parse_quote! {_check_field_compatibility_sqlite},
28 ),
29 (
30 {
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, "internal");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "derives");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "has_query");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "expand_mysql");
::quote::__private::push_bang(&mut _s);
_s
}quote::quote! {
31 diesel::internal::derives::has_query::expand_mysql!
32 },
33 ::syn::__private::parse_quote({
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, "mysql");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Mysql");
_s
})parse_quote! {diesel::mysql::Mysql},
34 ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"_check_field_compatibility_mysql");
_s
})parse_quote! {_check_field_compatibility_mysql},
35 ),
36 (
37 {
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, "internal");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "derives");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "has_query");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "expand_mariadb");
::quote::__private::push_bang(&mut _s);
_s
}quote::quote! {
38 diesel::internal::derives::has_query::expand_mariadb!
39 },
40 ::syn::__private::parse_quote({
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, "mariadb");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Mariadb");
_s
})parse_quote! {diesel::mariadb::Mariadb},
41 ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s,
"_check_field_compatibility_mariadb");
_s
})parse_quote! {_check_field_compatibility_mariadb},
42 ),
43 ]
44 .into_iter()
45 .map(|(backend_macro, backend_ty, function)| {
46 let mut backend = Punctuated::new();
47 backend.push(backend_ty);
48
49 let check = super::selectable::generate_check_function(
50 model,
51 original_impl_generics,
52 original_where_clause,
53 field_select_expression_type_builders,
54 &backend,
55 function,
56 )?;
57 Ok({
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&backend_macro, &mut _s);
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&check, &mut _s);
_s
});
_s
}quote::quote! {
58 #backend_macro {#check}
59 })
60 })
61 .collect::<syn::Result<Vec<_>>>()?;
62
63 Ok({
let mut _s = ::quote::__private::TokenStream::new();
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut checks, i) = checks.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let checks =
match checks.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&checks, &mut _s);
}
}
_s
}quote::quote! { #(#checks)*})
64}
65
66pub(crate) fn derive(item: DeriveInput) -> syn::Result<TokenStream> {
67 let selectable = super::selectable::derive(item.clone(), Some(generate_default_checks))?;
70 let queryable = super::queryable::derive(item.clone())?;
71
72 let ident = &item.ident;
73 let model = Model::from_item(&item, false, false)?;
74 let (_original_impl_generics, ty_generics, _original_where_clause) =
75 item.generics.split_for_impl();
76
77 let mut generics = item.generics.clone();
78 generics
79 .params
80 .push(::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_ident(&mut _s, "__DB");
::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, "backend");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Backend");
_s
})parse_quote!(__DB: diesel::backend::Backend));
81
82 let (impl_generics, _, where_clause) = generics.split_for_impl();
83
84 let mut errors = Vec::new();
85
86 let (query_expr, query_type) = if let Some(base_query) = model.base_query {
87 if let Some(query_type) = model.base_query_type {
88 (base_query, query_type)
89 } else {
90 use dsl_auto_type::auto_type::expression_type_inference as type_inference;
91
92 let (inferred_type, infer_errors) = type_inference::infer_expression_type(
93 &base_query,
94 None,
95 &type_inference::InferrerSettings::builder()
96 .dsl_path(::syn::__private::parse_quote({
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");
_s
})parse_quote!(diesel::dsl))
97 .function_types_case(crate::AUTO_TYPE_DEFAULT_FUNCTION_TYPE_CASE)
98 .method_types_case(crate::AUTO_TYPE_DEFAULT_METHOD_TYPE_CASE)
99 .build(),
100 );
101
102 errors = infer_errors
103 .into_iter()
104 .map(|e| e.into_compile_error())
105 .collect();
106 (base_query, inferred_type)
107 }
108 } else {
109 let table_name = &model.table_names()[0];
110 let query_type =
111 ::syn::__private::parse_quote({
let mut _s = ::quote::__private::TokenStream::new();
::quote::__private::push_lt(&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_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, "AsQuery");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "Query");
_s
})parse_quote!(<#table_name::table as diesel::query_builder::AsQuery>::Query);
112
113 let query_expr = ::syn::__private::parse_quote({
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, "AsQuery");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "as_query");
::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::__private::push_ident(&mut _s, "table");
_s
});
_s
})parse_quote! {
114 diesel::query_builder::AsQuery::as_query(#table_name::table)
115 };
116 (query_expr, query_type)
117 };
118
119 let mut query_model = crate::util::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, "HasQuery");
::quote::__private::push_lt(&mut _s);
::quote::__private::push_ident(&mut _s, "__DB");
::quote::__private::push_gt(&mut _s);
::quote::__private::push_ident(&mut _s, "for");
::quote::ToTokens::to_tokens(&ident, &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, "BaseQuery");
::quote::__private::push_eq(&mut _s);
::quote::ToTokens::to_tokens(&query_type, &mut _s);
::quote::__private::push_semi(&mut _s);
::quote::__private::push_ident(&mut _s, "fn");
::quote::__private::push_ident(&mut _s, "base_query");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Parenthesis,
::quote::__private::TokenStream::new());
::quote::__private::push_rarrow(&mut _s);
::quote::__private::push_ident(&mut _s, "Self");
::quote::__private::push_colon2(&mut _s);
::quote::__private::push_ident(&mut _s, "BaseQuery");
::quote::__private::push_group(&mut _s,
::quote::__private::Delimiter::Brace,
{
let mut _s = ::quote::__private::TokenStream::new();
::quote::ToTokens::to_tokens(&query_expr, &mut _s);
_s
});
_s
});
{
use ::quote::__private::ext::*;
let has_iter = ::quote::__private::HasIterator::<false>;
#[allow(unused_mut)]
let (mut errors, i) = errors.quote_into_iter();
let has_iter = has_iter | i;
<_ as ::quote::__private::CheckHasIterator<true>>::check(has_iter);
while true {
let errors =
match errors.next() {
Some(_x) => ::quote::__private::RepInterp(_x),
None => break,
};
::quote::ToTokens::to_tokens(&errors, &mut _s);
}
}
_s
}quote::quote! {
120 impl #impl_generics diesel::HasQuery<__DB> for #ident #ty_generics #where_clause {
121 type BaseQuery = #query_type;
122
123 fn base_query() -> Self::BaseQuery {
124 #query_expr
125 }
126
127 }
128 #(#errors)*
129 });
130 query_model.extend(selectable);
131 query_model.extend(queryable);
132 Ok(query_model)
133}