Skip to content

Commit 1fcd04d

Browse files
authored
Merge pull request #684 from vemoo/better-params-iter
better api for passing parameters to `*_raw` methods
2 parents 5e065c3 + 46b4b80 commit 1fcd04d

File tree

11 files changed

+126
-63
lines changed

11 files changed

+126
-63
lines changed

postgres-types/src/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@
108108
#![doc(html_root_url = "https://docs.rs/postgres-types/0.1")]
109109
#![warn(clippy::all, rust_2018_idioms, missing_docs)]
110110

111+
use crate::sealed::Sealed;
111112
use fallible_iterator::FallibleIterator;
112113
use postgres_protocol::types::{self, ArrayDimension};
113114
use std::any::type_name;
@@ -951,3 +952,32 @@ fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
951952
Ok(len as i32)
952953
}
953954
}
955+
956+
mod sealed {
957+
pub trait Sealed {}
958+
}
959+
960+
/// A helper trait used internally by Rust-Postgres
961+
/// to be able create a parameters iterator from `&dyn ToSql` or `T: ToSql`.
962+
///
963+
/// This cannot be implemented outside of this crate.
964+
pub trait BorrowToSql: sealed::Sealed {
965+
/// Get a reference to a `ToSql` trait object
966+
fn borrow_to_sql(&self) -> &dyn ToSql;
967+
}
968+
969+
impl Sealed for &dyn ToSql {}
970+
971+
impl BorrowToSql for &dyn ToSql {
972+
fn borrow_to_sql(&self) -> &dyn ToSql {
973+
*self
974+
}
975+
}
976+
977+
impl<T: ToSql> Sealed for T {}
978+
979+
impl<T: ToSql> BorrowToSql for T {
980+
fn borrow_to_sql(&self) -> &dyn ToSql {
981+
self
982+
}
983+
}

