git.iko.soy/typeable/postgresql-simple
on master help sign in
Extend TypeInfo to cover Composite types
commitf4e2ff627ef081972d75cbb036bf85a9a7dece35 authorLeon P Smith <leon@melding-monads.com> dateTue 26 Mar 2013, 22:01 (14 years ago) parent4e1b449
3 files changed+58−7
src/Database/PostgreSQL/Simple/FromRow.hs-boot+9−2 src/Database/PostgreSQL/Simple/TypeInfo.hs+34−5 src/Database/PostgreSQL/Simple/TypeInfo/Types.hs+15
src/Database/PostgreSQL/Simple/FromRow.hs-boot+9−2
@@ -6,6 +6,13 @@ import Database.PostgreSQL.Simple.Types
66class FromRow a
77
88instance (FromField a) => FromRow (Only a)
9−instance (FromField a, FromField b, FromField c, FromField d) => FromRow (a,b,c,d)
10−instance (FromField a, FromField b, FromField c, FromField d, FromField e) => FromRow (a,b,c,d,e)
9+instance (FromField a, FromField b)
10+ => FromRow (a,b)
11+instance (FromField a, FromField b, FromField c, FromField d)
12+ => FromRow (a,b,c,d)
13+instance (FromField a, FromField b, FromField c, FromField d, FromField e)
14+ => FromRow (a,b,c,d,e)
15+instance (FromField a, FromField b, FromField c, FromField d, FromField e
16+ ,FromField f)
17+ => FromRow (a,b,c,d,e,f)
1118
src/Database/PostgreSQL/Simple/TypeInfo.hs+34−5
@@ -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)
src/Database/PostgreSQL/Simple/TypeInfo/Types.hs+15
@@ -12,6 +12,7 @@ module Database.PostgreSQL.Simple.TypeInfo.Types where
1212
1313import Data.ByteString(ByteString)
1414import Database.PostgreSQL.LibPQ(Oid)
15+import Data.Vector(Vector)
1516
1617-- | A structure representing some of the metadata regarding a PostgreSQL
1718-- type, mostly taken from the @pg_type@ table.
@@ -38,4 +39,18 @@ data TypeInfo
3839 , rngsubtype :: !TypeInfo
3940 }
4041
42+ | Composite { typoid :: {-# UNPACK #-} !Oid
43+ , typcategory :: {-# UNPACK #-} !Char
44+ , typdelim :: {-# UNPACK #-} !Char
45+ , typname :: !ByteString
46+ , typrelid :: {-# UNPACK #-} !Oid
47+ , attributes :: !(Vector Attribute)
48+ }
49+
4150 deriving (Show)
51+
52+data Attribute
53+ = Attribute { attname :: !ByteString
54+ , atttype :: !TypeInfo
55+ }
56+ deriving (Show)