PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 12.21 » Internes » Index B-Tree » Fonctions de support B-Tree

63.3. Fonctions de support B-Tree

Comme montré dans Tableau 37.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.