From 40f11ebb77a329a3e2b9a790d63d2b45313a75d6 Mon Sep 17 00:00:00 2001 From: sid Date: Mon, 30 Mar 2020 19:14:48 +0530 Subject: [PATCH] Process keyword fields correctly in FromRow macro This PR fixes the the incorrect handling of keywords fields of a struct in the FromRow macro. Currently a struct with a field like 'r#type' will try to read values from a column with the exact same name with r# prefix. With this change this field will now map to a database column with the correct name 'type' without the r# prefix. --- sqlx-macros/src/derives/row.rs | 2 +- tests/postgres-derives.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/sqlx-macros/src/derives/row.rs b/sqlx-macros/src/derives/row.rs index 6541053c..60100f6f 100644 --- a/sqlx-macros/src/derives/row.rs +++ b/sqlx-macros/src/derives/row.rs @@ -74,7 +74,7 @@ fn expand_derive_from_row_struct( let reads = fields.iter().filter_map(|field| -> Option { let id = &field.ident.as_ref()?; - let id_s = id.to_string(); + let id_s = id.to_string().trim_start_matches("r#").to_owned(); let ty = &field.ty; Some(parse_quote!( diff --git a/tests/postgres-derives.rs b/tests/postgres-derives.rs index d3266c73..c8199d2a 100644 --- a/tests/postgres-derives.rs +++ b/tests/postgres-derives.rs @@ -132,3 +132,36 @@ async fn test_from_row() -> anyhow::Result<()> { Ok(()) } + +#[cfg(feature = "macros")] +#[cfg_attr(feature = "runtime-async-std", async_std::test)] +#[cfg_attr(feature = "runtime-tokio", tokio::test)] +async fn test_from_row_with_keyword() -> anyhow::Result<()> { + use sqlx::prelude::*; + + #[derive(Debug, sqlx::FromRow)] + struct AccountKeyword { + r#type: i32, + r#static: String, + r#let: Option, + r#struct: Option, + name: Option, + } + + let mut conn = new::().await?; + + let account: AccountKeyword = sqlx::query_as( + r#"SELECT * from (VALUES (1, 'foo', 'bar', null, null)) accounts(type, static, let, struct, name)"# + ) + .fetch_one(&mut conn) + .await?; + println!("{:?}", account); + + assert_eq!(1, account.r#type); + assert_eq!("foo", account.r#static); + assert_eq!(None, account.r#struct); + assert_eq!(Some("bar".to_owned()), account.r#let); + assert_eq!(None, account.name); + + Ok(()) +}