@@ -99,7 +99,7 @@ mod util;
9999pub mod types;
100100
101101const CANARY : u32 = 0xdeadbeef ;
102- const TYPENAME_QUERY : & ' static str = "t" ;
102+ const TYPEINFO_QUERY : & ' static str = "t" ;
103103
104104/// A type alias of the result returned by many methods.
105105pub type Result < T > = result:: Result < T , Error > ;
@@ -456,15 +456,34 @@ impl InnerConnection {
456456 }
457457 }
458458
459- match conn. raw_prepare ( TYPENAME_QUERY ,
460- "SELECT typname, typelem FROM pg_catalog.pg_type WHERE oid = $1" ) {
461- Ok ( ..) => { }
459+ try!( conn. setup_typeinfo_query ( ) ) ;
460+
461+ Ok ( conn)
462+ }
463+
464+ fn setup_typeinfo_query ( & mut self ) -> result:: Result < ( ) , ConnectError > {
465+ match self . raw_prepare ( TYPEINFO_QUERY ,
466+ "SELECT t.typname, t.typelem, r.rngsubtype \
467+ FROM pg_catalog.pg_type t \
468+ LEFT OUTER JOIN pg_catalog.pg_range r \
469+ ON r.rngtypid = t.oid \
470+ WHERE t.oid = $1") {
471+ Ok ( ..) => return Ok ( ( ) ) ,
462472 Err ( Error :: IoError ( e) ) => return Err ( ConnectError :: IoError ( e) ) ,
473+ // Range types weren't added until Postgres 9.2, so pg_range may not exist
474+ Err ( Error :: DbError ( DbError { code : SqlState :: UndefinedTable , .. } ) ) => { }
463475 Err ( Error :: DbError ( e) ) => return Err ( ConnectError :: DbError ( e) ) ,
464476 _ => unreachable ! ( )
465477 }
466478
467- Ok ( conn)
479+ match self . raw_prepare ( TYPEINFO_QUERY ,
480+ "SELECT typname, typelem, NULL::OID FROM pg_catalog.pg_type \
481+ WHERE oid = $1") {
482+ Ok ( ..) => Ok ( ( ) ) ,
483+ Err ( Error :: IoError ( e) ) => Err ( ConnectError :: IoError ( e) ) ,
484+ Err ( Error :: DbError ( e) ) => Err ( ConnectError :: DbError ( e) ) ,
485+ _ => unreachable ! ( )
486+ }
468487 }
469488
470489 fn write_messages ( & mut self , messages : & [ FrontendMessage ] ) -> IoResult < ( ) > {
@@ -683,7 +702,7 @@ impl InnerConnection {
683702 try!( self . write_messages ( & [
684703 Bind {
685704 portal : "" ,
686- statement : TYPENAME_QUERY ,
705+ statement : TYPEINFO_QUERY ,
687706 formats : & [ 1 ] ,
688707 values : & [ try!( oid. to_sql ( & Type :: Oid ) ) ] ,
689708 result_formats : & [ 1 ]
@@ -701,10 +720,12 @@ impl InnerConnection {
701720 }
702721 _ => bad_response ! ( self )
703722 }
704- let ( name, elem_oid) : ( String , Oid ) = match try!( self . read_message ( ) ) {
723+ let ( name, elem_oid, rngsubtype) : ( String , Oid , Option < Oid > ) =
724+ match try!( self . read_message ( ) ) {
705725 DataRow { row } => {
706726 ( try!( FromSql :: from_sql ( & Type :: Name , row[ 0 ] . as_ref ( ) . map ( |r| & * * r) ) ) ,
707- try!( FromSql :: from_sql ( & Type :: Oid , row[ 1 ] . as_ref ( ) . map ( |r| & * * r) ) ) )
727+ try!( FromSql :: from_sql ( & Type :: Oid , row[ 1 ] . as_ref ( ) . map ( |r| & * * r) ) ) ,
728+ try!( FromSql :: from_sql ( & Type :: Oid , row[ 2 ] . as_ref ( ) . map ( |r| & * * r) ) ) )
708729 }
709730 ErrorResponse { fields } => {
710731 try!( self . wait_for_ready ( ) ) ;
@@ -722,10 +743,14 @@ impl InnerConnection {
722743 }
723744 try!( self . wait_for_ready ( ) ) ;
724745
725- let element_type = if elem_oid != 0 {
726- Some ( Box :: new ( try! ( self . get_type ( oid ) ) ) )
746+ let elem_oid = if elem_oid != 0 {
747+ Some ( elem_oid )
727748 } else {
728- None
749+ rngsubtype
750+ } ;
751+ let element_type = match elem_oid {
752+ Some ( oid) => Some ( Box :: new ( try!( self . get_type ( oid) ) ) ) ,
753+ None => None ,
729754 } ;
730755 let type_ = Type :: Unknown {
731756 oid : oid,
0 commit comments