diff --git a/sqlx-core/src/from_row.rs b/sqlx-core/src/from_row.rs index a3bf6bd2a1..6181484d69 100644 --- a/sqlx-core/src/from_row.rs +++ b/sqlx-core/src/from_row.rs @@ -288,22 +288,6 @@ where } } -impl<'r, R, T> FromRow<'r, R> for Option -where - R: Row, - T: FromRow<'r, R>, -{ - fn from_row(row: &'r R) -> Result { - let value = T::from_row(row).map(Some); - if let Err(Error::ColumnDecode { source, .. }) = value.as_ref() { - if let Some(UnexpectedNullError) = source.downcast_ref() { - return Ok(None); - } - } - value - } -} - // implement FromRow for tuples of types that implement Decode // up to tuples of 9 values @@ -506,3 +490,45 @@ impl_from_row_for_tuple!( (14) -> T15; (15) -> T16; ); + +pub struct Wrapper; + +pub trait FromOptRow<'r, R, T> { + fn __from_row(&self, row: &'r R) -> Result; +} + +impl<'r, R, T> FromOptRow<'r, R, Option> for &Wrapper +where + R: Row, + T: FromRow<'r, R>, +{ + fn __from_row(&self, row: &'r R) -> Result, Error> { + let value = T::from_row(row).map(Some); + if let Err(Error::ColumnDecode { source, .. }) = value.as_ref() { + if let Some(UnexpectedNullError) = source.downcast_ref() { + return Ok(None); + } + } + value + } +} + +impl<'r, R, T> FromOptRow<'r, R, T> for Wrapper +where + R: Row, + T: FromRow<'r, R>, +{ + fn __from_row(&self, row: &'r R) -> Result { + T::from_row(row) + } +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __from_opt_row { + ($t:ty, $row:expr) => {{ + use $crate::from_row::{FromOptRow, Wrapper}; + let value: Result<$t, sqlx::Error> = Wrapper.__from_row($row); + value + }}; +} diff --git a/sqlx-macros-core/src/derives/row.rs b/sqlx-macros-core/src/derives/row.rs index 5f7b6dca70..4ddc1f32af 100644 --- a/sqlx-macros-core/src/derives/row.rs +++ b/sqlx-macros-core/src/derives/row.rs @@ -109,7 +109,8 @@ fn expand_derive_from_row_struct( // Flatten (true, None, false) => { predicates.push(parse_quote!(#ty: ::sqlx::FromRow<#lifetime, R>)); - parse_quote!(<#ty as ::sqlx::FromRow<#lifetime, R>>::from_row(__row)) + //parse_quote!(<#ty as ::sqlx::FromRow<#lifetime, R>>::from_row(__row)) + parse_quote!(::sqlx::__from_opt_row!(#ty, __row)) } // Flatten + Try from (true, Some(try_from), false) => { diff --git a/src/lib.rs b/src/lib.rs index 870fa703c5..0fbf7df945 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,8 @@ pub use sqlx_core::connection::{ConnectOptions, Connection}; pub use sqlx_core::database::{self, Database}; pub use sqlx_core::describe::Describe; pub use sqlx_core::executor::{Execute, Executor}; -pub use sqlx_core::from_row::FromRow; +pub use sqlx_core::from_row::{FromRow, Wrapper, FromOptRow}; +pub use sqlx_core::__from_opt_row; pub use sqlx_core::pool::{self, Pool}; #[doc(hidden)] pub use sqlx_core::query::query_with_result as __query_with_result;