56.2. Créer des parcours de plans personnalisés

Un parcours personnalisé est représenté dans un arbre de plans finalisé en utilisant la structure suivante :

typedef struct CustomScan
{
    Scan      scan;
    uint32    flags;
    List     *custom_plans;
    List     *custom_exprs;
    List     *custom_private;
    List     *custom_scan_tlist;
    Bitmapset *custom_relids;
    const CustomScanMethods *methods;
} CustomScan;

scan doit être initialisé comme pour tous les autres parcours, y compris le coût estimé, les listes cibles, les qualifications, et ainsi de suite. flags est un masque de bits avec la même signification que dans CustomPath. custom_plans peut être utilisé pour stocker des nœuds enfants de type Plan. custom_exprs devrait être utilisé pour stocker des arbres d'expressions qui devront être corrigés par setrefs.c et subselect.c, tandis que custom_private devrait être utilisé pour stocker d'autres données privées qui sont seulement utilisées par le module de parcours personnalisé lui-même. custom_scan_tlist peut être à NIL lors du parcours d'une relation de base, indiquant que le parcours personnalisé renvoie des lignes parcourues qui correspondent au type des lignes de la relation de base. Dans le cas contraire, il s'agit d'une liste de cibles décrivant les lignes actuellement parcourues. custom_scan_tlist devrait être fourni pour les jointures, et peut être fourni pour les parcours dont le module de parcours personnalisé peut calculer certaines expressions non variables. custom_relids est positionné par le code du serveur sur l'ensemble des relations (index de l'ensemble des tables) que ce nœud de parcours gère ; sauf lorsque ce parcours remplace une jointure, il aura alors un seul membre. methods doit pointer sur un objet (généralement alloué statiquement) implémentant les méthodes requises d'un parcours personnalisé, lesquelles sont détaillées ci-dessous.

Lorsqu'un CustomScan parcourt une simple relation, scan.scanrelid doit être l'index dans l'ensemble des tables de la table à parcourir. Lorsqu'il remplace une jointure, scan.scanrelid devrait être à zéro.

Les arbres de plan doivent pouvoir être dupliqués en utilisant la fonction copyObject, aussi les données stockées dans les champs « custom » doivent consister en des nœuds que cette fonction peut gérer. De plus, les modules de parcours personnalisés ne peuvent pas substituer une structure plus large qui incorporerait une structure de type CustomScan, comme il est possible pour les structures CustomPath ou CustomScanState.

56.2.1. Fonctions callbacks d'un plan de parcours personnalisé

Node *(*CreateCustomScanState) (CustomScan *cscan);

Alloue une structure CustomScanState pour ce CustomScan. L'allocation actuelle sera souvent plus grande que requis pour une structure ordinaire CustomScanState car beaucoup de modules voudront incorporer celui-ci comme le premier champ d'une structure plus large. La valeur renvoyée doit avoir la marque du nœud et le champ methods positionnés correctement, les autres champs devraient être laissés à zéro à ce stade ; après que la fonction ExecInitCustomScan ait effectué une initialisation basique, la fonction BeginCustomScan sera appelée pour permettre au module de parcours personnalisé d'effectuer ce qu'il a besoin de faire.

void (*TextOutCustomScan) (StringInfo str,
                           const CustomScan *node);

Génére une sortie additionnelle lorsque la fonction nodeToString est appelée sur ce nœud de plan personnalisé. Cette fonction callback est facultative. Dans la mesure où la fonction nodeToString enverra automatiquement sur la sortie l'ensemble des champs de la structure, y compris les sous-structures des champs « custom », il n'y a généralement pas besoin de cette fonction callback.