Skip to content

better api for passing parameters to *_raw methods #684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions postgres-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
#![doc(html_root_url = "https://docs.rs/postgres-types/0.1")]
#![warn(clippy::all, rust_2018_idioms, missing_docs)]

use crate::sealed::Sealed;
use fallible_iterator::FallibleIterator;
use postgres_protocol::types::{self, ArrayDimension};
use std::any::type_name;
Expand Down Expand Up @@ -951,3 +952,32 @@ fn downcast(len: usize) -> Result<i32, Box<dyn Error + Sync + Send>> {
Ok(len as i32)
}
}

mod sealed {
pub trait Sealed {}
}

/// A helper trait used internally by Rust-Postgres
/// to be able create a parameters iterator from `&dyn ToSql` or `T: ToSql`.
///
/// This cannot be implemented outside of this crate.
pub trait BorrowToSql: sealed::Sealed {
/// Get a reference to a `ToSql` trait object
fn borrow_to_sql(&self) -> &dyn ToSql;
}

impl Sealed for &dyn ToSql {}

impl BorrowToSql for &dyn ToSql {
fn borrow_to_sql(&self) -> &dyn ToSql {
*self
}
}

impl<T: ToSql> Sealed for T {}

impl<T: ToSql> BorrowToSql for T {
fn borrow_to_sql(&self) -> &dyn ToSql {
self
}
}
7 changes: 4 additions & 3 deletions postgres/src/binary_copy.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Utilities for working with the PostgreSQL binary copy format.

