TRUNCATEEXPLAINANALYZEIMPORT FOREIGN SCHEMA
   La fonction de gestion d'une FDW renvoie une structure
   FdwRoutine allouée avec palloc. Elle
   contient des pointeurs vers les fonctions de callback décrites
   ci-dessous. Les fonctions relatives aux parcours sont requises,
   le reste est optionnel.
  
   Le type de structure FdwRoutine est déclaré dans
   src/include/foreign/fdwapi.h, où vous trouverez plus de
   détails.
  
void
GetForeignRelSize (PlannerInfo *root,
                   RelOptInfo *baserel,
                   Oid foreigntableid);
    
    Obtient des estimations de la taille de la relation pour une table distante.
    Elle est appelée au début de la planification d'une requête parcourant une
    table distante. root est l'information globale du
    planificateur sur la requête ; baserel est
    l'information du planificateur sur la table ; et
    foreigntableid est l'OID provenant de
    pg_class pour cette table distante.
    (foreigntableid pourrait être obtenu à partir de la
    structure de données du planificateur mais il est directement fourni pour
    ne pas avoir à faire cet effort.)
   
    Cette fonction doit mettre à jour baserel->rows pour
    que cela corresponde au nombre de lignes renvoyées par un parcours de table
    après avoir pris en compte le filtre réalisé par les clauses de restriction.
    La valeur initiale de baserel->rows est une estimation
    par défaut, qui doit être remplacée si possible. La fonction pourrait aussi
    choisir de mettre à jour baserel->width si elle
    peut calculer une meilleure estimation de la largeur moyenne d'une ligne du
    résultat.
    (La valeur initiale est basée sur les types de données des colonnes et sur
    les valeurs de largeur moyenne des colonnes, mesurées par le dernier
    ANALYZE.) De plus, cette fonction pourrait mettre à
    jour baserel->tuples s'il peut calculer une
    meilleure estimation du nombre total de lignes de ma table distante.
    (La valeur initiale provient de
    pg_class.reltuples
    qui représente le nombre total de lignes vues par le dernier
    ANALYZE ; ça sera -1 si
    aucun ANALYZE n'a été exécuté sur la table distante.)
   
Voir Section 57.4 pour plus d'informations.
void
GetForeignPaths (PlannerInfo *root,
                 RelOptInfo *baserel,
                 Oid foreigntableid);
    
    Crée les chemins d'accès possibles pour un parcours sur une table distante.
    Cette fonction est appelée lors de la planification de la requête. Les
    paramètres sont identiques à ceux de GetForeignRelSize,
    qui a déjà été appelée.
   
    Cette fonction doit générer au moins un chemin d'accès (nœud
    ForeignPath) pour un parcours sur une table
    distante et doit appeler add_path pour ajouter chaque
    chemin à baserel->pathlist. Il est recommandé
    d'utiliser create_foreignscan_path pour construire les
    nœuds ForeignPath. La fonction peut générer plusieurs
    chemins d'accès, c'est-à-dire un chemin qui a un champ
    pathkeys valide pour représenter un résultat pré-trié.
    Chaque chemin d'accès doit contenir les estimations de coûts et peut contenir
    toute information privée au FDW qui est nécessaire pour identifier la méthode
    attendue du parcours spécifique.
   
Voir Section 57.4 pour plus d'informations.
ForeignScan *
GetForeignPlan (PlannerInfo *root,
                RelOptInfo *baserel,
                Oid foreigntableid,
                ForeignPath *best_path,
                List *tlist,
                List *scan_clauses,
                Plan *outer_plan);
    
    Crée un nœud de plan ForeignScan à partir du chemin
    d'accès distant sélectionné. Cette fonction est appelé à la fin de la
    planification de la requête.
    Les paramètres sont identiques à ceux de la fonction
    GetForeignRelSize, avec en plus le
    ForeignPath sélectionné (précédemment produit par
    GetForeignPaths, GetForeignJoinPaths
    ou GetForeignUpperPaths), la liste cible à émettre par le
    nœud du plan, les clauses de restriction forcées par le nœud du plan,
    et le sous-plan externe de ForeignScan, utilisé
    pour les vérifications réalisées par RecheckForeignScan.
    (Si le chemin est pour une jointure plutôt qu'une relation de base,
    foreigntableid est InvalidOid.)
   
    Cette fonction doit créer et renvoyer un nœud ForeignScan.
    Il est recommandé d'utiliser make_foreignscan pour
    construire le nœud ForeignScan.
   
Voir Section 57.4 pour plus d'informations.
Si un FDW supporte l'exécution distante de jointure après parcours, comme une agrégation distante, il doit fournir cette fonction callback :
void
GetForeignUpperPaths(PlannerInfo *root,
                     UpperRelationKind stage,
                     RelOptInfo *input_rel,
                     RelOptInfo *output_rel,
                     void *extra);
    
    Crée les chemins d'accès possibles pour le traitement relation
     de niveau supérieur, qui est le terme de l'optimiseur pour tout
    traitement après parcours/jointure, comme les agrégats, les fonctions de
    fenêtrage, le tri et les mises à jour de table. Cette fonction optionnelle
    est appelée lors de l'optimisation de la requête. Actuellement, elle est
    seulement appelée si toutes les relations de base impliquées appartiennent
    au même FDW. Cette fonction doit générer des chemins
    ForeignPath pour tout traitement
    post-parcours/jointure que le FDW sait réaliser à distance
    (utilisez create_foreign_upper_path pour les construire),
    et appeler
    add_path pour ajouter ces chemins à la relation
    indiquée du niveau supérieur. Tout comme
    GetForeignJoinPaths, il n'est pas nécessaire que
    cette fonction réussisse à créer des chemins, étant donnée qu'il est
    toujours possible d'utiliser des chemins de traitement local.
   
    Le paramètre stage identifie l'étape post-
    parcours/jointure est en cours de considération.
    output_rel est la relation supérieure devant recevoir
    les chemins représentation le traitement de cette étape, et
    input_rel est la relation représentant la source de
    cette étape. Le paramètre extra fournit des détails
    supplémentaires. Pour le moment, il est uniquement positionné pour
    UPPERREL_PARTIAL_GROUP_AGG ou
    UPPERREL_GROUP_AGG, auquel cas il pointe vers une
    structure GroupPathExtraData ;
    ou pour UPPERREL_FINAL, auquel cas il pointe
    vers une structure FinalPathExtraData.
    (Notez que les chemins ForeignPath
    ajoutés à output_rel n'auront typiquement pas de
    dépendances directes avec les chemins de input_rel car
    leur traitement se fait en externe. Néanmoins, examiner les chemins
    précédemment générés pour l'étape de traitement précédente peut se
    révéler utile pour éviter un travail redondant de planification.)
   
Voir Section 57.4 pour plus d'informations.
void
BeginForeignScan (ForeignScanState *node,
                  int eflags);
    
    Commence l'exécution d'un parcours distant. L'appel se fait lors du
    démarrage de l'exécuteur. Cette fonction doit réaliser toutes les
    initialisation nécessaires avant le démarrage du parcours, mais ne
    doit pas commencer à exécuter le vrai parcours (cela se fera lors
    du premier appel à IterateForeignScan). Le
    nœud ForeignScanState est déjà créé
    mais son champ fdw_state vaut toujours
    NULL. Les informations sur la table à parcourir sont accessibles
    via le nœud ForeignScanState (en
    particulier à partir du nœud sous-jacent
    ForeignScan qui contient toute information
    privée au FDW fournie par GetForeignPlan).
    eflags contient les bits de drapeaux décrivant le
    mode opératoire de l'exécuteur pour ce nœud du plan.
   
    Notez que quand (eflags & EXEC_FLAG_EXPLAIN_ONLY)
    est vraie, cette fonction ne doit pas réaliser d'actions visibles
    en externe. Elle doit seulement faire le minimum requis pour que
    l'état du nœud soit valide pour
    ExplainForeignScan et
    EndForeignScan.
   
