TRUNCATEEXPLAINANALYZEIMPORT FOREIGN SCHEMA
La función de manejo del FDW devuelve una estructura FdwRoutine
asignada con palloc que contiene punteros a las funciones de retrollamada descritas a continuación.
Las funciones relacionadas con el escaneo son obligatorias, el resto son opcionales.
El tipo de estructura FdwRoutine se declara en
src/include/foreign/fdwapi.h, el cual puedes consultar para obtener detalles
adicionales.
void
GetForeignRelSize(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid);
Obtiene estimaciones del tamaño de la relación para una tabla externa. Se llama al comienzo de la
planificación de una consulta que escanea una tabla externa.
root es la información global del planificador sobre la consulta;
baserel es la información del planificador sobre esta tabla; y
foreigntableid es el OID de pg_class de la tabla
externa. (foreigntableid podría obtenerse de las estructuras de datos del
planificador, pero se pasa explícitamente para ahorrar esfuerzo).
Esta función debe actualizar baserel->rows para que sea el número esperado
de filas devueltas por el escaneo de la tabla, después de tener en cuenta el filtrado realizado
por las condiciones de restricción (restriction quals). El valor inicial de
baserel->rows es solo una estimación constante por defecto, la cual debe ser
reemplazada si es posible. La función también puede optar por actualizar
baserel->width si puede calcular una mejor estimación del ancho promedio de las
filas de resultado. (El valor inicial se basa en los tipos de datos de las columnas y en los valores
de ancho promedio de columna medidos por el último ANALYZE).
Además, esta función puede actualizar baserel->tuples si puede calcular una mejor
estimación del número total de filas de la tabla externa. (El valor inicial proviene de
pg_class.reltuples, que representa el número total
de filas visto por el último ANALYZE; será -1 si no se ha realizado
ningún ANALYZE en esta tabla externa).
Consulta la Section 58.4 para obtener información adicional.
void
GetForeignPaths(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid);
Crea posibles rutas de acceso (access paths) para un escaneo en una tabla externa.
Se llama durante la planificación de la consulta.
Los parámetros son los mismos que para GetForeignRelSize, la cual ya ha
sido llamada.
Esta función debe generar al menos una ruta de acceso (nodo ForeignPath)
para un escaneo en la tabla externa y debe llamar a add_path para añadir cada una de
esas rutas a baserel->pathlist. Se recomienda usar
create_foreignscan_path para construir los nodos ForeignPath.
La función puede generar múltiples rutas de acceso, por ejemplo, una ruta que tenga
pathkeys válidos para representar un resultado preordenado. Cada ruta de acceso
debe contener estimaciones de costo, y puede contener cualquier información privada de FDW que sea
necesaria para identificar el método de escaneo específico previsto.
Consulta la Section 58.4 para obtener información adicional.
ForeignScan *
GetForeignPlan(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid,
ForeignPath *best_path,
List *tlist,
List *scan_clauses,
Plan *outer_plan);
Crea un nodo de plan ForeignScan a partir de la ruta de acceso externa
seleccionada. Se llama al final de la planificación de la consulta.
Los parámetros son como para GetForeignRelSize, más la ruta
ForeignPath seleccionada (producida previamente por
GetForeignPaths, GetForeignJoinPaths o
GetForeignUpperPaths), la lista de objetivos (target list) a emitir por el nodo de
plan, las cláusulas de restricción a imponer por el nodo de plan, y el subplan externo de
ForeignScan, el cual se utiliza para las recomprobaciones realizadas por
RecheckForeignScan.
(Si la ruta es para una unión (join) en lugar de una relación base, foreigntableid
es InvalidOid).
Esta función debe crear y devolver un nodo de plan ForeignScan; se recomienda
usar make_foreignscan para construir el nodo ForeignScan.
Consulta la Section 58.4 para obtener información adicional.
void
BeginForeignScan(ForeignScanState *node,
int eflags);
Comienza a ejecutar un escaneo externo. Se llama durante el inicio del ejecutor.
Debe realizar cualquier inicialización necesaria antes de que pueda comenzar el escaneo, pero no
comenzar a ejecutar el escaneo real (eso debe hacerse en la primera llamada a
IterateForeignScan).
El nodo ForeignScanState ya ha sido creado, pero su campo
fdw_state sigue siendo NULL. La información sobre la tabla a escanear es
accesible a través del nodo ForeignScanState (en particular, desde el nodo
de plan ForeignScan subyacente, que contiene cualquier información privada
de FDW proporcionada por GetForeignPlan).
eflags contiene bits de banderas que describen el modo de funcionamiento del
ejecutor para este nodo de plan.
Ten en cuenta que cuando (eflags & EXEC_FLAG_EXPLAIN_ONLY) es verdadero,
esta función no debe realizar ninguna acción externamente visible; solo debe hacer lo mínimo
requerido para que el estado del nodo sea válido para ExplainForeignScan y
EndForeignScan.
TupleTableSlot * IterateForeignScan(ForeignScanState *node);
Obtiene una fila de la fuente externa, devolviéndola en una ranura de tabla de tuplas (se debe usar
la ranura ScanTupleSlot del nodo para este propósito). Devuelve NULL si
no hay más filas disponibles. La infraestructura de ranuras de tablas de tuplas permite devolver
una tupla física o virtual; en la mayoría de los casos, la última opción es preferible desde una
perspectiva de rendimiento. Ten en cuenta que esto se llama en un contexto de memoria de corta duración
que se restablecerá entre invocaciones. Crea un contexto de memoria en
BeginForeignScan si necesitas un almacenamiento de mayor duración, o usa
el es_query_cxt del EState del nodo.
Las filas devueltas deben coincidir con la lista de objetivos fdw_scan_tlist
si se proporcionó una, de lo contrario deben coincidir con el tipo de fila de la tabla externa que se
está escaneando. Si decides optimizar omitiendo la obtención de columnas que no son necesarias, debes
insertar nulos en esas posiciones de columna, o bien generar una lista
fdw_scan_tlist con esas columnas omitidas.
Ten en cuenta que al ejecutor de PostgreSQL no le importa si las filas devueltas violan alguna restricción que se haya definido en la tabla externa — pero al planificador sí le importa, y puede optimizar incorrectamente las consultas si hay filas visibles en la tabla externa que no satisfacen una restricción declarada. Si se viola una restricción cuando el usuario ha declarado que la restricción debe cumplirse, puede ser apropiado generar un error (tal como tendrías que hacer en el caso de una discrepancia de tipos de datos).
void ReScanForeignScan(ForeignScanState *node);
Reinicia el escaneo desde el principio. Ten en cuenta que cualquier parámetro del que dependa el escaneo puede haber cambiado de valor, por lo que el nuevo escaneo no necesariamente devolverá exactamente las mismas filas.
void EndForeignScan(ForeignScanState *node);
Finaliza el escaneo y libera los recursos. Normalmente no es importante liberar la memoria asignada con palloc, pero por ejemplo, se deben cerrar los archivos abiertos y las conexiones a servidores remotos.
Si un FDW admite la realización de uniones externas de forma remota (en lugar de obtener los datos de ambas tablas y realizar la unión localmente), debe proporcionar esta función de retrollamada:
void
GetForeignJoinPaths(PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
RelOptInfo *innerrel,
JoinType jointype,
JoinPathExtraData *extra);
Crea posibles rutas de acceso para una unión de dos (o más) tablas externas que pertenecen todas al mismo
servidor externo. Esta función opcional se llama durante la planificación de la consulta. Al igual que con
GetForeignPaths, esta función debe generar ruta(s)
ForeignPath para la joinrel proporcionada (usa
create_foreign_join_path para construirlas), y llamar a add_path
para añadir estas rutas al conjunto de rutas consideradas para la unión. Pero a diferencia de
GetForeignPaths, no es necesario que esta función tenga éxito en la creación de
al menos una ruta, ya que las rutas que involucran uniones locales siempre son posibles.
Ten en cuenta que esta función se invocará repetidamente para la misma relación de unión, con diferentes combinaciones de relaciones internas y externas; es responsabilidad del FDW minimizar el trabajo duplicado.
Ten en cuenta también que el conjunto de cláusulas de unión a aplicar a la unión, que se pasa como
extra->restrictlist, varía según la combinación de relaciones internas y externas.
Una ruta ForeignPath generada para la joinrel debe contener
el conjunto de cláusulas de unión que utiliza, que el planificador usará para convertir la ruta
ForeignPath en un plan, si el planificador la selecciona como la mejor ruta para
la joinrel.
Si se elige una ruta ForeignPath para la unión, esta representará todo el proceso
de unión; las rutas generadas para las tablas componentes y las uniones subsidiarias no se utilizarán.
El procesamiento posterior de la ruta de unión procede de manera muy similar a como lo hace para una ruta
que escanea una sola tabla externa. Una diferencia es que el campo scanrelid
del nodo de plan ForeignScan resultante debe establecerse en cero, ya que no hay
una sola relación que represente; en su lugar, el campo fs_relids del nodo
ForeignScan representa el conjunto de relaciones que se unieron. (Este último
campo se configura automáticamente por el código del planificador principal y no necesita ser completado
por el FDW). Otra diferencia es que, debido a que la lista de columnas para una unión remota no se puede
encontrar en los catálogos del sistema, el FDW debe completar fdw_scan_tlist
con una lista adecuada de nodos TargetEntry, que representen el conjunto de
columnas que suministrará en tiempo de ejecución en las tuplas que devuelva.
A partir de PostgreSQL 16, fs_relids incluye
los índices de la tabla de rango (rangetable indexes) de las uniones externas, si alguna estuvo
involucrada en esta unión. El nuevo campo fs_base_relids incluye solo índices
de relación base y, por lo tanto, imita la antigua semántica de fs_relids.
Consulta la Section 58.4 para obtener información adicional.
Si un FDW admite la realización de un procesamiento remoto posterior al escaneo/unión, como la agregación remota, debe proporcionar esta función de retrollamada:
void
GetForeignUpperPaths(PlannerInfo *root,
UpperRelationKind stage,
RelOptInfo *input_rel,
RelOptInfo *output_rel,
void *extra);
Crea posibles rutas de acceso para el procesamiento de la relación superior (upper
relation), que es el término del planificador para todo el procesamiento de consultas posterior al
escaneo/unión, como agregaciones, funciones de ventana, ordenamiento y actualizaciones de tablas. Esta
función opcional se llama durante la planificación de la consulta. Actualmente, se llama solo si todas las
relaciones base involucradas en la consulta pertenecen al mismo FDW. Esta función debe generar ruta(s)
ForeignPath para cualquier procesamiento posterior al escaneo/unión que el FDW
sepa cómo realizar de forma remota (usa create_foreign_upper_path para construirlas),
y llamar a add_path para añadir estas rutas a la relación superior indicada. Al igual
que con GetForeignJoinPaths, no es necesario que esta función tenga éxito en la
creación de ninguna ruta, ya que las rutas que involucran procesamiento local siempre son posibles.
El parámetro stage identifica qué paso posterior al escaneo/unión se está considerando
actualmente. output_rel es la relación superior que debe recibir las rutas que
representan la computación de este paso, e input_rel es la relación que representa la
entrada a este paso. El parámetro extra proporciona detalles adicionales, actualmente,
se establece solo para UPPERREL_PARTIAL_GROUP_AGG o
UPPERREL_GROUP_AGG, en cuyo caso apunta a una estructura
GroupPathExtraData; o para UPPERREL_FINAL, en cuyo caso apunta a una
estructura FinalPathExtraData. (Ten en cuenta que las rutas
ForeignPath añadidas a output_rel normalmente no tendrían
ninguna dependencia directa en las rutas de input_rel, ya que se espera que su
procesamiento se realice externamente. Sin embargo, examinar las rutas generadas previamente para el paso
de procesamiento anterior puede ser útil para evitar trabajo de planificación redundante).
Consulta la Section 58.4 para obtener información adicional.
Si un FDW admite tablas externas de escritura, debe proporcionar algunas o todas las siguientes funciones de retrollamada, según las necesidades y capacidades del FDW:
void
AddForeignUpdateTargets(PlannerInfo *root,
Index rtindex,
RangeTblEntry *target_rte,
Relation target_relation);
Las operaciones UPDATE y DELETE se realizan contra filas previamente
obtenidas por las funciones de escaneo de tablas. El FDW puede necesitar información adicional, como un
ID de fila o los valores de las columnas de clave primaria, para garantizar que pueda identificar la fila
exacta a actualizar o eliminar. Para dar soporte a eso, esta función puede añadir columnas de destino
ocultas adicionales, o “junk” (basura), a la lista de columnas que se recuperarán de la tabla
externa durante un UPDATE o DELETE.
Para hacer eso, construye un Var que represente el valor adicional que necesitas
y pásalo a add_row_identity_var, junto con un nombre para la columna junk. (Puedes
hacer esto más de una vez si se necesitan varias columnas). Debes elegir un nombre de columna junk
distinto para cada Var diferente que necesites, excepto que las variables
Var que son idénticas excepto por el campo varno
pueden y deben compartir el nombre de columna.
El sistema principal utiliza los nombres de columna junk tableoid para la columna
tableoid de una tabla, ctid o
ctid para Nctid,
wholerow para una variable Var de fila completa marcada con
vartype = RECORD, y
wholerow para una variable NVar de
fila completa con vartype igual al tipo de fila declarado de la tabla. Reutiliza
estos nombres cuando puedas (el planificador combinará solicitudes duplicadas de columnas junk idénticas).
Si necesitas otro tipo de columna junk además de estas, sería aconsejable elegir un nombre con el prefijo
del nombre de tu extensión para evitar conflictos con otros FDW.
Si el puntero AddForeignUpdateTargets se establece en NULL, no se
añaden expresiones de destino adicionales. (Esto imposibilitará la implementación de operaciones
DELETE, aunque UPDATE aún puede ser factible si el FDW confía en una
clave primaria inalterable para identificar las filas).
List *
PlanForeignModify(PlannerInfo *root,
ModifyTable *plan,
Index resultRelation,
int subplan_index);
Realiza cualquier acción de planificación adicional necesaria para una inserción, actualización o
eliminación en una tabla externa. Esta función genera la información privada de FDW que se adjuntará al
nodo de plan ModifyTable que realiza la acción de actualización. Esta información
privada debe tener la forma de una lista List, y se entregará a
BeginForeignModify durante la etapa de ejecución.
root is la información global del planificador sobre la consulta.
plan es el nodo de plan ModifyTable, que está completo excepto
por el campo fdwPrivLists.
resultRelation identifica la tabla externa de destino mediante su índice de tabla de
rango (range table index). subplan_index identifica qué destino del nodo de plan
ModifyTable es este, contando desde cero; usa esto si deseas indexar en las
subestructuras por relación de destino del nodo de plan.
Consulta la Section 58.4 para obtener información adicional.
Si el puntero PlanForeignModify se establece en NULL, no se
realizan acciones adicionales en tiempo de planificación, y la lista fdw_private
entregada a BeginForeignModify será NIL.
void
BeginForeignModify(ModifyTableState *mtstate,
ResultRelInfo *rinfo,
List *fdw_private,
int subplan_index,
int eflags);
Comienza a ejecutar una operación de modificación de tabla externa. Esta rutina se llama durante el
inicio del ejecutor. Debe realizar cualquier inicialización necesaria antes de las modificaciones reales
de la tabla. Posteriormente, se llamará a
ExecForeignInsert/ExecForeignBatchInsert, ExecForeignUpdate o
ExecForeignDelete para la(s) tupla(s) a insertar, actualizar o eliminar.
mtstate es el estado general del nodo de plan ModifyTable que
se está ejecutando; los datos globales sobre el plan y el estado de ejecución están disponibles a través
de esta estructura.
rinfo es la estructura ResultRelInfo que describe la tabla
externa de destino. (El campo ri_FdwState de
ResultRelInfo está disponible para que el FDW almacene cualquier estado privado
que necesite para esta operación).
fdw_private contiene los datos privados generados por
PlanForeignModify, si los hay.
subplan_index identifica qué destino del nodo de plan
ModifyTable es este.
eflags contiene bits de banderas que describen el modo de funcionamiento del ejecutor
para este nodo de plan.
Ten en cuenta que cuando (eflags & EXEC_FLAG_EXPLAIN_ONLY) es verdadero, esta
función no debe realizar ninguna acción externamente visible; solo debe hacer lo mínimo requerido para
que el estado del nodo sea válido para ExplainForeignModify y
EndForeignModify.
Si el puntero BeginForeignModify se establece en NULL, no se
realiza ninguna acción durante el inicio del ejecutor.
TupleTableSlot *
ExecForeignInsert(EState *estate,
ResultRelInfo *rinfo,
TupleTableSlot *slot,
TupleTableSlot *planSlot);
Inserta una tupla en la tabla externa.
estate es el estado de ejecución global para la consulta.
rinfo es la estructura ResultRelInfo que describe la tabla
externa de destino.
slot contiene la tupla a insertar; coincidirá con la definición del tipo de fila de la
tabla externa.
planSlot contiene la tupla generada por el subplan del nodo de plan
ModifyTable; difiere de slot en que posiblemente contiene
columnas “junk” adicionales. (El planSlot suele ser de poco interés para los
casos de INSERT, pero se proporciona para completar la interfaz).
El valor de retorno es una ranura que contiene los datos que realmente se insertaron (esto podría diferir
de los datos suministrados, por ejemplo, como resultado de las acciones de los disparadores), o NULL si
no se insertó ninguna fila realmente (nuevamente, típicamente como resultado de los disparadores). La
ranura slot pasada se puede reutilizar para este propósito.
Los datos en la ranura devuelta se usan solo si la sentencia INSERT tiene una cláusula
RETURNING o involucra una vista WITH CHECK OPTION; o si la tabla
externa tiene un disparador AFTER ROW. Los disparadores requieren todas las columnas,
pero el FDW podría optar por optimizar omitiendo la devolución de algunas o todas las columnas según el
contenido de la cláusula RETURNING o las restricciones de
WITH CHECK OPTION. De todos modos, se debe devolver alguna ranura para indicar el éxito,
o de lo contrario el recuento de filas reportado por la consulta será incorrecto.
Si el puntero ExecForeignInsert se establece en NULL, los intentos
de insertar en la tabla externa fallarán con un mensaje de error.
Ten en cuenta que esta función también se llama cuando se insertan tuplas enrutadas en una partición de
tabla externa o al ejecutar COPY FROM en una tabla externa, en cuyo caso se llama de
una manera diferente a la del caso de INSERT. Consulta las funciones de retrollamada
descritas a continuación que permiten al FDW dar soporte a eso.
TupleTableSlot **
ExecForeignBatchInsert(EState *estate,
ResultRelInfo *rinfo,
TupleTableSlot **slots,
TupleTableSlot **planSlots,
int *numSlots);
Inserta múltiples tuplas en lote (bulk) en la tabla externa.
Los parámetros son los mismos que para ExecForeignInsert excepto que
slots y planSlots contienen múltiples tuplas y
*numSlots especifica el número de tuplas en esos arrays.
El valor de retorno es un array de ranuras que contienen los datos que realmente se insertaron (esto
podría diferir de los datos suministrados, por ejemplo, como resultado de las acciones de los
disparadores). Las ranuras slots pasadas se pueden reutilizar para este propósito. El
número de tuplas insertadas con éxito se devuelve en *numSlots.
Los datos en la ranura devuelta se usan solo si la sentencia INSERT involucra una vista
WITH CHECK OPTION; o si la tabla externa tiene un disparador
AFTER ROW. Los disparadores requieren todas las columnas, pero el FDW podría optar por
optimizar omitiendo la devolución de algunas o todas las columnas según el contenido de las restricciones de
WITH CHECK OPTION.
Si el puntero ExecForeignBatchInsert o
GetForeignModifyBatchSize se establece en NULL, los intentos de
insertar en la tabla externa utilizarán ExecForeignInsert. Esta función no se utiliza
si el INSERT tiene la cláusula RETURNING.
Ten en cuenta que esta función también se llama cuando se insertan tuplas enrutadas en una partición de
tabla externa o al ejecutar COPY FROM en una tabla externa, en cuyo caso se llama de
una manera diferente a la del caso de INSERT. Consulta las funciones de retrollamada
descritas a continuación que permiten al FDW dar soporte a eso.
int GetForeignModifyBatchSize(ResultRelInfo *rinfo);
Reporta el número máximo de tuplas que una sola llamada a ExecForeignBatchInsert
puede manejar para la tabla externa especificada. El ejecutor pasa como máximo el número dado de tuplas a
ExecForeignBatchInsert.
rinfo es la estructura ResultRelInfo que describe la tabla
externa de destino.
Se espera que el FDW proporcione una opción de servidor externo y/o tabla externa para que el usuario
configure este valor, o bien algún valor codificado en duro (hard-coded).
Si el puntero ExecForeignBatchInsert o
GetForeignModifyBatchSize se establece en NULL, los intentos de
insertar en la tabla externa utilizarán ExecForeignInsert.
TupleTableSlot *
ExecForeignUpdate(EState *estate,
ResultRelInfo *rinfo,
TupleTableSlot *slot,
TupleTableSlot *planSlot);
Actualiza una tupla en la tabla externa.
estate es el estado de ejecución global para la consulta.
rinfo es la estructura ResultRelInfo que describe la tabla
externa de destino.
slot contiene los nuevos datos para la tupla; coincidirá con la definición del tipo de
fila de la tabla externa.
planSlot contiene la tupla generada por el subplan del nodo de plan
ModifyTable. A diferencia de slot, esta tupla contiene solo
los nuevos valores para las columnas cambiadas por la consulta, así que no confíes en los números de
atributo de la tabla externa para indexar en planSlot.
Además, planSlot suele contener columnas “junk” adicionales. In particular,
cualquier columna junk que haya sido solicitada por AddForeignUpdateTargets estará
disponible en esta ranura.
El valor de retorno es una ranura que contiene la fila tal como fue realmente actualizada (esto podría
diferir de los datos suministrados, por ejemplo, como resultado de las acciones de los disparadores), o
NULL si no se actualizó ninguna fila realmente (nuevamente, típicamente como resultado de los
disparadores). La ranura slot pasada se puede reutilizar para este propósito.
Los datos en la ranura devuelta se usan solo si la sentencia UPDATE tiene una cláusula
RETURNING o involucra una vista WITH CHECK OPTION; o si la tabla
externa tiene un disparador AFTER ROW. Los disparadores requieren todas las columnas,
pero el FDW podría optar por optimizar omitiendo la devolución de algunas o todas las columnas según el
contenido de la cláusula RETURNING o las restricciones de
WITH CHECK OPTION. De todos modos, se debe devolver alguna ranura para indicar el éxito,
o de lo contrario el recuento de filas reportado por la consulta será incorrecto.
Si el puntero ExecForeignUpdate se establece en NULL, los intentos
de actualizar la tabla externa fallarán con un mensaje de error.
TupleTableSlot *
ExecForeignDelete(EState *estate,
ResultRelInfo *rinfo,
TupleTableSlot *slot,
TupleTableSlot *planSlot);
Elimina una tupla de la tabla externa.
estate es el estado de ejecución global para la consulta.
rinfo es la estructura ResultRelInfo que describe la tabla
externa de destino.
slot no contiene nada útil al ser llamada, pero se puede usar para contener la tupla
devuelta.
planSlot contiene la tupla generada por el subplan del nodo de plan
ModifyTable; en particular, llevará cualquier columna junk que haya sido
solicitada por AddForeignUpdateTargets. Las columnas junk deben usarse para
identificar la tupla a eliminar.
El valor de retorno es una ranura que contiene la fila que fue eliminada, o NULL si no se eliminó ninguna
fila (típicamente como resultado de los disparadores). La ranura slot pasada se puede
usar para contener la tupla a devolver.
Los datos en la ranura devuelta se usan solo si la consulta DELETE tiene una cláusula
RETURNING o la tabla externa tiene un disparador AFTER ROW. Los
disparadores requieren todas las columnas, pero el FDW podría optar por optimizar omitiendo la devolución
de algunas o todas las columnas según el contenido de la cláusula RETURNING. De todos
modos, se debe devolver alguna ranura para indicar el éxito, o de lo contrario el recuento de filas
reportado por la consulta será incorrecto.
Si el puntero ExecForeignDelete se establece en NULL, los intentos
de eliminar de la tabla externa fallarán con un mensaje de error.
void
EndForeignModify(EState *estate,
ResultRelInfo *rinfo);
Finaliza la actualización de la tabla y libera los recursos. Normalmente no es importante liberar la memoria asignada con palloc, pero por ejemplo, se deben cerrar los archivos abiertos y las conexiones a servidores remotos.
Si el puntero EndForeignModify se establece en NULL, no se realiza
ninguna acción durante el cierre del ejecutor.
Las tuplas insertadas en una tabla particionada mediante INSERT o
COPY FROM se enrutan a las particiones. Si un FDW admite particiones de tabla externa
enrutables, también debe proporcionar las siguientes funciones de retrollamada. Estas funciones también
se llaman cuando se ejecuta COPY FROM en una tabla externa.
void
BeginForeignInsert(ModifyTableState *mtstate,
ResultRelInfo *rinfo);
Comienza a ejecutar una operación de inserción en una tabla externa. Esta rutina se llama justo antes de
que se inserte la primera tupla en la tabla externa en ambos casos: cuando es la partición elegida para el
enrutamiento de tuplas y cuando es el destino especificado en un comando COPY FROM.
Debe realizar cualquier inicialización necesaria antes de la inserción real. Posteriormente, se llamará a
ExecForeignInsert o ExecForeignBatchInsert para la(s) tupla(s)
a insertar en la tabla externa.
mtstate es el estado general del nodo de plan ModifyTable que
se está ejecutando; los datos globales sobre el plan y el estado de ejecución están disponibles a través
de esta estructura.
rinfo es la estructura ResultRelInfo que describe la tabla
externa de destino. (El campo ri_FdwState de
ResultRelInfo está disponible para que el FDW almacene cualquier estado privado
que necesite para esta operación).
Cuando esto es llamado por un comando COPY FROM, no se proporcionan los datos globales
relacionados con el plan en mtstate y el parámetro planSlot de
ExecForeignInsert llamado posteriormente para cada tupla insertada es
NULL, ya sea que la tabla externa sea la partición elegida para el enrutamiento de
tuplas o el destino especificado en el comando.
Si el puntero BeginForeignInsert se establece en NULL, no se
realiza ninguna acción para la inicialización.
Ten en cuenta que si el FDW no admite particiones de tablas externas enrutables y/o ejecutar
COPY FROM en tablas externas, esta función o
ExecForeignInsert/ExecForeignBatchInsert llamadas posteriormente deben lanzar un error
según sea necesario.
void
EndForeignInsert(EState *estate,
ResultRelInfo *rinfo);
Finaliza la operación de inserción y libera los recursos. Normalmente no es importante liberar la memoria asignada con palloc, pero por ejemplo, se deben cerrar los archivos abiertos y las conexiones a servidores remotos.
Si el puntero EndForeignInsert se establece en NULL, no se realiza
ninguna acción para la finalización.
int IsForeignRelUpdatable(Relation rel);
Informa qué operaciones de actualización admite la tabla externa especificada. El valor de retorno debe
ser una máscara de bits de números de eventos de reglas que indiquen qué operaciones son compatibles con
la tabla externa, utilizando la enumeración CmdType; es decir,
(1 << CMD_UPDATE) = 4 para UPDATE,
(1 << CMD_INSERT) = 8 for INSERT, y
(1 << CMD_DELETE) = 16 para DELETE.
Si el puntero IsForeignRelUpdatable se establece en NULL, se asume
que las tablas externas admiten inserciones, actualizaciones o eliminaciones si el FDW proporciona
ExecForeignInsert, ExecForeignUpdate, o
ExecForeignDelete respectivamente. Esta función solo es necesaria si el FDW admite
algunas tablas que son actualizables y otras que no lo son. (Incluso en ese caso, es admisible lanzar un
error en la rutina de ejecución en lugar de verificarlo en esta función. Sin embargo, esta función se usa
para determinar la capacidad de actualización para mostrarla en las vistas de
information_schema).
Algunas inserciones, actualizaciones y eliminaciones en tablas externas pueden optimizarse implementando
un conjunto alternativo de interfaces. Las interfaces ordinarias para inserciones, actualizaciones y
eliminaciones obtienen las filas del servidor remoto y luego modifican esas filas una a la vez. En algunos
casos, este enfoque fila por fila es necesario, pero puede ser ineficiente. Si es posible que el servidor
remoto determine qué filas deben modificarse sin tener que recuperarlas realmente, y si no hay estructuras
locales que afecten la operación (disparadores locales a nivel de fila, columnas generadas almacenadas o
restricciones WITH CHECK OPTION de vistas padre), entonces es posible organizar las
cosas para que toda la operación se realice en el servidor remoto. Las interfaces descritas a continuación
hacen esto posible.
bool
PlanDirectModify(PlannerInfo *root,
ModifyTable *plan,
Index resultRelation,
int subplan_index);
Decide si es seguro ejecutar una modificación directa en el servidor remoto. Si es así, devuelve
true después de realizar las acciones de planificación necesarias para ello. De lo
contrario, devuelve false. Esta función opcional se llama durante la planificación de la
consulta. Si esta función tiene éxito, se llamará a BeginDirectModify,
IterateDirectModify y EndDirectModify en la etapa de ejecución,
en su lugar. De lo contrario, la modificación de la tabla se ejecutará utilizando las funciones de
actualización descritas anteriormente. Los parámetros son los mismos que para
PlanForeignModify.
Para ejecutar la modificación directa en el servidor remoto, esta función debe reescribir el subplan de
destino con un nodo de plan ForeignScan que ejecute la modificación directa en el
servidor remoto. Los campos operation y
resultRelation de ForeignScan deben establecerse de
manera adecuada.
operation debe establecerse en la enumeración CmdType
correspondiente al tipo de sentencia (es decir, CMD_UPDATE para
UPDATE, CMD_INSERT para INSERT, y
CMD_DELETE para DELETE), y el argumento
resultRelation debe copiarse al campo resultRelation.
Consulta la Section 58.4 para obtener información adicional.
Si el puntero PlanDirectModify se establece en NULL, no se
realizan intentos de ejecutar una modificación directa en el servidor remoto.
void
BeginDirectModify(ForeignScanState *node,
int eflags);
Se prepara para ejecutar una modificación directa en el servidor remoto.
Se llama durante el inicio del ejecutor. Debe realizar cualquier inicialización necesaria antes de la
modificación directa (que debe hacerse en la primera llamada a IterateDirectModify).
El nodo ForeignScanState ya ha sido creado, pero su campo
fdw_state sigue siendo NULL. La información sobre la tabla a modificar es
accesible a través del nodo ForeignScanState (en particular, desde el nodo de
plan ForeignScan subyacente, que contiene cualquier información privada de FDW
proporcionada por PlanDirectModify).
eflags contiene bits de banderas que describen el modo de funcionamiento del ejecutor
para este nodo de plan.
Ten en cuenta que cuando (eflags & EXEC_FLAG_EXPLAIN_ONLY) es verdadero, esta
función no debe realizar ninguna acción externamente visible; solo debe hacer lo mínimo requerido para
que el estado del nodo sea válido para ExplainDirectModify y
EndDirectModify.
Si el puntero BeginDirectModify se establece en NULL, no se
realizan intentos de ejecutar una modificación directa en el servidor remoto.
TupleTableSlot * IterateDirectModify(ForeignScanState *node);
Cuando la consulta INSERT, UPDATE o DELETE no
tiene una cláusula RETURNING, simplemente devuelve NULL después de una modificación
directa en el servidor remoto.
Cuando la consulta tiene la cláusula, obtiene un resultado que contiene los datos necesarios para el
cálculo de RETURNING, devolviéndolo en una ranura de tabla de tuplas (se debe usar la
ranura ScanTupleSlot del nodo para este propósito). Los datos que realmente se
insertaron, actualizaron o eliminaron deben almacenarse en
node->resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple.
Devuelve NULL si no hay más filas disponibles.
Ten en cuenta que esto se llama en un contexto de memoria de corta duración que se restablecerá entre
invocaciones. Crea un contexto de memoria en BeginDirectModify si necesitas un
almacenamiento de mayor duración, o usa el es_query_cxt del
EState del nodo.
Las filas devueltas deben coincidir con la lista de objetivos fdw_scan_tlist
si se proporcionó una, de lo contrario deben coincidir con el tipo de fila de la tabla externa que se está
actualizando. Si decides optimizar omitiendo la obtención de columnas que no son necesarias para el
cálculo de RETURNING, debes insertar nulos en esas posiciones de columna, o bien
generar una lista fdw_scan_tlist con esas columnas omitidas.
Independientemente de si la consulta tiene la cláusula o no, el recuento de filas reportado por la consulta
debe ser incrementado por el propio FDW. Cuando la consulta no tiene la cláusula, el FDW también debe
incrementar el recuento de filas para el nodo ForeignScanState en el caso de
EXPLAIN ANALYZE.
Si el puntero IterateDirectModify se establece en NULL, no se
realizan intentos de ejecutar una modificación directa en el servidor remoto.
void EndDirectModify(ForeignScanState *node);
Limpia después de una modificación directa en el servidor remoto. Normalmente no es importante liberar la memoria asignada con palloc, pero por ejemplo, se deben cerrar los archivos abiertos y las conexiones al servidor remoto.
Si el puntero EndDirectModify se establece en NULL, no se realizan
intentos de ejecutar una modificación directa en el servidor remoto.
TRUNCATE #
void
ExecForeignTruncate(List *rels,
DropBehavior behavior,
bool restart_seqs);
Vacía (truncate) tablas externas. Esta función se llama cuando se ejecuta TRUNCATE
en una tabla externa.
rels is una lista de estructuras de datos Relation de las
tablas externas a vaciar.
behavior es DROP_RESTRICT o DROP_CASCADE, lo que
indica que se solicitó la opción RESTRICT o CASCADE en el comando
TRUNCATE original, respectivamente.
Si restart_seqs es true, el comando TRUNCATE
original solicitó el comportamiento RESTART IDENTITY, de lo contrario se solicitó el
comportamiento CONTINUE IDENTITY.
Ten en cuenta que las opciones ONLY especificadas en el comando
TRUNCATE original no se pasan a ExecForeignTruncate. Este
comportamiento es similar al de las funciones de retrollamada de SELECT,
UPDATE y DELETE en una tabla externa.
ExecForeignTruncate se invoca una vez por servidor externo para el cual se van a
vaciar las tablas externas. Esto significa que todas las tablas externas incluidas en rels
deben pertenecer al mismo servidor.
Si el puntero ExecForeignTruncate se establece en NULL, los intentos
de vaciar tablas externas fallarán con un mensaje de error.
Si un FDW desea admitir el bloqueo tardío de filas (late row locking) (como se describe en la Section 58.5), debe proporcionar las siguientes funciones de retrollamada:
RowMarkType
GetForeignRowMarkType(RangeTblEntry *rte,
LockClauseStrength strength);
Informa qué opción de marcado de filas usar para una tabla externa.
rte es el nodo RangeTblEntry para la tabla y
strength describe la fuerza del bloqueo solicitada por la cláusula
FOR UPDATE/SHARE relevante, si la hay. El resultado debe ser un miembro del tipo
enumerado RowMarkType.
Esta función se llama durante la planificación de la consulta para cada tabla externa que aparece en una
consulta UPDATE, DELETE o SELECT FOR UPDATE/SHARE
y no es el destino de UPDATE o DELETE.
Si el puntero GetForeignRowMarkType se establece en NULL, siempre
se utiliza la opción ROW_MARK_COPY. (Esto implica que
RefetchForeignRow nunca se llamará, por lo que tampoco es necesario proporcionarla).
Consulta la Section 58.5 para obtener más información.
void
RefetchForeignRow(EState *estate,
ExecRowMark *erm,
Datum rowid,
TupleTableSlot *slot,
bool *updated);
Vuelve a obtener una ranura de tupla de la tabla externa, después de bloquearla si es necesario.
estate es el estado de ejecución global para la consulta.
erm es la estructura ExecRowMark que describe la tabla externa
de destino y el tipo de bloqueo de fila (si lo hay) a adquirir.
rowid identifica la tupla a obtener.
slot no contiene nada útil al ser llamada, pero se puede usar para contener la tupla
devuelta. updated es un parámetro de salida.
Esta función debe almacenar la tupla en la ranura proporcionada, o limpiarla si no se pudo obtener el
bloqueo de fila. El tipo de bloqueo de fila a adquirir se define mediante
erm->markType, que es el valor devuelto previamente por
GetForeignRowMarkType. (ROW_MARK_REFERENCE significa simplemente
volver a obtener la tupla sin adquirir ningún bloqueo, y esta rutina nunca verá
ROW_MARK_COPY).
Además, *updated debe establecerse en true si lo que se obtuvo fue una
versión actualizada de la tupla en lugar de la misma versión obtenida anteriormente. (Si el FDW no puede
estar seguro de esto, se recomienda devolver siempre true).
Ten en cuenta que, por defecto, el fallo al adquirir un bloqueo de fila debe resultar en el lanzamiento
de un error; devolver una ranura vacía solo es apropiado si la opción SKIP LOCKED está
especificada por erm->waitPolicy.
El rowid es el valor de ctid leído previamente para la fila
a volver a obtener. Aunque el valor de rowid se pasa como un Datum,
actualmente solo puede ser un tid. Se elige la API de la función con la esperanza de que
sea posible permitir otros tipos de datos para los ID de fila en el futuro.
Si el puntero RefetchForeignRow se establece en NULL, los intentos
de volver a obtener filas fallarán con un mensaje de error.
Consulta la Section 58.5 para obtener más información.
bool
RecheckForeignScan(ForeignScanState *node,
TupleTableSlot *slot);
Vuelve a comprobar que una tupla devuelta previamente siga coincidiendo con los calificadores de escaneo y
unión pertinentes, y posiblemente proporciona una versión modificada de la tupla. Para los adaptadores de
datos externos que no realizan la inserción de uniones (join pushdown), normalmente será más conveniente
establecer esto en NULL y, en su lugar, configurar
fdw_recheck_quals adecuadamente. Sin embargo, cuando se empujan hacia abajo las
uniones externas, no es suficiente volver a aplicar los controles pertinentes a todas las tablas base a
la tupla de resultado, incluso si todos los atributos necesarios están presentes, porque el fallo en la
coincidencia de algún calificador podría hacer que algunos atributos pasen a ser NULL, en lugar de que no
se devuelva ninguna tupla. RecheckForeignScan puede volver a comprobar los calificadores
y devolver true si todavía se cumplen y false en caso contrario, pero también puede almacenar una tupla
de reemplazo en la ranura suministrada.
Para implementar la inserción de uniones, un adaptador de datos externos normalmente construirá un plan
de unión local alternativo que se utiliza solo para las recomprobaciones; este se convertirá en el
subplan externo del ForeignScan. Cuando se requiere una recomprobación, este subplan
se puede ejecutar y la tupla resultante se puede almacenar en la ranura. Este plan no necesita ser
eficiente ya que ninguna tabla base devolverá más de una fila; por ejemplo, puede implementar todas las
uniones como bucles anidados. La función GetExistingLocalJoinPath se puede usar para
buscar en las rutas existentes una ruta de unión local adecuada, que se puede usar como el plan de unión
local alternativo. GetExistingLocalJoinPath busca una ruta no parametrizada en la lista
de rutas de la relación de unión especificada. (Si no encuentra dicha ruta, devuelve NULL, en cuyo caso
un adaptador de datos externos puede construir la ruta local por sí mismo o puede optar por no crear rutas
de acceso para esa unión).
EXPLAIN #
void
ExplainForeignScan(ForeignScanState *node,
ExplainState *es);
Imprime salida adicional de EXPLAIN para un escaneo de tabla externa.
Esta función puede llamar a ExplainPropertyText y funciones relacionadas para añadir
campos a la salida de EXPLAIN. Los campos de banderas en es se
pueden usar para determinar qué imprimir, y el estado del nodo ForeignScanState
se puede inspeccionar para proporcionar estadísticas de tiempo de ejecución en el caso de
EXPLAIN ANALYZE.
Si el puntero ExplainForeignScan se establece en NULL, no se
imprime información adicional durante un EXPLAIN.
void
ExplainForeignModify(ModifyTableState *mtstate,
ResultRelInfo *rinfo,
List *fdw_private,
int subplan_index,
struct ExplainState *es);
Imprime salida adicional de EXPLAIN para una actualización de tabla externa.
Esta función puede llamar a ExplainPropertyText y funciones relacionadas para añadir
campos a la salida de EXPLAIN. Los campos de banderas en es se
pueden usar para determinar qué imprimir, y el estado del nodo ModifyTableState
se puede inspeccionar para proporcionar estadísticas de tiempo de ejecución en el caso de
EXPLAIN ANALYZE. Los primeros cuatro argumentos son los mismos que para
BeginForeignModify.
Si el puntero ExplainForeignModify se establece en NULL, no se
imprime información adicional durante un EXPLAIN.
void
ExplainDirectModify(ForeignScanState *node,
ExplainState *es);
Imprime salida de EXPLAIN adicional para una modificación directa en el servidor remoto.
Esta función puede llamar a ExplainPropertyText y funciones relacionadas para añadir
campos a la salida de EXPLAIN. Los campos de banderas en es se pueden
usar para determinar qué imprimir, y el estado del nodo ForeignScanState se puede
inspeccionar para proporcionar estadísticas de tiempo de ejecución en el caso de
EXPLAIN ANALYZE.
Si el puntero ExplainDirectModify se establece en NULL, no se
imprime información adicional durante un EXPLAIN.
ANALYZE #
bool
AnalyzeForeignTable(Relation relation,
AcquireSampleRowsFunc *func,
BlockNumber *totalpages);
Esta función se llama cuando se ejecuta ANALYZE en una tabla externa. Si el FDW
puede recopilar estadísticas para esta tabla externa, debe devolver true y proporcionar
un puntero a una función que recopilará filas de muestra de la tabla en func, más
el tamaño estimado de la tabla en páginas en totalpages. De lo contrario, devuelve
false.
If el FDW no admite la recopilación de estadísticas para ninguna tabla, el puntero
AnalyzeForeignTable se puede establecer en NULL.
Si se proporciona, la función de recopilación de muestras debe tener la firma:
int
AcquireSampleRowsFunc(Relation relation,
int elevel,
HeapTuple *rows,
int targrows,
double *totalrows,
double *totaldeadrows);
Se debe recopilar una muestra aleatoria de hasta targrows filas de la tabla y
almacenarse en el array rows proporcionado por el invocador. Se debe devolver el
número real de filas recopiladas. Además, almacena estimaciones de los números totales de filas vivas y
muertas en la tabla en los parámetros de salida totalrows y
totaldeadrows. (Establece totaldeadrows en cero si el FDW
no tiene ningún concepto de filas muertas).
IMPORT FOREIGN SCHEMA #
List * ImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid);
Obtiene una lista de comandos de creación de tablas externas. Esta función se llama al ejecutar IMPORT FOREIGN SCHEMA, y se le pasa el árbol de análisis (parse tree) para esa sentencia, así como el OID del servidor externo a usar. Debe devolver una lista de cadenas de C, cada una de las cuales debe contener un comando CREATE FOREIGN TABLE. Estas cadenas serán analizadas y ejecutadas por el servidor principal.
Dentro de la estructura ImportForeignSchemaStmt,
remote_schema es el nombre del esquema remoto desde el cual se van a importar
las tablas.
list_type identifica cómo filtrar los nombres de las tablas:
FDW_IMPORT_SCHEMA_ALL significa que se deben importar todas las tablas del esquema
remoto (en este caso table_list está vacía),
FDW_IMPORT_SCHEMA_LIMIT_TO significa incluir solo las tablas enumeradas en
table_list, y FDW_IMPORT_SCHEMA_EXCEPT significa excluir
las tablas enumeradas en table_list.
options es una lista de opciones utilizadas para el proceso de importación. El
significado de las opciones depende del FDW. Por ejemplo, un FDW podría usar una opción para definir si
se deben importar los atributos NOT NULL de las columnas. Estas opciones no tienen por
qué tener nada que ver con las admitidas por el FDW como opciones de objeto de base de datos.
El FDW puede ignorar el campo local_schema de la estructura
ImportForeignSchemaStmt, porque el servidor principal insertará automáticamente
ese nombre en los comandos CREATE FOREIGN TABLE analizados.
El FDW tampoco tiene que preocuparse por implementar el filtrado especificado por
list_type y table_list, ya que el servidor
principal omitirá automáticamente cualquier comando devuelto para las tablas excluidas según esas opciones.
Sin embargo, a menudo es útil para evitar el trabajo de crear comandos para tablas excluidas en primer
lugar. La función IsImportableForeignTable() puede ser útil para probar si un nombre
de tabla externa dado pasará el filtro.
Si el FDW no admite la importación de definiciones de tablas, el puntero
ImportForeignSchema se puede establecer en NULL.
Un nodo ForeignScan puede, opcionalmente, admitir la ejecución en paralelo. Un
ForeignScan en paralelo se ejecutará en múltiples procesos y debe devolver cada
fila exactamente una vez entre todos los procesos que cooperan. Para hacer esto, los procesos pueden
coordinarse a través de fragmentos de tamaño fijo de memoria compartida dinámica. No se garantiza que esta
memoria compartida esté mapeada en la misma dirección en cada proceso, por lo que no debe contener
punteros. Las siguientes funciones son todas opcionales, pero la mayoría son requeridas si se va a
admitir la ejecución en paralelo.
bool
IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
RangeTblEntry *rte);
Comprueba si se puede realizar un escaneo dentro de un trabajador en paralelo. Esta función solo se llamará cuando el planificador crea que un plan paralelo podría ser posible, y debe devolver true si es seguro que ese escaneo se ejecute dentro de un trabajador paralelo. Este no será el caso generalmente si la fuente de datos remota tiene semántica de transacción, a menos que la conexión del trabajador a los datos se pueda hacer de alguna manera para compartir el mismo contexto de transacción que el líder.
If esta función no está definida, se asume que el escaneo debe realizarse dentro del líder en paralelo. Ten en cuenta que devolver true no significa que el escaneo en sí pueda realizarse en paralelo, solo que el escaneo se puede realizar dentro de un trabajador en paralelo. Por lo tanto, puede ser útil definir este método incluso cuando la ejecución en paralelo no sea compatible.
Size EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
Estima la cantidad de memoria compartida dinámica que se requerirá para la operación en paralelo. Esto puede ser mayor que la cantidad que realmente se usará, pero no debe ser menor. El valor de retorno es en bytes. Esta función es opcional y puede omitirse si no es necesaria; pero si se omite, las siguientes tres funciones también deben omitirse, ya que no se asignará memoria compartida para el uso del FDW.
void
InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
void *coordinate);
Inicializa la memoria compartida dinámica que se requerirá para la operación paralela.
coordinate apunta a un área de memoria compartida de tamaño igual al valor de retorno de
EstimateDSMForeignScan. Esta función es opcional y puede omitirse si no es necesaria.
void
ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
void *coordinate);
Vuelve a inicializar la memoria compartida dinámica requerida para la operación paralela cuando el nodo de
plan de escaneo externo está a punto de volver a escanearse. Esta función es opcional y puede omitirse si
no es necesaria. La práctica recomendada es que esta función restablezca solo el estado compartido,
mientras que la función ReScanForeignScan restablece solo el estado local. Actualmente,
esta función se llamará antes de ReScanForeignScan, pero es mejor no confiar en ese
orden.
void
InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
void *coordinate);
Inicializa el estado local de un trabajador paralelo basándose en el estado compartido configurado por el
líder durante InitializeDSMForeignScan. Esta función es opcional y puede omitirse si
no es necesaria.
void ShutdownForeignScan(ForeignScanState *node);
Libera recursos cuando se prevé que el nodo no se ejecutará hasta su finalización. Esto no se llama en todos
los casos; a veces, se puede llamar a EndForeignScan sin que esta función se haya
llamado primero. Dado que el segmento DSM utilizado por la consulta paralela se destruye justo después de que
se invoque esta retrollamada, los adaptadores de datos externos que deseen realizar alguna acción antes de
que el segmento DSM desaparezca deben implementar este método.
Un nodo ForeignScan puede, opcionalmente, admitir la ejecución asíncrona como se
describe en src/backend/executor/README. Las siguientes funciones son todas
opcionales, pero son requeridas si se va a admitir la ejecución asíncrona.
bool IsForeignPathAsyncCapable(ForeignPath *path);
Comprueba si una ruta ForeignPath dada puede escanear la relación externa
subyacente de forma asíncrona. Esta función solo se llamará al final de la planificación de la consulta
cuando la ruta dada sea hija directa de una ruta AppendPath y cuando el
planificador crea que la ejecución asíncrona mejora el rendimiento, y debe devolver true si la ruta dada
es capaz de escanear la relación externa de forma asíncrona.
Si esta función no está definida, se asume que la ruta dada escanea la relación externa usando
IterateForeignScan. (Esto implica que las funciones de retrollamada descritas a
continuación nunca se llamarán, por lo que tampoco es necesario proporcionarlas).
void ForeignAsyncRequest(AsyncRequest *areq);
Produce una tupla de forma asíncrona desde el nodo ForeignScan.
areq es la estructura AsyncRequest que describe el nodo
ForeignScan y el nodo Append padre que solicitó la
tupla de este. Esta función debe almacenar la tupla en la ranura especificada por
areq->result, y establecer areq->request_complete en
true; o bien, si necesita esperar un evento externo al servidor principal, como E/S de
red, y no puede producir ninguna tupla inmediatamente, establecer la bandera en false, y
establecer areq->callback_pending en true para que el nodo
ForeignScan obtenga una llamada de las funciones de retrollamada descritas a
continuación. Si no hay más tuplas disponibles, establece la ranura en NULL o en una ranura vacía, y la
bandera areq->request_complete en true. Se recomienda usar
ExecAsyncRequestDone o ExecAsyncRequestPending para configurar
los parámetros de salida en areq.
void ForeignAsyncConfigureWait(AsyncRequest *areq);
Configura un evento de descriptor de archivo por el cual el nodo ForeignScan desea
esperar. Esta función solo se llamará cuando el nodo ForeignScan tenga establecida
la bandera areq->callback_pending, y debe añadir el evento al campo
as_eventset del nodo Append padre descrito por el
parámetro areq. Consulta los comentarios para
ExecAsyncConfigureWait en src/backend/executor/execAsync.c para
obtener información adicional. Cuando ocurra el evento del descriptor de archivo, se llamará a
ForeignAsyncNotify.
void ForeignAsyncNotify(AsyncRequest *areq);
Procesa un evento relevante que ha ocurrido, luego produce una tupla de forma asíncrona desde el nodo
ForeignScan. Esta función debe configurar los parámetros de salida en
areq de la misma manera que ForeignAsyncRequest.
List *
ReparameterizeForeignPathByChild(PlannerInfo *root, List *fdw_private,
RelOptInfo *child_rel);
Esta función se llama al convertir una ruta parametrizada por el padre de nivel superior de la relación
hija dada child_rel para que sea parametrizada por la relación hija. La función se utiliza
para parametrizar de nuevo cualquier ruta o traducir cualquier nodo de expresión guardado en el miembro
fdw_private dado de una ruta ForeignPath. La retrollamada puede
usar reparameterize_path_by_child, adjust_appendrel_attrs o
adjust_appendrel_attrs_multilevel según sea necesario.