Skip to content

Commit 05badcd

Browse files
authored
Support range types (#127)
This will add support for all 6 range types in postgres, using a new library `postgres-range` which supports empty and infinite ranges as well.
1 parent 6611981 commit 05badcd

File tree

3 files changed

+189
-8
lines changed

3 files changed

+189
-8
lines changed

lib/textParsers.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const array = require('postgres-array')
22
const parseTimestampTz = require('postgres-date')
33
const parseInterval = require('postgres-interval')
44
const parseByteA = require('postgres-bytea')
5+
const range = require('postgres-range')
56

67
function parseBool (value) {
78
return value === 'TRUE' ||
@@ -118,6 +119,26 @@ const parseCircle = function (value) {
118119
return result
119120
}
120121

122+
function parseInt4Range (raw) {
123+
return range.parse(raw, parseBaseTenInt)
124+
}
125+
126+
function parseNumRange (raw) {
127+
return range.parse(raw, parseFloat)
128+
}
129+
130+
function parseInt8Range (raw) {
131+
return range.parse(raw, parseBigInteger)
132+
}
133+
134+
function parseTimestampRange (raw) {
135+
return range.parse(raw, parseTimestamp)
136+
}
137+
138+
function parseTimestampTzRange (raw) {
139+
return range.parse(raw, parseTimestampTz)
140+
}
141+
121142
const init = function (register) {
122143
register(20, parseBigInteger) // int8
123144
register(21, parseBaseTenInt) // int2
@@ -157,7 +178,13 @@ const init = function (register) {
157178
register(3802, JSON.parse) // jsonb
158179
register(199, parseJsonArray) // json[]
159180
register(3807, parseJsonArray) // jsonb[]
181+
register(3904, parseInt4Range) // int4range
182+
register(3906, parseNumRange) // numrange
160183
register(3907, parseStringArray) // numrange[]
184+
register(3908, parseTimestampRange) // tsrange
185+
register(3910, parseTimestampTzRange) // tstzrange
186+
register(3912, range.parse) // daterange
187+
register(3926, parseInt8Range) // int8range
161188
register(2951, parseStringArray) // uuid[]
162189
register(791, parseStringArray) // money[]
163190
register(1183, parseStringArray) // time[]

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
"postgres-array": "~3.0.1",
4242
"postgres-bytea": "~3.0.0",
4343
"postgres-date": "~2.0.1",
44-
"postgres-interval": "^3.0.0"
44+
"postgres-interval": "^3.0.0",
45+
"postgres-range": "^1.0.0"
4546
},
4647
"files": [
4748
"index.js",

test/types.js

Lines changed: 160 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
'use strict'
22
const PostgresInterval = require('postgres-interval')
33

4+
const {
5+
Range,
6+
RANGE_EMPTY,
7+
RANGE_LB_INC,
8+
RANGE_LB_INF,
9+
RANGE_UB_INF,
10+
RANGE_UB_INC
11+
} = require('postgres-range')
12+
413
exports['string/varchar'] = {
514
format: 'text',
615
id: 1043,
@@ -179,13 +188,157 @@ exports.numrange = {
179188
format: 'text',
180189
id: 3906,
181190
tests: [
182-
['[,]', '[,]'],
183-
['(,)', '(,)'],
184-
['(,]', '(,]'],
185-
['[1,)', '[1,)'],
186-
['[,1]', '[,1]'],
187-
['(1,2)', '(1,2)'],
188-
['(1,20.5]', '(1,20.5]']
191+
['empty', function (t, value) {
192+
t.deepEqual(value, new Range(null, null, RANGE_EMPTY))
193+
}],
194+
['(,)', function (t, value) {
195+
t.deepEqual(value, new Range(null, null, RANGE_LB_INF | RANGE_UB_INF))
196+
}],
197+
['(1.5,)', function (t, value) {
198+
t.deepEqual(value, new Range(1.5, null, RANGE_UB_INF))
199+
}],
200+
['(,1.5)', function (t, value) {
201+
t.deepEqual(value, new Range(null, 1.5, RANGE_LB_INF))
202+
}],
203+
['(0,5)', function (t, value) {
204+
t.deepEqual(value, new Range(0, 5, 0))
205+
}],
206+
['(,1.5]', function (t, value) {
207+
t.deepEqual(value, new Range(null, 1.5, RANGE_LB_INF | RANGE_UB_INC))
208+
}],
209+
['[1.5,)', function (t, value) {
210+
t.deepEqual(value, new Range(1.5, null, RANGE_LB_INC | RANGE_UB_INF))
211+
}],
212+
['[0,0.5)', function (t, value) {
213+
t.deepEqual(value, new Range(0, 0.5, RANGE_LB_INC))
214+
}],
215+
['(0,0.5]', function (t, value) {
216+
t.deepEqual(value, new Range(0, 0.5, RANGE_UB_INC))
217+
}],
218+
['[0,0.5]', function (t, value) {
219+
t.deepEqual(value, new Range(0, 0.5, RANGE_LB_INC | RANGE_UB_INC))
220+
}]
221+
]
222+
}
223+
224+
exports.int4range = {
225+
format: 'text',
226+
id: 3904,
227+
tests: [
228+
['empty', function (t, value) {
229+
t.deepEqual(value, new Range(null, null, RANGE_EMPTY))
230+
}],
231+
['(,)', function (t, value) {
232+
t.deepEqual(value, new Range(null, null, RANGE_LB_INF | RANGE_UB_INF))
233+
}],
234+
['(1,)', function (t, value) {
235+
t.deepEqual(value, new Range(1, null, RANGE_UB_INF))
236+
}],
237+
['(,1)', function (t, value) {
238+
t.deepEqual(value, new Range(null, 1, RANGE_LB_INF))
239+
}],
240+
['(0,5)', function (t, value) {
241+
t.deepEqual(value, new Range(0, 5, 0))
242+
}],
243+
['(,1]', function (t, value) {
244+
t.deepEqual(value, new Range(null, 1, RANGE_LB_INF | RANGE_UB_INC))
245+
}],
246+
['[1,)', function (t, value) {
247+
t.deepEqual(value, new Range(1, null, RANGE_LB_INC | RANGE_UB_INF))
248+
}],
249+
['[0,5)', function (t, value) {
250+
t.deepEqual(value, new Range(0, 5, RANGE_LB_INC))
251+
}],
252+
['(0,5]', function (t, value) {
253+
t.deepEqual(value, new Range(0, 5, RANGE_UB_INC))
254+
}],
255+
['[0,5]', function (t, value) {
256+
t.deepEqual(value, new Range(0, 5, RANGE_LB_INC | RANGE_UB_INC))
257+
}]
258+
]
259+
}
260+
261+
exports.int8range = {
262+
format: 'text',
263+
id: 3926,
264+
tests: [
265+
['empty', function (t, value) {
266+
t.deepEqual(value, new Range(null, null, RANGE_EMPTY))
267+
}],
268+
['(,)', function (t, value) {
269+
t.deepEqual(value, new Range(null, null, RANGE_LB_INF | RANGE_UB_INF))
270+
}],
271+
['(1,)', function (t, value) {
272+
t.deepEqual(value, new Range('1', null, RANGE_UB_INF))
273+
}],
274+
['(,1)', function (t, value) {
275+
t.deepEqual(value, new Range(null, '1', RANGE_LB_INF))
276+
}],
277+
['(0,5)', function (t, value) {
278+
t.deepEqual(value, new Range('0', '5', 0))
279+
}],
280+
['(,1]', function (t, value) {
281+
t.deepEqual(value, new Range(null, '1', RANGE_LB_INF | RANGE_UB_INC))
282+
}],
283+
['[1,)', function (t, value) {
284+
t.deepEqual(value, new Range('1', null, RANGE_LB_INC | RANGE_UB_INF))
285+
}],
286+
['[0,5)', function (t, value) {
287+
t.deepEqual(value, new Range('0', '5', RANGE_LB_INC))
288+
}],
289+
['(0,5]', function (t, value) {
290+
t.deepEqual(value, new Range('0', '5', RANGE_UB_INC))
291+
}],
292+
['[0,5]', function (t, value) {
293+
t.deepEqual(value, new Range('0', '5', RANGE_LB_INC | RANGE_UB_INC))
294+
}]
295+
]
296+
}
297+
298+
const tsrangeEquals = ([lower, upper]) => {
299+
const timestamp = date => new Date(Date.UTC.apply(Date, date)).toUTCString()
300+
return (t, value) => {
301+
if (lower !== null) {
302+
t.equal(value.lower.toUTCString(), timestamp(lower))
303+
}
304+
if (upper !== null) {
305+
t.equal(value.upper.toUTCString(), timestamp(upper))
306+
}
307+
}
308+
}
309+
exports.tstzrange = {
310+
format: 'text',
311+
id: 3910,
312+
tests: [
313+
['(2010-10-31 14:54:13.74-05:30,)', tsrangeEquals([[2010, 9, 31, 20, 24, 13, 74], null])],
314+
['(,2010-10-31 14:54:13.74-05:30)', tsrangeEquals([null, [2010, 9, 31, 20, 24, 13, 74]])],
315+
['(2010-10-30 10:54:13.74-05:30,2010-10-31 14:54:13.74-05:30)', tsrangeEquals([[2010, 9, 30, 16, 24, 13, 74], [2010, 9, 31, 20, 24, 13, 74]])]
316+
]
317+
}
318+
exports.tsrange = {
319+
format: 'text',
320+
id: 3908,
321+
tests: [
322+
['(2010-10-31 14:54:13.74,)', tsrangeEquals([[2010, 9, 31, 14, 54, 13, 74], null])],
323+
['(2010-10-31 14:54:13.74,infinity)', tsrangeEquals([[2010, 9, 31, 14, 54, 13, 74], null])],
324+
['(,2010-10-31 14:54:13.74)', tsrangeEquals([null, [2010, 9, 31, 14, 54, 13, 74]])],
325+
['(-infinity,2010-10-31 14:54:13.74)', tsrangeEquals([null, [2010, 9, 31, 14, 54, 13, 74]])],
326+
['(2010-10-30 10:54:13.74,2010-10-31 14:54:13.74)', tsrangeEquals([[2010, 9, 30, 10, 54, 13, 74], [2010, 9, 31, 14, 54, 13, 74]])]
327+
]
328+
}
329+
exports.daterange = {
330+
format: 'text',
331+
id: 3912,
332+
tests: [
333+
['(2010-10-31,)', function (t, value) {
334+
t.deepEqual(value, new Range('2010-10-31', null, RANGE_UB_INF))
335+
}],
336+
['(,2010-10-31)', function (t, value) {
337+
t.deepEqual(value, new Range(null, '2010-10-31', RANGE_LB_INF))
338+
}],
339+
['[2010-10-30,2010-10-31]', function (t, value) {
340+
t.deepEqual(value, new Range('2010-10-30', '2010-10-31', RANGE_LB_INC | RANGE_UB_INC))
341+
}]
189342
]
190343
}
191344

0 commit comments

Comments
 (0)