TupleTableSlot *
IterateForeignScan (ForeignScanState *node);
    
    Récupère une ligne de la source distante, la renvoyant dans un
    emplacement de ligne de table (le champ
    ScanTupleSlot du nœud doit être
    utilisé dans ce but). Renvoie NULL s'il n'y a plus de lignes
    disponibles. L'infrastructure d'emplacement de ligne de table permet
    qu'une ligne physique ou virtuelle soit renvoyée. Dans la plupart
    des cas, la deuxième possibilité (virtuelle), est préférable d'un
    point de vue des performances. Notez que cette fonction est appelée
    dans un contexte mémoire dont la durée de vie est très courte et
    qui sera réinitialisé entre chaque appel. Créez un contexte mémoire
    dans BeginForeignScan si vous avez besoin d'un
    stockage qui tient plus longtemps ou utilisez le champ
    es_query_cxt de EState.
   
    Les lignes renvoyées doivent correspondre à la liste cible
    fdw_scan_tlist si elle a été fournie,
    sinon elles doivent correspondre au type de ligne de la table distante
    parcourue. Si vous choisissez d'optimiser en récupérant d'avance des
    colonnes non nécessaires, vous devriez insérer des valeurs NULL
    dans les positions de ces colonnes, ou sinon générer une liste
    fdw_scan_tlist avec ces colonnes omises.
   
Notez que l'exécuteur de PostgreSQL ne se préoccupe pas de savoir si les lignes renvoyées violent les contraintes définies sur la table distante -- mais le planificateur s'en préoccupe, et peut optimiser les requêtes incorrectement si il y a des lignes visibles dans la table distante qui ne satisfont pas une contrainte déclarée. Si une contrainte est violée lorsque l'utilisateur a déclaré que la contrainte devrait être vrai, il peut être approprié de lever une erreur (de la même manière que vous devriez le faire dans le cas où les types de données ne correspondent pas).
void
ReScanForeignScan (ForeignScanState *node);
    Recommence le parcours depuis le début. Notez que les paramètres dont dépent le parcours peuvent avoir changés de valeur, donc le nouveau parcours ne va pas forcément renvoyer les mêmes lignes.
void
EndForeignScan (ForeignScanState *node);
    Termine le parcours et relâche les ressources. Il n'est habituellement pas nécessaire de relâcher la mémoire allouée via palloc. Par contre, les fichiers ouverts et les connexions aux serveurs distants doivent être nettoyés.
Si un FDW permet d'effectuer des jointures distantes (autrement qu'en récupérant les données des deux tables et en faisant la jointure localement), il devrait fournir cette fonction callback :
void
GetForeignJoinPaths (PlannerInfo *root,
                     RelOptInfo *joinrel,
                     RelOptInfo *outerrel,
                     RelOptInfo *innerrel,
                     JoinType jointype,
                     JoinPathExtraData *extra);
    
    Crée les chemins possibles d'accès pour une jointure de
    deux (ou plus) tables distantes qui toutes proviennent du
    même serveur distant. Cette fonction optionnelle est appelée
    durant la planification de la requête. De la même façon que
    GetForeignPaths, cette fonction devrait
    générer des chemins ForeignPath pour
    le paramètre joinrel fourni
    (utilisez create_foreign_join_path pour les construire),
    et appeler la
    fonction add_path pour ajouter ces chemins
    à l'ensemble des chemins à considérer pour la jointure. Mais
    contrairement à GetForeignPaths, il n'est
    pas nécessaire que cette fonction réussisse à créer au moins
    un chemin, dans la mesure où des chemins entraînant des jointures
    locales sont toujours possibles.
   
