49.2. Fonctions de la méthode d'accès aux index
Les fonctions de construction et de maintenance d'index que doit
fournir une méthode d'accès aux index sont :
IndexBuildResult *
ambuild (Relation heapRelation,
Relation indexRelation,
IndexInfo *indexInfo);
Construit un nouvel index. La relation de l'index a été créée
physiquement mais elle est vide. Elle doit être remplie avec les
données fixes dont a besoin la méthode d'accès, ainsi que les entrées
pour toutes les lignes existant déjà dans la table. D'habitude, la
fonction ambuild appellera IndexBuildHeapScan() pour parcourir la table avec les
lignes qui existent déjà et pour calculer les clés qui doivent être
insérées dans l'index. La fonction doit renvoyer une structure
allouée par palloc contenant les statistiques sur le nouvel index.
bool
aminsert (Relation indexRelation,
Datum *values,
bool *isnull,
ItemPointer heap_tid,
Relation heapRelation,
bool check_uniqueness);
Insère une nouvelle ligne dans un index existant. Les tableaux
values et isnull
donnent les valeurs clés à indexer. heap_tid
est le TID à indexer. Si la méthode d'accès supporte les index
uniques (son drapeau pg_am.
amcanunique
vaut true), alors check_uniqueness pourrait aussi valoir true, auquel
cas la méthode d'accès doit vérifier qu'il n'y a pas de lignes en
conflit ; c'est la seule situation dans laquelle la méthode d'accès a
habituellement besoin du paramètre heapRelation. Voir Section 49.5,
« Vérification de l'unicité de l'index » pour les
détails. Le résultat vaut TRUE si une entrée de l'index a été
insérée, FALSE sinon (un résultat FALSE l'indique par forcément une
erreur mais est utilisé dans les cas comme un index AM refusant
d'indexer une valeur NULL).
IndexBulkDeleteResult *
ambulkdelete (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats,
IndexBulkDeleteCallback callback,
void *callback_state);
Supprime le(s) ligne(s) de l'index. C'est une opération de
« suppression en flot » qui a
pour but d'être implémentée par le parcours complet de l'index et par
la vérification de chaque entrée pour vérifier si elle doit être
supprimée. La fonction callback passée doit
être appelée, dans le style callback(
TID
, callback_state) renvoie bool,
pour déterminer si une entrée d'index particulière, identifiée par
son TID référencé, est à supprimer. Doit renvoyer soit NULL soit une
structure issue d'un palloc et contenant des statistiques sur les
effets de l'opération de suppression. Il est bien de renvoyer NULL
s'il n'est pas nécessaire de renvoyer des informations à amvacuumcleanup.
À cause d'un maintenance_work_mem limité,
ambulkdelete pourrait nécessiter d'être
appelé plus d'une fois lorsque plusieurs lignes sont supprimées.
L'argument stats est le résultat du dernier
appel pour cet index (il est NULL pour le premier appel à l'intérieur
d'une opération
VACUUM
). Ceci permet à l'AM
d'accumuler les statistiques sur une même opération. Typiquement,
ambulkdelete modifiera et renverra la même
structure si le stats fourni n'est pas NULL.
IndexBulkDeleteResult *
amvacuumcleanup (IndexVacuumInfo *info,
IndexBulkDeleteResult *stats);
Nettoie après une opération
VACUUM
(zéro ou plus d'appels à
ambulkdelete). Ceci n'a rien à voir avec
autre chose que le renvoi des statistiques des index, mais il peut
réaliser un nettoyage en masse, comme réclamer les pages d'index
vides. stats est ce que renvoie l'appel à
ambulkdelete, ou NULL si ambulkdelete n'a pas été appelé car aucune ligne
n'avait besoin d'être supprimée. Si le résultat n'est pas NULL, il
est une structure allouée avec palloc. Les statistiques qu'elle
contient seront utilisées pour mettre à jour pg_class, et seront rapportées par
VACUUM
si VERBOSE est indiqué. Il est bien de renvoyer NULL si
l'index n'a pas changé du tout lors de l'opération de
VACUUM
mais, sinon, des
statistiques correctes devront être renvoyées.
void
amcostestimate (PlannerInfo *root,
IndexOptInfo *index,
List *indexQuals,
RelOptInfo *outer_rel,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
double *indexCorrelation);
Estime les coûts d'un parcours d'index. Cette fonction est décrite
complètement dans Section 49.6,
« Fonctions d'estimation des coûts d'index »,
ci-dessous.
bytea *
amoptions (ArrayType *reloptions,
bool validate);
Analyse et valide le tableau reloptions pour un index. C'est appelé
seulement quand un tableau reloptions non NULL existe pour l'index.
reloptions
est un tableau de type
text contenant des entrées de la forme
nom
=
valeur
. La
fonction devrait construire une valeur de type bytea qui sera copiée dans le champ
rd_options
de l'entrée relcache de
l'index. Les données contenues dans la valeur bytea dépendent de la méthode d'accès mais les méthodes
d'accès standards utilisent actuellement tous la structure
StdRdOptions. Quand
validate
est true, la fonction devrait
rapporter un message d'erreur convenable si aucune des option n'est
pas reconnue ou a des valeurs invalides ; quand
validate
est false, les entrées invalides
devraient être ignorées silencieusement. (
validate
est faux lors du chargement des
options déjà stockées dans pg_catalog
; une entrée invalide pourrait seulement être trouvée si la méthode
d'accès a modifié ses règles pour les options et, dans ce cas,
ignorer les entrées obsolètes est approprié.) Il est aussi bon de
renvoyer NULL si le comportement par défaut est voulu.
Bien sûr, Le but d'un index est de supporter les parcours de lignes
correspondant à une condition WHERE
indexable, souvent appelée un qualifieur
ou une clé de parcours. La sémantique du
parcours d'index est décrite plus complètement dans Section 49.3, « Parcours
d'index », ci-dessous. Les fonctions relatives au parcours
qu'une méthode d'accès à l'index doit fournir sont :
IndexScanDesc
ambeginscan (Relation indexRelation,
int nkeys,
ScanKey key);
Débute un nouveau parcours. Le tableau key
(de longueur nkeys) décrit les clés de
parcours pour le parcours de l'index. Le résultat doit être une
structure issue de palloc. Pour les raisons de l'implémentation, la
méthode d'accès à l'index
doit
créer cette structure en appelant RelationGetIndexScan(). Dans la plupart des cas,
ambeginscan fait peu en dehors de cet appel
; les parties intéressantes de début du parcours d'index sont dans
amrescan.
boolean
amgettuple (IndexScanDesc scan,
ScanDirection direction);
Récupère la prochaine ligne dans le parcours donné, se déplaçant dans
bonne direction (en avant ou en arrière dans l'index). Renvoie TRUE
si une ligne a été obtenue, FALSE s'il ne reste aucune ligne
correspondante. Dans le cas TRUE, le TID de la ligne est stocké dans
la structure scan. Notez que
« success » signifie seulement
que l'index contient une entrée correspondant aux clés de parcours,
pas que la ligne existe toujours dans l'en-tête ou réussira le test
de l'appelant.
boolean
amgetmulti (IndexScanDesc scan,
ItemPointer tids,
int32 max_tids,
int32 *returned_tids);
Récupère plusieurs lignes dans le parcours donné. Renvoie TRUE si le
parcours devait continuer, FALSE si aucune ligne correspondante ne
reste. tids pointe vers un tableau de
max_tids fourni par l'appelant. ItemPointerData enregistre, ce que l'appel
remplit avec les TID des lignes correspondantes. *returned_tids est initialisé au nombre de TID
réellement renvoyé. Ceci peut être moins que max_tids, voire même zéro, même si la valeur de retour
vaut TRUE (ceci permet à la méthode d'accès de choisir les points
d'arrêt les plus efficaces dans son parcours, par exemple les limites
de la page d'index). amgetmulti et
amgettuple ne peuvent pas être utilisés
dans le même parcours d'index ; il y a aussi d'autres restrictions
lors de l'utilisation de amgetmulti, comme
expliqué dans Section 49.3, « Parcours
d'index ».
void
amrescan (IndexScanDesc scan,
ScanKey key);
Recommence le parcours donné, si possible avec de nouvelles clés de
parcours (pour continuer à utiliser les anciennes clés, NULL est
passé pour key). Notez qu'il n'est pas
possible de changer le nombre de clés. En pratique, la fonctionnalité
de relancement est utilisée quand une nouvelle ligne externe est
sélectionné par une jointure imbriquée en boucle et, du coup, la
valeur de la comparaison d'une nouvelle clé est nécessaire mais la
structure de la clé de parcours reste identique. Cette fonction est
aussi appelée par RelationGetIndexScan(),
donc c'est utilisé pour une configuration initiale d'un parcours
d'index ainsi que pour parcourir de nouveau.
void
amendscan (IndexScanDesc scan);
Termine un parcours et libère les ressources. La structure scan elle-même ne devrait pas être libérée, mais aucun
verrou pris en interne par la méthode d'accès doit être libéré.
void
ammarkpos (IndexScanDesc scan);
Marque la position courante du parcours. La méthode d'accès a
seulement besoin de supporter le rappel d'une position de parcours
par parcours.
void
amrestrpos (IndexScanDesc scan);
Restaure le parcours à sa plus récente position marquée.
Par convention, l'entrée pg_proc de toute
fonction de méthode d'accès aux index devrait afficher le bon nombre
d'arguments, mais les déclarer comme étant du type internal (car la plupart des arguments ont des types
qui ne sont pas connus en SQL, et nous ne voulons pas que les
utilisateurs appelent les fonctions directement). Le type renvoyé est
déclaré comme void, internal ou boolean suivant
le cas. La seule exception est amoptions,
qui devrait être correctement déclarée comme prenant text[] et bool et renvoyer
bytea. Cette provision autorise le code du
client à exécuter amoptions pour tester la
validité des paramètres.