@@ -63,10 +63,11 @@ data TypeInfo = TypeInfo
63 , typdelim :: Char
63 , typdelim :: Char
64 , typname :: ByteString
64 , typname :: ByteString
65 , typelem :: Oid
65 , typelem :: Oid
66+ , rngsubtype :: Maybe Oid
68−instance FromRow TypeInfo where
69+instance FromRow TypeInfo where
69− fromRow = TypeInfo <$> field <*> field <*> field <*> field <*> field
70+ fromRow = TypeInfo <$> field <*> field <*> field <*> field <*> field <*> field
71type NameMap = Map.Map B.ByteString TypeInfo
72type NameMap = Map.Map B.ByteString TypeInfo
@@ -176,6 +177,18 @@ _varbit array_varbit
176_refcursor array_refcursor
177_refcursor array_refcursor
177_uuid array_uuid
178_uuid array_uuid
178_jsonb array_jsonb
179_jsonb array_jsonb
181instance IsString Blaze.Builder where
194instance IsString Blaze.Builder where
@@ -187,28 +200,31 @@ withPostgreSQL = bracket (connectPostgreSQL connectionString) close
188getTypeInfos :: TypeNames -> IO (OidMap, NameMap)
201getTypeInfos :: TypeNames -> IO (OidMap, NameMap)
189getTypeInfos typnames = withPostgreSQL $ \conn -> do
202getTypeInfos typnames = withPostgreSQL $ \conn -> do
190− infos <- query conn [sql|
203+ infos <- query conn [sql|
191− SELECT oid, typcategory, typdelim, typname, typelem
205+ (SELECT oid, typcategory, typdelim, typname, typelem
193− WHERE typname IN ?
206+ FROM pg_type WHERE typname IN ?)
194− |]
207+ SELECT types.*, rngsubtype FROM types LEFT JOIN pg_range ON oid = rngtypid
195− (Only (In (sort (map pg typnames))))
208+ |] (Only (In (sort (map pg typnames))))
196 loop conn (oidMap infos) (nameMap infos) infos
209 loop conn (oidMap infos) (nameMap infos) infos
198 oidMap = Map.fromList . map (typoid &&& id)
211 oidMap = Map.fromList . map (typoid &&& id)
199 nameMap = Map.fromList . map (typname &&& id)
212 nameMap = Map.fromList . map (typname &&& id)
200 loop conn oids names infos = do
213 loop conn oids names infos = do
201− let unknowns = [ x | x <- map typelem infos,
214+ let unknowns = [ x | x <- map typelem infos ++
215+ [ x | Just x <- map rngsubtype infos ],
202 x /= Oid 0,
216 x /= Oid 0,
203 not (Map.member x oids) ]
217 not (Map.member x oids) ]
204 case unknowns of
218 case unknowns of
205 [] -> return (oids, names)
219 [] -> return (oids, names)
206 (_:_) -> do
220 (_:_) -> do
207 infos' <- query conn [sql|
221 infos' <- query conn [sql|
208− SELECT oid, typcategory, typdelim, typname, typelem
223+ (SELECT oid, typcategory, typdelim, typname, typelem
209− FROM pg_type
224+ FROM pg_type WHERE oid IN ?)
210− WHERE oid IN ?
225+ SELECT types.*, rngsubtype
226+ FROM types LEFT JOIN pg_range ON oid = rngtypid
211− |] (Only (In (sort unknowns)))
227+ |] (Only (In (sort unknowns)))
212 let oids' = oids `Map.union` oidMap infos'
228 let oids' = oids `Map.union` oidMap infos'
213 names' = names `Map.union` nameMap infos'
229 names' = names `Map.union` nameMap infos'
214 loop conn oids' names' infos'
230 loop conn oids' names' infos'
@@ -239,9 +255,13 @@ renderTypeInfo :: OidMap -> TypeInfo -> TypeName -> Blaze.Builder
239renderTypeInfo byOid info name
255renderTypeInfo byOid info name
240 | typcategory info == 'A' || typname info == "_record" =
256 | typcategory info == 'A' || typname info == "_record" =
241 let (Just typelem_info) = Map.lookup (typelem info) byOid
257 let (Just typelem_info) = Map.lookup (typelem info) byOid
242− typelem_hs_name = case lookup (typname typelem_info) typeNames of
259+ case lookup (typname typelem_info) typeNames of
260+ Nothing -> error ( "type not found: "
261+ ++ B.unpack( typname typelem_info)
243− Nothing -> error ("type not found: " ++ B.unpack( typname typelem_info) ++ " (typelem of " ++ B.unpack (typname info) ++ ")")
262+ ++ " (typelem of " ++ B.unpack (typname info)
244− Just x -> x
264+ Just x -> x
245 in concat
265 in concat
247 , bs (hs name), " :: TypeInfo\n"
267 , bs (hs name), " :: TypeInfo\n"
@@ -253,7 +273,27 @@ renderTypeInfo byOid info name
253 , " typelem = ", bs typelem_hs_name, "\n"
273 , " typelem = ", bs typelem_hs_name, "\n"
256− | typcategory info == 'R' = undefined
276+ | typcategory info == 'R' =
277+ let (Just rngsubtype_oid) = rngsubtype info
278+ (Just rngsubtype_info) = Map.lookup rngsubtype_oid byOid
279+ rngsubtype_hs_name =
280+ case lookup (typname rngsubtype_info) typeNames of
281+ Nothing -> error ( "type not found: "
282+ ++ B.unpack (typname rngsubtype_info)
283+ ++ " (rngsubtype of "
284+ ++ B.unpack (typname info) ++ ")")
288+ , bs (hs name), " :: TypeInfo\n"
289+ , bs (hs name), " = Range {\n"
290+ , " typoid = ", fromString (show (typoid info)), ",\n"
291+ , " typcategory = '", Blaze.fromChar (typcategory info), "',\n"
292+ , " typdelim = '", Blaze.fromChar (typdelim info), "',\n"
293+ , " typname = \"", bs (typname info), "\",\n"
294+ , " rngsubtype = ", bs rngsubtype_hs_name, "\n"
257 | otherwise =
297 | otherwise =