Notez que cette fonction sera invoquée de manière répétitive pour la même jointure, avec des combinaisons différentes de relations internes ou externes ; il est de la responsabilité du FDW de minimiser les tâches dupliquées.
    Si un chemin ForeignPath est choisi
    pour la jointure, il représentera l'ensemble du processus
    de jointure ; les chemins générés pour les tables qui
    la composent et les jointures auxiliaires ne seront pas
    utilisés. Les traitements suivants des chemins de jointure
    procèdent essentiellement de la même manière que pour un chemin
    parcourant une simple table distante. Une différence est que le
    scanrelid résultant du nœud du plan
    ForeignScan devrait être mis à zéro,
    dans la mesure où il ne représente aucune relation simple ; à
    la place, le champ fd_relids du nœud
    ForeignScan représente l'ensemble des
    relations qui ont été jointes. (Le dernier champ est positionné
    automatiquement par le code interne du planificateur, et n'a pas
    besoin d'être rempli par le FDW.) Une autre différence est que,
    comme la liste des colonnes pour une jointure distante ne peut
    être trouvée dans les catalogues systèmes, le FDW doit remplir
    fdw_scan_tlist avec une liste appropriée
    de nœuds TargetEntry, représentant
    l'ensemble des colonnes qu'il fournira à l'exécution dans les
    lignes qu'il retournera.
   
Voir Section 57.4 pour des informations supplémentaires.
Si un FDW supporte la modification des tables distantes, il doit fournir certaines ou toutes les fonctions callback suivant les besoins et les capacités du FDW :
void
AddForeignUpdateTargets (PlannerInfo *root,
                         Index rtindex,
                         RangeTblEntry *target_rte,
                         Relation target_relation);
    
    Les opérations UPDATE et DELETE sont
    réalisées contre des lignes précédemment récupérées par des fonctions de
    parcours de table. Le FDW peut avoir besoin d'informations supplémentaires,
    comme l'identifiant de la ligne ou les valeurs des colonnes formant la clé
    primaire pour s'assurer qu'il peut identifier la ligne exacte à mettre à
    jour ou à supprimer. Pour supporter cela, cette fonction peut ajouter des
    colonnes cibles supplémentaires cachées à la liste des colonnes qui doivent
    être récupérées de la table distante pendant une opération
    UPDATE ou DELETE.
   
    Pour faire cela, construisez une Var représentant
    une valeur supplémentaire dont vous avez besoin, et passez la à
    add_row_identity_var, avec un nom pour la colonne
    cachée. (Vous pouvez effectuer cela plusieurs fois, si plusieurs colonnes
    sont nécessaires.) Vous devez choisir une colonne cachée distincte pour
    chaque Var différente dont vous avez besoin, à
    l'exception des Var identiques, sauf pour le
    champ varno, qui peuvent, et doivent partager
    un même nom de colonne. Le cœur du système utilise les colonnes cachées
    nommées tableoid pour une colonne
    tableoid de table, ctid ou
    ctid pour
    Nctid, wholerow pour une
    Var de ligne entière marquée avec
    vartype = RECORD, et
    wholerow pour une
    NVar de ligne entière avec
    vartype égal au type de ligne déclaré de la
    table. Ré-utiliser ces noms quand vous le pouvez (le planificateur
    combinera les demandes dupliquées pour les colonnes cachées identiques).
    Si vous avez besoin d'autres type de colonnes cachées en dehors de
    celles-ci, il est préférable de choisir un nom préfixé avec le nom de
    votre extension pour éviter des conflits avec d'autres FDW.
   
    Si le pointeur AddForeignUpdateTargets est initialisé
    à NULL, aucune expression cible supplémentaire ne sera
    ajoutée.
    (Ceci rend impossible l'implémentation des opérations
    DELETE bien que l'UPDATE est toujours
    faisable si le FDW se base sur une clé primaire ne changeant pas pour
    identifier les lignes.)
   
List *
PlanForeignModify (PlannerInfo *root,
                   ModifyTable *plan,
                   Index resultRelation,
                   int subplan_index);
    
    Réalise toute opération supplémentaire de planification nécessaire pour
    une insertion, mise à jour ou suppression sur une table distante. Cette
    fonction génère l'information privée du FDW qui sera attachée au nœud
    du plan ModifyTable qui réalise la mise à jour.
    Cette information privée doit avoir la forme d'une
    List, et sera réalisée par
    BeginForeignModify lors de l'exécution.
   
    root est l'information globale du planificateur sur la
    requête.
    plan est le nœud du plan
    ModifyTable qui est complet sauf pour le champ
    fdwPrivLists.
    resultRelation identifie la table distante cible par son
    index rangetable. subplan_index identifie la cible
    du nœud de plan ModifyTable en comptant à
    partir de zéro ; utilisez ceci si vous voulez indexer dans
    les sous-structures « per-target-relation »
    des nœuds du plan.
   
Voir Section 57.4 pour plus d'informations.
    Si le pointeur PlanForeignModify est initialisé à
    NULL, aucune action supplémentaire n'est réalisée au
    moment de la planification, et la liste fdw_private
    renvoyée par BeginForeignModify vaudra NIL.
   
void
BeginForeignModify (ModifyTableState *mtstate,
                    ResultRelInfo *rinfo,
                    List *fdw_private,
                    int subplan_index,
                    int eflags);
    
    Commence l'exécution d'une opération de modification de la table distante.
    Cette routine est appelée lors du démarrage de l'exécuteur. Elle doit
    réaliser toute initialisation nécessaire avant de procéder aux
    modifications de la table. En conséquence,
    ExecForeignInsert/ExecForeignBatchInsert,
    ExecForeignUpdate ou
    ExecForeignDelete seront appelées pour chaque ligne
    à insérer, mettre à jour ou supprimer.
   
    mtstate est l'état général du nœud de plan
    ModifyTable en cours d'exécution ; les
    données globales sur le plan et l'état d'exécution sont disponibles via
    cette structure.
    rinfo est la structure
    ResultRelInfo décrivant la table distante cible.
    (Le champ ri_FdwState de
    ResultRelInfo est disponible pour que le FDW
    enregistre tout état privé dont il aurait besoin pour réaliser cette
    opération.)
    fdw_private contient les données privées générées par
    PlanForeignModify.
    subplan_index identifie la cible du nœud de
    plan ModifyTable.
    eflags contient les bits de drapeaux décrivant le mode
    opératoire de l'exécuteur pour ce nœud de plan.
   
    Notez que quand (eflags & EXEC_FLAG_EXPLAIN_ONLY)
    est vrai, cette fonction ne devrait réaliser aucune action visible
    externe ; il devrait seulement faire le minimum requis pour rendre
    l'état du nœud valide pour
    ExplainForeignModify et
    EndForeignModify.
   
    Si le pointeur BeginForeignModify est initialisé à
    NULL, aucune action n'est prise lors du démarrage
    de l'exécuteur.
   
    Notez que cette fonction est aussi appelée lors de l'insertion de lignes
    déplacées dans une partition de type table distante ou lors de
    l'exécution de COPY FROM sur une table distante,
    auquel cas elle est appelée d'une façon différente que dans le cas d'un
    INSERT. Voir les fonctions callback décrites
    ci-dessous permettant au FDW de le supporter. described below that allow
    the FDW to support that.
   
TupleTableSlot *
ExecForeignInsert (EState *estate,
                   ResultRelInfo *rinfo,
                   TupleTableSlot *slot,
                   TupleTableSlot *planSlot);
    
    Insère une ligne dans la table distante.
    estate est un état global de l'exécution de la requête.
    rinfo est la structure ResultRelInfo
    décrivant la table distante cible.
    slot contient la ligne à insérer ; ça correspondra
    à la définition du type de la ligne de la table distante.
    planSlot contient la ligne qui a été générée par le
    sous-plan du nœud ModifyTable ; cela
    diffère du slot qui contient aussi les colonnes
    supplémentaires.
    (Le planSlot a typiquement peu d'intérêt pour
    INSERT mais est fourni pour être complet.)
   
    La valeur de retour est soit un emplacement contenant les données
    effectivement insérées (elles peuvent différer des données fournies, par
    exemple suite à l'action de triggers), soit NULL si aucune ligne
    n'a été insérée (là aussi typiquement le résultat d'un trigger). Le
    slot peut être ré-utilisé dans ce contexte.
   
    Les données du slot retourné ne sont utilisées que si la commande
    INSERT a une clause RETURNING
    ou implique une vue WITH CHECK OPTION ;
    ou si la table étrangère a un trigger AFTER ROW.
    Les triggers ont besoin de toutes les colonnes,
    mais le FDW peut choisir d'optimiser en ne retournant que certaines colonnes,
    voire aucune, selon la clause RETURNING
    ou les contraintes WITH CHECK OPTION.
    Cependant, un slot doit être retourné pour indiquer un succès, sinon le
    nombre de lignes retournées rapporté par la requête sera faux.
   
    Si le pointeur ExecForeignInsert est initialisé à
    NULL, les tentatives d'insertion dans la table distante
    échoueront avec un message d'erreur.
   
    Notez que cette fonction est aussi appelée à l'insertion de lignes
    reroutées vers une partition qui est une table étrangère, ou à l'exécution
    de COPY FROM sur une table étrangère, auxquels cas
    elle sera appelée d'une manière différente du cas d'un
    INSERT. Voir les fonctions callback décrites plus bas
    qui permettent au FDW de supporter cela.
   
TupleTableSlot **
ExecForeignBatchInsert(EState *estate,
                       ResultRelInfo *rinfo,
                       TupleTableSlot **slots,
                       TupleTableSlot **planSlots,
                       int *numSlots);
     Insère plusieurs lignes en bloc dans la table distante. Les paramètres
     sont les même que pour ExecForeignInsert mis à part
     que slots et planSlots contiennent
     de plusieurs lignes et *numSlots spécifie le nombre
     de lignes dans ces tableaux.
    
     La valeur de retour est un tableau d'emplacements
     (« slots ») contenant les données qui sont réellement
     insérées (et peut différer des données fournies, par exemple avec le
     résultat d'actions de trigger.) Les emplacements en entrée peuvent être
     réutilisés à ce propos. Le nombre de lignes insérées avec succès est
     retourné dans *numSlots.
    
     Les données dans l'emplacement retour sont utilisés uniquement si
     l'expression INSERT implique une vue WITH
     CHECK OPTION ou si une table distance a un trigger
     AFTER ROW. Les triggers nécessitent toutes les
     colonnes, mais le FDW peut choisir, par optimisation distante, de
     retourner toutes ou quelques unes des colonnes, en fonction du contenu
     des contraintes WITH CHECK OPTION.
    
     Si les pointeurs ExecForeignBatchInsert ou
     GetForeignModifyBatchSize sont mis à
     NULL, les tentatives d'insérer dans la table distante
     utiliseront ExecForeignInsert. Cette fonction n'est
     pas utilisée si l'expression INSERT dispose de la
     clause RETURNING.
    
Notez que cette fonction est aussi appelée lors de l'insertion de lignes dirigées dans une partition de table distante. Voir les fonctions callback décrites ci-dessous qui permettent au FDW de supporter cela.
int GetForeignModifyBatchSize(ResultRelInfo *rinfo);
     Affiche le nombre maximum de lignes qu'un simple appel à
     ExecForeignBatchInsert peut gérer pour la table
     distante spécifiée. L'exécuteur passe au plus le nombre donnée de lignes
     à ExecForeignBatchInsert. rinfo
     est la structure ResultRelInfo décrivant la
     cible de la table distante. Le FDW doit fournir le serveur distant et/ou
     l'option de table distante pour que l'utilisateur affecte cette valeur
     ou une valeur codée en dur.
    
     Si le pointeur de ExecForeignBatchInsert ou
     GetForeignModifyBatchSize est mis à
     NULL, les tentatives d'insertion dans la table
     distante utiliseront ExecForeignInsert.
    
TupleTableSlot *
ExecForeignUpdate (EState *estate,
                   ResultRelInfo *rinfo,
                   TupleTableSlot *slot,
                   TupleTableSlot *planSlot);
    
    Met à jour une ligne dans la table distante. estate est
    l'état global de l'exécution de la requête. rinfo est
    la structure ResultRelInfo décrivant la table
    distante cible. slot contient les nouvelles données de
    la ligne ; elles correspondront à la définition du type de ligne
    pour la table distante. planSlot contient la ligne qui
    a été générée par le sous-plan du nœud
    ModifyTable. Contrairement au
    slot, cette ligne contient seulement les nouvelles
    valeurs pour les colonnes modifiées dans la requête. De ce fait, ne vous
    appuyez pas sur les nombres d'attributs de la table distante à indexer
    dans planSlot. De plus, planSlot
    contient typiquement des colonnes « inutiles »
    (junk) supplémentaires. En particulier,
    toutes les colonnes inutiles demandées par
    AddForeignUpdateTargets seront disponibles pour ce
    slot.
   
    La valeur de retour est soit un emplacement contenant la nouvelle ligne
    modifiée (elle peut différer des données fournies suite, par exemple, à
    l'exécution d'un trigger), ou NULL si aucune ligne n'a été réellement
    mise à jour (là-encore typiquement l'action d'un trigger).
    L'emplacement slot fourni peut être réutilisé dans
    ce contexte.
   
    Les données du slot retourné ne sont utilisées que si la commande
    >UPDATE a une clause RETURNING
    ou implique une vue WITH CHECK OPTION ;
    ou si la table étrangère a un trigger AFTER ROW.
    Les triggers ont besoin de toutes les colonnes,
    mais le FDW peut choisir d'optimiser en ne retournant que certaines colonnes,
    voire aucune, selon la clause RETURNING
    ou les contraintes WITH CHECK OPTION.
    Cependant, un slot doit être retourné pour indiquer un succès, sinon le
    nombre de lignes retournées rapporté par la requête sera faux.
   
    Si le pointeur ExecForeignUpdate est initialisé à
    NULL, les tentatives de mise à jour de la table
    distante échoueront avec un message d'erreur.
   
TupleTableSlot *
ExecForeignDelete (EState *estate,
                   ResultRelInfo *rinfo,
                   TupleTableSlot *slot,
                   TupleTableSlot *planSlot);
    
    Supprime une ligne de la table distante.
    estate est l'état global de l'exécution de la requête.
    rinfo est la structure ResultRelInfo
    décrivant la table distante cible.
    slot ne contient rien d'utile à l'appel de la fonction
    mais peut être utilisé pour contenir la ligne renvoyée.
    planSlot contient la ligne générée par le sous-plan du
    nœud du plan ModifyTable ; en particulier,
    elle contient toute colonne supplémentaire réclamée par
    AddForeignUpdateTargets. Les colonnes supplémentaires
    doivent être utilisées pour identifier la ligne à supprimer.
   
    La valeur de retour est soit un slot contenant la ligne supprimée soit
    NULL si aucune ligne n'a été supprimée (par exemple suite a déclenchement
    d'un trigger). Le slot fourni en référence peut être
    utilisé pour contenir la ligne à renvoyer.
   
    Les données placées dans l'emplacement sont utilisées seulement si la
    requête DELETE dispose de la clause
    RETURNING ou si la table externe a un trigger
    AFTER ROW. Les triggers nécessitent toutes les colonnes
    mais le FDW pourrait choisir d'optimiser en ne renvoyant que certaines
    colonnes ou toutes suivant le contenu de la clause
    RETURNING. Néanmoins, un slot doit être renvoyé pour
    indiquer le succès. Dans le cas contraire, le nombre de lignes rapporté
    par la requête sera faux.
   
    Si le pointeur ExecForeignDelete est initialisé à
    NULL, les tentatives de suppression dans la table
    distante échoueront avec un message d'erreur.
   
void
EndForeignModify (EState *estate,
                  ResultRelInfo *rinfo);
    Termine la mise à jour et libère les ressources. Il n'est normalement pas importante de libérer la mémoire prise avec palloc mais, par exemple, les fichiers ouverts et les connexions vers des serveurs distants doivent être nettoyés.
    Si le pointeur vers EndForeignModify est initialisé
    à NULL, aucune action n'a lieu pendant l'arrêt de
    l'exécuteur.
   
    Les lignes insérées dans une table partitionnée à l'aide
    d'INSERT ou COPY FROM sont redirigées
    vers les partitions. Si un FDW supporte la redirection des lignes pour
    les partitions déclarées comme table distantes, il devra également
    fournir les fonctions de callback suivantes. Ces fonctions sont également
    appelées quand COPY FROM est exécuté sur une table
    distante.
   
void
BeginForeignInsert(ModifyTableState *mtstate,
                   ResultRelInfo *rinfo);
    
    Débute l'exécution d'une opération d'insertion sur une table distante.
    Cette routine est appelée juste avant que la première ligne soit insérée
    dans la table distante quand il s'agit de la partition choisie par la
    redirection de ligne ou quand il s'agit de la cible spécifiée dans une
    commande COPY FROM.  Elle devrait effectuer toute
    initialisation nécessaire avant l'insertion elle-même.  Ensuite,
    ExecForeignInsert ou
    ExecForeignBatchInsert seront appelées pour chaque
    ligne devant être insérée dans la table distante.
   
    mtstate est l'état général du nœud de plan
    ModifyTable en cours d'exécution ;; les données
    globales sur le plan et l'état d'exécution sont disponibles via cette
    structure.
    rinfo est la structure
    ResultRelInfo décrivant la table distante cible.
    (Le champ ri_FdwState de
    ResultRelInfo est disponible pour que le FDW
    enregistre tout état privé dont il aurait besoin pour réaliser cette
    opération.)
   
    Quand elle est appelée par une commande COPY FROM, les
    données globales liées au plan contenues dans mtstate
    ne sont pas fournies et le paramètre planSlot de
    ExecForeignInsert/ExecForeignBatchInsert appelée par
    la suite pour chaque
    ligne insérée vaut NULL, que la table distante soit la
    partition choisie par la redirection de ligne ou que cela soit la cible
    spécifiée dans la commande.
   
    Si le pointeur BeginForeignInsert est initialisé à
    NULL, aucune action n'est faite pour l'initialisation.
   
    Notez que si le FDW ne supporte pas les tables étrangères comme partitions
    routables et/ou l'exécution de COPY FROM sur des
    tables étrangères, cette fonction, ou
    ExecForeignInsert appelée après, doivent renvoyer
    une erreur si nécessaire.
   
void
EndForeignInsert(EState *estate,
                 ResultRelInfo *rinfo);
    Termine l'opération d'insertion et libère les ressources. Il n'est habituellement pas nécessaire de libérer la mémoire allouée via palloc. Par contre, les fichiers ouverts et les connexions aux serveurs distants doivent être libérés par exemple.
    Si le pointeur EndForeignInsert est initialisé à
    NULL, aucune action n'est faite pour la fin de
    l'opération d'insertion.
   
int
IsForeignRelUpdatable (Relation rel);
    
    Indique les opérations de mise à jour supportées par la table distante
    indiquée. La valeur de retour doit être un masque de bits correspondant
    aux numéros d'événement des règles, indiquant les opérations supportées
    par la table disante, en utilisant l'énumération CmdType.
    Autrement dit
    (1 << CMD_UPDATE) = 4 pour UPDATE,
    (1 << CMD_INSERT) = 8 pour INSERT et
    (1 << CMD_DELETE) = 16 pour DELETE.
   
    Si le pointeur IsForeignRelUpdatable est configuré à
    NULL, les tables distantes sont supposées accepter les
    INSERT, UPDATE et DELETE si le connecteur FDW fournit respectivement les
    fonctions ExecForeignInsert,
    ExecForeignUpdate et
    ExecForeignDelete. Cette fonction est uniquement
    nécessaire si le FDW supporte quelques tables modifiables et d'autres qui
    ne le sont pas. (Et même là, il est possible de renvoyer une erreur dans la
    routine d'exécution au lieu de vérifier avec cette fonction. Néanmoins, cette
    fonction est utilisé pour déterminer l'état modifiable des tables qui sera
    affiché dans les vues information_schema.)
   
    Certaines insertions, mises à jour et suppressions vers des tables
    distantes peuvent être optimisées en implémentant un ensemble alternatif
    d'interfaces. Les interfaces habituelles pour les insertions, mises à
    jour et suppressions récupèrent les lignes du serveur distant, puis
    modifient les lignes, une par une. Dans certains cas, cette approche
    ligne par ligne est nécessaire mais elle peut s'avérer inefficace. S'il
    est possible pour le serveur distant de déterminer les lignes à modifier
    sans avoir à les récupérer, et qu'il n'y a pas de structures locales qui
    pourraient affecter l'opération (triggers locaux au niveau ligne,
    colonnes calculées automatiquement ou contraintes WITH CHECK OPTION
    provenant des vues parents), alors il est possible de s'arranger pour
    que l'opération entière soit réalisée sur le serveur distant. Les
    interfaces décrites ci-dessous rendent cela possible.
   
bool
PlanDirectModify (PlannerInfo *root,
                  ModifyTable *plan,
                  Index resultRelation,
                  int subplan_index);
    
    Décide si l'exécution d'une modification directement sur le serveur
    distant est sûre. Dans ce cas, renvoie true après
    avoir réalisé les actions d'optimisation nécessaire pour cela. Dans le
    cas contraire, renvoie false. Cette fonction
    optionnelle est appelée lors de la planification de la requête. Si cette
    fonction réussit, BeginDirectModify,
    IterateDirectModify et
    EndDirectModify seront appelées à l'étape
    d'exécution. Dans le cas contraire, la modification de la table sera
    exécutée en utilisant les fonctions de modification de la table décrites
    ci-dessus. Les paramètres sont les mêmes que pour
    PlanForeignModify.
   
    Pour exécuter la modification directe sur le serveur distant, cette
    fonction doit ré-écrire le sous-plan cible avec un nœud de plan
    ForeignScan qui exécute la modification directe
    sur le serveur distant. Les champs operation
    et resultRelation du
    ForeignScan doivent être configurés de façon
    approprié. operation doit être affecté à la
    valeur de l'énumération CmdType correspondante au type
    d'expression (et qui est CMD_UPDATE pour
    UPDATE, CMD_INSERT pour
    INSERT et CMD_DELETE pour
    DELETE), et l'argument
    resultRelation doit être copié dans le champ
    resultRelation.
   
