From 3ba416ded6d0f5b9a41e980a1b090828eac7be9b Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 2 Jan 2020 20:58:38 -0500 Subject: [PATCH 1/2] Add tokio_postgres::GenericClient We have to make the trait methods differ from the normal methods a bit by adding Sync + Send bounds to the ToStatement parameter which is a bit unfortunate, but necessary until GATs async_trait unnecessary. Closes #357 --- postgres/src/generic_client.rs | 7 +++-- tokio-postgres/Cargo.toml | 1 + tokio-postgres/src/client.rs | 40 +++++++++++++++++++++++----- tokio-postgres/src/generic_client.rs | 27 +++++++++++++++++++ tokio-postgres/src/lib.rs | 2 ++ tokio-postgres/src/transaction.rs | 30 +++++++++++++++++++++ 6 files changed, 97 insertions(+), 10 deletions(-) create mode 100644 tokio-postgres/src/generic_client.rs diff --git a/postgres/src/generic_client.rs b/postgres/src/generic_client.rs index 354c6bb0..b586d0d4 100644 --- a/postgres/src/generic_client.rs +++ b/postgres/src/generic_client.rs @@ -1,8 +1,7 @@ -use crate::{Statement, ToStatement, Transaction}; -use tokio_postgres::types::ToSql; -use tokio_postgres::{Error, Row}; +use crate::types::ToSql; +use crate::{Error, Row, Statement, ToStatement, Transaction}; -/// A trait allowing abstraction over connections and transactions +/// A trait allowing abstraction over connections and transactions. pub trait GenericClient { /// Like `Client::execute`. fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result diff --git a/tokio-postgres/Cargo.toml b/tokio-postgres/Cargo.toml index 4c16758f..dc2c140a 100644 --- a/tokio-postgres/Cargo.toml +++ b/tokio-postgres/Cargo.toml @@ -35,6 +35,7 @@ with-serde_json-1 = ["postgres-types/with-serde_json-1"] with-uuid-0_8 = ["postgres-types/with-uuid-0_8"] [dependencies] +async-trait = "0.1" bytes = "0.5" byteorder = "1.0" fallible-iterator = "0.2" diff --git a/tokio-postgres/src/client.rs b/tokio-postgres/src/client.rs index d9b4a311..50cca9dd 100644 --- a/tokio-postgres/src/client.rs +++ b/tokio-postgres/src/client.rs @@ -4,18 +4,17 @@ use crate::connection::{Request, RequestMessages}; use crate::copy_out::CopyOutStream; use crate::query::RowStream; use crate::simple_query::SimpleQueryStream; -use crate::slice_iter; #[cfg(feature = "runtime")] use crate::tls::MakeTlsConnect; use crate::tls::TlsConnect; -use crate::to_statement::ToStatement; use crate::types::{Oid, ToSql, Type}; #[cfg(feature = "runtime")] use crate::Socket; -use crate::{copy_in, copy_out, query, CancelToken, CopyInSink, Transaction}; -use crate::{prepare, SimpleQueryMessage}; -use crate::{simple_query, Row}; -use crate::{Error, Statement}; +use crate::{ + copy_in, copy_out, prepare, query, simple_query, slice_iter, CancelToken, CopyInSink, Error, + GenericClient, Row, SimpleQueryMessage, Statement, ToStatement, Transaction, +}; +use async_trait::async_trait; use bytes::{Buf, BytesMut}; use fallible_iterator::FallibleIterator; use futures::channel::mpsc; @@ -495,3 +494,32 @@ impl Client { self.inner.sender.is_closed() } } + +#[async_trait] +impl GenericClient for Client { + async fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + where + T: ?Sized + ToStatement + Sync + Send, + { + self.execute(query, params).await + } + + async fn query( + &mut self, + query: &T, + params: &[&(dyn ToSql + Sync)], + ) -> Result, Error> + where + T: ?Sized + ToStatement + Sync + Send, + { + self.query(query, params).await + } + + async fn prepare(&mut self, query: &str) -> Result { + self.prepare(query).await + } + + async fn transaction(&mut self) -> Result, Error> { + self.transaction().await + } +} diff --git a/tokio-postgres/src/generic_client.rs b/tokio-postgres/src/generic_client.rs new file mode 100644 index 00000000..949ad4f0 --- /dev/null +++ b/tokio-postgres/src/generic_client.rs @@ -0,0 +1,27 @@ +use crate::types::ToSql; +use crate::{Error, Row, Statement, ToStatement, Transaction}; +use async_trait::async_trait; + +/// A trait allowing abstraction over connections and transactions. +#[async_trait] +pub trait GenericClient { + /// Like `Client::execute`. + async fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + where + T: ?Sized + ToStatement + Sync + Send; + + /// Like `Client::query`. + async fn query( + &mut self, + query: &T, + params: &[&(dyn ToSql + Sync)], + ) -> Result, Error> + where + T: ?Sized + ToStatement + Sync + Send; + + /// Like `Client::prepare`. + async fn prepare(&mut self, query: &str) -> Result; + + /// Like `Client::transaction`. + async fn transaction(&mut self) -> Result, Error>; +} diff --git a/tokio-postgres/src/lib.rs b/tokio-postgres/src/lib.rs index ff87baf0..98428424 100644 --- a/tokio-postgres/src/lib.rs +++ b/tokio-postgres/src/lib.rs @@ -107,6 +107,7 @@ pub use crate::copy_in::CopyInSink; pub use crate::copy_out::CopyOutStream; use crate::error::DbError; pub use crate::error::Error; +pub use crate::generic_client::GenericClient; pub use crate::portal::Portal; pub use crate::query::RowStream; pub use crate::row::{Row, SimpleQueryRow}; @@ -140,6 +141,7 @@ mod connection; mod copy_in; mod copy_out; pub mod error; +mod generic_client; mod maybe_tls_stream; mod portal; mod prepare; diff --git a/tokio-postgres/src/transaction.rs b/tokio-postgres/src/transaction.rs index a1ee4f6c..4fa25a7a 100644 --- a/tokio-postgres/src/transaction.rs +++ b/tokio-postgres/src/transaction.rs @@ -12,6 +12,7 @@ use crate::{ bind, query, slice_iter, CancelToken, Client, CopyInSink, Error, Portal, Row, SimpleQueryMessage, Statement, ToStatement, }; +use async_trait::async_trait; use bytes::Buf; use futures::TryStreamExt; use postgres_protocol::message::frontend; @@ -285,3 +286,32 @@ impl<'a> Transaction<'a> { }) } } + +#[async_trait] +impl crate::GenericClient for Transaction<'_> { + async fn execute(&mut self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result + where + T: ?Sized + ToStatement + Sync + Send, + { + self.execute(query, params).await + } + + async fn query( + &mut self, + query: &T, + params: &[&(dyn ToSql + Sync)], + ) -> Result, Error> + where + T: ?Sized + ToStatement + Sync + Send, + { + self.query(query, params).await + } + + async fn prepare(&mut self, query: &str) -> Result { + self.prepare(query).await + } + + async fn transaction<'a>(&'a mut self) -> Result, Error> { + self.transaction().await + } +} From 24d4b9233666c1b9517da5ff9f027b1c1f851396 Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Thu, 2 Jan 2020 21:05:38 -0500 Subject: [PATCH 2/2] Whitelist clippy lint async_trait requires this to be explicit --- tokio-postgres/src/transaction.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tokio-postgres/src/transaction.rs b/tokio-postgres/src/transaction.rs index 4fa25a7a..75a93930 100644 --- a/tokio-postgres/src/transaction.rs +++ b/tokio-postgres/src/transaction.rs @@ -311,6 +311,7 @@ impl crate::GenericClient for Transaction<'_> { self.prepare(query).await } + #[allow(clippy::needless_lifetimes)] async fn transaction<'a>(&'a mut self) -> Result, Error> { self.transaction().await }