@@ -63,10 +63,11 @@ data TypeInfo = TypeInfo
6363 , typdelim :: Char
6464 , typname :: ByteString
6565 , typelem :: Oid
66+ , rngsubtype :: Maybe Oid
6667 }
6768
68−instance FromRow TypeInfo where
69− fromRow = TypeInfo <$> field <*> field <*> field <*> field <*> field
69+instance FromRow TypeInfo where
70+ fromRow = TypeInfo <$> field <*> field <*> field <*> field <*> field <*> field
7071
7172type NameMap = Map.Map B.ByteString TypeInfo
7273
@@ -176,6 +177,18 @@ _varbit array_varbit
176177_refcursor array_refcursor
177178_uuid array_uuid
178179_jsonb array_jsonb
180+int4range
181+_int4range
182+numrange
183+_numrange
184+tsrange
185+_tsrange
186+tstzrange
187+_tstzrange
188+daterange
189+_daterange
190+int8range
191+_int8range
179192|]
180193
181194instance IsString Blaze.Builder where
@@ -187,28 +200,31 @@ withPostgreSQL = bracket (connectPostgreSQL connectionString) close
187200
188201getTypeInfos :: TypeNames -> IO (OidMap, NameMap)
189202getTypeInfos typnames = withPostgreSQL $ \conn -> do
190− infos <- query conn [sql|
191− SELECT oid, typcategory, typdelim, typname, typelem
192− FROM pg_type
193− WHERE typname IN ?
194− |]
195− (Only (In (sort (map pg typnames))))
203+ infos <- query conn [sql|
204+ WITH types AS
205+ (SELECT oid, typcategory, typdelim, typname, typelem
206+ FROM pg_type WHERE typname IN ?)
207+ SELECT types.*, rngsubtype FROM types LEFT JOIN pg_range ON oid = rngtypid
208+ |] (Only (In (sort (map pg typnames))))
196209 loop conn (oidMap infos) (nameMap infos) infos
197210 where
198211 oidMap = Map.fromList . map (typoid &&& id)
199212 nameMap = Map.fromList . map (typname &&& id)
200213 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 ],
202216 x /= Oid 0,
203217 not (Map.member x oids) ]
204218 case unknowns of
205219 [] -> return (oids, names)
206220 (_:_) -> do
207221 infos' <- query conn [sql|
208− SELECT oid, typcategory, typdelim, typname, typelem
209− FROM pg_type
210− WHERE oid IN ?
211− |] (Only (In (sort unknowns)))
222+ WITH types AS
223+ (SELECT oid, typcategory, typdelim, typname, typelem
224+ FROM pg_type WHERE oid IN ?)
225+ SELECT types.*, rngsubtype
226+ FROM types LEFT JOIN pg_range ON oid = rngtypid
227+ |] (Only (In (sort unknowns)))
212228 let oids' = oids `Map.union` oidMap infos'
213229 names' = names `Map.union` nameMap infos'
214230 loop conn oids' names' infos'
@@ -239,9 +255,13 @@ renderTypeInfo :: OidMap -> TypeInfo -> TypeName -> Blaze.Builder
239255renderTypeInfo byOid info name
240256 | typcategory info == 'A' || typname info == "_record" =
241257 let (Just typelem_info) = Map.lookup (typelem info) byOid
242− typelem_hs_name = case lookup (typname typelem_info) typeNames of
243− Nothing -> error ("type not found: " ++ B.unpack( typname typelem_info) ++ " (typelem of " ++ B.unpack (typname info) ++ ")")
244− Just x -> x
258+ typelem_hs_name =
259+ case lookup (typname typelem_info) typeNames of
260+ Nothing -> error ( "type not found: "
261+ ++ B.unpack( typname typelem_info)
262+ ++ " (typelem of " ++ B.unpack (typname info)
263+ ++ ")")
264+ Just x -> x
245265 in concat
246266 [ "\n"
247267 , bs (hs name), " :: TypeInfo\n"
@@ -253,7 +273,27 @@ renderTypeInfo byOid info name
253273 , " typelem = ", bs typelem_hs_name, "\n"
254274 , " }\n"
255275 ]
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) ++ ")")
285+ Just x -> x
286+ in concat
287+ [ "\n"
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"
295+ , " }\n"
296+ ]
257297 | otherwise =
258298 concat
259299 [ "\n"