Voir Section 57.4 pour plus d'informations.
    Si le pointeur PlanDirectModify est configuré à
    NULL, aucune tentative ne sera réalisée pour exécuter
    une modification directe sur le serveur distant.
   
void
BeginDirectModify (ForeignScanState *node,
                   int eflags);
    
    Prépare une exécution d'une modification directe sur le serveur distant.
    Cette fonction est appelée lors du démarrage de l'exécuteur. Elle doit
    réaliser toute initialisation nécessaire avant la modification directe,
    qui doit être réalisée lors du premier appel à
    IterateDirectModify). Le nœud
    ForeignScanState a déjà été créée mais son champ
    fdw_state vaut toujours NULL. Des informations
    sur la table à modifier sont disponibles au travers du nœud
    ForeignScanState (en particulier, à partir du
    nœud ForeignScan sous-jacent, qui contient des
    informations privées au FDW fournies par
    PlanDirectModify). eflags
    contient des bits d'informations décrivant le mode d'opération de
    l'exécuteur pour ce nœud de plan.
   
    Notez que quand (eflags & EXEC_FLAG_EXPLAIN_ONLY)
    est vrai, cette fonction ne doit pas réaliser d'actions visibles
    extérieurement ; elle doit seulement faire le minimum requis pour
    rendre valide l'état du nœud pour
    ExplainDirectModify et
    EndDirectModify.
   
    Si le pointeur BeginDirectModify est configuré à
    NULL, aucune tentative ne sera réalisée pour exécuter
    une modification directe sur le serveur distant.
   
