64.3. Функции поддержки B-дерева#
64.3. Функции поддержки B-дерева #
Согласно Таблица 35.8, btree определяет одну обязательную и четыре дополнительные функции поддержки. Пять пользовательских методов включают:
order
Для каждой комбинации типов данных, для которых семейство операторов btree предоставляет операторы сравнения, оно должно предоставлять опорную функцию сравнения, зарегистрированную в
pg_amproc
с номером опорной функции 1 иamproclefttype
/amprocrighttype
, равными левому и правому типам данных для сравнения (т.е. тем же типам данных, с которыми зарегистрированы соответствующие операторы вpg_amop
). Функция сравнения должна принимать два ненулевых значенияA
иB
и возвращать значениеint32
, которое является<
0
,0
или>
0
, когдаA
<
B
,A
=
B
илиA
>
B
соответственно. Результат null запрещен: все значения типа данных должны быть сравнимыми. См. примеры вsrc/backend/access/nbtree/nbtcompare.c
.Если сравниваемые значения имеют тип данных, который поддерживает правило сортировки, соответствующий OID правила сортировки будет передан в функцию поддержки сравнения с использованием стандартного механизма
PG_GET_COLLATION()
.sortsupport
По желанию, семейство операторов btree может предоставлять функции поддержки сортировки, зарегистрированные под номером 2. Эти функции позволяют реализовать сравнения для целей сортировки более эффективным способом, чем просто вызов опорные функции сравнения. Соответствующие API определены в файле
src/include/utils/sortsupport.h
.in_range
По желанию, семейство операторов btree может предоставлять опорные функции in_range, зарегистрированные под номером 3. Они не используются во время операций индексирования btree; вместо этого они расширяют семантику семейства операторов таким образом, чтобы оно могло поддерживать оконные предложения, содержащие типы границ рамки
RANGE
offset
PRECEDING
иRANGE
offset
FOLLOWING
(см. Раздел 4.2.8). В основном, предоставляемая дополнительная информация определяет, как добавить или вычесть значениеoffset
таким образом, чтобы оно было совместимо с упорядочиванием данных семейства.Функция
in_range
должна иметь сигнатуруin_range(
val
type1,base
type1,offset
type2,sub
bool,less
bool) returns boolval
иbase
должны быть одного типа, который является одним из типов, поддерживаемых семейством операторов (т.е. типом, для которого он предоставляет упорядочение). Однако,offset
может быть другого типа, который может быть неподдерживаемым семейством. Примером является встроенное семействоtime_ops
, которое предоставляет функциюin_range
, у которойoffset
имеет типinterval
. Семейство может предоставлять функцииin_range
для любого из поддерживаемых типов и одного или нескольких типовoffset
. Каждая функцияin_range
должна быть введена вpg_amproc
сamproclefttype
, равнымtype1
, иamprocrighttype
, равнымtype2
.Существенная семантика функции
in_range
зависит от двух логических флаговых параметров. Она должна добавить или вычестьbase
иoffset
, затем сравнитьval
с результатом, следующим образом:если
!
sub
и!
less
, вернутьval
>=
(base
+
offset
)если
!
sub
иless
, вернутьval
<=
(base
+
offset
)если
sub
и!
less
, вернутьval
>=
(base
-
offset
)если
sub
иless
, вернутьval
<=
(base
-
offset
)
Перед этим функция должна проверить знак переменной
offset
: если он меньше нуля, вызвать ошибкуERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE
(22013) с текстом ошибки вида “недопустимый размер предшествующего или следующего значения в оконной функции”. (Это требуется стандартом SQL, хотя нестандартные семейства операторов, возможно, могут игнорировать это ограничение, так как, кажется, нет особой семантической необходимости в нем). Это требование делегируется функцииin_range
, чтобы основной код не должен был понимать, что означает “меньше нуля” для конкретного типа данных.Дополнительное ожидание состоит в том, что функции
in_range
должны, если это возможно, избегать генерации ошибки, еслиbase
+
offset
илиbase
-
offset
приведут к переполнению. Правильный результат сравнения может быть определен даже если это значение будет выходить за диапазон типа данных. Обратите внимание, что если тип данных включает понятия, такие как “бесконечность” или “NaN”, необходимо удостовериться, что результаты функцииin_range
согласуются с нормальным порядком сортировки семейства операторов.Результаты функции
in_range
должны быть согласованы с порядком сортировки, установленным операторной семьей. А именно, при заданных значенияхoffset
иsub
, должно выполняться следующее:Если
in_range
сless
= true истинно для некоторыхval1
иbase
, то оно должно быть истинно для каждогоval2
<=
val1
с тем жеbase
.Если
in_range
сless
= true равно false для некоторыхval1
иbase
, то оно должно быть false для каждогоval2
>=
val1
с тем жеbase
.Если
in_range
сless
= true истинно для некоторогоval
иbase1
, то оно должно быть истинно для каждогоbase2
>=
base1
с тем жеval
.Если
in_range
сless
= true равно false для некоторыхval
иbase1
, то оно должно быть false для каждогоbase2
<=
base1
с тем жеval
.
Аналогичные операторы с инвертированными условиями выполняются, когда
less
= false.Если заказываемый тип (
type1
) является сортируемым, соответствующий OID правила сортировки будет передан в функциюin_range
с использованием стандартного механизма PG_GET_COLLATION().in_range
функции не обязаны обрабатывать NULL входные данные и обычно будут помечены как строгие.equalimage
По желанию, семейство операторов btree может предоставлять опорные функции
equalimage
(“равенство подразумевает равенство изображения”), зарегистрированные под номером 4. Эти функции позволяют основному коду определить, когда безопасно применять оптимизацию дедупликации btree. В настоящее время функцииequalimage
вызываются только при создании или перестроении индекса.Функция
equalimage
должна иметь сигнатуруequalimage(
opcintype
oid
) returns boolВозвращаемое значение представляет собой статическую информацию о классе операторов и сортировке. Возвращение
true
указывает, что функцияorder
для класса операторов гарантированно возвращает только0
(“аргументы равны”), когда его аргументыA
иB
также взаимозаменяемы без потери семантической информации. Не регистрирование функцииequalimage
или возвращениеfalse
указывает на то, что это условие не может быть считано верным.Аргумент
opcintype
является
типа данных, индексируемого классом операторов. Это удобство, позволяющее повторно использовать одну и ту же базовую функциюpg_type
.oidequalimage
в разных классах операторов. Еслиopcintype
является сортируемым типом данных, соответствующий OID правила сортировки будет передан функцииequalimage
с использованием стандартного механизмаPG_GET_COLLATION()
.С точки зрения класса операторов, возвращение
true
указывает на то, что дедупликация безопасна (или безопасна для правила сортировки, идентификатор которого был передан в функциюequalimage
). Однако, основной код будет считать дедупликацию безопасной только для индекса, когда каждый индексируемый столбец использует класс операторов, который регистрирует функциюequalimage
, и каждая функция действительно возвращаетtrue
при вызове.Равенство изображений почти то же самое условие, что и простое побитовое равенство. Есть одно тонкое отличие: при индексировании типа данных varlena, представление на диске двух равных изображений может не быть побитово равным из-за несогласованного применения сжатия TOAST на входе. Формально, когда функция
equalimage
класса операторов возвращаетtrue
, можно считать, что функцияdatum_image_eq()
на языке C всегда согласуется с функциейorder
класса операторов (при условии, что один и тот же OID правила сортировки передается и в функциюequalimage
, и в функциюorder
).Основной код фундаментально неспособен вывести какую-либо информацию о статусе “равенство подразумевает равенство изображения” класса операторов внутри семейства множественных типов данных, основываясь на деталях других классов операторов в том же семействе. Кроме того, не имеет смысла для семейства операторов зарегистрировать функцию
equalimage
для перекрестного типа, и попытка сделать это приведет к ошибке. Это связано с тем, что статус “равенство подразумевает равенство изображения” не зависит только от семантики сортировки/равенства, которая более или менее определена на уровне семейства операторов. Обычно, семантику, которую реализует конкретный тип данных, необходимо рассматривать отдельно.Конвенция, которую следуют классы операторов, включенные в базовую дистрибуцию Tantor BE, заключается в регистрации стандартной обобщенной функции
equalimage
. Большинство классов операторов регистрируютbtequalimage()
, что указывает на безопасность дедупликации безусловно. Классы операторов для сравнимых типов данных, таких какtext
, регистрируютbtvarstrequalimage()
, что указывает на безопасность дедупликации с детерминированными правилами сортировки. Лучшей практикой для сторонних расширений является регистрация собственной пользовательской функции для сохранения контроля.options
По желанию, семейство операторов B-дерева может предоставлять опорные функции
options
(“опции, специфичные для класса операторов”), зарегистрированные под номером 5. Эти функции определяют набор пользовательских параметров, которые управляют поведением класса операторов.Опорная функция
options
должна иметь сигнатуруoptions(
relopts
local_relopts *
) returns voidФункции передается указатель на структуру
local_relopts
, которую необходимо заполнить набором специфических для класса операторов опций. Опции могут быть доступны из других вспомогательных функций с использованием макросовPG_HAS_OPCLASS_OPTIONS()
иPG_GET_OPCLASS_OPTIONS()
.В настоящее время ни один класс операторов B-Tree не имеет функции поддержки
options
. B-дерево не позволяет гибкого представления ключей, как это делают GiST, SP-GiST, GIN и BRIN. Поэтому, вероятно,options
не имеет большого применения в текущем методе доступа к индексу B-дерева. Тем не менее, эта Опорная функция была добавлена в B-дерево для обеспечения единообразия и, вероятно, найдет применение во время дальнейшего развития B-дерева в Tantor BE.