2015-01-15 2 views
5

Использование PostgreSQL 9.4:Postgres int4range верхней границы неожиданное значение

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 

Давайте посмотрим дальше:

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 

От стр документации:

верхняя (anyrange) | тип элемента диапазона | верхняя граница диапазона | upper (numrange (1.1.2.2)) | 2,2

В то время как 3 технически это верхняя граница диапазона целых чисел [1,3) ∩ ℕ = {1, 2}, так что все натуральные числа ≥ 2. Я хотел бы ожидать, что функция возвращает upperсупремумом (верхняя грань) диапазона.

Я что-то упустил?

ответ

1

Это происходит потому, что int4range является discrete range. Такие диапазоны всегда автоматически преобразуются в их каноническое представление для того, чтобы иметь возможность проверить эквивалентность, f.ex .:

SELECT '[4,8]'::int4range = '(3,9)'::int4range 

Встроенный типов диапазона int4range, int8range и daterange все используют каноническую форму, включает нижнюю границу и исключает верхнюю границу; то есть [). Однако пользовательские типы диапазонов могут использовать другие соглашения.

+0

Да, они преобразуются в канонической форме. И диапазон [1,2] в точности совпадает с [1,3] в N. Но 3 в sup. ни того, ни другого. – damians

+0

@FireBiker да, 3 не является супремумом, но это верхняя граница (по определению PostgreSQL) '[1,3)'. Вы можете использовать 'upper_inc()' для обнаружения, если он включен или нет. Я думаю, что это потому, что эти функции согласованы (т.е. как «upper (« [1,3) »:: int4range), так и' upper ('[1,3)' :: numrange) 'будут давать' 3') - обратите внимание, что верхняя грань может быть названа * наименьшей верхней границей *, а PostgreSQL использует только термин * верхняя граница * – pozs

0

Каноническая форма диапазона [1,2] является [1,3). Функция upper() возвращает верхнюю границу канонической формы.

select upper(int4range(1, 2, '[]')); -- Canonical form is '[1,3)' 
 
3 

Этот диапазон не содержит значение 3.

select int4range(1, 2, '[]') @> 3; 
 
f 

Там совсем другая функция, которая вызывается, если вам нужно знать, является ли значение, возвращаемое верхней() включительно.

select upper_inc(int4range(1, 2, '[]')); 
 
f