Skip to content

Commit

Permalink
derive FromRow: sqlx(default) for all fields
Browse files Browse the repository at this point in the history
  • Loading branch information
grgi committed Oct 6, 2023
1 parent 846dcfe commit e5c3827
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 9 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions sqlx-core/src/from_row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,20 @@ use crate::{error::Error, row::Row};
/// will set the value of the field `location` to the default value of `Option<String>`,
/// which is `None`.
///
/// Moreover, if all field types have an implementation for [`Default`], you can use the `default``
/// attribute at the struct level rather than each single field.
/// For example:
///
/// ```rust, ignore
/// #[derive(sqlx::FromRow)]
/// #[sqlx(default)]
/// struct Options {
/// option_a: Option<i32>,
/// option_b: Option<String>,
/// option_c: Option<bool>,
/// }
/// ```
///
/// ### `flatten`
///
/// If you want to handle a field that implements [`FromRow`],
Expand Down
7 changes: 7 additions & 0 deletions sqlx-macros-core/src/derives/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ pub struct SqlxContainerAttributes {
pub rename_all: Option<RenameAll>,
pub repr: Option<Ident>,
pub no_pg_array: bool,
pub default: bool,
}

pub struct SqlxChildAttributes {
Expand All @@ -74,6 +75,7 @@ pub fn parse_container_attributes(input: &[Attribute]) -> syn::Result<SqlxContai
let mut type_name = None;
let mut rename_all = None;
let mut no_pg_array = None;
let mut default = None;

for attr in input
.iter()
Expand Down Expand Up @@ -129,6 +131,10 @@ pub fn parse_container_attributes(input: &[Attribute]) -> syn::Result<SqlxContai
)
}

Meta::Path(p) if p.is_ident("default") => {
try_set!(default, true, value)
}

u => fail!(u, "unexpected attribute"),
},
u => fail!(u, "unexpected attribute"),
Expand Down Expand Up @@ -156,6 +162,7 @@ pub fn parse_container_attributes(input: &[Attribute]) -> syn::Result<SqlxContai
type_name,
rename_all,
no_pg_array: no_pg_array.unwrap_or(false),
default: default.unwrap_or(false),
})
}

Expand Down
2 changes: 1 addition & 1 deletion sqlx-macros-core/src/derives/row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ fn expand_derive_from_row_struct(
},
};

if attributes.default {
if attributes.default || container_attributes.default {
Some(parse_quote!(let #id: #ty = #expr.or_else(|e| match e {
::sqlx::Error::ColumnNotFound(_) => {
::std::result::Result::Ok(Default::default())
Expand Down
25 changes: 25 additions & 0 deletions tests/postgres/derives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -621,6 +621,31 @@ async fn test_default() -> anyhow::Result<()> {
Ok(())
}

#[cfg(feature = "macros")]
#[sqlx_macros::test]
async fn test_struct_default() -> anyhow::Result<()> {
#[derive(Debug, sqlx::FromRow)]
#[sqlx(default)]
struct HasDefault {
value: Option<i32>,
default_a: Option<String>,
default_b: Option<i32>,
}

let mut conn = new::<Postgres>().await?;

let has_default: HasDefault = sqlx::query_as(r#"SELECT 1 AS not_default"#)
.fetch_one(&mut conn)
.await?;
println!("{has_default:?}");

assert_eq!(has_default.value, Some(1));
assert_eq!(has_default.default_a, None);
assert_eq!(has_default.default_b, None);

Ok(())
}

#[cfg(feature = "macros")]
#[sqlx_macros::test]
async fn test_flatten() -> anyhow::Result<()> {
Expand Down

0 comments on commit e5c3827

Please sign in to comment.