Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit b33fdcd

Browse files
authored
Merge pull request sfackler#304 from jwilm/simple-query-api
Implement simple query API
2 parents 993f2fc + 39a4cdf commit b33fdcd

File tree

5 files changed

+350
-28
lines changed

5 files changed

+350
-28
lines changed

postgres/src/lib.rs

Lines changed: 112 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ use stmt::{Column, Statement};
103103
use tls::TlsHandshake;
104104
use transaction::{IsolationLevel, Transaction};
105105
use types::{Field, FromSql, IsNull, Kind, Oid, ToSql, Type};
106+
use text_rows::TextRows;
106107

107108
#[doc(inline)]
108109
pub use error::Error;
@@ -118,6 +119,7 @@ pub mod notification;
118119
pub mod params;
119120
mod priv_io;
120121
pub mod rows;
122+
pub mod text_rows;
121123
pub mod stmt;
122124
pub mod tls;
123125
pub mod transaction;
@@ -534,18 +536,7 @@ impl InnerConnection {
534536
.and_then(|oid| self.get_type(oid))
535537
.collect()?;
536538

537-
let columns = match raw_columns {
538-
Some(body) => body.fields()
539-
.and_then(|field| {
540-
Ok(Column::new(
541-
field.name().to_owned(),
542-
self.get_type(field.type_oid())?,
543-
))
544-
})
545-
.collect()?,
546-
None => vec![],
547-
};
548-
539+
let columns = self.parse_cols(raw_columns)?;
549540
Ok((param_types, columns))
550541
}
551542

@@ -735,6 +726,22 @@ impl InnerConnection {
735726
Ok(ty)
736727
}
737728

