Skip to content

Commit ea3fb4a

Browse files
committed
QueryableByName supoort non ident column name
delete #[allow(dead_code)]
1 parent 3978cdc commit ea3fb4a

3 files changed

Lines changed: 49 additions & 12 deletions

File tree

diesel_derives/src/field.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ pub struct Field {
1313
pub span: Span,
1414
pub sql_type: Option<syn::Type>,
1515
pub flags: MetaItem,
16-
column_name_from_attribute: Option<syn::Ident>,
16+
column_name_from_attribute: Option<MetaItem>,
1717
}
1818

1919
impl Field {
2020
pub fn from_struct_field(field: &syn::Field, index: usize) -> Self {
21-
let column_name_from_attribute =
22-
MetaItem::with_name(&field.attrs, "column_name").map(|m| m.expect_ident_value());
21+
let column_name_from_attribute = MetaItem::with_name(&field.attrs, "column_name");
2322
let name = match field.ident.clone() {
2423
Some(mut x) => {
2524
// https://github.com/rust-lang/rust/issues/47983#issuecomment-362817105
@@ -51,7 +50,8 @@ impl Field {
5150

5251
pub fn column_name(&self) -> syn::Ident {
5352
self.column_name_from_attribute
54-
.clone()
53+
.as_ref()
54+
.map(|m| m.expect_ident_value())
5555
.unwrap_or_else(|| match self.name {
5656
FieldName::Named(ref x) => x.clone(),
5757
_ => {
@@ -65,6 +65,23 @@ impl Field {
6565
})
6666
}
6767

68+
pub fn column_str_name(&self) -> String {
69+
self.column_name_from_attribute
70+
.as_ref()
71+
.map(|m| {
72+
m.str_value().unwrap_or_else(|e| {
73+
e.emit();
74+
"unknown_column".to_string()
75+
})
76+
})
77+
.unwrap_or_else(|| {
78+
self.span
79+
.error("All fields of tuple structs must be annotated with `#[column_name]`")
80+
.emit();
81+
"unknown_column".to_string()
82+
})
83+
}
84+
6885
pub fn has_flag(&self, flag: &str) -> bool {
6986
self.flags.has_flag(flag)
7087
}

diesel_derives/src/queryable_by_name.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,25 @@ pub fn derive(item: syn::DeriveInput) -> Result<proc_macro2::TokenStream, Diagno
2222
row,
2323
)?))
2424
} else {
25-
let name = f.column_name();
2625
let field_ty = &f.ty;
2726
let deserialize_ty = f.ty_for_deserialize()?;
28-
Ok(quote!(
29-
{
30-
let field = diesel::row::NamedRow::get(row, stringify!(#name))?;
31-
<#deserialize_ty as Into<#field_ty>>::into(field)
32-
}
33-
))
27+
if model.has_table_name_attribute() {
28+
let name = f.column_name();
29+
Ok(quote!(
30+
{
31+
let field = diesel::row::NamedRow::get(row, stringify!(#name))?;
32+
<#deserialize_ty as Into<#field_ty>>::into(field)
33+
}
34+
))
35+
} else {
36+
let name = f.column_str_name();
37+
Ok(quote!(
38+
{
39+
let field = diesel::row::NamedRow::get(row, stringify!(#name))?;
40+
<#deserialize_ty as Into<#field_ty>>::into(field)
41+
}
42+
))
43+
}
3444
}
3545
})
3646
.collect::<Result<Vec<_>, Diagnostic>>()?;
@@ -93,12 +103,12 @@ fn get_ident(field: &Field) -> Ident {
93103

94104
fn sql_type(field: &Field, model: &Model) -> syn::Type {
95105
let table_name = model.table_name();
96-
let column_name = field.column_name();
97106

98107
match field.sql_type {
99108
Some(ref st) => st.clone(),
100109
None => {
101110
if model.has_table_name_attribute() {
111+
let column_name = field.column_name();
102112
parse_quote!(diesel::dsl::SqlTypeOf<#table_name::#column_name>)
103113
} else {
104114
let field_name = match field.name {

diesel_derives/tests/queryable_by_name.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ fn named_struct_definition() {
2424
assert_eq!(Ok(MyStruct { foo: 1, bar: 2 }), data);
2525
}
2626

27+
#[test]
28+
fn non_ident_column_name() {
29+
#[derive(QueryableByName)]
30+
struct Out {
31+
#[sql_type = "diesel::sql_types::Text"]
32+
#[column_name = "QUERY PLAN "]
33+
qp: String,
34+
}
35+
}
36+
2737
#[test]
2838
fn tuple_struct() {
2939
#[derive(Debug, Clone, Copy, PartialEq, Eq, QueryableByName)]

0 commit comments

Comments
 (0)