Skip to content

Commit 0689b0a

Browse files
authored
Merge pull request diesel-rs#1529 from diesel-rs/sg-rewrite-queryable
Rewrite `#[derive(Queryable)]` in derives2
2 parents 5669551 + fbe7ca4 commit 0689b0a

8 files changed

Lines changed: 79 additions & 58 deletions

File tree

diesel_derives/src/lib.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,13 @@ mod from_sql_row;
3131
mod insertable;
3232
mod model;
3333
mod query_id;
34-
mod queryable;
3534
mod queryable_by_name;
3635
mod sql_type;
3736
mod util;
3837

3938
use proc_macro::TokenStream;
4039
use syn::parse_derive_input;
4140

42-
#[proc_macro_derive(Queryable, attributes(column_name))]
43-
pub fn derive_queryable(input: TokenStream) -> TokenStream {
44-
expand_derive(input, queryable::derive_queryable)
45-
}
46-
4741
#[proc_macro_derive(QueryableByName, attributes(table_name, column_name, sql_type, diesel))]
4842
pub fn derive_queryable_by_name(input: TokenStream) -> TokenStream {
4943
expand_derive(input, queryable_by_name::derive)

diesel_derives/src/queryable.rs

Lines changed: 0 additions & 49 deletions
This file was deleted.

diesel_derives/tests/tests.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@ extern crate diesel;
55
#[macro_use]
66
extern crate diesel_derives;
77

8-
mod queryable;
98
mod queryable_by_name;
109
mod test_helpers;

diesel_derives2/src/field.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,19 @@ pub enum FieldName {
5454
Unnamed(syn::Index),
5555
}
5656

57+
impl FieldName {
58+
pub fn for_assignment(&self) -> quote::Tokens {
59+
match *self {
60+
FieldName::Named(mut x) => {
61+
// https://github.com/rust-lang/rust/issues/47311
62+
x.span = Span::call_site();
63+
quote!(#x)
64+
}
65+
FieldName::Unnamed(ref x) => quote!(#x),
66+
}
67+
}
68+
}
69+
5770
impl quote::ToTokens for FieldName {
5871
fn to_tokens(&self, tokens: &mut quote::Tokens) {
5972
use proc_macro2::{Spacing, TokenNode, TokenTree};

diesel_derives2/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ mod util;
2929
mod as_changeset;
3030
mod associations;
3131
mod identifiable;
32+
mod queryable;
3233

3334
use diagnostic_shim::*;
3435

@@ -48,6 +49,11 @@ pub fn derive_identifiable(input: TokenStream) -> TokenStream {
4849
expand_derive(input, identifiable::derive)
4950
}
5051

52+
#[proc_macro_derive(Queryable, attributes(column_name))]
53+
pub fn derive_queryable(input: TokenStream) -> TokenStream {
54+
expand_derive(input, queryable::derive)
55+
}
56+
5157
fn expand_derive(
5258
input: TokenStream,
5359
f: fn(syn::DeriveInput) -> Result<quote::Tokens, Diagnostic>,

diesel_derives2/src/queryable.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use proc_macro2::Span;
2+
use quote;
3+
use syn;
4+
5+
use model::*;
6+
use util::*;
7+
8+
pub fn derive(item: syn::DeriveInput) -> Result<quote::Tokens, Diagnostic> {
9+
let model = Model::from_item(&item)?;
10+
11+
let struct_name = item.ident;
12+
let field_ty = model.fields().iter().map(|f| &f.ty).collect::<Vec<_>>();
13+
let field_ty = &field_ty;
14+
let build_expr = model.fields().iter().enumerate().map(|(i, f)| {
15+
let field_name = &f.name.for_assignment();
16+
let i: syn::Index = i.into();
17+
// Make sure `row` has a `def_site` span
18+
let row = quote!(row);
19+
// https://github.com/rust-lang/rust/issues/47311
20+
let span = Span::call_site();
21+
quote_spanned!(span=> #field_name: (#row.#i))
22+
});
23+
24+
let (_, ty_generics, _) = item.generics.split_for_impl();
25+
let mut generics = item.generics.clone();
26+
generics
27+
.params
28+
.push(parse_quote!(__DB: diesel::backend::Backend));
29+
generics.params.push(parse_quote!(__ST));
30+
{
31+
let where_clause = generics.where_clause.get_or_insert(parse_quote!(where));
32+
where_clause
33+
.predicates
34+
.push(parse_quote!((#(#field_ty,)*): Queryable<__ST, __DB>));
35+
}
36+
let (impl_generics, _, where_clause) = generics.split_for_impl();
37+
38+
Ok(wrap_in_dummy_mod(
39+
model.dummy_mod_name("queryable"),
40+
quote! {
41+
use self::diesel::Queryable;
42+
43+
impl #impl_generics Queryable<__ST, __DB> for #struct_name #ty_generics
44+
#where_clause
45+
{
46+
type Row = <(#(#field_ty,)*) as Queryable<__ST, __DB>>::Row;
47+
48+
fn build(row: Self::Row) -> Self {
49+
let row: (#(#field_ty,)*) = Queryable::build(row);
50+
Self {
51+
#(#build_expr,)*
52+
}
53+
}
54+
}
55+
},
56+
))
57+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use diesel::dsl::sql;
22
use diesel::*;
33
use diesel::sql_types::Integer;
44

5-
use test_helpers::connection;
5+
use helpers::connection;
66

77
#[test]
88
fn named_struct_definition() {
@@ -20,7 +20,7 @@ fn named_struct_definition() {
2020
#[test]
2121
fn tuple_struct() {
2222
#[derive(Debug, Clone, Copy, PartialEq, Eq, Queryable)]
23-
struct MyStruct(#[column_name(foo)] i32, #[column_name(bar)] i32);
23+
struct MyStruct(#[column_name = "foo"] i32, #[column_name = "bar"] i32);
2424

2525
let conn = connection();
2626
let data = select(sql::<(Integer, Integer)>("1, 2")).get_result(&conn);

diesel_derives2/tests/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ mod schema;
1313
mod as_changeset;
1414
mod associations;
1515
mod identifiable;
16+
mod queryable;

0 commit comments

Comments
 (0)