63.3. Опорные функции B-деревьев
Как показано в Таблице 38.8, btree определяет одну необходимую и две необязательных опорных функции.
Для всех комбинаций типов данных, для которых семейство операторов btree предоставляет операторы сравнения, оно должно предоставлять опорную функцию сравнения в pg_amproc
с номером 1 и c amproclefttype
/amprocrighttype
, равными левому и правому типу сравнения (то есть тем же типам данных, с которыми соответствующие операторы зарегистрированы в pg_amop
). Эта функция сравнения должна принимать два отличных от NULL значения A
и B
и возвращать значение int32
, которое будет <
0
, 0
или >
0
, когда A
<
B
, A
=
B
или A
>
B
, соответственно. Результат NULL не допускается: все значения типа данных должны быть сравнимыми. Примеры можно найти в src/backend/access/nbtree/nbtcompare.c
.
Если сравниваемые значения имеют сортируемый тип данных, опорной функции сравнения будет передан OID соответствующего правила сортировки через стандартный механизм PG_GET_COLLATION()
.
Дополнительно семейство операторов btree может предоставить функции поддержки сортировки, которые регистрируются под номером опорной функции 2. Эти функции позволяют реализовывать сравнения для целей сортировки гораздо эффективнее, чем это возможно при прямолинейном вызове функции поддержки сравнения. Задействованные в этом программные интерфейсы определены в src/include/utils/sortsupport.h
.
Дополнительно семейство операторов btree может предоставить опорные функции in_range, которые регистрируются под номером 3. Они не используются в ходе операций с индексом btree; вместо этого они расширяют семантику семейства операторов, чтобы оно могло поддерживать оконные предложения RANGE
смещение
PRECEDING
и RANGE
смещение
FOLLOWING
(см. Подраздел 4.2.8). По сути они предоставляют дополнительную информацию, позволяющую добавлять или вычитать смещение
в соответствии с порядком сортировки, принятым в семействе.
Функция in_range
должна иметь сигнатуру
in_range(значение
type1,база
type1,смещение
type2,вычитание
bool,меньше
bool) returns bool
Значение
и база
должны быть одного типа данных, и этот тип должен поддерживаться семейством операторов (то есть это должен быть тип, для которого реализуется сортировка). Однако смещение
может быть другого типа, который никаким другим образом не поддерживается данным семейством. Например, встроенное семейство time_ops
предоставляет функцию, для которой смещение
имеет тип interval
. Семейство может предоставлять функции in_range
для любых из своих поддерживаемых типов и одного или нескольких типов смещений
. Каждая функция in_range
должна регистрироваться в pg_amproc
с полем amproclefttype
, равным type1
, и amprocrighttype
, равным type2
.
Суть действия функции in_range
зависит от двух логических флагов. Она должна прибавить или вычесть из базы
смещение
, а затем сравнить значение
с результатом следующим образом:
если
!
вычитание
и!
меньше
, возвращаетсязначение
>=
(база
+
смещение
)если
!
вычитание
именьше
, возвращаетсязначение
<=
(база
+
смещение
)если
вычитание
и!
меньше
, возвращаетсязначение
>=
(база
-
смещение
)если
вычитание
именьше
, возвращаетсязначение
<=
(база
-
смещение
)
Прежде чем делать это, функция должна проверить знак смещения
и, если оно отрицательное, выдать ошибку ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE
(22013) с текстом ошибки «invalid preceding or following size in window function» (неверная предшествующая или последующая величина в оконной функции). (Это требуется стандартом SQL, но нестандартные семейства операторов могут проигнорировать данное ограничение, так как оно не несёт большой смысловой нагрузки.) Проверка этого требования делегируется функции in_range
, чтобы коду ядра не требовалось понимать, что означает «меньше нуля» для произвольного типа данных.
Кроме того, функции in_range
, если это практично, могут не выдавать ошибку, когда операция база
+
смещение
или база
-
смещение
приводит к переполнению. Правильный результат сравнения можно получить, даже если это значение выходит за границы допустимого диапазона этого типа данных. Заметьте, что если для типа данных определены такие понятия, как «бесконечность» и «NaN», могут потребоваться дополнительные меры для обеспечения согласованности результатов in_range
с обычным порядком сортировки данного семейства операторов.
Результаты функции in_range
должны соответствовать порядку сортировки, устанавливаемому семейством операторов. Точнее говоря, при любых фиксированных аргументах смещение
и вычитание
справедливо:
Если
in_range
сменьше
= true возвращает true для некоторогозначения1
ибазы
, true должно возвращаться для каждогозначения2
<=
значению1
с той жебазой
.Если
in_range
сменьше
= true возвращает false для некоторогозначения1
ибазы
, false должно возвращаться для любогозначения2
>=
значению1
с той жебазой
.Если
in_range
сменьше
= true возвращает true для некоторогозначения
ибазы1
, true должно возвращаться для каждойбазы2
>=
базе1
с тем жезначением
.Если
in_range
сменьше
= true возвращает false для некоторогозначения
ибазы1
, false должно возвращаться для любойбазы2
<=
базе1
с тем жезначением
.
Аналогичные утверждения с противоположными условиями должны выполняться при меньше
= false.
Если упорядочиваемый тип (type1
) является сортируемым, функции in_range
будет передан OID соответствующего правила сортировки через стандартный механизм PG_GET_COLLATION().
Функции in_range
не должны обрабатывать NULL в аргументах и обычно помечаются как строгие.