TupleTableSlot *
IterateDirectModify (ForeignScanState *node);
    
    Quand la requête INSERT, UPDATE ou
    DELETE ne contient pas de clause
    RETURNING, renvoie simplement NULL après une
    modification directe sur le serveur distant. Quand la requête contient
    cette clause, récupère un résultat contenant la donnée nécessaire pour le
    traitement du RETURNING, le renvoyant dans un slot de
    ligne de table (le champ ScanTupleSlot du nœud
    doit être utilisé pour cela). Les données insérées, mises à jour ou
    supprimées doivent être enregistrées dans le champ
    node->resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple. Renvoie NULL s'il n'y a plus
    de lignes disponibles. Notez que cette fonction est appelée dans un
    contexte mémoire à court terme qui sera réinitialisée à chaque appel.
    Créez un contexte mémoire dans BeginDirectModify si
    vous avez besoin d'un stockage d'une durée de vie plus importante ou
    utilisez es_query_cxt du champ
    EState du nœud.
   
    Les lignes renvoyées doivent correspondre à la liste cible
    fdw_scan_tlist si une liste a été fournie.
    Sinon, elles doivent correspondre au type de ligne de la table externe en
    cours de modification. Si vous choisissez d'optimiser la récupération des
    colonnes inutiles pour le traitement de RETURNING,
    vous devez placer des valeurs NULL à la position de ces colonnes ou
    générer une liste fdw_scan_tlist en omettant
    les colonnes inutiles.
   
    Que la requête ait la clause ou non, le nombre de lignes rapporté par la
    requête doit être incrémenté par le FDW lui-même. Quand la requête n'a
    pas de clause, le FDW doit aussi incrémenté le nombre de lignes pour le
    nœud ForeignScanState dans le cas d'un
    EXPLAIN ANALYZE case.
   
    Si le pointeur IterateDirectModify est configuré à
    NULL, aucune tentative ne sera réalisée pour exécuter
    une modification directe sur le serveur distant.
   