use crate::connection::ConnectionRef;
use crate::types::{ToSql, Type};
use crate::types::{BorrowToSql, ToSql, Type};
use crate::{CopyInWriter, CopyOutReader, Error};
use fallible_iterator::FallibleIterator;
use futures::StreamExt;
Expand Down Expand Up @@ -46,9 +46,10 @@ impl<'a> BinaryCopyInWriter<'a> {
/// # Panics
///
/// Panics if the number of values provided does not match the number expected.
pub fn write_raw<'b, I>(&mut self, values: I) -> Result<(), Error>
pub fn write_raw<P, I>(&mut self, values: I) -> Result<(), Error>
where
I: IntoIterator<Item = &'b dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
self.connection
Expand Down
11 changes: 6 additions & 5 deletions postgres/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::{
};
use std::task::Poll;
use tokio_postgres::tls::{MakeTlsConnect, TlsConnect};
use tokio_postgres::types::{ToSql, Type};
use tokio_postgres::types::{BorrowToSql, ToSql, Type};
use tokio_postgres::{Error, Row, SimpleQueryMessage, Socket};

/// A synchronous PostgreSQL client.
Expand Down Expand Up @@ -227,7 +227,7 @@ impl Client {
/// let mut client = Client::connect("host=localhost user=postgres", NoTls)?;
///
/// let baz = true;
/// let mut it = client.query_raw("SELECT foo FROM bar WHERE baz = $1", iter::once(&baz as _))?;
/// let mut it = client.query_raw("SELECT foo FROM bar WHERE baz = $1", iter::once(baz))?;
///
/// while let Some(row) = it.next()? {
/// let foo: i32 = row.get("foo");
Expand All @@ -253,7 +253,7 @@ impl Client {
/// ];
/// let mut it = client.query_raw(
/// "SELECT foo FROM bar WHERE biz = $1 AND baz = $2",
/// params.iter().map(|p| p as &dyn ToSql),
/// params,
/// )?;
///
/// while let Some(row) = it.next()? {
Expand All @@ -263,10 +263,11 @@ impl Client {
/// # Ok(())
/// # }
/// ```
pub fn query_raw<'a, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
pub fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
where
T: ?Sized + ToStatement,
I: IntoIterator<Item = &'a dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
let stream = self
Expand Down
17 changes: 10 additions & 7 deletions postgres/src/generic_client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::types::{ToSql, Type};
use crate::types::{BorrowToSql, ToSql, Type};
use crate::{
Client, CopyInWriter, CopyOutReader, Error, Row, RowIter, SimpleQueryMessage, Statement,
ToStatement, Transaction,
Expand Down Expand Up @@ -37,10 +37,11 @@ pub trait GenericClient: private::Sealed {
T: ?Sized + ToStatement;

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

/// Like `Client::prepare`.
Expand Down Expand Up @@ -104,10 +105,11 @@ impl GenericClient for Client {
self.query_opt(query, params)
}

fn query_raw<'a, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
where
T: ?Sized + ToStatement,
I: IntoIterator<Item = &'a dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
self.query_raw(query, params)
Expand Down Expand Up @@ -183,10 +185,11 @@ impl GenericClient for Transaction<'_> {
self.query_opt(query, params)
}

fn query_raw<'a, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
where
T: ?Sized + ToStatement,
I: IntoIterator<Item = &'a dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
self.query_raw(query, params)
Expand Down
7 changes: 4 additions & 3 deletions postgres/src/transaction.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::connection::ConnectionRef;
use crate::{CancelToken, CopyInWriter, CopyOutReader, Portal, RowIter, Statement, ToStatement};
use tokio_postgres::types::{ToSql, Type};
use tokio_postgres::types::{BorrowToSql, ToSql, Type};
use tokio_postgres::{Error, Row, SimpleQueryMessage};

/// A representation of a PostgreSQL database transaction.
Expand Down Expand Up @@ -102,10 +102,11 @@ impl<'a> Transaction<'a> {
}

/// Like `Client::query_raw`.
pub fn query_raw<'b, T, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
pub fn query_raw<T, P, I>(&mut self, query: &T, params: I) -> Result<RowIter<'_>, Error>
where
T: ?Sized + ToStatement,
I: IntoIterator<Item = &'b dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
let stream = self
Expand Down
7 changes: 5 additions & 2 deletions tokio-postgres/src/binary_copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use byteorder::{BigEndian, ByteOrder};
use bytes::{Buf, BufMut, Bytes, BytesMut};
use futures::{ready, SinkExt, Stream};
use pin_project_lite::pin_project;
use postgres_types::BorrowToSql;
use std::convert::TryFrom;
use std::io;
use std::io::Cursor;
Expand Down Expand Up @@ -58,9 +59,10 @@ impl BinaryCopyInWriter {
/// # Panics
///
/// Panics if the number of values provided does not match the number expected.
pub async fn write_raw<'a, I>(self: Pin<&mut Self>, values: I) -> Result<(), Error>
pub async fn write_raw<P, I>(self: Pin<&mut Self>, values: I) -> Result<(), Error>
where
I: IntoIterator<Item = &'a dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
let mut this = self.project();
Expand All @@ -79,6 +81,7 @@ impl BinaryCopyInWriter {
let idx = this.buf.len();
this.buf.put_i32(0);
let len = match value
.borrow_to_sql()
.to_sql_checked(type_, this.buf)
.map_err(|e| Error::to_sql(e, i))?
{
Expand Down
7 changes: 4 additions & 3 deletions tokio-postgres/src/bind.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::client::InnerClient;
use crate::codec::FrontendMessage;
use crate::connection::RequestMessages;
use crate::types::ToSql;
use crate::types::BorrowToSql;
use crate::{query, Error, Portal, Statement};
use postgres_protocol::message::backend::Message;
use postgres_protocol::message::frontend;
Expand All @@ -10,13 +10,14 @@ use std::sync::Arc;

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

pub async fn bind<'a, I>(
pub async fn bind<P, I>(
client: &Arc<InnerClient>,
statement: Statement,
params: I,
) -> Result<Portal, Error>
where
I: IntoIterator<Item = &'a dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
let name = format!("p{}", NEXT_ID.fetch_add(1, Ordering::SeqCst));
Expand Down
16 changes: 8 additions & 8 deletions tokio-postgres/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use futures::channel::mpsc;
use futures::{future, pin_mut, ready, StreamExt, TryStreamExt};
use parking_lot::Mutex;
use postgres_protocol::message::backend::Message;
use postgres_types::BorrowToSql;
use std::collections::HashMap;
use std::fmt;
use std::sync::Arc;
Expand Down Expand Up @@ -317,9 +318,6 @@ impl Client {
///
/// # Examples
///
/// If you have a type like `Vec<T>` 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`.
///
/// ```no_run
/// # async fn async_main(client: &tokio_postgres::Client) -> Result<(), tokio_postgres::Error> {
/// use tokio_postgres::types::ToSql;
Expand All @@ -331,7 +329,7 @@ impl Client {
/// ];
/// let mut it = client.query_raw(
/// "SELECT foo FROM bar WHERE biz = $1 AND baz = $2",
/// params.iter().map(|p| p as &dyn ToSql),
/// params,
/// ).await?;
///
/// pin_mut!(it);
Expand All @@ -342,10 +340,11 @@ impl Client {
/// # Ok(())
/// # }
/// ```
pub async fn query_raw<'a, T, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
pub async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement,
I: IntoIterator<Item = &'a dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
let statement = statement.__convert().into_statement(self).await?;
Expand Down Expand Up @@ -391,10 +390,11 @@ impl Client {
/// Panics if the number of parameters provided does not match the number expected.
///
/// [`execute`]: #method.execute
pub async fn execute_raw<'a, T, I>(&self, statement: &T, params: I) -> Result<u64, Error>
pub async fn execute_raw<T, P, I>(&self, statement: &T, params: I) -> Result<u64, Error>
where
T: ?Sized + ToStatement,
I: IntoIterator<Item = &'a dyn ToSql>,
P: BorrowToSql,
I: IntoIterator<Item = P>,
I::IntoIter: ExactSizeIterator,
{
let statement = statement.__convert().into_statement(self).await?;
Expand Down
32 changes: 19 additions & 13 deletions tokio-postgres/src/generic_client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::query::RowStream;
use crate::types::{ToSql, Type};
use crate::types::{BorrowToSql, ToSql, Type};
use crate::{Client, Error, Row, Statement, ToStatement, Transaction};
use async_trait::async_trait;

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

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

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

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

/// Like `Client::prepare`.
Expand Down Expand Up @@ -79,10 +81,11 @@ impl GenericClient for Client {
self.execute(query, params).await
}

async fn execute_raw<'b, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
async fn execute_raw<P, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
where
T: ?Sized + ToStatement + Sync + Send,
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
P: BorrowToSql,
I: IntoIterator<Item = P> + Sync + Send,
I::IntoIter: ExactSizeIterator,
{
self.execute_raw(statement, params).await
Expand Down Expand Up @@ -117,10 +120,11 @@ impl GenericClient for Client {
self.query_opt(statement, params).await
}

async fn query_raw<'b, T, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement + Sync + Send,
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
P: BorrowToSql,
I: IntoIterator<Item = P> + Sync + Send,
I::IntoIter: ExactSizeIterator,
{
self.query_raw(statement, params).await
Expand Down Expand Up @@ -155,10 +159,11 @@ impl GenericClient for Transaction<'_> {
self.execute(query, params).await
}

async fn execute_raw<'b, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
async fn execute_raw<P, I, T>(&self, statement: &T, params: I) -> Result<u64, Error>
where
T: ?Sized + ToStatement + Sync + Send,
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
P: BorrowToSql,
I: IntoIterator<Item = P> + Sync + Send,
I::IntoIter: ExactSizeIterator,
{
self.execute_raw(statement, params).await
Expand Down Expand Up @@ -193,10 +198,11 @@ impl GenericClient for Transaction<'_> {
self.query_opt(statement, params).await
}

async fn query_raw<'b, T, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
async fn query_raw<T, P, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement + Sync + Send,
I: IntoIterator<Item = &'b dyn ToSql> + Sync + Send,
P: BorrowToSql,
I: IntoIterator<Item = P> + Sync + Send,
I::IntoIter: ExactSizeIterator,
{
self.query_raw(statement, params).await
Expand Down
Loading