Documentation PostgreSQL 9.2.24 > Internes > Écrire un wrapper de données distantes > Routines callback des wrappers de données distantes | |
Écrire un wrapper de données distantes | Fonctions d'aide pour les wrapper 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 suivantes :
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 impliquant 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 50.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 50.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 50.4, « Planification de la requête avec un wrapper de données distantes » pour plus d'informations.
void ExplainForeignScan (ForeignScanState *node, ExplainState *es);
Affiche une sortie EXPLAIN supplémentaire pour un parcours de table distante. Elle peut ne rien renvoyer si ce n'est pas nécessaire. Sinon, elle doit appeler ExplainPropertyText et les fonctions relatives pour ajouter des champs à la sortie du 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 à l'exécution dans le cas d'un EXPLAIN ANALYZE.
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).
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.
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.)
Le type de structure FdwRoutine est déclaré dans src/include/foreign/fdwapi.h, qui donne quelques informations supplémentaires.