Skip to content

Commit

Permalink
make raw_txt not prepare statements
Browse files Browse the repository at this point in the history
  • Loading branch information
conradludgate committed Oct 31, 2023
1 parent 7434d93 commit d80293b
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 22 deletions.
6 changes: 2 additions & 4 deletions tokio-postgres/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,18 +376,16 @@ impl Client {

/// Pass text directly to the Postgres backend to allow it to sort out typing itself and
/// to save a roundtrip
pub async fn query_raw_txt<'a, T, S, I>(
pub async fn query_raw_txt<S, I>(
&self,
statement: &T,
statement: &str,
params: I,
) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement,
S: AsRef<str>,
I: IntoIterator<Item = Option<S>>,
I::IntoIter: ExactSizeIterator,
{
let statement = statement.__convert().into_statement(self).await?;
query::query_txt(&self.inner, statement, params).await
}

Expand Down
13 changes: 3 additions & 10 deletions tokio-postgres/src/generic_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,8 @@ pub trait GenericClient: private::Sealed {
I::IntoIter: ExactSizeIterator;

/// Like `Client::query_raw_txt`.
async fn query_raw_txt<'a, T, S, I>(
&self,
statement: &T,
params: I,
) -> Result<RowStream, Error>
async fn query_raw_txt<S, I>(&self, statement: &str, params: I) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement + Sync + Send,
S: AsRef<str> + Sync + Send,
I: IntoIterator<Item = Option<S>> + Sync + Send,
I::IntoIter: ExactSizeIterator + Sync + Send;
Expand Down Expand Up @@ -145,9 +140,8 @@ impl GenericClient for Client {
self.query_raw(statement, params).await
}

async fn query_raw_txt<'a, T, S, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
async fn query_raw_txt<S, I>(&self, statement: &str, params: I) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement + Sync + Send,
S: AsRef<str> + Sync + Send,
I: IntoIterator<Item = Option<S>> + Sync + Send,
I::IntoIter: ExactSizeIterator + Sync + Send,
Expand Down Expand Up @@ -237,9 +231,8 @@ impl GenericClient for Transaction<'_> {
self.query_raw(statement, params).await
}

async fn query_raw_txt<'a, T, S, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
async fn query_raw_txt<S, I>(&self, statement: &str, params: I) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement + Sync + Send,
S: AsRef<str> + Sync + Send,
I: IntoIterator<Item = Option<S>> + Sync + Send,
I::IntoIter: ExactSizeIterator + Sync + Send,
Expand Down
60 changes: 54 additions & 6 deletions tokio-postgres/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ use crate::client::{InnerClient, Responses};
use crate::codec::FrontendMessage;
use crate::connection::RequestMessages;
use crate::types::{BorrowToSql, IsNull};
use crate::{Error, Portal, ReadyForQueryStatus, Row, Statement};
use crate::{Column, Error, Portal, ReadyForQueryStatus, Row, Statement};
use bytes::{BufMut, Bytes, BytesMut};
use fallible_iterator::FallibleIterator;
use futures_util::{ready, Stream};
use log::{debug, log_enabled, Level};
use pin_project_lite::pin_project;
use postgres_protocol::message::backend::Message;
use postgres_protocol::message::frontend;
use postgres_types::Format;
use postgres_types::{Format, Type};
use std::fmt;
use std::marker::PhantomPinned;
use std::pin::Pin;
Expand Down Expand Up @@ -63,7 +64,7 @@ where

pub async fn query_txt<S, I>(
client: &Arc<InnerClient>,
statement: Statement,
query: &str,
params: I,
) -> Result<RowStream, Error>
where
Expand All @@ -74,10 +75,18 @@ where
let params = params.into_iter();

let buf = client.with_buf(|buf| {
frontend::parse(
"", // unnamed prepared statement
query, // query to parse
std::iter::empty(), // give no type info
buf,
)
.map_err(Error::encode)?;
frontend::describe(b'S', "", buf).map_err(Error::encode)?;
// Bind, pass params as text, retrieve as binary
match frontend::bind(
"", // empty string selects the unnamed portal
statement.name(), // named prepared statement
"", // unnamed prepared statement
std::iter::empty(), // all parameters use the default format (text)
params,
|param, buf| match param {
Expand All @@ -104,9 +113,48 @@ where
})?;

// now read the responses
let responses = start(client, buf).await?;
let mut responses = client.send(RequestMessages::Single(FrontendMessage::Raw(buf)))?;

match responses.next().await? {
Message::ParseComplete => {}
_ => return Err(Error::unexpected_message()),
}

let parameter_description = match responses.next().await? {
Message::ParameterDescription(body) => body,
_ => return Err(Error::unexpected_message()),
};

let row_description = match responses.next().await? {
Message::RowDescription(body) => Some(body),
Message::NoData => None,
_ => return Err(Error::unexpected_message()),
};

match responses.next().await? {
Message::BindComplete => {}
_ => return Err(Error::unexpected_message()),
}

let mut parameters = vec![];
let mut it = parameter_description.parameters();
while let Some(oid) = it.next().map_err(Error::parse)? {
let type_ = Type::from_oid(oid).unwrap_or(Type::UNKNOWN);
parameters.push(type_);
}

let mut columns = vec![];
if let Some(row_description) = row_description {
let mut it = row_description.fields();
while let Some(field) = it.next().map_err(Error::parse)? {
let type_ = Type::from_oid(field.type_oid()).unwrap_or(Type::UNKNOWN);
let column = Column::new(field.name().to_string(), type_, field);
columns.push(column);
}
}

Ok(RowStream {
statement,
statement: Statement::new_anonymous(parameters, columns),
responses,
command_tag: None,
status: ReadyForQueryStatus::Unknown,
Expand Down
9 changes: 9 additions & 0 deletions tokio-postgres/src/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ impl Statement {
}))
}

pub(crate) fn new_anonymous(params: Vec<Type>, columns: Vec<Column>) -> Statement {
Statement(Arc::new(StatementInner {
client: Weak::new(),
name: String::new(),
params,
columns,
}))
}

pub(crate) fn name(&self) -> &str {
&self.0.name
}
Expand Down
3 changes: 1 addition & 2 deletions tokio-postgres/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,8 @@ impl<'a> Transaction<'a> {
}

/// Like `Client::query_raw_txt`.
pub async fn query_raw_txt<T, S, I>(&self, statement: &T, params: I) -> Result<RowStream, Error>
pub async fn query_raw_txt<S, I>(&self, statement: &str, params: I) -> Result<RowStream, Error>
where
T: ?Sized + ToStatement,
S: AsRef<str>,
I: IntoIterator<Item = Option<S>>,
I::IntoIter: ExactSizeIterator,
Expand Down

0 comments on commit d80293b

Please sign in to comment.