postgres/src/binary_copy.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Utilities for working with the PostgreSQL binary copy format.
22
33
use crate::connection::ConnectionRef;
4-
use crate::types::{ToSql, Type};
4+
use crate::types::{BorrowToSql, ToSql, Type};
55
use crate::{CopyInWriter, CopyOutReader, Error};
66
use fallible_iterator::FallibleIterator;
77
use futures::StreamExt;
@@ -46,9 +46,10 @@ impl<'a> BinaryCopyInWriter<'a> {
4646
/// # Panics
4747
///
4848
/// Panics if the number of values provided does not match the number expected.
49-
pub fn write_raw<'b, I>(&mut self, values: I) -> Result<(), Error>
49+
pub fn write_raw<P, I>(&mut self, values: I) -> Result<(), Error>
5050
where
51-
I: IntoIterator<Item = &'b dyn ToSql>,
51+
P: BorrowToSql,
52+
I: IntoIterator<Item = P>,
5253
I::IntoIter: ExactSizeIterator,
5354
{
5455
self.connection

postgres/src/client.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::{
55
};
66
use std::task::Poll;
77
use tokio_postgres::tls::{MakeTlsConnect, TlsConnect};
8-
use tokio_postgres::types::{ToSql, Type};
8+
use tokio_postgres::types::{BorrowToSql, ToSql, Type};
99
use tokio_postgres::{Error, Row, SimpleQueryMessage, Socket};
1010

1111
/// A synchronous PostgreSQL client.
@@ -227,7 +227,7 @@ impl Client {
227227
/// let mut client = Client::connect("host=localhost user=postgres", NoTls)?;
228228
///
229229
/// let baz = true;
230-
/// let mut it = client.query_raw("SELECT foo FROM bar WHERE baz = $1", iter::once(&baz as _))?;
230+
/// let mut it = client.query_raw("SELECT foo FROM bar WHERE baz = $1", iter::once(baz))?;
231231
///
232232
/// while let Some(row) = it.next()? {
233233
/// let foo: i32 = row.get("foo");
@@ -253,7 +253,7 @@ impl Client {
253253
/// ];
254254
/// let mut it = client.query_raw(
255255
/// "SELECT foo FROM bar WHERE biz = $1 AND baz = $2",
256-
/// params.iter().map(|p| p as &dyn ToSql),
256+
/// params,
257257
/// )?;
258258
///
259259
/// while let Some(row) = it.next()? {
@@ -263,10 +263,11 @@ impl Client {
263263
/// # Ok(())
264264
/// # }
265265
/// ```
266-
pub fn query_raw<'a, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
266+
pub fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
267267
where
268268
T: ?Sized + ToStatement,
269-
I: IntoIterator<Item = &'a dyn ToSql>,
269+
P: BorrowToSql,
270+
I: IntoIterator<Item = P>,
270271
I::IntoIter: ExactSizeIterator,
271272
{
272273
let stream = self

postgres/src/generic_client.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::types::{ToSql, Type};
1+
use crate::types::{BorrowToSql, ToSql, Type};
22
use crate::{
33
Client, CopyInWriter, CopyOutReader, Error, Row, RowIter, SimpleQueryMessage, Statement,
44
ToStatement, Transaction,
@@ -37,10 +37,11 @@ pub trait GenericClient: private::Sealed {
3737
T: ?Sized + ToStatement;
3838

3939
/// Like `Client::query_raw`.
40-
fn query_raw<'a, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
40+
fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
4141
where
4242
T: ?Sized + ToStatement,
43-
I: IntoIterator<Item = &'a dyn ToSql>,
43+
P: BorrowToSql,
44+
I: IntoIterator<Item = P>,
4445
I::IntoIter: ExactSizeIterator;
4546

4647
/// Like `Client::prepare`.
@@ -104,10 +105,11 @@ impl GenericClient for Client {
104105
self.query_opt(query, params)
105106
}
106107

107-
fn query_raw<'a, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
108+
fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
108109
where
109110
T: ?Sized + ToStatement,
110-
I: IntoIterator<Item = &'a dyn ToSql>,
111+
P: BorrowToSql,
112+
I: IntoIterator<Item = P>,
111113
I::IntoIter: ExactSizeIterator,
112114
{
113115
self.query_raw(query, params)
@@ -183,10 +185,11 @@ impl GenericClient for Transaction<'_> {
183185
self.query_opt(query, params)
184186
}
185187

186-
fn query_raw<'a, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
188+
fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
187189
where
188190
T: ?Sized + ToStatement,
189-
I: IntoIterator<Item = &'a dyn ToSql>,
191+
P: BorrowToSql,
192+
I: IntoIterator<Item = P>,
190193
I::IntoIter: ExactSizeIterator,
191194
{
192195
self.query_raw(query, params)

postgres/src/transaction.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::connection::ConnectionRef;
22
use crate::{CancelToken, CopyInWriter, CopyOutReader, Portal, RowIter, Statement, ToStatement};
3-
use tokio_postgres::types::{ToSql, Type};
3+
use tokio_postgres::types::{BorrowToSql, ToSql, Type};
44
use tokio_postgres::{Error, Row, SimpleQueryMessage};
55

66
/// A representation of a PostgreSQL database transaction.
@@ -102,10 +102,11 @@ impl<'a> Transaction<'a> {
102102
}
103103

104104
/// Like `Client::query_raw`.
105-
pub fn query_raw<'b, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
105+
pub fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
106106
where
107107
T: ?Sized + ToStatement,
108-
I: IntoIterator<Item = &'b dyn ToSql>,
108+
P: BorrowToSql,
109+
I: IntoIterator<Item = P>,
109110
I::IntoIter: ExactSizeIterator,
110111
{
111112
let stream = self

tokio-postgres/src/binary_copy.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use byteorder::{BigEndian, ByteOrder};
66
use bytes::{Buf, BufMut, Bytes, BytesMut};
77
use futures::{ready, SinkExt, Stream};
88
use pin_project_lite::pin_project;
9+
use postgres_types::BorrowToSql;
910
use std::convert::TryFrom;
1011
use std::io;
1112
use std::io::Cursor;
@@ -58,9 +59,10 @@ impl BinaryCopyInWriter {
5859
/// # Panics
5960
///
6061
/// Panics if the number of values provided does not match the number expected.
61-
pub async fn write_raw<'a, I>(self: Pin<&mut Self>, values: I) -> Result<(), Error>
62+
pub async fn write_raw<P, I>(self: Pin<&mut Self>, values: I) -> Result<(), Error>
6263
where
63-
I: IntoIterator<Item = &'a dyn ToSql>,
64+
P: BorrowToSql,
65+
I: IntoIterator<Item = P>,
6466
I::IntoIter: ExactSizeIterator,
6567
{
6668
let mut this = self.project();
@@ -79,6 +81,7 @@ impl BinaryCopyInWriter {
7981
let idx = this.buf.len();
8082
this.buf.put_i32(0);
8183
let len = match value
84+
.borrow_to_sql()
8285
.to_sql_checked(type_, this.buf)
8386
.map_err(|e| Error::to_sql(e, i))?
8487
{

tokio-postgres/src/bind.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::client::InnerClient;
22
use crate::codec::FrontendMessage;
33
use crate::connection::RequestMessages;
4-
use crate::types::ToSql;
4+
use crate::types::BorrowToSql;
55
use crate::{query, Error, Portal, Statement};
66
use postgres_protocol::message::backend::Message;
77
use postgres_protocol::message::frontend;
@@ -10,13 +10,14 @@ use std::sync::Arc;
1010

1111
static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
1212

13-
pub async fn bind<'a, I>(
13+
pub async fn bind<P, I>(
1414
client: &Arc<InnerClient>,
1515
statement: Statement,
1616
params: I,
1717
) -> Result<Portal, Error>
1818
where
19-
I: IntoIterator<Item = &'a dyn ToSql>,
19+
P: BorrowToSql,
20+
I: IntoIterator<Item = P>,
2021
I::IntoIter: ExactSizeIterator,
2122
{
2223
let name = format!("p{}", NEXT_ID.fetch_add(1, Ordering::SeqCst));

tokio-postgres/src/client.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use futures::channel::mpsc;
2020
use futures::{future, pin_mut, ready, StreamExt, TryStreamExt};
2121
use parking_lot::Mutex;
2222
use postgres_protocol::message::backend::Message;
23+
use postgres_types::BorrowToSql;
2324
use std::collections::HashMap;
2425
use std::fmt;
2526
use std::sync::Arc;
@@ -317,9 +318,6 @@ impl Client {
317318
///
318319
/// # Examples
319320
///
320-
/// If you have a type like `Vec<T>` where `T: ToSql` Rust will not know how to use it as params. To get around
321-
/// this the type must explicitly be converted to `&dyn ToSql`.
322-
///
323321
/// ```no_run
324322
/// # async fn async_main(client: &tokio_postgres::Client) -> Result<(), tokio_postgres::Error> {
325323
/// use tokio_postgres::types::ToSql;
@@ -331,7 +329,7 @@ impl Client {
331329
/// ];
332330
/// let mut it = client.query_raw(
333331
/// "SELECT foo FROM bar WHERE biz = $1 AND baz = $2",
334-
/// params.iter().map(|p| p as &dyn ToSql),
332+
/// params,
335333
/// ).await?;
336334
///
337335
/// pin_mut!(it);
@@ -342,10 +340,11 @@ impl Client {
342340
/// # Ok(())
343341
/// # }
344342
/// ```
345-
pub async fn query_raw<'a, T, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
343+
pub async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
346344
where
347345
T: ?Sized + ToStatement,
348-
I: IntoIterator<Item = &'a dyn ToSql>,
346+
P: BorrowToSql,
347+
I: IntoIterator<Item = P>,
349348
I::IntoIter: ExactSizeIterator,
350349
{
351350
let statement = statement.__convert().into_statement(self).await?;
@@ -391,10 +390,11 @@ impl Client {
391390
/// Panics if the number of parameters provided does not match the number expected.
392391
///
393392
/// [`execute`]: #method.execute
394-
pub async fn execute_raw<'a, T, I>(&self, statement: &T, params: I) -> Result<u64, Error>
393+
pub async fn execute_raw<T, P, I>(&self, statement: &T, params: I) -> Result<u64, Error>
395394
where
396395
T: ?Sized + ToStatement,
397-
I: IntoIterator<Item = &'a dyn ToSql>,
396+
P: BorrowToSql,
397+
I: IntoIterator<Item = P>,
398398
I::IntoIter: ExactSizeIterator,
399399
{
400400
let statement = statement.__convert().into_statement(self).await?;

tokio-postgres/src/generic_client.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::query::RowStream;
2-
use crate::types::{ToSql, Type};
2+
use crate::types::{BorrowToSql, ToSql, Type};
33
use crate::{Client, Error, Row, Statement, ToStatement, Transaction};
44
use async_trait::async_trait;
55

@@ -18,10 +18,11 @@ pub trait GenericClient: private::Sealed {
1818
T: ?Sized + ToStatement + Sync + Send;
1919

2020
/// Like `Client::execute_raw`.
21-
async fn execute_raw<'b, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
21+
async fn execute_raw<P, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
2222
where
2323
T: ?Sized + ToStatement + Sync + Send,
24-
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
24+
P: BorrowToSql,
25+
I: IntoIterator<Item = P> + Sync + Send,
2526
I::IntoIter: ExactSizeIterator;
2627

2728
/// Like `Client::query`.
@@ -48,10 +49,11 @@ pub trait GenericClient: private::Sealed {
4849
T: ?Sized + ToStatement + Sync + Send;
4950

5051
/// Like `Client::query_raw`.
51-
async fn query_raw<'b, T, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
52+
async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
5253
where
5354
T: ?Sized + ToStatement + Sync + Send,
54-
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
55+
P: BorrowToSql,
56+
I: IntoIterator<Item = P> + Sync + Send,
5557
I::IntoIter: ExactSizeIterator;
5658

5759
/// Like `Client::prepare`.
@@ -79,10 +81,11 @@ impl GenericClient for Client {
7981
self.execute(query, params).await
8082
}
8183

82-
async fn execute_raw<'b, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
84+
async fn execute_raw<P, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
8385
where
8486
T: ?Sized + ToStatement + Sync + Send,
85-
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
87+
P: BorrowToSql,
88+
I: IntoIterator<Item = P> + Sync + Send,
8689
I::IntoIter: ExactSizeIterator,
8790
{
8891
self.execute_raw(statement, params).await
@@ -117,10 +120,11 @@ impl GenericClient for Client {
117120
self.query_opt(statement, params).await
118121
}
119122

120-
async fn query_raw<'b, T, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
123+
async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
121124
where
122125
T: ?Sized + ToStatement + Sync + Send,
123-
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
126+
P: BorrowToSql,
127+
I: IntoIterator<Item = P> + Sync + Send,
124128
I::IntoIter: ExactSizeIterator,
125129
{
126130
self.query_raw(statement, params).await
@@ -155,10 +159,11 @@ impl GenericClient for Transaction<'_> {
155159
self.execute(query, params).await
156160
}
157161

158-
async fn execute_raw<'b, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
162+
async fn execute_raw<P, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
159163
where
160164
T: ?Sized + ToStatement + Sync + Send,
161-
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
165+
P: BorrowToSql,
166+
I: IntoIterator<Item = P> + Sync + Send,
162167
I::IntoIter: ExactSizeIterator,
163168
{
164169
self.execute_raw(statement, params).await
@@ -193,10 +198,11 @@ impl GenericClient for Transaction<'_> {
193198
self.query_opt(statement, params).await
194199
}
195200

196-
async fn query_raw<'b, T, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
201+
async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
197202
where
198203
T: ?Sized + ToStatement + Sync + Send,
199-
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
204+
P: BorrowToSql,
205+
I: IntoIterator<Item = P> + Sync + Send,
200206
I::IntoIter: ExactSizeIterator,
201207
{
202208
self.query_raw(statement, params).await

0 commit comments

Comments
 (0)