TRUNCATE
EXPLAIN
ANALYZE
IMPORT 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.
Notez aussi que l'ensemble des clauses de jointures à appliquer, passé
en tant que extra->restrictlist
, varie suivant
la combinaison des relations interne et externe. Un chemin
ForeignPath
généré pour
joinrel
doit contenir l'ensemble des clauses de
jointure qu'il utilise, qui sera utilisé par l'optimiseur pour
convertir le chemin
ForeignPath
en un plan, s'il est sélectionné
par l'optimiseur comme meilleur chemin pour joinrel
.
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.
À partir de PostgreSQL 16,
fs_relids
inclut les index rangetable des
jointures externes, si une d'entre elles était impliquée dans cette
jointure. Le nouveau champ fs_base_relids
inclut uniquement les index des relations de base et, de ce fait,
mimique les anciennes sémantiques de fs_relids
.
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
N
ctid
, wholerow
pour une
Var
de ligne entière marquée avec
vartype
= RECORD
, et
wholerow
pour une
N
Var
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.
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 ou lors de l'exécution de
COPY FROM
sur une table distante, auquel cas il est
appelé d'une façon différente que dans le cas d'un
INSERT
. 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éral, 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.