void
EndDirectModify (ForeignScanState *node);
    Nettoie après une modification directe sur le serveur distant. Il n'est normalement pas important de relâcher la mémoire allouée avec palloc mais, par exemple, des fichiers et des connexions ouvertes sur le serveur distant doivent fermés.
    Si le pointeur EndDirectModify est configuré à
    NULL, aucune tentative ne sera réalisée pour exécuter
    une modification directe sur le serveur distant.
   
TRUNCATE
void
ExecForeignTruncate(List *rels,
                    DropBehavior behavior,
                    bool restart_seqs);
    Tronque les tables distantes. Cette fonction est appelée quand TRUNCATE est exécuté sur une table distante.
    rels est une liste de structure de données
    Relation des table distantes à tronquer.
   
    Le comportement est soit DROP_RESTRICT, soit
    DROP_CASCADE indiquant que l'option
    RESTRICT ou CASCADE,
    respectivement, a été indiquée dans la commande
    TRUNCATE originelle.
   
    Si restart_seqs vaut true, la
    commande TRUNCATE originelle a requis le comportement
    RESTART IDENTITY, sinon le comportement
    CONTINUE IDENTITY a été requis.
   
    Notez que les options ONLY spécifiées dans la commande
    TRUNCATE originelle ne sont pas passées à
    ExecForeignTruncate. Ce comportement est similaire
    aux fonctions callback des SELECT,
    UPDATE et DELETE sur une table
    distante.
   
    ExecForeignTruncate est invoquée une fois par serveur
    distant pour lequel des tables distantes sont tronquées. Cela signifie
    que toutes les tables distantes incluses dans rels
    doivent appartenir au même serveur.
   
    Si le pointeur de ExecForeignTruncate est mis à
    NULL, les tentatives de tronquer des tables distantes
    échoueront avec un message d'erreur.
   
Si un FDW veut supporter le verrouillage tardif de lignes (comme décrit à Section 57.5), il doit fournir les fonctions callbacks suivantes :
RowMarkType
GetForeignRowMarkType (RangeTblEntry *rte,
                       LockClauseStrength strength);
    
    Indique quelle option de marquage de ligne utiliser pour
    une table distante. rte est le nœud
    RangeTblEntry pour la table et
    strength décrit la force du verrou
    requis par la clause FOR UPDATE/SHARE, si
    applicable. Le résultat doit être un membre du type énumération
    RowMarkType.
   
    Cette fonction est appelée durant la planification de la
    requête pour chaque table distante qui apparaît dans une
    requête UPDATE, DELETE,
    ou SELECT FOR UPDATE/SHARE et n'est
    pas la cible d'une commande UPDATE ou
    DELETE.
   
    Si le pointeur de fonction
    GetForeignRowMarkType est positionné à
    NULL, l'option ROW_MARK_COPY
    est toujours utilisée. (Ceci implique que la fonction
    RefetchForeignRow ne sera jamais appelée,
    aussi elle n'a pas besoin d'être fournie non plus.)
   
Voir Section 57.5 pour plus d'informations.
void
RefetchForeignRow (EState *estate,
                   ExecRowMark *erm,
                   Datum rowid,
                   TupleTableSlot *slot,
                   bool *updated);
    
    Récupère à nouveau une ligne à partir de
    la table distante, après l'avoir verrouillée si
    nécessaire. estate est l'état global
    d'exécution de la requête. erm est la
    structure ExecRowMark décrivant la
    table distante cible et le type de verrou ligne (si applicable)
    à prendre.
    rowid identifie la ligne à récupérer.
    slot ne contient rien d'utile lors de l'appel,
    mais peut être utilisé pour retourner l'enregistrement renvoyé.
    updated est un paramètre de sortie.
   
    Cette fonction doit renvoyer l'enregistrement dans le slot fourni à cet effet,
    ou l'effacer si le verrou sur la ligne ne peut être obtenu.
    Le type de verrou de ligne à acquérir est défini par
    erm->markType, qui est la valeur retournée
    précédemment par la fonction GetForeignRowMarkType.
    (ROW_MARK_REFERENCE signifie qu'il faut juste
    re-récupérer l'enregistrement sans poser aucun verrou,
    et ROW_MARK_COPY ne sera jamais envoyé à cette
    fonction.)
   
    En complément, *updated devrait être positionné
    à true si ce qui a été récupéré est une
    version mise à jour de la ligne plutôt que la même version
    obtenue précédemment. (Si le FDW ne peut être sûr à propos
    de cette information, retourner toujours true
    est recommandé.)
   
    Notez que par défaut, l'échec pour prendre un verrou ligne devrait avoir
    pour conséquence de lever une erreur ; renvoyer un emplacement vide
    n'est approprié que si l'option SKIP LOCKED est
    spécifiée par erm->waitPolicy.
   
    rowid est la valeur de
    ctid précédemment lue pour la ligne
    récupérée à nouveau. Bien que la valeur rowid
    est envoyée comme type Datnum, elle ne peut être
    actuellement que de type tid. L'API de la fonction est
    choisie dans l'espoir qu'il sera possible d'autoriser d'autre types
    de données pour les identifiants des lignes dans le futur.
   
    Si le pointeur de fonction RefetchForeignRow
    est positionné sur NULL, les tentatives de
    récupération à nouveau des lignes échoueront avec un message
    d'erreur.
   
