PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 17.2 » Internes » Écrire un module de parcours personnalisé » Créer des parcours de chemin personnalisés

59.1. Créer des parcours de chemin personnalisés #

Un module de parcours personnalisé ajoutera classiquement des chemins pour une relation de base en mettant en place le hook suivant, qui est appelé après que le code de base ait généré tous les chemins d'accès possibles pour la relation (sauf les chemins Gather et Gather Merge, qui sont réalisés après cet appel pour qu'ils puissent utiliser les chemins partiels ajoutés par le hook :

typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
                                            RelOptInfo *rel,
                                            Index rti,
                                            RangeTblEntry *rte);
extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
   

Bien que cette fonction puisse être utilisée pour examiner, modifier ou supprimer des chemins générés par le système de base, un module de parcours personnalisé se limitera généralement lui-même à générer des objets CustomPath et à les ajouter à rel en utilisant la fonction add_path ou la fonction add_partial_path si ce sont des chemins partiels. Le module de parcours personnalisé a la charge d'initialiser l'objet CustomPath, qui est déclaré comme suit :

typedef struct CustomPath
{
    Path      path;
    uint32    flags;
    List     *custom_paths;
    List     *custom_restrictinfo;
    List     *custom_private;
    const CustomPathMethods *methods;
} CustomPath;
   

path doit être initialisé comme pour tous les autres chemins, y compris l'estimation du nombre de lignes, le coût de départ et le coût total, et l'ordre de tri fourni par ce chemin. flags est un masque de bits, qui indique si le fournisseur de parcours peut accepter certaines fonctionnalités optionnelles. flags devrait inclure CUSTOMPATH_SUPPORT_BACKWARD_SCAN si le chemin personnalisé supporte le parcours inverse et CUSTOM_SUPPORT_MARK_RESTORE si il peut supporter le marquage et la restauration, et CUSTOMPATH_SUPPORT_PROJECTION s'il peut réaliser projections. (Si CUSTOMPATH_SUPPORT_PROJECTION n'est pas configuré, le nœud de parcours se verra seulement demandé de produire le Vars de la relation parcourue ; alors que s'il est configuré, le nœud du parcours doit être caoavle d'évaluer les expressions scalaires sur ces Vars.) Une liste optionnelle custom_paths est une liste de nœuds Path utilisés par ce nœud de chemin personnalisé ; ils seront transformés en nœuds Plan par le planificateur. Comme décrit ci-dessous, les chemins personnalisés peuvent aussi être créés pour les relations de jointure. Dans un tel cas, custom_restrictinfo doit être utilisé pour enregistrer l'ensemble des clauses de jointure à appliquer à la jointure que le chemin personnalisé remplace. Sinon, il vaudra NUL. custom_private peut être utilisé pour stocker les données privées du chemin personnalisé. Les données privées devraient être stockées dans une forme qui puisse être traitée par nodeToString, de telle manière que les routines de debuggage qui essaient d'imprimer le chemin personnalisé fonctionnent comme prévu. methods doit pointer vers un objet (généralement alloué statiquement) implémentant les méthodes obligatoires d'un chemin personnalisé, qui sont détaillées plus bas.

Un module de parcours personnalisé peut également fournir des chemins de jointure. De la même manière que pour les relations de base, un tel chemin doit produire la même sortie qui serait normalement produite par la jointure qu'il remplace. Pour réaliser ceci, le module de jointure devrait mettre en place le hook suivant, puis, à l'intérieur de cette fonction, créer un ou des chemins CustomPath pour la relation de jointure.

typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
                                             RelOptInfo *joinrel,
                                             RelOptInfo *outerrel,
                                             RelOptInfo *innerrel,
                                             JoinType jointype,
                                             JoinPathExtraData *extra);
extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
   

Cette fonction sera appelée de manière répétée pour la même relation de jointure, avec différentes combinaisons de relations internes ou externes ; la fonction a la charge de minimiser la duplication des travaux.

Notez aussi que l'ensemble des clauses de jointure à appliquer à la jointure, passée en tant que extra->restrictlist, varie suivant la combinaison de relations interne et externe. Un chemin CustomPath généré pour joinrel doit contenir l'ensemble des clauses de jointure qu'il utiliser, qui sera utilisé par l'optimiseur pour convertir le chemin CustomPath en un plan, s'il est sélectionné par l'optimiseur comme meilleur plan pour joinrel.

59.1.1. Fonctions callbacks d'un parcours de chemin personnalisé #

Plan *(*PlanCustomPath) (PlannerInfo *root,
                         RelOptInfo *rel,
                         CustomPath *best_path,
                         List *tlist,
                         List *clauses,
                         List *custom_plans);
    

Convertit un chemin personnalisé en un plan finalisé. La valeur de retour sera généralement un objet CustomScan, que la fonction callback doit alloué et initialisé. Voir Section 59.2 pour plus de détails.

List *(*ReparameterizeCustomPathByChild) (PlannerInfo *root,
                                          List *custom_private,
                                          RelOptInfo *child_rel);

Cette fonction callback est appelée lors de la conversion d'un chemin avec paramètres par le parent le plus haut de la relation enfant indiquée par child_rel pour qu'elle soit paramétrée par la relation enfant. La fonction callback est utilisée pour reparamétrer tout chemin ou traduire tout nœud d'expression sauvegardé dans le membre custom_private donné d'un CustomPath. La fonction callback pourrait utiliser reparameterize_path_by_child, adjust_appendrel_attrs ou adjust_appendrel_attrs_multilevel comme requis.