diff --git a/tokio-postgres/CHANGELOG.md b/tokio-postgres/CHANGELOG.md
index 91e78b780..61f3e7117 100644
--- a/tokio-postgres/CHANGELOG.md
+++ b/tokio-postgres/CHANGELOG.md
@@ -1,5 +1,11 @@
# Change Log
+## Unreleased
+
+### Added
+
+* Added `execute_prepared` functions.
+
## v0.7.7 - 2022-08-21
## Added
diff --git a/tokio-postgres/src/client.rs b/tokio-postgres/src/client.rs
index ad5aa2866..e8a5a2a26 100644
--- a/tokio-postgres/src/client.rs
+++ b/tokio-postgres/src/client.rs
@@ -6,7 +6,7 @@ use crate::connection::{Request, RequestMessages};
use crate::copy_out::CopyOutStream;
#[cfg(feature = "runtime")]
use crate::keepalive::KeepaliveConfig;
-use crate::query::RowStream;
+use crate::query::{Execute, RowStream};
use crate::simple_query::SimpleQueryStream;
#[cfg(feature = "runtime")]
use crate::tls::MakeTlsConnect;
@@ -422,6 +422,26 @@ impl Client {
query::execute(self.inner(), statement, params).await
}
+ /// A version of [`execute_raw`] that does not borrow its arguments.
+ ///
+ /// This function is identical to [`execute_raw`] except that:
+ ///
+ /// 1. The returned future does not borrow the parameters or `self`.
+ /// 2. The type of the returned future does not depend on the parameters.
+ /// 3. If multiple such futures are being used concurrently, then they are executed on the server in the order
+ /// in which this function was called, regardless of the order in which the futures are polled.
+ /// 4. This function can only be used with prepared statements.
+ ///
+ /// [`execute_raw`]: #method.execute_raw
+ pub fn execute_prepared
(&self, statement: &Statement, params: I) -> Execute
+ where
+ P: BorrowToSql,
+ I: IntoIterator- ,
+ I::IntoIter: ExactSizeIterator,
+ {
+ query::execute(self.inner(), statement.clone(), params)
+ }
+
/// Executes a `COPY FROM STDIN` statement, returning a sink used to write the copy data.
///
/// PostgreSQL does not support parameters in `COPY` statements, so this method does not take any. The copy *must*
diff --git a/tokio-postgres/src/generic_client.rs b/tokio-postgres/src/generic_client.rs
index 50cff9712..d1040d42e 100644
--- a/tokio-postgres/src/generic_client.rs
+++ b/tokio-postgres/src/generic_client.rs
@@ -1,4 +1,4 @@
-use crate::query::RowStream;
+use crate::query::{Execute, RowStream};
use crate::types::{BorrowToSql, ToSql, Type};
use crate::{Client, Error, Row, Statement, ToStatement, Transaction};
use async_trait::async_trait;
@@ -25,6 +25,13 @@ pub trait GenericClient: private::Sealed {
I: IntoIterator
- + Sync + Send,
I::IntoIter: ExactSizeIterator;
+ /// Like `Client::execute_prepared`.
+ fn execute_prepared
(&self, statement: &Statement, params: I) -> Execute
+ where
+ P: BorrowToSql,
+ I: IntoIterator- ,
+ I::IntoIter: ExactSizeIterator;
+
/// Like `Client::query`.
async fn query(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error>
where
@@ -97,6 +104,15 @@ impl GenericClient for Client {
self.execute_raw(statement, params).await
}
+ fn execute_prepared
(&self, statement: &Statement, params: I) -> Execute
+ where
+ P: BorrowToSql,
+ I: IntoIterator- ,
+ I::IntoIter: ExactSizeIterator,
+ {
+ self.execute_prepared(statement, params)
+ }
+
async fn query(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error>
where
T: ?Sized + ToStatement + Sync + Send,
@@ -183,6 +199,15 @@ impl GenericClient for Transaction<'_> {
self.execute_raw(statement, params).await
}
+ fn execute_prepared
(&self, statement: &Statement, params: I) -> Execute
+ where
+ P: BorrowToSql,
+ I: IntoIterator- ,
+ I::IntoIter: ExactSizeIterator,
+ {
+ self.execute_prepared(statement, params)
+ }
+
async fn query(&self, query: &T, params: &[&(dyn ToSql + Sync)]) -> Result, Error>
where
T: ?Sized + ToStatement + Sync + Send,
diff --git a/tokio-postgres/src/lib.rs b/tokio-postgres/src/lib.rs
index a9ecba4f1..fa2c9943d 100644
--- a/tokio-postgres/src/lib.rs
+++ b/tokio-postgres/src/lib.rs
@@ -129,6 +129,7 @@ use crate::error::DbError;
pub use crate::error::Error;
pub use crate::generic_client::GenericClient;
pub use crate::portal::Portal;
+pub use crate::query::Execute;
pub use crate::query::RowStream;
pub use crate::row::{Row, SimpleQueryRow};
pub use crate::simple_query::SimpleQueryStream;
diff --git a/tokio-postgres/src/query.rs b/tokio-postgres/src/query.rs
index 12176353b..f468fc660 100644
--- a/tokio-postgres/src/query.rs
+++ b/tokio-postgres/src/query.rs
@@ -10,6 +10,7 @@ use pin_project_lite::pin_project;
use postgres_protocol::message::backend::{CommandCompleteBody, Message};
use postgres_protocol::message::frontend;
use std::fmt;
+use std::future::Future;
use std::marker::PhantomPinned;
use std::pin::Pin;
use std::task::{Context, Poll};
@@ -91,11 +92,68 @@ pub fn extract_row_affected(body: &CommandCompleteBody) -> Result {
Ok(rows)
}
-pub async fn execute
(
- client: &InnerClient,
- statement: Statement,
- params: I,
-) -> Result
+/// A future that completes with the result of an `execute_prepared` function call.
+// Once https://github.com/rust-lang/rust/issues/63063 is stable, we might want to replace this by
+// type Execute = impl Future