diff --git a/sqlx-core/src/decode.rs b/sqlx-core/src/decode.rs index 90b75534c..82e14d0d9 100644 --- a/sqlx-core/src/decode.rs +++ b/sqlx-core/src/decode.rs @@ -2,6 +2,7 @@ use crate::database::{Database, HasValueRef}; use crate::error::BoxDynError; +use crate::value::ValueRef; /// A type that can be decoded from the database. /// @@ -61,24 +62,17 @@ pub trait Decode<'r, DB: Database>: Sized { fn decode(value: >::ValueRef) -> Result; } -#[allow(unused_macros)] -macro_rules! impl_decode_for_option { - ($DB:ident) => { - impl<'r, T> crate::decode::Decode<'r, $DB> for Option - where - T: crate::decode::Decode<'r, $DB>, - { - fn decode( - value: <$DB as crate::database::HasValueRef<'r>>::ValueRef, - ) -> Result { - use crate::value::ValueRef; - - if value.is_null() { - Ok(None) - } else { - Ok(Some(T::decode(value)?)) - } - } +// implement `Decode` for Option for all SQL types +impl<'r, DB, T> Decode<'r, DB> for Option +where + DB: Database, + T: Decode<'r, DB>, +{ + fn decode(value: >::ValueRef) -> Result { + if value.is_null() { + Ok(None) + } else { + Ok(Some(T::decode(value)?)) } - }; + } } diff --git a/sqlx-core/src/encode.rs b/sqlx-core/src/encode.rs index 1608a4bfc..ba4392632 100644 --- a/sqlx-core/src/encode.rs +++ b/sqlx-core/src/encode.rs @@ -45,44 +45,31 @@ pub trait Encode<'q, DB: Database> { } } -// de-generified using macros because Any doesn't want this -#[allow(unused_macros)] -macro_rules! impl_encode_for_ref { - ($DB:ident) => { - impl<'q, T> crate::encode::Encode<'q, $DB> for &'_ T - where - T: crate::encode::Encode<'q, $DB>, - { - #[inline] - fn encode( - self, - buf: &mut <$DB as crate::database::HasArguments<'q>>::ArgumentBuffer, - ) -> crate::encode::IsNull { - >::encode_by_ref(self, buf) - } +impl<'q, T, DB: Database> Encode<'q, DB> for &'_ T +where + T: Encode<'q, DB>, +{ + #[inline] + fn encode(self, buf: &mut >::ArgumentBuffer) -> IsNull { + >::encode_by_ref(self, buf) + } - #[inline] - fn encode_by_ref( - &self, - buf: &mut <$DB as crate::database::HasArguments<'q>>::ArgumentBuffer, - ) -> crate::encode::IsNull { - <&T as crate::encode::Encode<$DB>>::encode(self, buf) - } + #[inline] + fn encode_by_ref(&self, buf: &mut >::ArgumentBuffer) -> IsNull { + <&T as Encode>::encode(self, buf) + } - #[inline] - fn produces(&self) -> Option<<$DB as crate::database::Database>::TypeInfo> { - (**self).produces() - } + #[inline] + fn produces(&self) -> Option { + (**self).produces() + } - #[inline] - fn size_hint(&self) -> usize { - (**self).size_hint() - } - } - }; + #[inline] + fn size_hint(&self) -> usize { + (**self).size_hint() + } } -// de-generified using macros because MSSQL has a different concept of how nullable encoding works #[allow(unused_macros)] macro_rules! impl_encode_for_option { ($DB:ident) => { diff --git a/sqlx-core/src/mssql/mod.rs b/sqlx-core/src/mssql/mod.rs index 1c2acbe08..9708f2299 100644 --- a/sqlx-core/src/mssql/mod.rs +++ b/sqlx-core/src/mssql/mod.rs @@ -31,10 +31,5 @@ impl_into_arguments_for_arguments!(MssqlArguments); impl_executor_for_pool_connection!(Mssql, MssqlConnection, MssqlRow); impl_executor_for_transaction!(Mssql, MssqlRow); -// required because of `Any` -impl_type_for_ref_and_option!(Mssql); -impl_encode_for_ref!(Mssql); -impl_decode_for_option!(Mssql); - // FIXME: RPC NULL parameter values / results // FIXME: RPC Empty String parameter values diff --git a/sqlx-core/src/mysql/mod.rs b/sqlx-core/src/mysql/mod.rs index 9d5ae5b48..64a5bbbaa 100644 --- a/sqlx-core/src/mysql/mod.rs +++ b/sqlx-core/src/mysql/mod.rs @@ -31,11 +31,6 @@ impl_into_arguments_for_arguments!(MySqlArguments); impl_executor_for_pool_connection!(MySql, MySqlConnection, MySqlRow); impl_executor_for_transaction!(MySql, MySqlRow); -// required because of `Any` -impl_type_for_ref_and_option!(MySql); -impl_encode_for_ref!(MySql); -impl_decode_for_option!(MySql); - // required because some databases have a different handling // of NULL impl_encode_for_option!(MySql); diff --git a/sqlx-core/src/mysql/types/bytes.rs b/sqlx-core/src/mysql/types/bytes.rs index 2758eb567..1426425a2 100644 --- a/sqlx-core/src/mysql/types/bytes.rs +++ b/sqlx-core/src/mysql/types/bytes.rs @@ -46,7 +46,7 @@ impl Type for Vec { } fn compatible(ty: &MySqlTypeInfo) -> bool { - <[u8] as Type>::compatible(ty) + <&[u8] as Type>::compatible(ty) } } diff --git a/sqlx-core/src/postgres/mod.rs b/sqlx-core/src/postgres/mod.rs index 024353117..c49cc7a6f 100644 --- a/sqlx-core/src/postgres/mod.rs +++ b/sqlx-core/src/postgres/mod.rs @@ -34,11 +34,6 @@ impl_into_arguments_for_arguments!(PgArguments); impl_executor_for_pool_connection!(Postgres, PgConnection, PgRow); impl_executor_for_transaction!(Postgres, PgRow); -// required because of `Any` -impl_type_for_ref_and_option!(Postgres); -impl_encode_for_ref!(Postgres); -impl_decode_for_option!(Postgres); - // required because some databases have a different handling // of NULL impl_encode_for_option!(Postgres); diff --git a/sqlx-core/src/postgres/types/array.rs b/sqlx-core/src/postgres/types/array.rs index 91574edb6..9dedfa031 100644 --- a/sqlx-core/src/postgres/types/array.rs +++ b/sqlx-core/src/postgres/types/array.rs @@ -37,6 +37,7 @@ impl<'q, T> Encode<'q, Postgres> for Vec where for<'a> &'a [T]: Encode<'q, Postgres>, T: Encode<'q, Postgres>, + Self: Type, { #[inline] fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { @@ -47,6 +48,7 @@ where impl<'q, T> Encode<'q, Postgres> for &'_ [T] where T: Encode<'q, Postgres> + Type, + Self: Type, { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { buf.extend(&1_i32.to_be_bytes()); // number of dimensions @@ -75,6 +77,7 @@ where impl<'r, T> Decode<'r, Postgres> for Vec where T: for<'a> Decode<'a, Postgres> + Type, + Self: Type, { fn decode(value: PgValueRef<'r>) -> Result { let element_type_info = T::type_info(); diff --git a/sqlx-core/src/postgres/types/mod.rs b/sqlx-core/src/postgres/types/mod.rs index 490da6f42..b65c29d49 100644 --- a/sqlx-core/src/postgres/types/mod.rs +++ b/sqlx-core/src/postgres/types/mod.rs @@ -171,7 +171,7 @@ pub use range::PgRange; pub use record::{PgRecordDecoder, PgRecordEncoder}; // Type::compatible impl appropriate for arrays -fn array_compatible>(ty: &PgTypeInfo) -> bool { +fn array_compatible>(ty: &PgTypeInfo) -> bool { // we require the declared type to be an _array_ with an // element type that is acceptable if let PgTypeKind::Array(element) = &ty.kind() { diff --git a/sqlx-core/src/postgres/types/str.rs b/sqlx-core/src/postgres/types/str.rs index 4d56730ba..3607a4b89 100644 --- a/sqlx-core/src/postgres/types/str.rs +++ b/sqlx-core/src/postgres/types/str.rs @@ -28,7 +28,7 @@ impl Type for [&'_ str] { } fn compatible(ty: &PgTypeInfo) -> bool { - array_compatible::(ty) + array_compatible::<&str>(ty) } } @@ -64,11 +64,11 @@ impl<'r> Decode<'r, Postgres> for &'r str { impl Type for String { fn type_info() -> PgTypeInfo { - >::type_info() + <&str as Type>::type_info() } fn compatible(ty: &PgTypeInfo) -> bool { - >::compatible(ty) + <&str as Type>::compatible(ty) } } diff --git a/sqlx-core/src/sqlite/mod.rs b/sqlx-core/src/sqlite/mod.rs index e029337ca..bb25f45fe 100644 --- a/sqlx-core/src/sqlite/mod.rs +++ b/sqlx-core/src/sqlite/mod.rs @@ -35,11 +35,6 @@ impl_into_arguments_for_arguments!(SqliteArguments<'q>); impl_executor_for_pool_connection!(Sqlite, SqliteConnection, SqliteRow); impl_executor_for_transaction!(Sqlite, SqliteRow); -// required because of `Any` -impl_type_for_ref_and_option!(Sqlite); -impl_encode_for_ref!(Sqlite); -impl_decode_for_option!(Sqlite); - // required because some databases have a different handling // of NULL impl_encode_for_option!(Sqlite); diff --git a/sqlx-core/src/sqlite/types/bytes.rs b/sqlx-core/src/sqlite/types/bytes.rs index 949aa0ee0..f3c972967 100644 --- a/sqlx-core/src/sqlite/types/bytes.rs +++ b/sqlx-core/src/sqlite/types/bytes.rs @@ -29,7 +29,7 @@ impl<'r> Decode<'r, Sqlite> for &'r [u8] { impl Type for Vec { fn type_info() -> SqliteTypeInfo { - <[u8] as Type>::type_info() + <&[u8] as Type>::type_info() } } diff --git a/sqlx-core/src/sqlite/types/str.rs b/sqlx-core/src/sqlite/types/str.rs index f9de2eb2e..6a3ed533b 100644 --- a/sqlx-core/src/sqlite/types/str.rs +++ b/sqlx-core/src/sqlite/types/str.rs @@ -29,7 +29,7 @@ impl<'r> Decode<'r, Sqlite> for &'r str { impl Type for String { fn type_info() -> SqliteTypeInfo { - >::type_info() + <&str as Type>::type_info() } } diff --git a/sqlx-core/src/types/mod.rs b/sqlx-core/src/types/mod.rs index 0d6ddb132..18e18423a 100644 --- a/sqlx-core/src/types/mod.rs +++ b/sqlx-core/src/types/mod.rs @@ -69,30 +69,24 @@ pub trait Type { } } -// de-generified using macros because Any doesn't want this -#[allow(unused_macros)] -macro_rules! impl_type_for_ref_and_option { - ($DB:ident) => { - // for references, the underlying SQL type is identical - impl> crate::types::Type<$DB> for &'_ T { - fn type_info() -> <$DB as crate::database::Database>::TypeInfo { - >::type_info() - } +// for references, the underlying SQL type is identical +impl, DB: Database> Type for &'_ T { + fn type_info() -> DB::TypeInfo { + >::type_info() + } - fn compatible(ty: &<$DB as crate::database::Database>::TypeInfo) -> bool { - >::compatible(ty) - } - } - - // for optionals, the underlying SQL type is identical - impl> crate::types::Type<$DB> for Option { - fn type_info() -> <$DB as crate::database::Database>::TypeInfo { - >::type_info() - } - - fn compatible(ty: &<$DB as crate::database::Database>::TypeInfo) -> bool { - >::compatible(ty) - } - } - }; + fn compatible(ty: &DB::TypeInfo) -> bool { + >::compatible(ty) + } +} + +// for optionals, the underlying SQL type is identical +impl, DB: Database> Type for Option { + fn type_info() -> DB::TypeInfo { + >::type_info() + } + + fn compatible(ty: &DB::TypeInfo) -> bool { + >::compatible(ty) + } }