Using PostgreSQL 9.4:
SELECT x, lower(x), upper(x) FROM (SELECT '[1,2]'::numrange x) q;
> [1,2] | 1 | 2 -- looks OK
SELECT x, lower(x), upper(x) FROM (SELECT '[1,2]'::int4range x) q;
> [1,3) | 1 | >>3<< -- this is unexpected
Let's check further:
SELECT x, lower(x), upper(x) FROM (SELECT '[1,3)'::numrange x) q1;
> [1,3) | 1 | 3 -- looks OK
SELECT x, lower(x), upper(x) FROM (SELECT '[1,3]'::numrange x) q1;
> [1,3] | 1 | 3 -- looks OK
From pg documentation:
upper(anyrange) | range's element type | upper bound of range | upper(numrange(1.1,2.2)) | 2.2
While 3
technically is an upper bound of the integer range [1,3) ∩ ℕ = {1, 2}
, so are all natural numbers ≥ 2. I would expect the upper
function returns the supremum (least upper bound) of the range.
Am I missing something?
This happens because int4range
is a discrete range. Such ranges always automatically converted to their canonical representation in order to be able to test equivalence, f.ex.:
SELECT '[4,8]'::int4range = '(3,9)'::int4range
The built-in range types
int4range
,int8range
, anddaterange
all use a canonical form that includes the lower bound and excludes the upper bound; that is,[)
. User-defined range types can use other conventions, however.
The canonical form of the closed range [1,2]
is the half-open (or half-closed) range [1,3)
. The function upper() returns the upper bound of the canonical form.
select upper(int4range(1, 2, '[]')); -- Canonical form is '[1,3)'
--
3
That range doesn't contain the value 3.
select int4range(1, 2, '[]') @> 3;
--
f
The built-in range types int4range, int8range, and daterange all use a canonical form that includes the lower bound and excludes the upper bound; that is, [). User-defined range types can use other conventions, however.
Source: PostgreSQL discrete range types
There's a different function to call if you need to know whether the value returned by upper() is inclusive.
select upper_inc(int4range(1, 2, '[]'));
--
f
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With