Voir Section 57.5 pour plus d'informations.
bool
RecheckForeignScan (ForeignScanState *node, TupleTableSlot *slot);
    
    Vérifie à nouveau qu'une ligne retournée précédemment
    correspond toujours au parcours et aux qualificatifs de jointures,
    et éventuellement fournit une version modifiée de la
    ligne. Pour les wrappers de données distantes qui ne supportent pas
    les jointures (join push-down), il
    sera plus pratique de positionner ce pointeur de fonction à
    NULL et, à la place, configurer
    fdw_recheck_quals
    de manière appropriée. Cependant lorsque des jointures
    externes sont poussées au serveur distant, il n'est pas suffisant d'appliquer à
    nouveau les vérifications applicables à toutes les tables
    de base à la ligne résultat, même si tous les attributs
    nécessaires sont présents, parce que l'impossibilité de mettre
    en correspondance certains qualificatifs pourrait résulter en la
    mise à NULL de certaines colonnes, plutôt qu'aucune ligne ne soit
    retournée. RecheckForeignScan peut vérifier
    à nouveau les qualificatifs et renvoyer true si ils sont toujours
    satisfaits et false dans le cas contraire, mais elle peut aussi
    stocker une ligne de remplacement dans l'emplacement fourni.
   
    Pour implémenter le support des jointures, un wrapper de données
    distantes construira typiquement un plan alternatif local qui est
    utilisé uniquement pour les revérifications ; celui-ci deviendra
    le sous-plan externe de ForeignScan. Lorsqu'une
    revérification est requise, ce sous-plan peut être exécuté
    et la ligne résultante peut être stockée dans l'emplacement. Ce
    plan n'a pas besoin d'être efficace car aucune table de base ne
    retournera plus d'une ligne ; par exemple, il peut réaliser toutes
    les jointures comme des boucles imbriquées.
    La fonction GetExistingLocalJoinPath peut être utilisée
    pour rechercher des chemins existants dans un chemin de jointure local
    convenable, qui est utilisable comme plan de jointure local alternatif.
    GetExistingLocalJoinPath recherche un chemin sans
    paramètre dans la liste de chemins de la relation de jointure spécifiée
    (si un tel chemin n'existe pas, elle renvoie NULL, ce qui fait que le FDW
    pourrait construire un chemin local lui-même ou pourrait choisir de ne pas
    créer de chemins d'accès pour cette jointure).
   
EXPLAIN
void
ExplainForeignScan (ForeignScanState *node,
                    ExplainState *es);
    
    Affiche une sortie EXPLAIN supplémentaire pour un
    parcours de table distante. Cette fonction peut faire appel à
    ExplainPropertyText et aux fonctions relatives pour
    ajouter des champs à la sortie d'EXPLAIN. Les champs
    drapeaux dans es peuvent être utilisés pour déterminer
    ce qui doit être affiché, et l'état du nœud
    ForeignScanState peut être inspecté pour fournir
    des statistiques d'exécution dans le cas du EXPLAIN
     ANALYZE.
   
    Si le pointeur ExplainForeignScan vaut
    NULL, aucune information supplémentaire n'est affichée
    lors de l'EXPLAIN.
   
void
ExplainForeignModify (ModifyTableState *mtstate,
                      ResultRelInfo *rinfo,
                      List *fdw_private,
                      int subplan_index,
                      struct ExplainState *es);
    
    Affiche une sortie supplémentaire pour EXPLAIN lors
    de la mise à jour d'une table distante. Cette fonction peut appeler
    ExplainPropertyText et les fonctions en relation
    pour ajouter des champs à la sortie d'EXPLAIN. Les champs
    drapeaux de es peuvent être utilisés pour déterminer
    quoi afficher, et l'état du nœud
    ModifyTableState peut être inspecté pour fournir
    des statistiques en exécution dans le cas du EXPLAIN
     ANALYZE. Les quatre premiers arguments sont les mêmes que pour
    BeginForeignModify.
   
    Si le pointeur ExplainForeignModify vaut
    NULL, aucune information supplémentaire n'est affichée
    lors de l'EXPLAIN.
   
void
ExplainDirectModify (ForeignScanState *node,
                     ExplainState *es);
    
    Affiche une sortie EXPLAIN supplémentaire pour une
    modification directe sur le serveur distant. Cette fonction peut appeler
    ExplainPropertyText et les fonctions relatives pour
    ajouter des champs à la sortie d'EXPLAIN. Les champs
    flag dans es peuvent être utilisés pour déterminer ce
    qui doit être affiché, et l'état du nœud
    ForeignScanState peut être inspecté pour fournir
    des statistiques à l'exécution dans le cas d'un EXPLAIN
     ANALYZE.
   
    Si le pointeur ExplainDirectModify est configuré à
    NULL, aucune information supplémentaire n'est affichée
    pendant un EXPLAIN.
   
ANALYZE
bool
AnalyzeForeignTable (Relation relation,
                     AcquireSampleRowsFunc *func,
                     BlockNumber *totalpages);
    
    Cette fonction est appelée quand ANALYZE est exécuté
    sur une table distante. Si le wrapper de données distantes peut récupérer
    des statistiques pour cette table distante, il doit renvoyer
    true, et fournir un pointeur vers une fonction qui
    récupérera un échantillon de lignes à partir de la table dans
    func, ainsi que la taille estimée de la table en
    blocs dans totalpages. Sinon, il doit renvoyer
    false.
   
    Si le wrapper de données distantes ne supporte
    pas la récupération de statistiques quelque soit la table, le pointeur
    AnalyzeForeignTable doit être configuré à
    NULL.
   
Si fourni, la fonction de récupération de l'échantillon doit avoir la signature suivante :
int
AcquireSampleRowsFunc(Relation relation,
                      int elevel,
                      HeapTuple *rows,
                      int targrows,
                      double *totalrows,
                      double *totaldeadrows);
    
    Un échantillon récupéré au hasard et comprenant au plus
    targrows lignes doit être récupéré à partir de la
    table et stocké dans le tableau rows fourni par
    l'appelant. Le nombre réel de lignes récupérées doit être renvoyé. De plus,
    les estimations du nombre total de lignes vivantes et mortes doivent être
    enregistrées dans les paramètres en sortie appelés
    totalrows et totaldeadrows.
    (Configurez totaldeadrows à zéro si le wrapper de
    données distantes ne connaît pas le concept des lignes mortes.)
   
IMPORT FOREIGN SCHEMA
List *
ImportForeignSchema (ImportForeignSchemaStmt *stmt, Oid serverOid);
    Obtient une liste des commandes de création de tables distantes. Cette fonction est appelée lors de l'exécution de IMPORT FOREIGN SCHEMA, et il lui est passé l'arbre d'analyse pour cette instruction, ainsi que l'OID du serveur distant à utiliser. Elle devrait renvoyer une liste de chaînes C, chacune d'entre elles devant contenir une commande CREATE FOREIGN TABLE. Ces chaînes seront analysées et exécutées par le serveur principal.
    À l'intérieur de la structure
    ImportForeignSchemaStmt,
    remote_schema est le nom
    du schéma distant à partir duquel les tables sont à
    importer. list_type indique comment
    filtrer les noms de tables : FDW_IMPORT_SCHEMA_ALL
    signifie que toutes les tables dans le schéma distant devraient
    être importées (dans ce cas, table_list
    est vide), FDW_IMPORT_SCHEMA_LIMIT_TO
    signifie d'inclure seulement les tables listées
    dans table_list, et
    FDW_IMPORT_SCHEMA_EXCEPT signifie d'exclure
    les tables listées dans table_list.
    options est une liste d'options utilisées
    pour le processus d'import. La signification des options relève du
    FDW. Par exemple, un FDW pourrait utiliser une option pour définir
    si les attributs NOT NULL des colonnes devraient
    être importés. Ces options n'ont pas besoin d'avoir une quelconque
    relation avec celles supportées par le FDW pour les objets base
    de données.
   
    Le FDW peut ignorer le champ local_schema
    de ImportForeignSchemaStmt, parce que
    le serveur principal insérera automatiquement ce nom dans les
    commandes CREATE FOREIGN TABLE analysées.
   
    Le FDW n'a pas besoin de mettre en place lui-même le
    filtrage spécifié par list_type
    et table_list, dans la mesure où
    le serveur principal ignorera automatiquement les commandes
    renvoyées pour les tables exclues selon ces options. Cependant,
    il est souvent utile d'éviter le travail de création des
    commandes pour les tables exclues dès le départ. La fonction
    IsImportableForeignTable() peut être utile
    pour tester si une table distante donnée passera ou pas le filtre.
   
    Si le FDW ne supporte pas l'import de définition de tables,
    le pointeur de fonction ImportForeignSchema
    peut être positionné à NULL.
   
    Un nœud ForeignScan peut, en option, supporter
    une exécution parallélisée. Un ForeignScan
    parallélisée sera exécutée par plusieurs processus et devra renvoyer
    chaque ligne une fois seulement au travers de tous les processus
    coopérant. Pour faire cela, les processus peuvent se coordonner avec des
    ensembles de taille fixe de mémoire partagée dynamique. Cette mémoire
    partagée n'est pas garantie d'être placée à la même adresse pour chaque
    processus, donc il ne doit pas contenir de pointeurs. Les fonctions
    suivantes sont toutes optionnelles généralement, mais elles sont requises si
    une exécution parallèle doit être supportée.
   
bool
IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
                          RangeTblEntry *rte);
    Teste si un parcours peut être réalisé avec un processus parallèle. Cette fonction sera seulement appelée quand le planificateur pense qu'un plan parallélisé est possible, et doit renvoyer true si un tel plan est sûr pour ce parcours. Ceci ne sera généralement pas le cas si la source de données distante a des sémantiques transactionnelles, sauf si la connexion du processus supplémentaire peut être en quelque sorte partagée dans le même contexte transactionnelle que celui du processus maître
