@@ -103,6 +103,7 @@ use stmt::{Column, Statement};
103103use tls:: TlsHandshake ;
104104use transaction:: { IsolationLevel , Transaction } ;
105105use types:: { Field , FromSql , IsNull , Kind , Oid , ToSql , Type } ;
106+ use text_rows:: TextRows ;
106107
107108#[ doc( inline) ]
108109pub use error:: Error ;
@@ -118,6 +119,7 @@ pub mod notification;
118119pub mod params;
119120mod priv_io;
120121pub mod rows;
122+ pub mod text_rows;
121123pub mod stmt;
122124pub mod tls;
123125pub 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
13771464impl 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
14071499impl < ' 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