From 927bfbae9e6eb26635439487f0cc1ec7104edcfa Mon Sep 17 00:00:00 2001 From: 50U10FCA7 Date: Mon, 26 Sep 2022 10:18:59 -0500 Subject: [PATCH 1/4] WIP [skip ci] --- postgres-derive-test/src/lib.rs | 4 +- postgres-derive/src/tosql.rs | 2 - postgres-types/CHANGELOG.md | 2 +- postgres-types/src/lib.rs | 168 ++++++++----------- postgres-types/src/pg_lsn.rs | 2 - postgres-types/src/special.rs | 4 - postgres/CHANGELOG.md | 2 +- postgres/src/binary_copy.rs | 6 +- postgres/src/client.rs | 14 +- postgres/src/generic_client.rs | 32 ++-- postgres/src/transaction.rs | 14 +- tokio-postgres/CHANGELOG.md | 4 +- tokio-postgres/src/binary_copy.rs | 8 +- tokio-postgres/src/bind.rs | 4 +- tokio-postgres/src/client.rs | 15 +- tokio-postgres/src/generic_client.rs | 38 ++--- tokio-postgres/src/lib.rs | 6 +- tokio-postgres/src/query.rs | 53 ++++-- tokio-postgres/src/transaction.rs | 18 +- tokio-postgres/tests/test/types/chrono_04.rs | 2 +- tokio-postgres/tests/test/types/mod.rs | 8 +- 21 files changed, 190 insertions(+), 216 deletions(-) diff --git a/postgres-derive-test/src/lib.rs b/postgres-derive-test/src/lib.rs index 8bfd147fb..239d4ebe9 100644 --- a/postgres-derive-test/src/lib.rs +++ b/postgres-derive-test/src/lib.rs @@ -19,11 +19,11 @@ where .prepare(&*format!("SELECT {}::{}", *repr, sql_type)) .unwrap(); let result = conn.query_one(&stmt, &[]).unwrap().get(0); - assert_eq!(val, &result); + assert!(val == &result); let stmt = conn.prepare(&*format!("SELECT $1::{}", sql_type)).unwrap(); let result = conn.query_one(&stmt, &[val]).unwrap().get(0); - assert_eq!(val, &result); + assert!(val == &result); } } diff --git a/postgres-derive/src/tosql.rs b/postgres-derive/src/tosql.rs index e51acc7fd..997bd4978 100644 --- a/postgres-derive/src/tosql.rs +++ b/postgres-derive/src/tosql.rs @@ -103,8 +103,6 @@ pub fn expand_derive_tosql(input: DeriveInput) -> Result { fn accepts(type_: &postgres_types::Type) -> bool { #accepts_body } - - postgres_types::to_sql_checked!(); } }; diff --git a/postgres-types/CHANGELOG.md b/postgres-types/CHANGELOG.md index 0e2167e5f..2953696e2 100644 --- a/postgres-types/CHANGELOG.md +++ b/postgres-types/CHANGELOG.md @@ -14,7 +14,7 @@ ### Added * Added `ToSql` and `FromSql` implementations for `Box`. -* Added `BorrowToSql` implementations for `Box` and `Box`. +* Added `BorrowToSqlChecked` implementations for `Box` and `Box`. * Added support for `cidr` 0.2 via the `with-cidr-02` feature. * Added conversions between the `LTREE`, `LQUERY` and `LTXTQUERY` types and Rust strings. * Added support for `uuid` 1.0 via the `with-uuid-1` feature. diff --git a/postgres-types/src/lib.rs b/postgres-types/src/lib.rs index f5d841cd1..9596918e4 100644 --- a/postgres-types/src/lib.rs +++ b/postgres-types/src/lib.rs @@ -172,42 +172,6 @@ macro_rules! accepts { ) } -/// Generates an implementation of `ToSql::to_sql_checked`. -/// -/// All `ToSql` implementations should use this macro. -#[macro_export] -macro_rules! to_sql_checked { - () => { - fn to_sql_checked( - &self, - ty: &$crate::Type, - out: &mut $crate::private::BytesMut, - ) -> ::std::result::Result< - $crate::IsNull, - Box, - > { - $crate::__to_sql_checked(self, ty, out) - } - }; -} - -// WARNING: this function is not considered part of this crate's public API. -// It is subject to change at any time. -#[doc(hidden)] -pub fn __to_sql_checked( - v: &T, - ty: &Type, - out: &mut BytesMut, -) -> Result> -where - T: ToSql, -{ - if !T::accepts(ty) { - return Err(Box::new(WrongType::new::(ty.clone()))); - } - v.to_sql(ty, out) -} - #[cfg(feature = "with-bit-vec-0_6")] mod bit_vec_06; #[cfg(feature = "with-chrono-0_4")] @@ -805,7 +769,7 @@ pub enum IsNull { /// /// **Note:** the impl for arrays only exist when the Cargo feature `array-impls` /// is enabled. -pub trait ToSql: fmt::Debug { +pub trait ToSql { /// Converts the value of `self` into the binary format of the specified /// Postgres `Type`, appending it to `out`. /// @@ -815,16 +779,21 @@ pub trait ToSql: fmt::Debug { /// The return value indicates if this value should be represented as /// `NULL`. If this is the case, implementations **must not** write /// anything to `out`. - fn to_sql(&self, ty: &Type, out: &mut BytesMut) -> Result> - where - Self: Sized; + fn to_sql(&self, ty: &Type, out: &mut BytesMut) + -> Result>; /// Determines if a value of this type can be converted to the specified /// Postgres `Type`. - fn accepts(ty: &Type) -> bool - where - Self: Sized; + fn accepts(ty: &Type) -> bool; + + /// Specify the encode format + fn encode_format(&self, _ty: &Type) -> Format { + Format::Binary + } +} +/// A trait used internally by Rust-Postgres to convert types into Postgres values. +pub trait ToSqlChecked { /// An adaptor method used internally by Rust-Postgres. /// /// *All* implementations of this method should be generated by the @@ -836,8 +805,23 @@ pub trait ToSql: fmt::Debug { ) -> Result>; /// Specify the encode format - fn encode_format(&self, _ty: &Type) -> Format { - Format::Binary + fn encode_format(&self, _ty: &Type) -> Format; +} + +impl ToSqlChecked for T { + fn to_sql_checked( + &self, + ty: &Type, + out: &mut BytesMut, + ) -> Result> { + if !T::accepts(ty) { + return Err(Box::new(WrongType::new::(ty.clone()))); + } + ToSql::to_sql(self, ty, out) + } + + fn encode_format(&self, ty: &Type) -> Format { + ToSql::encode_format(self, ty) } } @@ -871,8 +855,6 @@ where fn encode_format(&self, ty: &Type) -> Format { (*self).encode_format(ty) } - - to_sql_checked!(); } impl ToSql for Option { @@ -897,11 +879,9 @@ impl ToSql for Option { None => Format::Binary, } } - - to_sql_checked!(); } -impl<'a, T: ToSql> ToSql for &'a [T] { +impl ToSql for [T] { fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { let member_type = match *ty.kind() { Kind::Array(ref member) => member, @@ -932,8 +912,20 @@ impl<'a, T: ToSql> ToSql for &'a [T] { _ => false, } } +} - to_sql_checked!(); +impl<'a, T: ToSql> ToSql for &'a [T] { + fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { + <[T]>::to_sql(*self, ty, w) + } + + fn accepts(ty: &Type) -> bool { + <[T]>::accepts(ty) + } + + fn encode_format(&self, ty: &Type) -> Format { + <[T]>::encode_format(*self, ty) + } } impl<'a> ToSql for &'a [u8] { @@ -943,8 +935,6 @@ impl<'a> ToSql for &'a [u8] { } accepts!(BYTEA); - - to_sql_checked!(); } #[cfg(feature = "array-impls")] @@ -962,11 +952,11 @@ impl ToSql for [u8; N] { #[cfg(feature = "array-impls")] impl ToSql for [T; N] { fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { - <&[T] as ToSql>::to_sql(&&self[..], ty, w) + <[T] as ToSql>::to_sql(&&self[..], ty, w) } fn accepts(ty: &Type) -> bool { - <&[T] as ToSql>::accepts(ty) + <[T] as ToSql>::accepts(ty) } to_sql_checked!(); @@ -974,26 +964,22 @@ impl ToSql for [T; N] { impl ToSql for Vec { fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { - <&[T] as ToSql>::to_sql(&&**self, ty, w) + <[T] as ToSql>::to_sql(&**self, ty, w) } fn accepts(ty: &Type) -> bool { - <&[T] as ToSql>::accepts(ty) + <[T] as ToSql>::accepts(ty) } - - to_sql_checked!(); } impl ToSql for Box<[T]> { fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { - <&[T] as ToSql>::to_sql(&&**self, ty, w) + <[T] as ToSql>::to_sql(&**self, ty, w) } fn accepts(ty: &Type) -> bool { - <&[T] as ToSql>::accepts(ty) + <[T] as ToSql>::accepts(ty) } - - to_sql_checked!(); } impl ToSql for Vec { @@ -1004,8 +990,6 @@ impl ToSql for Vec { fn accepts(ty: &Type) -> bool { <&[u8] as ToSql>::accepts(ty) } - - to_sql_checked!(); } impl<'a> ToSql for &'a str { @@ -1033,8 +1017,6 @@ impl<'a> ToSql for &'a str { _ => false, } } - - to_sql_checked!(); } impl<'a> ToSql for Cow<'a, str> { @@ -1045,8 +1027,6 @@ impl<'a> ToSql for Cow<'a, str> { fn accepts(ty: &Type) -> bool { <&str as ToSql>::accepts(ty) } - - to_sql_checked!(); } impl ToSql for String { @@ -1057,8 +1037,6 @@ impl ToSql for String { fn accepts(ty: &Type) -> bool { <&str as ToSql>::accepts(ty) } - - to_sql_checked!(); } impl ToSql for Box { @@ -1069,8 +1047,6 @@ impl ToSql for Box { fn accepts(ty: &Type) -> bool { <&str as ToSql>::accepts(ty) } - - to_sql_checked!(); } macro_rules! simple_to { @@ -1085,8 +1061,6 @@ macro_rules! simple_to { } accepts!($($expected),+); - - to_sql_checked!(); } } } @@ -1115,8 +1089,6 @@ where fn accepts(ty: &Type) -> bool { ty.name() == "hstore" } - - to_sql_checked!(); } impl ToSql for SystemTime { @@ -1136,8 +1108,6 @@ impl ToSql for SystemTime { } accepts!(TIMESTAMP, TIMESTAMPTZ); - - to_sql_checked!(); } impl ToSql for IpAddr { @@ -1151,8 +1121,6 @@ impl ToSql for IpAddr { } accepts!(INET); - - to_sql_checked!(); } fn downcast(len: usize) -> Result> { @@ -1167,61 +1135,61 @@ mod sealed { pub trait Sealed {} } -/// A trait used by clients to abstract over `&dyn ToSql` and `T: ToSql`. +/// A trait used by clients to abstract over `&dyn ToSqlChecked` and `T: ToSql`. /// /// This cannot be implemented outside of this crate. -pub trait BorrowToSql: sealed::Sealed { +pub trait BorrowToSqlChecked: sealed::Sealed { /// Returns a reference to `self` as a `ToSql` trait object. - fn borrow_to_sql(&self) -> &dyn ToSql; + fn borrow_to_sql(&self) -> &dyn ToSqlChecked; } -impl sealed::Sealed for &dyn ToSql {} +impl sealed::Sealed for &dyn ToSqlChecked {} -impl BorrowToSql for &dyn ToSql { +impl BorrowToSqlChecked for &dyn ToSqlChecked { #[inline] - fn borrow_to_sql(&self) -> &dyn ToSql { + fn borrow_to_sql(&self) -> &dyn ToSqlChecked { *self } } -impl sealed::Sealed for Box {} +impl sealed::Sealed for Box {} -impl BorrowToSql for Box { +impl BorrowToSqlChecked for Box { #[inline] - fn borrow_to_sql(&self) -> &dyn ToSql { + fn borrow_to_sql(&self) -> &dyn ToSqlChecked { self.as_ref() } } -impl sealed::Sealed for Box {} -impl BorrowToSql for Box { +impl sealed::Sealed for Box {} +impl BorrowToSqlChecked for Box { #[inline] - fn borrow_to_sql(&self) -> &dyn ToSql { + fn borrow_to_sql(&self) -> &dyn ToSqlChecked { self.as_ref() } } -impl sealed::Sealed for &(dyn ToSql + Sync) {} +impl sealed::Sealed for &(dyn ToSqlChecked + Sync) {} /// In async contexts it is sometimes necessary to have the additional /// Sync requirement on parameters for queries since this enables the /// resulting Futures to be Send, hence usable in, e.g., tokio::spawn. /// This instance is provided for those cases. -impl BorrowToSql for &(dyn ToSql + Sync) { +impl BorrowToSqlChecked for &(dyn ToSqlChecked + Sync) { #[inline] - fn borrow_to_sql(&self) -> &dyn ToSql { + fn borrow_to_sql(&self) -> &dyn ToSqlChecked { *self } } -impl sealed::Sealed for T where T: ToSql {} +impl sealed::Sealed for T where T: ToSqlChecked {} -impl BorrowToSql for T +impl BorrowToSqlChecked for T where - T: ToSql, + T: ToSqlChecked, { #[inline] - fn borrow_to_sql(&self) -> &dyn ToSql { + fn borrow_to_sql(&self) -> &dyn ToSqlChecked { self } } diff --git a/postgres-types/src/pg_lsn.rs b/postgres-types/src/pg_lsn.rs index f0bbf4022..f9683a828 100644 --- a/postgres-types/src/pg_lsn.rs +++ b/postgres-types/src/pg_lsn.rs @@ -74,6 +74,4 @@ impl ToSql for PgLsn { } accepts!(PG_LSN); - - to_sql_checked!(); } diff --git a/postgres-types/src/special.rs b/postgres-types/src/special.rs index 1a865287e..c83c48f75 100644 --- a/postgres-types/src/special.rs +++ b/postgres-types/src/special.rs @@ -49,8 +49,6 @@ impl ToSql for Date { fn accepts(ty: &Type) -> bool { *ty == Type::DATE && T::accepts(ty) } - - to_sql_checked!(); } /// A wrapper that can be used to represent infinity with `Type::Timestamp` and `Type::Timestamptz` @@ -98,6 +96,4 @@ impl ToSql for Timestamp { fn accepts(ty: &Type) -> bool { matches!(*ty, Type::TIMESTAMP | Type::TIMESTAMPTZ if T::accepts(ty)) } - - to_sql_checked!(); } diff --git a/postgres/CHANGELOG.md b/postgres/CHANGELOG.md index c467c8b73..adb2bdd5f 100644 --- a/postgres/CHANGELOG.md +++ b/postgres/CHANGELOG.md @@ -35,7 +35,7 @@ ### Changed * Upgraded to `tokio-postgres` 0.7. -* Methods taking iterators of `ToSql` values can now take both `&dyn ToSql` and `T: ToSql` values. +* Methods taking iterators of `ToSql` values can now take both `&dyn ToSqlChecked` and `T: ToSql` values. ### Added diff --git a/postgres/src/binary_copy.rs b/postgres/src/binary_copy.rs index 1c4eb7d3b..5f0634530 100644 --- a/postgres/src/binary_copy.rs +++ b/postgres/src/binary_copy.rs @@ -1,7 +1,7 @@ //! Utilities for working with the PostgreSQL binary copy format. use crate::connection::ConnectionRef; -use crate::types::{BorrowToSql, ToSql, Type}; +use crate::types::{BorrowToSqlChecked, ToSqlChecked, Type}; use crate::{CopyInWriter, CopyOutReader, Error}; use fallible_iterator::FallibleIterator; use futures_util::StreamExt; @@ -37,7 +37,7 @@ impl<'a> BinaryCopyInWriter<'a> { /// # Panics /// /// Panics if the number of values provided does not match the number expected. - pub fn write(&mut self, values: &[&(dyn ToSql + Sync)]) -> Result<(), Error> { + pub fn write(&mut self, values: &[&(dyn ToSqlChecked + Sync)]) -> Result<(), Error> { self.connection.block_on(self.sink.as_mut().write(values)) } @@ -48,7 +48,7 @@ impl<'a> BinaryCopyInWriter<'a> { /// Panics if the number of values provided does not match the number expected. pub fn write_raw(&mut self, values: I) -> Result<(), Error> where - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { diff --git a/postgres/src/client.rs b/postgres/src/client.rs index 29cac840d..cb5f7facc 100644 --- a/postgres/src/client.rs +++ b/postgres/src/client.rs @@ -6,7 +6,7 @@ use crate::{ use std::task::Poll; use std::time::Duration; use tokio_postgres::tls::{MakeTlsConnect, TlsConnect}; -use tokio_postgres::types::{BorrowToSql, ToSql, Type}; +use tokio_postgres::types::{BorrowToSqlChecked, ToSqlChecked, Type}; use tokio_postgres::{Error, Row, SimpleQueryMessage, Socket}; /// A synchronous PostgreSQL client. @@ -80,7 +80,7 @@ impl Client { /// # Ok(()) /// # } /// ``` - pub fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + pub fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { @@ -116,7 +116,7 @@ impl Client { /// # Ok(()) /// # } /// ``` - pub fn query(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + pub fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement, { @@ -153,7 +153,7 @@ impl Client { /// # Ok(()) /// # } /// ``` - pub fn query_one(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + pub fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { @@ -199,7 +199,7 @@ impl Client { pub fn query_opt( &mut self, query: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -239,7 +239,7 @@ impl Client { /// ``` /// /// If you have a type like `Vec` where `T: ToSql` Rust will not know how to use it as params. To get around - /// this the type must explicitly be converted to `&dyn ToSql`. + /// this the type must explicitly be converted to `&dyn ToSqlChecked`. /// /// ```no_run /// # use postgres::{Client, NoTls}; @@ -267,7 +267,7 @@ impl Client { pub fn query_raw(&mut self, query: &T, params: I) -> Result, Error> where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { diff --git a/postgres/src/generic_client.rs b/postgres/src/generic_client.rs index 12f07465d..fd4c19775 100644 --- a/postgres/src/generic_client.rs +++ b/postgres/src/generic_client.rs @@ -1,4 +1,4 @@ -use crate::types::{BorrowToSql, ToSql, Type}; +use crate::types::{BorrowToSqlChecked, ToSqlChecked, Type}; use crate::{ Client, CopyInWriter, CopyOutReader, Error, Row, RowIter, SimpleQueryMessage, Statement, ToStatement, Transaction, @@ -13,17 +13,17 @@ mod private { /// This trait is "sealed", and cannot be implemented outside of this crate. pub trait GenericClient: private::Sealed { /// Like `Client::execute`. - fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement; /// Like `Client::query`. - fn query(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement; /// Like `Client::query_one`. - fn query_one(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement; @@ -31,7 +31,7 @@ pub trait GenericClient: private::Sealed { fn query_opt( &mut self, query: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement; @@ -40,7 +40,7 @@ pub trait GenericClient: private::Sealed { fn query_raw(&mut self, query: &T, params: I) -> Result, Error> where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator; @@ -73,21 +73,21 @@ pub trait GenericClient: private::Sealed { impl private::Sealed for Client {} impl GenericClient for Client { - fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { self.execute(query, params) } - fn query(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement, { self.query(query, params) } - fn query_one(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { @@ -97,7 +97,7 @@ impl GenericClient for Client { fn query_opt( &mut self, query: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -108,7 +108,7 @@ impl GenericClient for Client { fn query_raw(&mut self, query: &T, params: I) -> Result, Error> where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -153,21 +153,21 @@ impl GenericClient for Client { impl private::Sealed for Transaction<'_> {} impl GenericClient for Transaction<'_> { - fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { self.execute(query, params) } - fn query(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement, { self.query(query, params) } - fn query_one(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { @@ -177,7 +177,7 @@ impl GenericClient for Transaction<'_> { fn query_opt( &mut self, query: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -188,7 +188,7 @@ impl GenericClient for Transaction<'_> { fn query_raw(&mut self, query: &T, params: I) -> Result, Error> where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { diff --git a/postgres/src/transaction.rs b/postgres/src/transaction.rs index 17c49c406..9028079fc 100644 --- a/postgres/src/transaction.rs +++ b/postgres/src/transaction.rs @@ -1,6 +1,6 @@ use crate::connection::ConnectionRef; use crate::{CancelToken, CopyInWriter, CopyOutReader, Portal, RowIter, Statement, ToStatement}; -use tokio_postgres::types::{BorrowToSql, ToSql, Type}; +use tokio_postgres::types::{BorrowToSqlChecked, ToSqlChecked, Type}; use tokio_postgres::{Error, Row, SimpleQueryMessage}; /// A representation of a PostgreSQL database transaction. @@ -62,7 +62,7 @@ impl<'a> Transaction<'a> { } /// Like `Client::execute`. - pub fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + pub fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { @@ -71,7 +71,7 @@ impl<'a> Transaction<'a> { } /// Like `Client::query`. - pub fn query(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + pub fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement, { @@ -80,7 +80,7 @@ impl<'a> Transaction<'a> { } /// Like `Client::query_one`. - pub fn query_one(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + pub fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { @@ -92,7 +92,7 @@ impl<'a> Transaction<'a> { pub fn query_opt( &mut self, query: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -105,7 +105,7 @@ impl<'a> Transaction<'a> { pub fn query_raw(&mut self, query: &T, params: I) -> Result, Error> where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -125,7 +125,7 @@ impl<'a> Transaction<'a> { /// # Panics /// /// Panics if the number of parameters provided does not match the number expected. - pub fn bind(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + pub fn bind(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement, { diff --git a/tokio-postgres/CHANGELOG.md b/tokio-postgres/CHANGELOG.md index 91e78b780..3ba7d85ce 100644 --- a/tokio-postgres/CHANGELOG.md +++ b/tokio-postgres/CHANGELOG.md @@ -67,7 +67,7 @@ ### Added -* Methods taking iterators of `ToSql` values can now take both `&dyn ToSql` and `T: ToSql` values. +* Methods taking iterators of `ToSql` values can now take both `&dyn ToSqlChecked` and `T: ToSql` values. ## v0.6.0 - 2020-10-17 @@ -161,7 +161,7 @@ * The library now uses `std::futures::Future` and async/await syntax. * Most methods now take `&self` rather than `&mut self`. * The transaction API has changed to more closely resemble the synchronous API and is significantly more ergonomic. -* Methods now take `&[&(dyn ToSql + Sync)]` rather than `&[&dyn ToSql]` to allow futures to be `Send`. +* Methods now take `&[&(dyn ToSqlChecked + Sync)]` rather than `&[&dyn ToSqlChecked]` to allow futures to be `Send`. * Methods are now "normal" async functions that no longer do work up-front. * Statements are no longer required to be prepared explicitly before use. Methods taking `&Statement` can now also take `&str`, and will internally prepare the statement. diff --git a/tokio-postgres/src/binary_copy.rs b/tokio-postgres/src/binary_copy.rs index dab141663..1edcd07d1 100644 --- a/tokio-postgres/src/binary_copy.rs +++ b/tokio-postgres/src/binary_copy.rs @@ -1,12 +1,12 @@ //! Utilities for working with the PostgreSQL binary copy format. -use crate::types::{FromSql, IsNull, ToSql, Type, WrongType}; +use crate::types::{FromSql, IsNull, ToSqlChecked, Type, WrongType}; use crate::{slice_iter, CopyInSink, CopyOutStream, Error}; use byteorder::{BigEndian, ByteOrder}; use bytes::{Buf, BufMut, Bytes, BytesMut}; use futures_util::{ready, SinkExt, Stream}; use pin_project_lite::pin_project; -use postgres_types::BorrowToSql; +use postgres_types::BorrowToSqlChecked; use std::convert::TryFrom; use std::io; use std::io::Cursor; @@ -50,7 +50,7 @@ impl BinaryCopyInWriter { /// # Panics /// /// Panics if the number of values provided does not match the number expected. - pub async fn write(self: Pin<&mut Self>, values: &[&(dyn ToSql + Sync)]) -> Result<(), Error> { + pub async fn write(self: Pin<&mut Self>, values: &[&(dyn ToSqlChecked + Sync)]) -> Result<(), Error> { self.write_raw(slice_iter(values)).await } @@ -61,7 +61,7 @@ impl BinaryCopyInWriter { /// Panics if the number of values provided does not match the number expected. pub async fn write_raw(self: Pin<&mut Self>, values: I) -> Result<(), Error> where - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { diff --git a/tokio-postgres/src/bind.rs b/tokio-postgres/src/bind.rs index 9c5c49218..fdffeca32 100644 --- a/tokio-postgres/src/bind.rs +++ b/tokio-postgres/src/bind.rs @@ -1,7 +1,7 @@ use crate::client::InnerClient; use crate::codec::FrontendMessage; use crate::connection::RequestMessages; -use crate::types::BorrowToSql; +use crate::types::BorrowToSqlChecked; use crate::{query, Error, Portal, Statement}; use postgres_protocol::message::backend::Message; use postgres_protocol::message::frontend; @@ -16,7 +16,7 @@ pub async fn bind( params: I, ) -> Result where - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { diff --git a/tokio-postgres/src/client.rs b/tokio-postgres/src/client.rs index ad5aa2866..b2ebb02e4 100644 --- a/tokio-postgres/src/client.rs +++ b/tokio-postgres/src/client.rs @@ -11,7 +11,7 @@ use crate::simple_query::SimpleQueryStream; #[cfg(feature = "runtime")] use crate::tls::MakeTlsConnect; use crate::tls::TlsConnect; -use crate::types::{Oid, ToSql, Type}; +use crate::types::{Oid, BorrowToSqlChecked, ToSqlChecked, Type}; #[cfg(feature = "runtime")] use crate::Socket; use crate::{ @@ -24,7 +24,6 @@ use futures_channel::mpsc; use futures_util::{future, pin_mut, ready, StreamExt, TryStreamExt}; use parking_lot::Mutex; use postgres_protocol::message::{backend::Message, frontend}; -use postgres_types::BorrowToSql; use std::collections::HashMap; use std::fmt; use std::sync::Arc; @@ -237,7 +236,7 @@ impl Client { pub async fn query( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -265,7 +264,7 @@ impl Client { pub async fn query_one( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement, @@ -302,7 +301,7 @@ impl Client { pub async fn query_opt( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -364,7 +363,7 @@ impl Client { pub async fn query_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -389,7 +388,7 @@ impl Client { pub async fn execute( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement, @@ -414,7 +413,7 @@ impl Client { pub async fn execute_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { diff --git a/tokio-postgres/src/generic_client.rs b/tokio-postgres/src/generic_client.rs index b2a907558..c9bff57da 100644 --- a/tokio-postgres/src/generic_client.rs +++ b/tokio-postgres/src/generic_client.rs @@ -1,5 +1,5 @@ use crate::query::RowStream; -use crate::types::{BorrowToSql, ToSql, Type}; +use crate::types::{BorrowToSqlChecked, ToSqlChecked, Type}; use crate::{Client, Error, Row, Statement, ToStatement, Transaction}; use async_trait::async_trait; @@ -13,7 +13,7 @@ mod private { #[async_trait] pub trait GenericClient: private::Sealed { /// Like `Client::execute`. - async fn execute(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + async fn execute(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement + Sync + Send; @@ -21,12 +21,12 @@ pub trait GenericClient: private::Sealed { async fn execute_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement + Sync + Send, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator + Sync + Send, I::IntoIter: ExactSizeIterator; /// Like `Client::query`. - async fn query(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + async fn query(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send; @@ -34,7 +34,7 @@ pub trait GenericClient: private::Sealed { async fn query_one( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement + Sync + Send; @@ -43,7 +43,7 @@ pub trait GenericClient: private::Sealed { async fn query_opt( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send; @@ -52,7 +52,7 @@ pub trait GenericClient: private::Sealed { async fn query_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement + Sync + Send, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator + Sync + Send, I::IntoIter: ExactSizeIterator; @@ -77,7 +77,7 @@ impl private::Sealed for Client {} #[async_trait] impl GenericClient for Client { - async fn execute(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + async fn execute(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement + Sync + Send, { @@ -87,14 +87,14 @@ impl GenericClient for Client { async fn execute_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement + Sync + Send, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator + Sync + Send, I::IntoIter: ExactSizeIterator, { self.execute_raw(statement, params).await } - async fn query(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + async fn query(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send, { @@ -104,7 +104,7 @@ impl GenericClient for Client { async fn query_one( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement + Sync + Send, @@ -115,7 +115,7 @@ impl GenericClient for Client { async fn query_opt( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send, @@ -126,7 +126,7 @@ impl GenericClient for Client { async fn query_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement + Sync + Send, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator + Sync + Send, I::IntoIter: ExactSizeIterator, { @@ -159,7 +159,7 @@ impl private::Sealed for Transaction<'_> {} #[async_trait] #[allow(clippy::needless_lifetimes)] impl GenericClient for Transaction<'_> { - async fn execute(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + async fn execute(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result where T: ?Sized + ToStatement + Sync + Send, { @@ -169,14 +169,14 @@ impl GenericClient for Transaction<'_> { async fn execute_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement + Sync + Send, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator + Sync + Send, I::IntoIter: ExactSizeIterator, { self.execute_raw(statement, params).await } - async fn query(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error> + async fn query(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send, { @@ -186,7 +186,7 @@ impl GenericClient for Transaction<'_> { async fn query_one( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement + Sync + Send, @@ -197,7 +197,7 @@ impl GenericClient for Transaction<'_> { async fn query_opt( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send, @@ -208,7 +208,7 @@ impl GenericClient for Transaction<'_> { async fn query_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement + Sync + Send, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator + Sync + Send, I::IntoIter: ExactSizeIterator, { diff --git a/tokio-postgres/src/lib.rs b/tokio-postgres/src/lib.rs index bd4d7b8ce..62fd94490 100644 --- a/tokio-postgres/src/lib.rs +++ b/tokio-postgres/src/lib.rs @@ -141,7 +141,7 @@ pub use crate::tls::NoTls; pub use crate::to_statement::ToStatement; pub use crate::transaction::Transaction; pub use crate::transaction_builder::{IsolationLevel, TransactionBuilder}; -use crate::types::ToSql; +use crate::types::ToSqlChecked; pub mod binary_copy; mod bind; @@ -250,7 +250,7 @@ pub enum SimpleQueryMessage { } fn slice_iter<'a>( - s: &'a [&'a (dyn ToSql + Sync)], -) -> impl ExactSizeIterator + 'a { + s: &'a [&'a (dyn ToSqlChecked + Sync)], +) -> impl ExactSizeIterator + 'a { s.iter().map(|s| *s as _) } diff --git a/tokio-postgres/src/query.rs b/tokio-postgres/src/query.rs index 71db8769a..a598777dc 100644 --- a/tokio-postgres/src/query.rs +++ b/tokio-postgres/src/query.rs @@ -1,7 +1,7 @@ use crate::client::{InnerClient, Responses}; use crate::codec::FrontendMessage; use crate::connection::RequestMessages; -use crate::types::{BorrowToSql, IsNull}; +use crate::types::{BorrowToSqlChecked, IsNull}; use crate::{Error, Portal, Row, Statement}; use bytes::{Bytes, BytesMut}; use futures_util::{ready, Stream}; @@ -14,16 +14,32 @@ use std::marker::PhantomPinned; use std::pin::Pin; use std::task::{Context, Poll}; -struct BorrowToSqlParamsDebug<'a, T>(&'a [T]); +/// Wrapper type used for the [autoderef-based specialization][1]. +/// +/// [1]: https://bit.ly/3UAJ1Fd +struct DebugWrap(T); -impl<'a, T> fmt::Debug for BorrowToSqlParamsDebug<'a, T> -where - T: BorrowToSql, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list() - .entries(self.0.iter().map(|x| x.borrow_to_sql())) - .finish() +/// Trait used if inner type of [`DebugWrap`] implements [`fmt::Debug`]. +trait Impl { + /// Formats inner type of [`DebugWrap`] using [`fmt::Debug`]. + fn format_debug(&self) -> String; +} + +/// Trait used if inner type of [`DebugWrap`] does not implement [`fmt::Debug`]. +trait Fallback { + /// Returns string contains `Unformattable` message. + fn format_debug(&self) -> String; +} + +impl Impl for &DebugWrap { + fn format_debug(&self) -> String { + format!("{:?}", &self.0) + } +} + +impl Fallback for DebugWrap { + fn format_debug(&self) -> String { + "Unformattable".to_string() } } @@ -33,7 +49,7 @@ pub async fn query( params: I, ) -> Result where - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -42,7 +58,7 @@ where debug!( "executing statement {} with parameters: {:?}", statement.name(), - BorrowToSqlParamsDebug(params.as_slice()), + DebugWrap(params.as_slice()).format_debug() ); encode(client, &statement, params)? } else { @@ -82,7 +98,7 @@ pub async fn execute( params: I, ) -> Result where - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -91,7 +107,7 @@ where debug!( "executing statement {} with parameters: {:?}", statement.name(), - BorrowToSqlParamsDebug(params.as_slice()), + DebugWrap(params.as_slice()).format_debug(), ); encode(client, &statement, params)? } else { @@ -133,7 +149,7 @@ async fn start(client: &InnerClient, buf: Bytes) -> Result { pub fn encode(client: &InnerClient, statement: &Statement, params: I) -> Result where - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -152,15 +168,16 @@ pub fn encode_bind( buf: &mut BytesMut, ) -> Result<(), Error> where - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { let param_types = statement.params(); let params = params.into_iter(); - assert!( - param_types.len() == params.len(), + assert_eq!( + param_types.len(), + params.len(), "expected {} parameters but got {}", param_types.len(), params.len() diff --git a/tokio-postgres/src/transaction.rs b/tokio-postgres/src/transaction.rs index 96a324652..7476aabd3 100644 --- a/tokio-postgres/src/transaction.rs +++ b/tokio-postgres/src/transaction.rs @@ -5,7 +5,7 @@ use crate::query::RowStream; #[cfg(feature = "runtime")] use crate::tls::MakeTlsConnect; use crate::tls::TlsConnect; -use crate::types::{BorrowToSql, ToSql, Type}; +use crate::types::{BorrowToSqlChecked, ToSqlChecked, Type}; #[cfg(feature = "runtime")] use crate::Socket; use crate::{ @@ -106,7 +106,7 @@ impl<'a> Transaction<'a> { pub async fn query( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -118,7 +118,7 @@ impl<'a> Transaction<'a> { pub async fn query_one( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement, @@ -130,7 +130,7 @@ impl<'a> Transaction<'a> { pub async fn query_opt( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result, Error> where T: ?Sized + ToStatement, @@ -142,7 +142,7 @@ impl<'a> Transaction<'a> { pub async fn query_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -153,7 +153,7 @@ impl<'a> Transaction<'a> { pub async fn execute( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement, @@ -165,7 +165,7 @@ impl<'a> Transaction<'a> { pub async fn execute_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { @@ -183,7 +183,7 @@ impl<'a> Transaction<'a> { pub async fn bind( &self, statement: &T, - params: &[&(dyn ToSql + Sync)], + params: &[&(dyn ToSqlChecked + Sync)], ) -> Result where T: ?Sized + ToStatement, @@ -197,7 +197,7 @@ impl<'a> Transaction<'a> { pub async fn bind_raw(&self, statement: &T, params: I) -> Result where T: ?Sized + ToStatement, - P: BorrowToSql, + P: BorrowToSqlChecked, I: IntoIterator, I::IntoIter: ExactSizeIterator, { diff --git a/tokio-postgres/tests/test/types/chrono_04.rs b/tokio-postgres/tests/test/types/chrono_04.rs index a8e9e5afa..42413d41c 100644 --- a/tokio-postgres/tests/test/types/chrono_04.rs +++ b/tokio-postgres/tests/test/types/chrono_04.rs @@ -161,7 +161,7 @@ async fn test_time_params() { async fn test_special_params_without_wrapper() { async fn assert_overflows(client: &mut Client, val: &str, sql_type: &str) where - T: FromSqlOwned + fmt::Debug, + T: FromSqlOwned, { let err = client .query_one(&*format!("SELECT {}::{}", val, sql_type), &[]) diff --git a/tokio-postgres/tests/test/types/mod.rs b/tokio-postgres/tests/test/types/mod.rs index 452d149fe..cb8af2add 100644 --- a/tokio-postgres/tests/test/types/mod.rs +++ b/tokio-postgres/tests/test/types/mod.rs @@ -1,4 +1,4 @@ -use postgres_types::to_sql_checked; +// use postgres_types::to_sql_checked; use std::collections::HashMap; use std::error::Error; use std::f32; @@ -51,14 +51,14 @@ where .await .unwrap(); let result = rows[0].get(0); - assert_eq!(val, &result); + assert!(val == &result); let rows = client .query(&*format!("SELECT $1::{}", sql_type), &[&val]) .await .unwrap(); let result = rows[0].get(0); - assert_eq!(val, &result); + assert!(val == &result); } } @@ -505,8 +505,6 @@ async fn domain() { fn accepts(ty: &Type) -> bool { ty.name() == "session_id" && matches!(ty.kind(), Kind::Domain(_)) } - - to_sql_checked!(); } impl<'a> FromSql<'a> for SessionId { From ae2c065528a5f1b427bcb8515083d037ae0b9fee Mon Sep 17 00:00:00 2001 From: 50U10FCA7 Date: Mon, 26 Sep 2022 11:00:01 -0500 Subject: [PATCH 2/4] WIP [skip ci] --- postgres-derive-test/src/lib.rs | 6 +-- postgres-types/src/bit_vec_06.rs | 1 - postgres-types/src/chrono_04.rs | 6 --- postgres-types/src/cidr_02.rs | 2 - postgres-types/src/eui48_04.rs | 1 - postgres-types/src/eui48_1.rs | 1 - postgres-types/src/geo_types_06.rs | 3 -- postgres-types/src/geo_types_07.rs | 3 -- postgres-types/src/lib.rs | 33 +++++++----- postgres-types/src/serde_json_1.rs | 2 - postgres-types/src/smol_str_01.rs | 2 - postgres-types/src/time_02.rs | 4 -- postgres-types/src/time_03.rs | 4 -- postgres-types/src/uuid_08.rs | 1 - postgres-types/src/uuid_1.rs | 1 - postgres/CHANGELOG.md | 2 +- tokio-postgres/tests/test/types/mod.rs | 71 ++++++++++++++++++++++++-- 17 files changed, 93 insertions(+), 50 deletions(-) diff --git a/postgres-derive-test/src/lib.rs b/postgres-derive-test/src/lib.rs index 239d4ebe9..32c019a1b 100644 --- a/postgres-derive-test/src/lib.rs +++ b/postgres-derive-test/src/lib.rs @@ -11,7 +11,7 @@ mod transparent; pub fn test_type(conn: &mut Client, sql_type: &str, checks: &[(T, S)]) where - T: PartialEq + FromSqlOwned + ToSql + Sync, + T: PartialEq + FromSqlOwned + ToSql + Sync + fmt::Debug, S: fmt::Display, { for &(ref val, ref repr) in checks.iter() { @@ -19,11 +19,11 @@ where .prepare(&*format!("SELECT {}::{}", *repr, sql_type)) .unwrap(); let result = conn.query_one(&stmt, &[]).unwrap().get(0); - assert!(val == &result); + assert_eq!(val, &result); let stmt = conn.prepare(&*format!("SELECT $1::{}", sql_type)).unwrap(); let result = conn.query_one(&stmt, &[val]).unwrap().get(0); - assert!(val == &result); + assert_eq!(val, &result); } } diff --git a/postgres-types/src/bit_vec_06.rs b/postgres-types/src/bit_vec_06.rs index 322472c6f..40c975a45 100644 --- a/postgres-types/src/bit_vec_06.rs +++ b/postgres-types/src/bit_vec_06.rs @@ -26,5 +26,4 @@ impl ToSql for BitVec { } accepts!(BIT, VARBIT); - to_sql_checked!(); } diff --git a/postgres-types/src/chrono_04.rs b/postgres-types/src/chrono_04.rs index fcd25e6d1..c40f58c67 100644 --- a/postgres-types/src/chrono_04.rs +++ b/postgres-types/src/chrono_04.rs @@ -31,7 +31,6 @@ impl ToSql for NaiveDateTime { } accepts!(TIMESTAMP); - to_sql_checked!(); } impl<'a> FromSql<'a> for DateTime { @@ -53,7 +52,6 @@ impl ToSql for DateTime { } accepts!(TIMESTAMPTZ); - to_sql_checked!(); } impl<'a> FromSql<'a> for DateTime { @@ -75,7 +73,6 @@ impl ToSql for DateTime { } accepts!(TIMESTAMPTZ); - to_sql_checked!(); } impl<'a> FromSql<'a> for DateTime { @@ -100,7 +97,6 @@ impl ToSql for DateTime { } accepts!(TIMESTAMPTZ); - to_sql_checked!(); } impl<'a> FromSql<'a> for NaiveDate { @@ -127,7 +123,6 @@ impl ToSql for NaiveDate { } accepts!(DATE); - to_sql_checked!(); } impl<'a> FromSql<'a> for NaiveTime { @@ -151,5 +146,4 @@ impl ToSql for NaiveTime { } accepts!(TIME); - to_sql_checked!(); } diff --git a/postgres-types/src/cidr_02.rs b/postgres-types/src/cidr_02.rs index 2de952c3c..d38bd1663 100644 --- a/postgres-types/src/cidr_02.rs +++ b/postgres-types/src/cidr_02.rs @@ -21,7 +21,6 @@ impl ToSql for IpCidr { } accepts!(CIDR); - to_sql_checked!(); } impl<'a> FromSql<'a> for IpInet { @@ -40,5 +39,4 @@ impl ToSql for IpInet { } accepts!(INET); - to_sql_checked!(); } diff --git a/postgres-types/src/eui48_04.rs b/postgres-types/src/eui48_04.rs index 45df89a84..f65d1c9ac 100644 --- a/postgres-types/src/eui48_04.rs +++ b/postgres-types/src/eui48_04.rs @@ -23,5 +23,4 @@ impl ToSql for MacAddress { } accepts!(MACADDR); - to_sql_checked!(); } diff --git a/postgres-types/src/eui48_1.rs b/postgres-types/src/eui48_1.rs index 4c35e63ce..199a6d2ce 100644 --- a/postgres-types/src/eui48_1.rs +++ b/postgres-types/src/eui48_1.rs @@ -23,5 +23,4 @@ impl ToSql for MacAddress { } accepts!(MACADDR); - to_sql_checked!(); } diff --git a/postgres-types/src/geo_types_06.rs b/postgres-types/src/geo_types_06.rs index 0f0b14fd9..73b96e62e 100644 --- a/postgres-types/src/geo_types_06.rs +++ b/postgres-types/src/geo_types_06.rs @@ -22,7 +22,6 @@ impl ToSql for Point { } accepts!(POINT); - to_sql_checked!(); } impl<'a> FromSql<'a> for Rect { @@ -44,7 +43,6 @@ impl ToSql for Rect { } accepts!(BOX); - to_sql_checked!(); } impl<'a> FromSql<'a> for LineString { @@ -68,5 +66,4 @@ impl ToSql for LineString { } accepts!(PATH); - to_sql_checked!(); } diff --git a/postgres-types/src/geo_types_07.rs b/postgres-types/src/geo_types_07.rs index 7dfb51056..b281e1934 100644 --- a/postgres-types/src/geo_types_07.rs +++ b/postgres-types/src/geo_types_07.rs @@ -22,7 +22,6 @@ impl ToSql for Point { } accepts!(POINT); - to_sql_checked!(); } impl<'a> FromSql<'a> for Rect { @@ -44,7 +43,6 @@ impl ToSql for Rect { } accepts!(BOX); - to_sql_checked!(); } impl<'a> FromSql<'a> for LineString { @@ -68,5 +66,4 @@ impl ToSql for LineString { } accepts!(PATH); - to_sql_checked!(); } diff --git a/postgres-types/src/lib.rs b/postgres-types/src/lib.rs index 9596918e4..8dd792526 100644 --- a/postgres-types/src/lib.rs +++ b/postgres-types/src/lib.rs @@ -763,7 +763,7 @@ pub enum IsNull { /// /// # Arrays /// -/// `ToSql` is implemented for `[u8; N]`, `Vec`, `&[T]`, `Box<[T]>` and `[T; N]` +/// `ToSql` is implemented for `[u8; N]`, `Vec`, `[T]`, `&[T]`, `Box<[T]>` and `[T; N]` /// where `T` implements `ToSql` and `N` is const usize, and corresponds to one-dimensional /// Postgres arrays with an index offset of 1. /// @@ -792,12 +792,11 @@ pub trait ToSql { } } -/// A trait used internally by Rust-Postgres to convert types into Postgres values. +/// Trait used by Rust-Postgres **internally** to convert types into Postgres values. +/// +/// **Note:** Avoid manual implementation of this trait, use [`ToSql`] instead. pub trait ToSqlChecked { - /// An adaptor method used internally by Rust-Postgres. - /// - /// *All* implementations of this method should be generated by the - /// `to_sql_checked!()` macro. + /// Converts `Self` into `ty` Postgres type. fn to_sql_checked( &self, ty: &Type, @@ -928,15 +927,29 @@ impl<'a, T: ToSql> ToSql for &'a [T] { } } -impl<'a> ToSql for &'a [u8] { +impl<'a> ToSql for [u8] { fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { - types::bytea_to_sql(*self, w); + types::bytea_to_sql(self, w); Ok(IsNull::No) } accepts!(BYTEA); } +impl<'a> ToSql for &'a [u8] { + fn to_sql(&self, ty: &Type, w: &mut BytesMut) -> Result> { + <[u8]>::to_sql(self, ty, w) + } + + fn accepts(ty: &Type) -> bool { + <[u8]>::accepts(ty) + } + + fn encode_format(&self, ty: &Type) -> Format { + <[u8]>::encode_format(self, ty) + } +} + #[cfg(feature = "array-impls")] impl ToSql for [u8; N] { fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { @@ -945,8 +958,6 @@ impl ToSql for [u8; N] { } accepts!(BYTEA); - - to_sql_checked!(); } #[cfg(feature = "array-impls")] @@ -958,8 +969,6 @@ impl ToSql for [T; N] { fn accepts(ty: &Type) -> bool { <[T] as ToSql>::accepts(ty) } - - to_sql_checked!(); } impl ToSql for Vec { diff --git a/postgres-types/src/serde_json_1.rs b/postgres-types/src/serde_json_1.rs index b98d561d1..974c27941 100644 --- a/postgres-types/src/serde_json_1.rs +++ b/postgres-types/src/serde_json_1.rs @@ -48,7 +48,6 @@ where } accepts!(JSON, JSONB); - to_sql_checked!(); } impl<'a> FromSql<'a> for Value { @@ -69,5 +68,4 @@ impl ToSql for Value { } accepts!(JSON, JSONB); - to_sql_checked!(); } diff --git a/postgres-types/src/smol_str_01.rs b/postgres-types/src/smol_str_01.rs index a0d024ce2..446ff4f15 100644 --- a/postgres-types/src/smol_str_01.rs +++ b/postgres-types/src/smol_str_01.rs @@ -22,6 +22,4 @@ impl ToSql for SmolStr { fn accepts(ty: &Type) -> bool { <&str as ToSql>::accepts(ty) } - - to_sql_checked!(); } diff --git a/postgres-types/src/time_02.rs b/postgres-types/src/time_02.rs index 19a8909e7..d84869f7d 100644 --- a/postgres-types/src/time_02.rs +++ b/postgres-types/src/time_02.rs @@ -31,7 +31,6 @@ impl ToSql for PrimitiveDateTime { } accepts!(TIMESTAMP); - to_sql_checked!(); } impl<'a> FromSql<'a> for OffsetDateTime { @@ -57,7 +56,6 @@ impl ToSql for OffsetDateTime { } accepts!(TIMESTAMPTZ); - to_sql_checked!(); } impl<'a> FromSql<'a> for Date { @@ -81,7 +79,6 @@ impl ToSql for Date { } accepts!(DATE); - to_sql_checked!(); } impl<'a> FromSql<'a> for Time { @@ -105,5 +102,4 @@ impl ToSql for Time { } accepts!(TIME); - to_sql_checked!(); } diff --git a/postgres-types/src/time_03.rs b/postgres-types/src/time_03.rs index f136fab7c..293a625ec 100644 --- a/postgres-types/src/time_03.rs +++ b/postgres-types/src/time_03.rs @@ -30,7 +30,6 @@ impl ToSql for PrimitiveDateTime { } accepts!(TIMESTAMP); - to_sql_checked!(); } impl<'a> FromSql<'a> for OffsetDateTime { @@ -56,7 +55,6 @@ impl ToSql for OffsetDateTime { } accepts!(TIMESTAMPTZ); - to_sql_checked!(); } impl<'a> FromSql<'a> for Date { @@ -80,7 +78,6 @@ impl ToSql for Date { } accepts!(DATE); - to_sql_checked!(); } impl<'a> FromSql<'a> for Time { @@ -104,5 +101,4 @@ impl ToSql for Time { } accepts!(TIME); - to_sql_checked!(); } diff --git a/postgres-types/src/uuid_08.rs b/postgres-types/src/uuid_08.rs index 72d5e82fc..7ead3f7f3 100644 --- a/postgres-types/src/uuid_08.rs +++ b/postgres-types/src/uuid_08.rs @@ -21,5 +21,4 @@ impl ToSql for Uuid { } accepts!(UUID); - to_sql_checked!(); } diff --git a/postgres-types/src/uuid_1.rs b/postgres-types/src/uuid_1.rs index d9969f60c..2713a1b24 100644 --- a/postgres-types/src/uuid_1.rs +++ b/postgres-types/src/uuid_1.rs @@ -21,5 +21,4 @@ impl ToSql for Uuid { } accepts!(UUID); - to_sql_checked!(); } diff --git a/postgres/CHANGELOG.md b/postgres/CHANGELOG.md index adb2bdd5f..c467c8b73 100644 --- a/postgres/CHANGELOG.md +++ b/postgres/CHANGELOG.md @@ -35,7 +35,7 @@ ### Changed * Upgraded to `tokio-postgres` 0.7. -* Methods taking iterators of `ToSql` values can now take both `&dyn ToSqlChecked` and `T: ToSql` values. +* Methods taking iterators of `ToSql` values can now take both `&dyn ToSql` and `T: ToSql` values. ### Added diff --git a/tokio-postgres/tests/test/types/mod.rs b/tokio-postgres/tests/test/types/mod.rs index cb8af2add..9adf919ce 100644 --- a/tokio-postgres/tests/test/types/mod.rs +++ b/tokio-postgres/tests/test/types/mod.rs @@ -1,4 +1,3 @@ -// use postgres_types::to_sql_checked; use std::collections::HashMap; use std::error::Error; use std::f32; @@ -438,7 +437,7 @@ async fn test_slice() { .await .unwrap(); let rows = client - .query(&stmt, &[&&[1i32, 3, 4][..]]) + .query(&stmt, &[&[1i32, 3, 4][..]]) .await .unwrap() .into_iter() @@ -465,7 +464,7 @@ async fn test_slice_wrong_type() { .prepare("SELECT * FROM foo WHERE id = ANY($1)") .await .unwrap(); - let err = client.query(&stmt, &[&&[&"hi"][..]]).await.err().unwrap(); + let err = client.query(&stmt, &[&[&"hi"][..]]).await.err().unwrap(); match err.source() { Some(e) if e.is::() => {} _ => panic!("Unexpected error {:?}", err), @@ -476,6 +475,72 @@ async fn test_slice_wrong_type() { async fn test_slice_range() { let client = connect("user=postgres").await; + let stmt = client.prepare("SELECT $1::INT8RANGE").await.unwrap(); + let err = client.query(&stmt, &[&[&1i64][..]]).await.err().unwrap(); + match err.source() { + Some(e) if e.is::() => {} + _ => panic!("Unexpected error {:?}", err), + }; +} + +#[tokio::test] +async fn test_slice_ref() { + let client = connect("user=postgres").await; + + client + .batch_execute( + "CREATE TEMPORARY TABLE foo ( + id SERIAL PRIMARY KEY, + f TEXT + ); + INSERT INTO foo (f) VALUES ('a'), ('b'), ('c'), ('d');", + ) + .await + .unwrap(); + + let stmt = client + .prepare("SELECT f FROM foo WHERE id = ANY($1)") + .await + .unwrap(); + let rows = client + .query(&stmt, &[&&[1i32, 3, 4][..]]) + .await + .unwrap() + .into_iter() + .map(|r| r.get(0)) + .collect::>(); + + assert_eq!(vec!["a".to_owned(), "c".to_owned(), "d".to_owned()], rows); +} + +#[tokio::test] +async fn test_slice_ref_wrong_type() { + let client = connect("user=postgres").await; + + client + .batch_execute( + "CREATE TEMPORARY TABLE foo ( + id SERIAL PRIMARY KEY + )", + ) + .await + .unwrap(); + + let stmt = client + .prepare("SELECT * FROM foo WHERE id = ANY($1)") + .await + .unwrap(); + let err = client.query(&stmt, &[&&[&"hi"][..]]).await.err().unwrap(); + match err.source() { + Some(e) if e.is::() => {} + _ => panic!("Unexpected error {:?}", err), + }; +} + +#[tokio::test] +async fn test_slice_ref_range() { + let client = connect("user=postgres").await; + let stmt = client.prepare("SELECT $1::INT8RANGE").await.unwrap(); let err = client.query(&stmt, &[&&[&1i64][..]]).await.err().unwrap(); match err.source() { From 678ccd409bcaa8e114070657e0df502073359527 Mon Sep 17 00:00:00 2001 From: 50U10FCA7 Date: Mon, 26 Sep 2022 12:16:30 -0500 Subject: [PATCH 3/4] Corrections [run ci] --- postgres-types/CHANGELOG.md | 2 +- postgres-types/src/lib.rs | 11 ++-- postgres/src/client.rs | 18 +++++-- postgres/src/generic_client.rs | 42 ++++++++++++--- postgres/src/transaction.rs | 24 +++++++-- tokio-postgres/CHANGELOG.md | 4 +- tokio-postgres/src/binary_copy.rs | 5 +- tokio-postgres/src/client.rs | 2 +- tokio-postgres/src/generic_client.rs | 36 ++++++++++--- tokio-postgres/src/query.rs | 38 ++++--------- tokio-postgres/tests/test/types/mod.rs | 74 ++------------------------ 11 files changed, 129 insertions(+), 127 deletions(-) diff --git a/postgres-types/CHANGELOG.md b/postgres-types/CHANGELOG.md index 2953696e2..0e2167e5f 100644 --- a/postgres-types/CHANGELOG.md +++ b/postgres-types/CHANGELOG.md @@ -14,7 +14,7 @@ ### Added * Added `ToSql` and `FromSql` implementations for `Box`. -* Added `BorrowToSqlChecked` implementations for `Box` and `Box`. +* Added `BorrowToSql` implementations for `Box` and `Box`. * Added support for `cidr` 0.2 via the `with-cidr-02` feature. * Added conversions between the `LTREE`, `LQUERY` and `LTXTQUERY` types and Rust strings. * Added support for `uuid` 1.0 via the `with-uuid-1` feature. diff --git a/postgres-types/src/lib.rs b/postgres-types/src/lib.rs index 8dd792526..32f6ab249 100644 --- a/postgres-types/src/lib.rs +++ b/postgres-types/src/lib.rs @@ -769,7 +769,7 @@ pub enum IsNull { /// /// **Note:** the impl for arrays only exist when the Cargo feature `array-impls` /// is enabled. -pub trait ToSql { +pub trait ToSql: fmt::Debug { /// Converts the value of `self` into the binary format of the specified /// Postgres `Type`, appending it to `out`. /// @@ -794,8 +794,8 @@ pub trait ToSql { /// Trait used by Rust-Postgres **internally** to convert types into Postgres values. /// -/// **Note:** Avoid manual implementation of this trait, use [`ToSql`] instead. -pub trait ToSqlChecked { +/// **Note:** Do not implement this trait directly, use [`ToSql`] instead. +pub trait ToSqlChecked: fmt::Debug { /// Converts `Self` into `ty` Postgres type. fn to_sql_checked( &self, @@ -927,7 +927,7 @@ impl<'a, T: ToSql> ToSql for &'a [T] { } } -impl<'a> ToSql for [u8] { +impl ToSql for [u8] { fn to_sql(&self, _: &Type, w: &mut BytesMut) -> Result> { types::bytea_to_sql(self, w); Ok(IsNull::No) @@ -1144,7 +1144,7 @@ mod sealed { pub trait Sealed {} } -/// A trait used by clients to abstract over `&dyn ToSqlChecked` and `T: ToSql`. +/// A trait used by clients to abstract over `&dyn ToSqlChecked` and `T: ToSqlChecked`. /// /// This cannot be implemented outside of this crate. pub trait BorrowToSqlChecked: sealed::Sealed { @@ -1171,6 +1171,7 @@ impl BorrowToSqlChecked for Box { } impl sealed::Sealed for Box {} + impl BorrowToSqlChecked for Box { #[inline] fn borrow_to_sql(&self) -> &dyn ToSqlChecked { diff --git a/postgres/src/client.rs b/postgres/src/client.rs index cb5f7facc..0075b9a0f 100644 --- a/postgres/src/client.rs +++ b/postgres/src/client.rs @@ -80,7 +80,11 @@ impl Client { /// # Ok(()) /// # } /// ``` - pub fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + pub fn execute( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement, { @@ -116,7 +120,11 @@ impl Client { /// # Ok(()) /// # } /// ``` - pub fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + pub fn query( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement, { @@ -153,7 +161,11 @@ impl Client { /// # Ok(()) /// # } /// ``` - pub fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + pub fn query_one( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement, { diff --git a/postgres/src/generic_client.rs b/postgres/src/generic_client.rs index fd4c19775..b17ebf9d0 100644 --- a/postgres/src/generic_client.rs +++ b/postgres/src/generic_client.rs @@ -13,17 +13,29 @@ mod private { /// This trait is "sealed", and cannot be implemented outside of this crate. pub trait GenericClient: private::Sealed { /// Like `Client::execute`. - fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + fn execute( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement; /// Like `Client::query`. - fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + fn query( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement; /// Like `Client::query_one`. - fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + fn query_one( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement; @@ -80,14 +92,22 @@ impl GenericClient for Client { self.execute(query, params) } - fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + fn query( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement, { self.query(query, params) } - fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + fn query_one( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement, { @@ -160,14 +180,22 @@ impl GenericClient for Transaction<'_> { self.execute(query, params) } - fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + fn query( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement, { self.query(query, params) } - fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + fn query_one( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement, { diff --git a/postgres/src/transaction.rs b/postgres/src/transaction.rs index 9028079fc..16062c0ec 100644 --- a/postgres/src/transaction.rs +++ b/postgres/src/transaction.rs @@ -62,7 +62,11 @@ impl<'a> Transaction<'a> { } /// Like `Client::execute`. - pub fn execute(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + pub fn execute( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement, { @@ -71,7 +75,11 @@ impl<'a> Transaction<'a> { } /// Like `Client::query`. - pub fn query(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + pub fn query( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement, { @@ -80,7 +88,11 @@ impl<'a> Transaction<'a> { } /// Like `Client::query_one`. - pub fn query_one(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + pub fn query_one( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement, { @@ -125,7 +137,11 @@ impl<'a> Transaction<'a> { /// # Panics /// /// Panics if the number of parameters provided does not match the number expected. - pub fn bind(&mut self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + pub fn bind( + &mut self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement, { diff --git a/tokio-postgres/CHANGELOG.md b/tokio-postgres/CHANGELOG.md index 3ba7d85ce..91e78b780 100644 --- a/tokio-postgres/CHANGELOG.md +++ b/tokio-postgres/CHANGELOG.md @@ -67,7 +67,7 @@ ### Added -* Methods taking iterators of `ToSql` values can now take both `&dyn ToSqlChecked` and `T: ToSql` values. +* Methods taking iterators of `ToSql` values can now take both `&dyn ToSql` and `T: ToSql` values. ## v0.6.0 - 2020-10-17 @@ -161,7 +161,7 @@ * The library now uses `std::futures::Future` and async/await syntax. * Most methods now take `&self` rather than `&mut self`. * The transaction API has changed to more closely resemble the synchronous API and is significantly more ergonomic. -* Methods now take `&[&(dyn ToSqlChecked + Sync)]` rather than `&[&dyn ToSqlChecked]` to allow futures to be `Send`. +* Methods now take `&[&(dyn ToSql + Sync)]` rather than `&[&dyn ToSql]` to allow futures to be `Send`. * Methods are now "normal" async functions that no longer do work up-front. * Statements are no longer required to be prepared explicitly before use. Methods taking `&Statement` can now also take `&str`, and will internally prepare the statement. diff --git a/tokio-postgres/src/binary_copy.rs b/tokio-postgres/src/binary_copy.rs index 1edcd07d1..bf8b9e28d 100644 --- a/tokio-postgres/src/binary_copy.rs +++ b/tokio-postgres/src/binary_copy.rs @@ -50,7 +50,10 @@ impl BinaryCopyInWriter { /// # Panics /// /// Panics if the number of values provided does not match the number expected. - pub async fn write(self: Pin<&mut Self>, values: &[&(dyn ToSqlChecked + Sync)]) -> Result<(), Error> { + pub async fn write( + self: Pin<&mut Self>, + values: &[&(dyn ToSqlChecked + Sync)], + ) -> Result<(), Error> { self.write_raw(slice_iter(values)).await } diff --git a/tokio-postgres/src/client.rs b/tokio-postgres/src/client.rs index b2ebb02e4..78c87b590 100644 --- a/tokio-postgres/src/client.rs +++ b/tokio-postgres/src/client.rs @@ -11,7 +11,7 @@ use crate::simple_query::SimpleQueryStream; #[cfg(feature = "runtime")] use crate::tls::MakeTlsConnect; use crate::tls::TlsConnect; -use crate::types::{Oid, BorrowToSqlChecked, ToSqlChecked, Type}; +use crate::types::{BorrowToSqlChecked, Oid, ToSqlChecked, Type}; #[cfg(feature = "runtime")] use crate::Socket; use crate::{ diff --git a/tokio-postgres/src/generic_client.rs b/tokio-postgres/src/generic_client.rs index c9bff57da..b01e620b4 100644 --- a/tokio-postgres/src/generic_client.rs +++ b/tokio-postgres/src/generic_client.rs @@ -13,7 +13,11 @@ mod private { #[async_trait] pub trait GenericClient: private::Sealed { /// Like `Client::execute`. - async fn execute(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + async fn execute( + &self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement + Sync + Send; @@ -26,7 +30,11 @@ pub trait GenericClient: private::Sealed { I::IntoIter: ExactSizeIterator; /// Like `Client::query`. - async fn query(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + async fn query( + &self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send; @@ -77,7 +85,11 @@ impl private::Sealed for Client {} #[async_trait] impl GenericClient for Client { - async fn execute(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + async fn execute( + &self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement + Sync + Send, { @@ -94,7 +106,11 @@ impl GenericClient for Client { self.execute_raw(statement, params).await } - async fn query(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + async fn query( + &self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send, { @@ -159,7 +175,11 @@ impl private::Sealed for Transaction<'_> {} #[async_trait] #[allow(clippy::needless_lifetimes)] impl GenericClient for Transaction<'_> { - async fn execute(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result + async fn execute( + &self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result where T: ?Sized + ToStatement + Sync + Send, { @@ -176,7 +196,11 @@ impl GenericClient for Transaction<'_> { self.execute_raw(statement, params).await } - async fn query(&self, query: &T, params: &[&(dyn ToSqlChecked + Sync)]) -> Result, Error> + async fn query( + &self, + query: &T, + params: &[&(dyn ToSqlChecked + Sync)], + ) -> Result, Error> where T: ?Sized + ToStatement + Sync + Send, { diff --git a/tokio-postgres/src/query.rs b/tokio-postgres/src/query.rs index a598777dc..d24cff92d 100644 --- a/tokio-postgres/src/query.rs +++ b/tokio-postgres/src/query.rs @@ -14,32 +14,16 @@ use std::marker::PhantomPinned; use std::pin::Pin; use std::task::{Context, Poll}; -/// Wrapper type used for the [autoderef-based specialization][1]. -/// -/// [1]: https://bit.ly/3UAJ1Fd -struct DebugWrap(T); - -/// Trait used if inner type of [`DebugWrap`] implements [`fmt::Debug`]. -trait Impl { - /// Formats inner type of [`DebugWrap`] using [`fmt::Debug`]. - fn format_debug(&self) -> String; -} - -/// Trait used if inner type of [`DebugWrap`] does not implement [`fmt::Debug`]. -trait Fallback { - /// Returns string contains `Unformattable` message. - fn format_debug(&self) -> String; -} - -impl Impl for &DebugWrap { - fn format_debug(&self) -> String { - format!("{:?}", &self.0) - } -} +struct BorrowToSqlParamsDebug<'a, T>(&'a [T]); -impl Fallback for DebugWrap { - fn format_debug(&self) -> String { - "Unformattable".to_string() +impl<'a, T> fmt::Debug for BorrowToSqlParamsDebug<'a, T> +where + T: BorrowToSqlChecked, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_list() + .entries(self.0.iter().map(|x| x.borrow_to_sql())) + .finish() } } @@ -58,7 +42,7 @@ where debug!( "executing statement {} with parameters: {:?}", statement.name(), - DebugWrap(params.as_slice()).format_debug() + BorrowToSqlParamsDebug(params.as_slice()), ); encode(client, &statement, params)? } else { @@ -107,7 +91,7 @@ where debug!( "executing statement {} with parameters: {:?}", statement.name(), - DebugWrap(params.as_slice()).format_debug(), + BorrowToSqlParamsDebug(params.as_slice()), ); encode(client, &statement, params)? } else { diff --git a/tokio-postgres/tests/test/types/mod.rs b/tokio-postgres/tests/test/types/mod.rs index 9adf919ce..681cc4e66 100644 --- a/tokio-postgres/tests/test/types/mod.rs +++ b/tokio-postgres/tests/test/types/mod.rs @@ -50,14 +50,14 @@ where .await .unwrap(); let result = rows[0].get(0); - assert!(val == &result); + assert_eq!(val, &result); let rows = client .query(&*format!("SELECT $1::{}", sql_type), &[&val]) .await .unwrap(); let result = rows[0].get(0); - assert!(val == &result); + assert_eq!(val, &result); } } @@ -421,72 +421,6 @@ async fn test_pg_database_datname() { async fn test_slice() { let client = connect("user=postgres").await; - client - .batch_execute( - "CREATE TEMPORARY TABLE foo ( - id SERIAL PRIMARY KEY, - f TEXT - ); - INSERT INTO foo (f) VALUES ('a'), ('b'), ('c'), ('d');", - ) - .await - .unwrap(); - - let stmt = client - .prepare("SELECT f FROM foo WHERE id = ANY($1)") - .await - .unwrap(); - let rows = client - .query(&stmt, &[&[1i32, 3, 4][..]]) - .await - .unwrap() - .into_iter() - .map(|r| r.get(0)) - .collect::>(); - - assert_eq!(vec!["a".to_owned(), "c".to_owned(), "d".to_owned()], rows); -} - -#[tokio::test] -async fn test_slice_wrong_type() { - let client = connect("user=postgres").await; - - client - .batch_execute( - "CREATE TEMPORARY TABLE foo ( - id SERIAL PRIMARY KEY - )", - ) - .await - .unwrap(); - - let stmt = client - .prepare("SELECT * FROM foo WHERE id = ANY($1)") - .await - .unwrap(); - let err = client.query(&stmt, &[&[&"hi"][..]]).await.err().unwrap(); - match err.source() { - Some(e) if e.is::() => {} - _ => panic!("Unexpected error {:?}", err), - }; -} - -#[tokio::test] -async fn test_slice_range() { - let client = connect("user=postgres").await; - - let stmt = client.prepare("SELECT $1::INT8RANGE").await.unwrap(); - let err = client.query(&stmt, &[&[&1i64][..]]).await.err().unwrap(); - match err.source() { - Some(e) if e.is::() => {} - _ => panic!("Unexpected error {:?}", err), - }; -} - -#[tokio::test] -async fn test_slice_ref() { - let client = connect("user=postgres").await; - client .batch_execute( "CREATE TEMPORARY TABLE foo ( @@ -514,7 +448,7 @@ async fn test_slice_ref() { } #[tokio::test] -async fn test_slice_ref_wrong_type() { +async fn test_slice_wrong_type() { let client = connect("user=postgres").await; client @@ -538,7 +472,7 @@ async fn test_slice_ref_wrong_type() { } #[tokio::test] -async fn test_slice_ref_range() { +async fn test_slice_range() { let client = connect("user=postgres").await; let stmt = client.prepare("SELECT $1::INT8RANGE").await.unwrap(); From e265ad06b2cf574da4cb14f1052ada4691b00ab3 Mon Sep 17 00:00:00 2001 From: 50U10FCA7 Date: Mon, 26 Sep 2022 14:18:19 -0500 Subject: [PATCH 4/4] Minor correction [run ci] --- postgres-derive-test/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/postgres-derive-test/src/lib.rs b/postgres-derive-test/src/lib.rs index 32c019a1b..8bfd147fb 100644 --- a/postgres-derive-test/src/lib.rs +++ b/postgres-derive-test/src/lib.rs @@ -11,7 +11,7 @@ mod transparent; pub fn test_type(conn: &mut Client, sql_type: &str, checks: &[(T, S)]) where - T: PartialEq + FromSqlOwned + ToSql + Sync + fmt::Debug, + T: PartialEq + FromSqlOwned + ToSql + Sync, S: fmt::Display, { for &(ref val, ref repr) in checks.iter() {