Skip to content

Commit 6d044b8

Browse files
committed
Add range types to static typeinfo table
1 parent d1a8c8f commit 6d044b8

File tree

2 files changed

+189
-17
lines changed

2 files changed

+189
-17
lines changed

src/Database/PostgreSQL/Simple/TypeInfo/Static.hs

+132
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,18 @@ module Database.PostgreSQL.Simple.TypeInfo.Static
114114
, array_refcursor
115115
, array_uuid
116116
, array_jsonb
117+
, int4range
118+
, _int4range
119+
, numrange
120+
, _numrange
121+
, tsrange
122+
, _tsrange
123+
, tstzrange
124+
, _tstzrange
125+
, daterange
126+
, _daterange
127+
, int8range
128+
, _int8range
117129
) where
118130

119131
import Database.PostgreSQL.LibPQ (Oid(..))
@@ -217,6 +229,18 @@ staticTypeInfo (Oid x) = case x of
217229
2201 -> Just array_refcursor
218230
2951 -> Just array_uuid
219231
3807 -> Just array_jsonb
232+
3904 -> Just int4range
233+
3905 -> Just _int4range
234+
3906 -> Just numrange
235+
3907 -> Just _numrange
236+
3908 -> Just tsrange
237+
3909 -> Just _tsrange
238+
3910 -> Just tstzrange
239+
3911 -> Just _tstzrange
240+
3912 -> Just daterange
241+
3913 -> Just _daterange
242+
3926 -> Just int8range
243+
3927 -> Just _int8range
220244
_ -> Nothing
221245

222246
bool :: TypeInfo
@@ -1035,3 +1059,111 @@ array_jsonb = Array {
10351059
typname = "_jsonb",
10361060
typelem = jsonb
10371061
}
1062+
1063+
int4range :: TypeInfo
1064+
int4range = Range {
1065+
typoid = Oid 3904,
1066+
typcategory = 'R',
1067+
typdelim = ',',
1068+
typname = "int4range",
1069+
rngsubtype = int4
1070+
}
1071+
1072+
_int4range :: TypeInfo
1073+
_int4range = Array {
1074+
typoid = Oid 3905,
1075+
typcategory = 'A',
1076+
typdelim = ',',
1077+
typname = "_int4range",
1078+
typelem = int4range
1079+
}
1080+
1081+
numrange :: TypeInfo
1082+
numrange = Range {
1083+
typoid = Oid 3906,
1084+
typcategory = 'R',
1085+
typdelim = ',',
1086+
typname = "numrange",
1087+
rngsubtype = numeric
1088+
}
1089+
1090+
_numrange :: TypeInfo
1091+
_numrange = Array {
1092+
typoid = Oid 3907,
1093+
typcategory = 'A',
1094+
typdelim = ',',
1095+
typname = "_numrange",
1096+
typelem = numrange
1097+
}
1098+
1099+
tsrange :: TypeInfo
1100+
tsrange = Range {
1101+
typoid = Oid 3908,
1102+
typcategory = 'R',
1103+
typdelim = ',',
1104+
typname = "tsrange",
1105+
rngsubtype = timestamp
1106+
}
1107+
1108+
_tsrange :: TypeInfo
1109+
_tsrange = Array {
1110+
typoid = Oid 3909,
1111+
typcategory = 'A',
1112+
typdelim = ',',
1113+
typname = "_tsrange",
1114+
typelem = tsrange
1115+
}
1116+
1117+
tstzrange :: TypeInfo
1118+
tstzrange = Range {
1119+
typoid = Oid 3910,
1120+
typcategory = 'R',
1121+
typdelim = ',',
1122+
typname = "tstzrange",
1123+
rngsubtype = timestamptz
1124+
}
1125+
1126+
_tstzrange :: TypeInfo
1127+
_tstzrange = Array {
1128+
typoid = Oid 3911,
1129+
typcategory = 'A',
1130+
typdelim = ',',
1131+
typname = "_tstzrange",
1132+
typelem = tstzrange
1133+
}
1134+
1135+
daterange :: TypeInfo
1136+
daterange = Range {
1137+
typoid = Oid 3912,
1138+
typcategory = 'R',
1139+
typdelim = ',',
1140+
typname = "daterange",
1141+
rngsubtype = date
1142+
}
1143+
1144+
_daterange :: TypeInfo
1145+
_daterange = Array {
1146+
typoid = Oid 3913,
1147+
typcategory = 'A',
1148+
typdelim = ',',
1149+
typname = "_daterange",
1150+
typelem = daterange
1151+
}
1152+
1153+
int8range :: TypeInfo
1154+
int8range = Range {
1155+
typoid = Oid 3926,
1156+
typcategory = 'R',
1157+
typdelim = ',',
1158+
typname = "int8range",
1159+
rngsubtype = int8
1160+
}
1161+
1162+
_int8range :: TypeInfo
1163+
_int8range = Array {
1164+
typoid = Oid 3927,
1165+
typcategory = 'A',
1166+
typdelim = ',',
1167+
typname = "_int8range",
1168+
typelem = int8range
1169+
}

tools/GenTypeInfo.hs

+57-17
Original file line numberDiff line numberDiff line change
@@ -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

7172
type 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

181194
instance IsString Blaze.Builder where
@@ -187,28 +200,31 @@ withPostgreSQL = bracket (connectPostgreSQL connectionString) close
187200

188201
getTypeInfos :: TypeNames -> IO (OidMap, NameMap)
189202
getTypeInfos 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
239255
renderTypeInfo 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"

0 commit comments

Comments
 (0)