@@ -27,7 +27,10 @@ module Database.PostgreSQL.Simple.TypeInfo
27 , TypeInfo(..)
27 , TypeInfo(..)
30+import qualified Data.ByteString as B
30import qualified Data.IntMap as IntMap
31import qualified Data.IntMap as IntMap
32+import qualified Data.Vector as V
33+import qualified Data.Vector.Mutable as MV
31import Control.Concurrent.MVar
34import Control.Concurrent.MVar
32import Control.Exception (throw)
35import Control.Exception (throw)
@@ -57,18 +60,19 @@ getTypeInfo' conn oid oidmap =
57 case IntMap.lookup (oid2int oid) oidmap of
60 case IntMap.lookup (oid2int oid) oidmap of
58 Just typeinfo -> return (oidmap, typeinfo)
61 Just typeinfo -> return (oidmap, typeinfo)
59 Nothing -> do
62 Nothing -> do
60− names <- query conn "SELECT oid, typcategory, typdelim, typname, typelem\
63+ names <- query conn "SELECT oid, typcategory, typdelim, typname,\
61 \ FROM pg_type WHERE oid = ?"
65 \ FROM pg_type WHERE oid = ?"
62 (Only oid)
66 (Only oid)
63 (oidmap', typeInfo) <-
67 (oidmap', typeInfo) <-
64 case names of
68 case names of
65 [] -> return $ throw (fatalError "invalid type oid")
69 [] -> return $ throw (fatalError "invalid type oid")
66− [(typoid, typcategory, typdelim, typname, typelem_)] -> do
70+ [(typoid, typcategory, typdelim, typname, typelem_, typrelid)] -> do
67 case typcategory of
71 case typcategory of
69 (oidmap', typelem) <- getTypeInfo' conn typelem_ oidmap
73 (oidmap', typelem) <- getTypeInfo' conn typelem_ oidmap
70 let !typeInfo = Array{..}
74 let !typeInfo = Array{..}
71− return (oidmap', typeInfo)
75+ return $! (oidmap', typeInfo)
73 rngsubtypeOids <- query conn "SELECT rngsubtype\
77 rngsubtypeOids <- query conn "SELECT rngsubtype\
74 \ FROM pg_range\
78 \ FROM pg_range\
@@ -79,13 +83,38 @@ getTypeInfo' conn oid oidmap =
79 (oidmap', rngsubtype) <-
83 (oidmap', rngsubtype) <-
80 getTypeInfo' conn rngsubtype_ oidmap
84 getTypeInfo' conn rngsubtype_ oidmap
81 let !typeInfo = Range{..}
85 let !typeInfo = Range{..}
82− return (oidmap', typeInfo)
86+ return $! (oidmap', typeInfo)
83 _ -> fail "range subtype query failed to return exactly one result"
87 _ -> fail "range subtype query failed to return exactly one result"
89+ cols <- query conn "SELECT attname, atttypid\
91+ \ WHERE attrelid = ?\
93+ \ AND NOT attisdropped\
96+ vec <- MV.new $! length cols
97+ (oidmap', attributes) <- getAttInfos conn cols oidmap vec 0
98+ let !typeInfo = Composite{..}
99+ return $! (oidmap', typeInfo)
85 let !typeInfo = Basic{..}
101 let !typeInfo = Basic{..}
86− return (oidmap, typeInfo)
102+ return $! (oidmap, typeInfo)
87 _ -> fail "typename query returned more than one result"
103 _ -> fail "typename query returned more than one result"
88 -- oid is a primary key, so the query should
104 -- oid is a primary key, so the query should
89 -- never return more than one result
105 -- never return more than one result
90 let !oidmap'' = IntMap.insert (oid2int oid) typeInfo oidmap'
106 let !oidmap'' = IntMap.insert (oid2int oid) typeInfo oidmap'
91 return $! (oidmap'', typeInfo)
107 return $! (oidmap'', typeInfo)
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 =
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)