729+
730+
fn parse_cols(&mut self, raw: Option<backend::RowDescriptionBody>) -> Result<Vec<Column>> {
731+
match raw {
732+
Some(body) => body.fields()
733+
.and_then(|field| {
734+
Ok(Column::new(
735+
field.name().to_owned(),
736+
self.get_type(field.type_oid())?,
737+
))
738+
})
739+
.collect()
740+
.map_err(From::from),
741+
None => Ok(vec![]),
742+
}
743+
}
744+
738745
fn setup_typeinfo_query(&mut self) -> Result<()> {
739746
if self.has_typeinfo_query {
740747
return Ok(());
@@ -919,6 +926,49 @@ impl InnerConnection {
919926
}
920927
}
921928

929+
fn simple_query_(&mut self, query: &str) -> Result<Vec<TextRows>> {
930+
check_desync!(self);
931+
debug!("executing query: {}", query);
932+
self.stream.write_message(|buf| frontend::query(query, buf))?;
933+
self.stream.flush()?;
934+
935+
let mut result = vec![];
936+
let mut rows = vec![];
937+
let mut columns = None;
938+
939+
loop {
940+
match self.read_message()? {
941+
backend::Message::ReadyForQuery(_) => break,
942+
backend::Message::DataRow(body) => {
943+
rows.push(RowData::new(body)?);
944+
}
945+
backend::Message::CopyInResponse(_) => {
946+
self.stream.write_message(|buf| {
947+
frontend::copy_fail("COPY queries cannot be directly executed", buf)
948+
})?;
949+
self.stream.write_message(
950+
|buf| Ok::<(), io::Error>(frontend::sync(buf)),
951+
)?;
952+
self.stream.flush()?;
953+
}
954+
backend::Message::ErrorResponse(body) => {
955+
self.wait_for_ready()?;
956+
return Err(err(&mut body.fields()));
957+
}
958+
backend::Message::RowDescription(body) => {
959+
columns = Some(self.parse_cols(Some(body))?);
960+
}
961+
backend::Message::CommandComplete(_) => {
962+
if let Some(cols) = columns.take() {
963+
result.push(TextRows::new(cols, mem::replace(&mut rows, Vec::new())));
964+
}
965+
}
966+
_ => bad_response!(self),
967+
}
968+
}
969+
Ok(result)
970+
}
971+
922972
fn quick_query(&mut self, query: &str) -> Result<Vec<Vec<Option<String>>>> {
923973
check_desync!(self);
924974
debug!("executing query: {}", query);
@@ -1254,7 +1304,8 @@ impl Connection {
12541304
pub fn set_transaction_config(&self, config: &transaction::Config) -> Result<()> {
12551305
let mut command = "SET SESSION CHARACTERISTICS AS TRANSACTION".to_owned();
12561306
config.build_command(&mut command);
1257-
self.batch_execute(&command)
1307+
self.simple_query(&command)
1308+
.map(|_| ())
12581309
}
12591310

12601311
/// Execute a sequence of SQL statements.
@@ -1291,10 +1342,42 @@ impl Connection {
12911342
/// CREATE INDEX ON purchase (time);
12921343
/// ").unwrap();
12931344
/// ```
1345+
#[deprecated(since="0.15.3", note="please use `simple_query` instead")]
12941346
pub fn batch_execute(&self, query: &str) -> Result<()> {
12951347
self.0.borrow_mut().quick_query(query).map(|_| ())
12961348
}
12971349

1350+
1351+
/// Send a simple, non-prepared query
1352+
///
1353+
/// Executes a query without making a prepared statement. All result columns
1354+
/// are returned in a UTF-8 text format rather than compact binary
1355+
/// representations. This can be useful when communicating with services
1356+
/// like _pgbouncer_ which speak "basic" postgres but don't support prepared
1357+
/// statements.
1358+
///
1359+
/// Because rust-postgres' query parameter substitution relies on prepared
1360+
/// statements, it's not possible to pass a separate parameters list with
1361+
/// this API.
1362+
///
1363+
/// In general, the `query` API should be prefered whenever possible.
1364+
///
1365+
/// # Example
1366+
///
1367+
/// ```rust,no_run
1368+
/// # use postgres::{Connection, TlsMode};
1369+
/// # let conn = Connection::connect("", TlsMode::None).unwrap();
1370+
/// for response in &conn.simple_query("SELECT foo FROM bar WHERE baz = 'quux'").unwrap() {
1371+
/// for row in response {
1372+
/// let foo: &str = row.get("foo");
1373+
/// println!("foo: {}", foo);
1374+
/// }
1375+
/// }
1376+
/// ```
1377+
pub fn simple_query(&self, query: &str) -> Result<Vec<TextRows>> {
1378+
self.0.borrow_mut().simple_query_(query)
1379+
}
1380+
12981381
/// Returns a structure providing access to asynchronous notifications.
12991382
///
13001383
/// Use the `LISTEN` command to register this connection for notifications.
@@ -1368,10 +1451,14 @@ pub trait GenericConnection {
13681451
fn transaction<'a>(&'a self) -> Result<Transaction<'a>>;
13691452

13701453
/// Like `Connection::batch_execute`.
1454+
#[deprecated(since="0.15.3", note="please use `simple_query` instead")]
13711455
fn batch_execute(&self, query: &str) -> Result<()>;
13721456

13731457
/// Like `Connection::is_active`.
13741458
fn is_active(&self) -> bool;
1459+
1460+
/// Like `Connection::simple_query`.
1461+
fn simple_query(&self, query: &str) -> Result<Vec<TextRows>>;
13751462
}
13761463

13771464
impl GenericConnection for Connection {
@@ -1396,12 +1483,17 @@ impl GenericConnection for Connection {
13961483
}
13971484

13981485
fn batch_execute(&self, query: &str) -> Result<()> {
1399-
self.batch_execute(query)
1486+
self.simple_query(query)
1487+
.map(|_| ())
14001488
}
14011489

14021490
fn is_active(&self) -> bool {
14031491
self.is_active()
14041492
}
1493+
1494+
fn simple_query(&self, query: &str) -> Result<Vec<TextRows>> {
1495+
self.simple_query(query)
1496+
}
14051497
}
14061498

14071499
impl<'a> GenericConnection for Transaction<'a> {
@@ -1426,7 +1518,12 @@ impl<'a> GenericConnection for Transaction<'a> {
14261518
}
14271519

14281520
fn batch_execute(&self, query: &str) -> Result<()> {
1429-
self.batch_execute(query)
1521+
self.simple_query(query)
1522+
.map(|_| ())
1523+
}
1524+
1525+
fn simple_query(&self, query: &str) -> Result<Vec<TextRows>> {
1526+
self.simple_query(query)
14301527
}
14311528

14321529
fn is_active(&self) -> bool {

0 commit comments

Comments
 (0)