@@ -14,19 +14,21 @@ use postgres_protocol::message::{backend, frontend};
14
14
use postgres_protocol:: message:: backend:: { ErrorResponseBody , ErrorFields } ;
15
15
use postgres_shared:: RowData ;
16
16
use std:: collections:: HashMap ;
17
+ use std:: error:: Error as StdError ;
17
18
use std:: fmt;
18
19
use std:: io;
19
20
use std:: mem;
21
+ use std:: sync:: Arc ;
20
22
use std:: sync:: mpsc:: { self , Sender , Receiver } ;
21
23
use tokio_core:: reactor:: Handle ;
22
24
23
25
#[ doc( inline) ]
24
- pub use postgres_shared:: { params, types} ;
26
+ pub use postgres_shared:: { params, types, Column , RowIndex } ;
25
27
26
28
use error:: { ConnectError , Error , DbError } ;
27
29
use params:: { ConnectParams , IntoConnectParams } ;
28
30
use stream:: PostgresStream ;
29
- use types:: { Oid , Type , ToSql , SessionInfo , IsNull } ;
31
+ use types:: { Oid , Type , ToSql , SessionInfo , IsNull , FromSql , WrongType } ;
30
32
31
33
pub mod error;
32
34
mod stream;
@@ -293,30 +295,6 @@ impl Connection {
293
295
. boxed ( )
294
296
}
295
297
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
-
320
298
fn ready < T > ( self , t : T ) -> BoxFuture < ( T , Connection ) , Error >
321
299
where T : ' static + Send
322
300
{
@@ -452,7 +430,7 @@ impl Connection {
452
430
s. get_types ( r. into_iter ( ) ,
453
431
vec ! [ ] ,
454
432
|f| f. 1 ,
455
- |f, t| Column { name : f. 0 , type_ : t } )
433
+ |f, t| Column :: new ( f. 0 , t ) )
456
434
. map ( |( r, s) | ( p, r, s) )
457
435
} )
458
436
. boxed ( )
@@ -594,7 +572,7 @@ impl Connection {
594
572
close_sender : conn. 0 . close_sender . clone ( ) ,
595
573
name : name,
596
574
params : params,
597
- columns : columns,
575
+ columns : Arc :: new ( columns) ,
598
576
} ;
599
577
( stmt, conn)
600
578
} )
@@ -615,26 +593,11 @@ impl Connection {
615
593
}
616
594
}
617
595
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
-
633
596
pub struct Statement {
634
597
close_sender : Sender < ( u8 , String ) > ,
635
598
name : String ,
636
599
params : Vec < Type > ,
637
- columns : Vec < Column > ,
600
+ columns : Arc < Vec < Column > > ,
638
601
}
639
602
640
603
impl Drop for Statement {
@@ -664,6 +627,42 @@ impl Statement {
664
627
}
665
628
}
666
629
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
+
667
666
fn connect_err ( fields : & mut ErrorFields ) -> ConnectError {
668
667
match DbError :: new ( fields) {
669
668
Ok ( err) => ConnectError :: Db ( Box :: new ( err) ) ,
0 commit comments