@@ -27,7 +27,10 @@ module Database.PostgreSQL.Simple.TypeInfo
2727 , TypeInfo(..)
2828 ) where
2929
30+import qualified Data.ByteString as B
3031import qualified Data.IntMap as IntMap
32+import qualified Data.Vector as V
33+import qualified Data.Vector.Mutable as MV
3134import Control.Concurrent.MVar
3235import Control.Exception (throw)
3336
@@ -57,18 +60,19 @@ getTypeInfo' conn oid oidmap =
5760 case IntMap.lookup (oid2int oid) oidmap of
5861 Just typeinfo -> return (oidmap, typeinfo)
5962 Nothing -> do
60− names <- query conn "SELECT oid, typcategory, typdelim, typname, typelem\
63+ names <- query conn "SELECT oid, typcategory, typdelim, typname,\
64+ \ typelem, typrelid\
6165 \ FROM pg_type WHERE oid = ?"
6266 (Only oid)
6367 (oidmap', typeInfo) <-
6468 case names of
6569 [] -> return $ throw (fatalError "invalid type oid")
66− [(typoid, typcategory, typdelim, typname, typelem_)] -> do
70+ [(typoid, typcategory, typdelim, typname, typelem_, typrelid)] -> do
6771 case typcategory of
6872 'A' -> do
6973 (oidmap', typelem) <- getTypeInfo' conn typelem_ oidmap
7074 let !typeInfo = Array{..}
71− return (oidmap', typeInfo)
75+ return $! (oidmap', typeInfo)
7276 'R' -> do
7377 rngsubtypeOids <- query conn "SELECT rngsubtype\
7478 \ FROM pg_range\
@@ -79,13 +83,38 @@ getTypeInfo' conn oid oidmap =
7983 (oidmap', rngsubtype) <-
8084 getTypeInfo' conn rngsubtype_ oidmap
8185 let !typeInfo = Range{..}
82− return (oidmap', typeInfo)
86+ return $! (oidmap', typeInfo)
8387 _ -> fail "range subtype query failed to return exactly one result"
88+ 'C' -> do
89+ cols <- query conn "SELECT attname, atttypid\
90+ \ FROM pg_attribute\
91+ \ WHERE attrelid = ?\
92+ \ AND attnum > 0\
93+ \ AND NOT attisdropped\
94+ \ ORDER BY attnum"
95+ (Only typrelid)
96+ vec <- MV.new $! length cols
97+ (oidmap', attributes) <- getAttInfos conn cols oidmap vec 0
98+ let !typeInfo = Composite{..}
99+ return $! (oidmap', typeInfo)
84100 _ -> do
85101 let !typeInfo = Basic{..}
86− return (oidmap, typeInfo)
102+ return $! (oidmap, typeInfo)
87103 _ -> fail "typename query returned more than one result"
88104 -- oid is a primary key, so the query should
89105 -- never return more than one result
90106 let !oidmap'' = IntMap.insert (oid2int oid) typeInfo oidmap'
91107 return $! (oidmap'', typeInfo)
108+
109+getAttInfos :: Connection -> [(B.ByteString, PQ.Oid)] -> TypeInfoCache
110+ -> MV.IOVector Attribute -> Int
111+ -> IO (TypeInfoCache, V.Vector Attribute)
112+getAttInfos conn cols oidmap vec n =
113+ case cols of
114+ [] -> do
115+ !attributes <- V.unsafeFreeze vec
116+ return $! (oidmap, attributes)
117+ ((attname, attTypeOid):xs) -> do
118+ (oidmap', atttype) <- getTypeInfo' conn attTypeOid oidmap
119+ MV.write vec n $! Attribute{..}
120+ getAttInfos conn xs oidmap' vec (n+1)