@@ -79,7 +79,7 @@ use message::{WriteMessage, ReadMessage};
79
79
use notification:: { Notifications , Notification } ;
80
80
use rows:: { Rows , LazyRows } ;
81
81
use stmt:: { Statement , Column } ;
82
- use types:: { IsNull , Kind , Type , SessionInfo , Oid , Other , WrongType , ToSql , FromSql } ;
82
+ use types:: { IsNull , Kind , Type , SessionInfo , Oid , Other , WrongType , ToSql , FromSql , Field } ;
83
83
use url:: Url ;
84
84
85
85
#[ macro_use]
@@ -97,7 +97,8 @@ pub mod stmt;
97
97
pub mod types;
98
98
pub mod notification;
99
99
100
- const TYPEINFO_QUERY : & ' static str = "t" ;
100
+ const TYPEINFO_QUERY : & ' static str = "__typeinfo" ;
101
+ const TYPEINFO_ARRAY_QUERY : & ' static str = "__typeinfo_array" ;
101
102
102
103
/// A type alias of the result returned by many methods.
103
104
pub type Result < T > = result:: Result < T , Error > ;
@@ -463,9 +464,22 @@ impl InnerConnection {
463
464
464
465
#[ cfg_attr( rustfmt, rustfmt_skip) ]
465
466
fn setup_typeinfo_query ( & mut self ) -> result:: Result < ( ) , ConnectError > {
467
+ match self . raw_prepare ( TYPEINFO_ARRAY_QUERY ,
468
+ "SELECT attname, atttypid \
469
+ FROM pg_catalog.pg_attribute \
470
+ WHERE attrelid = $1 \
471
+ AND NOT attisdropped \
472
+ AND attnum > 0 \
473
+ ORDER BY attnum") {
474
+ Ok ( ..) => { }
475
+ Err ( Error :: Io ( e) ) => return Err ( ConnectError :: Io ( e) ) ,
476
+ Err ( Error :: Db ( e) ) => return Err ( ConnectError :: Db ( e) ) ,
477
+ Err ( Error :: Conversion ( _) ) => unreachable ! ( ) ,
478
+ }
479
+
466
480
match self . raw_prepare ( TYPEINFO_QUERY ,
467
481
"SELECT t.typname, t.typtype, t.typelem, r.rngsubtype, \
468
- t.typbasetype, n.nspname \
482
+ t.typbasetype, n.nspname, t.typrelid \
469
483
FROM pg_catalog.pg_type t \
470
484
LEFT OUTER JOIN pg_catalog.pg_range r ON \
471
485
r.rngtypid = t.oid \
@@ -823,7 +837,7 @@ impl InnerConnection {
823
837
try!( self . read_rows ( & mut rows) ) ;
824
838
let row = rows. pop_front ( ) . unwrap ( ) ;
825
839
826
- let ( name, type_, elem_oid, rngsubtype, basetype, schema) = {
840
+ let ( name, type_, elem_oid, rngsubtype, basetype, schema, relid ) = {
827
841
let ctx = SessionInfo :: new ( self ) ;
828
842
let name = try!( String :: from_sql ( & Type :: Name ,
829
843
& mut & * * row[ 0 ] . as_ref ( ) . unwrap ( ) ,
@@ -844,7 +858,10 @@ impl InnerConnection {
844
858
let schema = try!( String :: from_sql ( & Type :: Name ,
845
859
& mut & * * row[ 5 ] . as_ref ( ) . unwrap ( ) ,
846
860
& ctx) ) ;
847
- ( name, type_, elem_oid, rngsubtype, basetype, schema)
861
+ let relid = try!( Oid :: from_sql ( & Type :: Oid ,
862
+ & mut & * * row[ 6 ] . as_ref ( ) . unwrap ( ) ,
863
+ & ctx) ) ;
864
+ ( name, type_, elem_oid, rngsubtype, basetype, schema, relid)
848
865
} ;
849
866
850
867
let kind = if type_ == b'e' as i8 {
@@ -855,6 +872,28 @@ impl InnerConnection {
855
872
Kind :: Domain ( try!( self . get_type ( basetype) ) )
856
873
} else if elem_oid != 0 {
857
874
Kind :: Array ( try!( self . get_type ( elem_oid) ) )
875
+ } else if relid != 0 {
876
+ try!( self . raw_execute ( TYPEINFO_ARRAY_QUERY , "" , 0 , & [ Type :: Oid ] , & [ & relid] ) ) ;
877
+ let mut rows = VecDeque :: new ( ) ;
878
+ try!( self . read_rows ( & mut rows) ) ;
879
+
880
+ let mut fields = vec ! [ ] ;
881
+ for row in rows {
882
+ let ( name, type_) = {
883
+ let ctx = SessionInfo :: new ( self ) ;
884
+ let name = try!( String :: from_sql ( & Type :: Name ,
885
+ & mut & * * row[ 0 ] . as_ref ( ) . unwrap ( ) ,
886
+ & ctx) ) ;
887
+ let type_ = try!( Oid :: from_sql ( & Type :: Oid ,
888
+ & mut & * * row[ 1 ] . as_ref ( ) . unwrap ( ) ,
889
+ & ctx) ) ;
890
+ ( name, type_)
891
+ } ;
892
+ let type_ = try!( self . get_type ( type_) ) ;
893
+ fields. push ( Field :: new ( name, type_) ) ;
894
+ }
895
+
896
+ Kind :: Composite ( fields)
858
897
} else {
859
898
match rngsubtype {
860
899
Some ( oid) => Kind :: Range ( try!( self . get_type ( oid) ) ) ,
@@ -1549,3 +1588,7 @@ trait NotificationsNew<'conn> {
1549
1588
trait WrongTypeNew {
1550
1589
fn new ( ty : Type ) -> WrongType ;
1551
1590
}
1591
+
1592
+ trait FieldNew {
1593
+ fn new ( name : String , type_ : Type ) -> Field ;
1594
+ }
0 commit comments