Comme montré dans Tableau 38.8, btree définit une fonction de support obligatoire et deux facultatives.
Pour chaque combinaison de types de données pour laquelle une famille
d'opérateur btree fournit des opérateurs de comparaison, elle doit fournir une
fonction de support de comparaison inscrite dans
pg_amproc
avec la fonction de support 1 et
amproclefttype
/amprocrighttype
égaux aux types de données gauche et droit pour la comparaison (c'est-à-dire
les même types de données que l'opérateur correspondant a inscrit dans
pg_amop
).
La fonction de comparaison doit prendre en entrée deux valeurs non nulles
A
et B
et retourner une
valeur int32
qui est
<
0
, 0
,
ou >
0
quand, respectivement A
<
B
, A
=
B
,
ou A
>
B
. Une valeur de retour NULL est également
interdite : toutes les valeurs du type de données doivent être
comparables. Voir
src/backend/access/nbtree/nbtcompare.c
pour plus
d'exemples.
Si les valeurs comparées sont d'un type avec collation, l'identifiant de
collation approprié sera passé à la fonction de support de comparaison, en
utilisant le mécanisme standard PG_GET_COLLATION()
.
De manière facultative, une famille d'opérateur btree peut fournir une ou
plusieurs fonctions sort support, inscrites comme
fonctions de support numéro 2. Ces fonctions permettent d'implémenter des
comparaisons dans l'optique de tri de manière plus efficace qu'appeler
naivement la fonction de support de comparaison. Les API impliquées pour
cela sont définies dans src/include/utils/sortsupport.h
.
De manière facultative, une famille d'opérateur btree peut fournir une ou
plusieurs fonctions de support in_range inscrites comme
fonction de support numéro 3. Celles-ci ne sont pas utilisées durant les
opérations d'index btree ; mais plutôt, elles étendent les sémantiques de la
famille d'opérateur de telle manière qu'elles puissent supporter les clauses de
fenêtrage contenant les types de limite de cadre
RANGE
décalage
PRECEDING
et RANGE
décalage
FOLLOWING
(voir
Section 4.2.8). Fondamentalement, les
informations supplémentaires fournies sont comment additionner et soustraire
une valeur d'un décalage
d'une manière qui est
compatible avec le tri de données de la famille.
Une fonction in_range
doit avoir la signature
in_range(val
type1,base
type1,offset
type2,sub
bool,less
bool) returns bool
val
et base
doivent
être du même type, qui est un des types supportés par la famille d'opérateur
(c'est-à-dire un type pour lequel elle fournit un tri). Cependant,
offset
peut être d'un type de données différent,
qui peut par ailleurs ne pas être supporté par la famille. Un exemple est
que la famille time_ops
incluse par défaut fournit une
fonction in_range
qui a un
offset
de type interval
.
Une famille peut fournir des fonctions in_range
pour
n'importe lesquels des types de données qu'elle supporte, et un ou plusieurs types
offset
. Chaque fonction
in_range
devrait être inscrite dans
pg_amproc
avec amproclefttype
égal à type1
et amprocrighttype
égal à type2
.
Les sémantiques essentielles pour une fonction in_range
dépendent des deux paramètres de drapeau booléens. Elle devrait ajouter ou
soustraire base
et
offset
, puis comparer
val
au résultat, comme ceci :
si !
sub
et
!
less
,
renvoyer val
>=
(base
+
offset
)
si !
sub
et less
,
renvoyer val
<=
(base
+
offset
)
si sub
et !
less
,
renvoyer val
>=
(base
-
offset
)
si sub
et less
,
renvoyer val
<=
(base
-
offset
)
Avant de procéder, la fonction devrait vérifier le signe d'
offset
: s'il est inférieur ou égal à zéro, lever l'erreur
ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE
(22013)
avec un message d'erreur tel que « taille précédente ou suivante invalide
dans la fonction de fenêtrage ». (Cela est requis par le standard SQL,
bien que des familles d'opérateur non standards pourraient peut être choisir
d'ignorer cette restriction, puisqu'il n'y a pas vraiment de nécessité de
sémantique dans ce cas.) Cette exigence est déléguée à la fonction
in_range
si bien que le code du moteur n'a pas besoin de
comprendre ce que « inférieur à zéro » signifie pour un type de
données particulier.
Une autre attente est que les fonctions in_range
devraient, si applicable, éviter de générer une erreur si
base
+
offset
ou base
-
offset
devait causer un débordement.
Le résultat de comparaison correct peut être déterminé même si cette valeur
devait être en dehors de l'intervalle des valeurs du type de données.
Notez que si le type de données inclut des concepts tels que
« infinity » ou « NaN », des précautions supplémentaires
pourraient être nécessaires pour s'assurer que les resultats de
in_range
soit en accord avec l'ordre de tri normal de la
famille d'opérateur.
Les résultats de la fonction in_range
doivent être
cohérents avec l'ordre de tri imposé par la famille d'opérateur. Pour être
précis, pour n'importe quelles valeurs fixées de
offset
et sub
, alors :
Si in_range
avec less
=
true est vrai pour certains val1
et base
, il doit être vrai pour chaque
val2
<=
val1
avec le même
base
.
Si in_range
avec less
=
true est faux pour certains val1
et base
, il doit être faux pour chaque
val2
>=
val1
avec le même
base
.
Si in_range
avec less
=
true est vrai pour certains val
et base1
, il doit être vrai pour chaque
base2
>=
base1
avec le même
val
.
Si in_range
avec less
=
true est faux pour certains val
et base1
, il doit être faux pour chaque
base2
<=
base1
avec le même
val
.
Des déclarations similaires avec des conditions inversées continuent à
s'appliquer quand less
= false.
Si le type est trié (type1
) par rapport à une collation, l'OID de collation
approprié sera passé à la fonction in_range
en utilisant
le mécanisme standard PG_GET_COLLATION()
.
Les fonctions in_range
n'ont pas besoin de gérer les
valeurs en entrée NULL, et typiquement elles seront marquées comme strict.