@@ -14,19 +14,21 @@ use postgres_protocol::message::{backend, frontend};
1414use postgres_protocol:: message:: backend:: { ErrorResponseBody , ErrorFields } ;
1515use postgres_shared:: RowData ;
1616use std:: collections:: HashMap ;
17+ use std:: error:: Error as StdError ;
1718use std:: fmt;
1819use std:: io;
1920use std:: mem;
21+ use std:: sync:: Arc ;
2022use std:: sync:: mpsc:: { self , Sender , Receiver } ;
2123use tokio_core:: reactor:: Handle ;
2224
2325#[ doc( inline) ]
24- pub use postgres_shared:: { params, types} ;
26+ pub use postgres_shared:: { params, types, Column , RowIndex } ;
2527
2628use error:: { ConnectError , Error , DbError } ;
2729use params:: { ConnectParams , IntoConnectParams } ;
2830use stream:: PostgresStream ;
29- use types:: { Oid , Type , ToSql , SessionInfo , IsNull } ;
31+ use types:: { Oid , Type , ToSql , SessionInfo , IsNull , FromSql , WrongType } ;
3032
3133pub mod error;
3234mod stream;
@@ -293,30 +295,6 @@ impl Connection {
293295 . boxed ( )
294296 }
295297
296- #[ allow( dead_code) ]
297- fn read_rows ( self , mut rows : Vec < RowData > ) -> BoxFuture < ( Vec < RowData > , Connection ) , Error > {
298- self . 0 . read ( )
299- . map_err ( Error :: Io )
300- . and_then ( |( m, s) | {
301- match m {
302- backend:: Message :: EmptyQueryResponse |
303- backend:: Message :: CommandComplete ( _) => Connection ( s) . ready ( rows) . boxed ( ) ,
304- backend:: Message :: DataRow ( body) => {
305- match body. values ( ) . collect ( ) {
306- Ok ( row) => {
307- rows. push ( row) ;
308- Connection ( s) . read_rows ( rows)
309- }
310- Err ( e) => Err ( Error :: Io ( e) ) . into_future ( ) . boxed ( ) ,
311- }
312- }
313- backend:: Message :: ErrorResponse ( body) => Connection ( s) . ready_err ( body) ,
314- _ => Err ( bad_message ( ) ) . into_future ( ) . boxed ( ) ,
315- }
316- } )
317- . boxed ( )
318- }
319-
320298 fn ready < T > ( self , t : T ) -> BoxFuture < ( T , Connection ) , Error >
321299 where T : ' static + Send
322300 {
@@ -452,7 +430,7 @@ impl Connection {
452430 s. get_types ( r. into_iter ( ) ,
453431 vec ! [ ] ,
454432 |f| f. 1 ,
455- |f, t| Column { name : f. 0 , type_ : t } )
433+ |f, t| Column :: new ( f. 0 , t ) )
456434 . map ( |( r, s) | ( p, r, s) )
457435 } )
458436 . boxed ( )
@@ -594,7 +572,7 @@ impl Connection {
594572 close_sender : conn. 0 . close_sender . clone ( ) ,
595573 name : name,
596574 params : params,
597- columns : columns,
575+ columns : Arc :: new ( columns) ,
598576 } ;
599577 ( stmt, conn)
600578 } )
@@ -615,26 +593,11 @@ impl Connection {
615593 }
616594}
617595
618- pub struct Column {
619- name : String ,
620- type_ : Type ,
621- }
622-
623- impl Column {
624- pub fn name ( & self ) -> & str {
625- & self . name
626- }
627-
628- pub fn type_ ( & self ) -> & Type {
629- & self . type_
630- }
631- }
632-
633596pub struct Statement {
634597 close_sender : Sender < ( u8 , String ) > ,
635598 name : String ,
636599 params : Vec < Type > ,
637- columns : Vec < Column > ,
600+ columns : Arc < Vec < Column > > ,
638601}
639602
640603impl Drop for Statement {
@@ -664,6 +627,42 @@ impl Statement {
664627 }
665628}
666629
630+ pub struct Row {
631+ columns : Arc < Vec < Column > > ,
632+ data : RowData ,
633+ }
634+
635+ impl Row {
636+ pub fn get < T , I > ( & self , idx : I ) -> T
637+ where T : FromSql ,
638+ I : RowIndex + fmt:: Debug
639+ {
640+ match self . try_get ( & idx) {
641+ Ok ( Some ( v) ) => v,
642+ Ok ( None ) => panic ! ( "no such column {:?}" , idx) ,
643+ Err ( e) => panic ! ( "error retrieving row {:?}: {}" , idx, e) ,
644+ }
645+ }
646+
647+ pub fn try_get < T , I > ( & self , idx : I ) -> Result < Option < T > , Box < StdError + Sync + Send > >
648+ where T : FromSql ,
649+ I : RowIndex
650+ {
651+ let idx = match idx. idx ( & self . columns ) {
652+ Some ( idx) => idx,
653+ None => return Ok ( None ) ,
654+ } ;
655+
656+ let ty = self . columns [ idx] . type_ ( ) ;
657+ if !T :: accepts ( ty) {
658+ return Err ( Box :: new ( WrongType :: new ( ty. clone ( ) ) ) ) ;
659+ }
660+
661+ // FIXME
662+ T :: from_sql_nullable ( ty, self . data . get ( idx) , & SessionInfo :: new ( & HashMap :: new ( ) ) ) . map ( Some )
663+ }
664+ }
665+
667666fn connect_err ( fields : & mut ErrorFields ) -> ConnectError {
668667 match DbError :: new ( fields) {
669668 Ok ( err) => ConnectError :: Db ( Box :: new ( err) ) ,
0 commit comments