Comme montré dans Tableau 38.2, une classe d'opérateur
btree doit fournir cinq opérateurs de comparaison,
<
,
<=
,
=
,
>=
et
>
.
On pourrait supposer que <>
devraient également faire
partie de la classe d'opérateur, mais ce n'est pas le cas car cela ne serait
presque jamais utile d'utiliser une clause WHERE <>
dans une recherche d'index. (Dans certains cas, le planificateur traite
<>
comme s'il était associé avec une classe
d'opérateur btree ; mais il trouve cet opérateur via le lien du négateur de
l'opérateur =
, plutôt que depuis
pg_amop
.)
Quand plusieurs types de données partagent des sémantiques de tri presque identiques, leurs classes d'opérateurs peuvent être regroupées dans une famille d'opérateur. Il est avantageux de procéder ainsi car cela permet au planificateur de faire des déductions quant aux comparaisons entre plusieurs types. Chaque classe d'opérateur au sein d'une famille devrait contenir les opérateurs concernant un seul type (et les fonctions de support associées), tandis que les opérateurs de comparaison inter-types et les fonctions de support sont « libres » dans la famille. Il est recommandé qu'un ensemble complet d'opérateurs inter-types soit inclus dans la famille, afin d'assurer que le planificateur puisse représenter n'importe quelle condition de comparaison qu'il pourrait déduire depuis la transitivité.
Il y a des supposition basiques qu'une famille d'opérateur btree doit satisfaire :
Un opérateur =
doit être une relation d'équivalence ;
c'est-à-dire que pour toutes les valeurs non nulles
A
,
B
, C
du type de
données :
A
=
A
est vrai
(loi de réflexivité)
si A
=
B
,
alors B
=
A
(loi de symétrie)
si A
=
B
et B
=
C
,
alors A
=
C
(loi de transitivité)
Un opérateur <
doit être une relation de tri forte ;
c'est-à-dire, pour toutes les valeurs non nulles
A
, B
,
C
:
A
<
A
est faux
(loi d'antiréflexivité)
si A
<
B
et B
<
C
,
alors A
<
C
(loi de transitivité)
De plus, le tri est total ; c'est-à-dire, pour toutes les valeurs non nulles
A
, B
:
exactement une seule des expressions
A
<
B
, A
=
B
, et
B
<
A
est vraie
(loi de trichotomie)
(Bien entendu, la loi de trichotomie justifie la définition de la fonction de support de comparaison).
Les trois autres opérateurs sont définis avec =
et <
de manière évidente, et doivent se comporter de
manière cohérentes avec ceux-ci.
Pour une famille d'opérateur supportant plusieurs types de données, les lois
définies auparavant doivent continuer à s'appliquer quand
A
, B
,
C
sont pris de n'importe quel type de données
de la famille. Les lois de transitivité sont les plus délicates à garantir,
car, dans des situations inter-types, elles représentent des déclarations comme
quoi les comportements de deux ou trois différents opérateurs sont cohérents.
Comme exemple, mettre float8
et numeric
dans la
même famille d'opérateur ne fonctionnerait pas, du moins pas avec les
sémantiques actuelles qui définissent que les valeurs de type
numeric
sont converties en float8
pour la
comparaison vers un float8
. Du fait de la précision limitée du
type float8
, cela veut dire que des valeurs
numeric
distinctes seraient considérées par la comparaison
comme égales à la même valeur float8
, et par conséquent la loi
de transitivé échouerait.
Une autre exigence pour les familles contenant plusieurs types est que les transtypages implicites ou de coercition binaire qui sont définis entre les types de données inclus dans la famille d'opérateur ne doivent pas changer l'ordre de tri associé.
La raison pour laquelle les index btree nécessitent que ces lois soient vérifiées pour un même type de données devraient être tout à fait claires : sans celles-ci, il n'y a pas d'ordre avec lequel organiser les clés. En outre, les recherches d'index utilisant une clé de comparaison d'un type de données différent nécessitent que la comparaison se comporte sainement à travers deux types de données. Les extensions à trois types de données ou plus au sein d'une famille ne sont pas strictement requis par le mécanisme d'index btree lui-même, mais le planificateur se repose sur eux pour des besoins d'optimisation.