PostgreSQLLa base de données la plus sophistiquée au monde.

Version anglaise

53.2. Routines callback des wrappers de données distantes

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.

53.2.1. Routines des FDW pour parcourir les tables distantes

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.

Voir Section 53.4, « Planification de la requête avec un wrapper de données distantes » 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 53.4, « Planification de la requête avec un wrapper de données distantes » pour plus d'informations.

ForeignScan *
GetForeignPlan (PlannerInfo *root,
                RelOptInfo *baserel,
                Oid foreigntableid,
                ForeignPath *best_path,
                List *tlist,
                List *scan_clauses);
    

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), la liste cible à émettre par le nœud du plan, et les clauses de restriction forcées par le nœud du plan.

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 53.4, « Planification de la requête avec un wrapper de données distantes » 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 signature de la colonne de la table distante parcourue. Si vous préférez optimiser la récupération des colonnes inutiles, vous devez insérer des NULL dans les positions de ces colonnes

Notez que l'exécuteur de PostgreSQL™ ne se préoccupe pas de savoir si les lignes renvoyées violent les contraintes NOT NULL définies sur les colonnes de la table distante. Le planificateur s'en préoccupe et pourrait mal optimiser les requêtes si des valeurs NULL sont présentes dans une colonne déclarée ne pas en contenir. Si une valeur NULL est découverte alors que l'utilisateur a déclaré qu'aucune valeur NULL ne devrait être présente, il pourrait être approprié de lever une erreur (exactement comme vous le feriez en cas d'un type de données inapproprié).

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.

53.2.2. Routines FDW pour la mise à jour des tables distantes

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 (Query *parsetree,
                         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, ajoutez les éléments TargetEntry à parsetree->targetList, contenant les expressions des valeurs supplémentaires à récupérer. Chacun de ces entrées doit être marquée resjunk = true, et doit avoir un resname distinct qui l'identifiera à l'exécution. Évitez d'utiliser des noms correspondant à ctidN, wholerow ou wholerowN, car le système peut générer des colonnes ayant ces noms.

Cette fonction est appelé par le processus de réécriture, et non pas par le planificateur. Les informations disponibles sont un peu différentes de celles des routines de planification. parsetree est l'arbre d'analyse pour la commande UPDATE ou DELETE alors que target_rte et target_relation décrivent la table distante cible.

Si le pointeur AddForeignUpdateTargets est initialisée à 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 plan->plans ou toute autre sous-structure du nœud plan.

Voir Section 53.4, « Planification de la requête avec un wrapper de données distantes » pour plus d'informations.

Si le pointeur PlanForeignModify est initialisée à 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, 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.

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 le résultat de 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 dans l'emplacement renvoyé sont utilisées seulement si la requête INSERT a une clause RETURNING ou si la table distante a un trigger AFTER ROW. Les triggers requièrent toutes les colonnes mais le Foreign Data Wrapper pourrait choisir d'optimiser en ne renvoyant que certaines ou toutes les colonnes suivant le contenu de la clause RETURNING. Quoi qu'il en soit, un slot doit être renvoyé pour indiquer le succès. Dans le cas contraire, le nombre de lignes renvoyé par la requête sera mauvais.

Si le pointeur ExecForeignInsert est initialisé à NULL, les tentatives d'insertion dans la table distante échoueront avec un message d'erreur.

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 ; il diffère de slot car il peut contenir des colonnes supplémentaires. En particulier, toute colonne supplémentaire qui était réclamée par AddForeignUpdateTargets sera disponible à partir de cet emplacement.

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 renvoyées dans l'emplacement sont utilisées seulement si la requête UPDATE a une clause RETURNING ou si la table distante a un trigger AFTER ROW. Les triggers requièrent toutes les colonnes mais le Foreign Data Wrapper pourrait choisir d'optimiser en ne renvoyant que certaines ou toutes les colonnes suivant le contenu de la clause RETURNING. Quoi qu'il en soit, un slot doit être renvoyé pour indiquer le succès. Dans le cas contraire, le nombre de lignes renvoyé par la requête sera mauvais.

Si le pointeur ExecForeignUpdate est initialisée à 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.

The return value is either a slot containing the row that was deleted, or NULL if no row was deleted (typically as a result of triggers). The passed-in slot can be used to hold the tuple to be returned.

les données placées dans l'emplacement sont utilisées seulement si la requête DELETE dispose de la clause RETURNING or the foreign table has an AFTER ROW trigger. Triggers require all columns, but the FDW could choose to optimize away returning some or all columns depending on the contents of the RETURNING clause. Regardless, some slot must be returned to indicate success, or the query's reported row count will be wrong.

Si le pointeur the 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.

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.)

53.2.3. Routines FDW pour 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.

53.2.4. Routines FDW pour ANALYZE

bool
AnalyzeForeignTable (Relation relation,
                     AcquireSampleRowsFunc *func,
                     BlockNumber *totalpages);
    

Cette fonction est appelée quand ANALYZE(7) 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.)