Si ce callback n'est pas défini, il est supposé que le parcours doit avoir lieu au niveau du processus maître. Notez que renvoyer true ne signifie pas que le parcours sera parallélisé. Cela signifie seulement qu'il est possible de l'effectuer avec des processus parallèles. De ce fait, il peut être utile de définir cette méthode même quand l'exécution parallélisée n'est pas supportée.
Size
EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
    Estime la quantité de mémoire partagée dynamique requis pour une opération parallélisée. Cette valeur pourrait être supérieure à la quantité réellement utilisée mais elle ne peut pas être inférieure. La valeur renvoyée est en octets. Cette fonction est optionnelle et peut être omise si elle n'est pas nécessaire. Mais si elle est omise, les trois fonctions suivantes peuvent elles-aussi être omises parce qu'aucune mémoire partagée ne sera allouée pour une utilisation avec le FDW.
void
InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
                         void *coordinate);
    
    Initialise la mémoire partagée dynamique qui sera requise pour une
    opération parallélisée ; coordinate pointe vers
    une partie de mémoire partagée de même taille que la valeur de retour de
    EstimateDSMForeignScan. Cette fonction est
    optionnelle et peut être omise si nécessaire.
   
void
ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
                           void *coordinate);
    
    Ré-initialise la mémoire partagée dynamique requise pour les opérations
    parallélisées quand le nœud du plan pour le parcours distant va être
    ré-exécuté. Cette fonction est optionnelle et peut être omise si
    nécessaire. La pratique recommandée est que cette fonction réinitialise
    seulement l'état partagé alors que la fonction
    ReScanForeignScan réinitialise seulement l'état
    local. Actuellement, cette fonction sera appelée avant
    ReScanForeignScan mais il est préférable de ne pas se
    baser sur cet ordre.
   
void
InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
                            void *coordinate);
    
    Initialise un état local d'un processus parallèle suivant l'état partagé
    configuré dans le processus maître par
    InitializeDSMForeignScan. Cette fonction est
    optionnelle et peut être omise si nécessaire.
   
void
ShutdownForeignScan(ForeignScanState *node);
    
    Libères les ressources quand il anticipé que le nœud ne sera pas exécuté
    entièrement.  Cette fonction ne sera pas appelée dans tous les cas;
    parfois, EndForeignScan peut être appelée sans que cette
    fonction ait été appelée avant.  Puisque le segment DSM utilisé par les
    requêtes parallèles est détruit juste après que ce callback soit appelé,
    les wrappers de données distantes qui désirent effectuer des actions avant
    que le segment DSM disparaissent devraient implémenter cette méthode.
   
    Un nœud ForeignScan peut, optionellement,
    supporter une exécution asynchrone tel que décrit dans
    src/backend/executor/README. Les fonctions suivantes
    sont toutes optionnelles, mais sont toutes requises si l'exécution
    asynchrone doit être supportée.
   
bool IsForeignPathAsyncCapable(ForeignPath *path);
    Vérifie si un chemin ForeignPath donné peut
    parcourir une relation distante sous-jacente asynchrone. Cette fonction
    ne sera appelée uniquement à la fin d'une planification de requête quand
    le chemin donné est un enfant direct du chemin
    AppendPath et quand le planificateur estime que
    l'exécution asynchrone améliore les performances, et devra retourner vrai
    (« true ») si un chemin donné est capable de parcourir la
    relation distante de façon asynchrone.
   
    Si cette fonction n'est pas définie, il est assumé que le chemin donné
    parcourt la relation distante en utilisant
    IterateForeignScan.(Ceci implique que les fonctions
    callbacks décrites ci-dessous ne seront jamais appelées, et n'ont pas
    besoin d'être fournies.)
  
void ForeignAsyncRequest(AsyncRequest *areq);
    Produit une ligne de manière asynchrone à partir du nœud
    ForeignScan. areq est la
    structure AsyncRequest décrivant le nœud
    ForeignScan et le nœud parent
    Append requis par les lignes qui en viennent.
    Cette fonction doit conserver la ligne dans un slot spécifié par
    areq->result, et défini avec
    areq->request_complete mis à
    true ; ou, s'il est nécessaire d'attendre un
    événement extérieur au cœur du serveur, tel que des I/O réseau, et qu'une
    ligne ne peut être générée immédiatement, le drapeau doit être mis à
    false, et défini avec
    areq->callback_pending mis à
    true pour que le nœud
    ForeignScan puisse recevoir un callback depuis
    les fonctions callbacks décrites ci-dessous. S'il n'y a plus de lignes
    diponibles, mettre le slot à NULL ou fournir un slot vide, et mettre le
    drapeau areq->request_complete à
    true. Il est recommandé d'utiliser
    ExecAsyncRequestDone ou
    ExecAsyncRequestPending pour affecter les paramètres
    de sortie dans areq.
   
void ForeignAsyncConfigureWait(AsyncRequest *areq);
    Configure un événement de descripteur de fichier pour lequel le nœud
    ForeignScan souhaite attendre. Cette fonction
    sera appelée uniquement quand le nœud
    ForeignScan a le drapeau
    areq->callback_pending affecté, et devra ajouter
    l'événement au as_eventset du nœud parent
    Append décrit par areq. Voir
    les commentaires pour ExecAsyncConfigureWait dans
    src/backend/executor/execAsync.c pour des
    informations additionnelles. Quand l'événement de descripteur de fichier
    a lieu, ForeignAsyncNotify sera appelée.
   
void ForeignAsyncNotify(AsyncRequest *areq);
    Traite un événement pertinent qui s'est déroulé, puis produit une ligne de
    façon asynchrone à partir du nœud ForeignScan.
    Cette fonction devra affecter les paramètres de sortie dans
    areq de la même façon que
    ForeignAsyncRequest.
   
List *
ReparameterizeForeignPathByChild(PlannerInfo *root, List *fdw_private,
                                 RelOptInfo *child_rel);
    
    Cette fonction est appelée lors de la conversion d'un chemin paramétré par
    le plus haut parent de la relation enfant child_rel
    spécifiée devant être paramétrée avec la relation enfant.  Cette fonction
    est utilisée pour reparamétrer n'importe quel chemin ou traduire n'importe
    quel nœud d'expression enregistré dans le membre
    fdw_private du ForeignPath
    spécifié.  Le callback peut utiliser
    reparameterize_path_by_child,
    adjust_appendrel_attrs ou
    adjust_appendrel_attrs_multilevel selon son besoin.