TRUNCATEEXPLAINANALYZEIMPORT FOREIGN SCHEMA
The FDW handler function returns a palloc'd FdwRoutine
struct containing pointers to the callback functions described below.
The scan-related functions are required, the rest are optional.
The FdwRoutine struct type is declared in
src/include/foreign/fdwapi.h, which see for additional
details.
void
GetForeignRelSize(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid);
Obtain relation size estimates for a foreign table. This is called
at the beginning of planning for a query that scans a foreign table.
root is the planner's global information about the query;
baserel is the planner's information about this table; and
foreigntableid is the pg_class OID of the
foreign table. (foreigntableid could be obtained from the
planner data structures, but it's passed explicitly to save effort.)
This function should update baserel->rows to be the
expected number of rows returned by the table scan, after accounting for
the filtering done by the restriction quals. The initial value of
baserel->rows is just a constant default estimate, which
should be replaced if at all possible. The function may also choose to
update baserel->width if it can compute a better estimate
of the average result row width.
(The initial value is based on column data types and on column
average-width values measured by the last ANALYZE.)
Also, this function may update baserel->tuples if
it can compute a better estimate of the foreign table's total row count.
(The initial value is
from pg_class.reltuples
which represents the total row count seen by the
last ANALYZE; it will be -1 if
no ANALYZE has been done on this foreign table.)
See Section 59.4 for additional information.
void
GetForeignPaths(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid);
Create possible access paths for a scan on a foreign table.
This is called during query planning.
The parameters are the same as for GetForeignRelSize,
which has already been called.
This function must generate at least one access path
(ForeignPath node) for a scan on the foreign table and
must call add_path to add each such path to
baserel->pathlist. It's recommended to use
create_foreignscan_path to build the
ForeignPath nodes. The function can generate multiple
access paths, e.g., a path which has valid pathkeys to
represent a pre-sorted result. Each access path must contain cost
estimates, and can contain any FDW-private information that is needed to
identify the specific scan method intended.
See Section 59.4 for additional information.
ForeignScan *
GetForeignPlan(PlannerInfo *root,
RelOptInfo *baserel,
Oid foreigntableid,
ForeignPath *best_path,
List *tlist,
List *scan_clauses,
Plan *outer_plan);
Create a ForeignScan plan node from the selected foreign
access path. This is called at the end of query planning.
The parameters are as for GetForeignRelSize, plus
the selected ForeignPath (previously produced by
GetForeignPaths, GetForeignJoinPaths,
or GetForeignUpperPaths),
the target list to be emitted by the plan node,
the restriction clauses to be enforced by the plan node,
and the outer subplan of the ForeignScan,
which is used for rechecks performed by RecheckForeignScan.
(If the path is for a join rather than a base
relation, foreigntableid is InvalidOid.)
This function must create and return a ForeignScan plan
node; it's recommended to use make_foreignscan to build the
ForeignScan node.
See Section 59.4 for additional information.
void
BeginForeignScan(ForeignScanState *node,
int eflags);
Begin executing a foreign scan. This is called during executor startup.
It should perform any initialization needed before the scan can start,
but not start executing the actual scan (that should be done upon the
first call to IterateForeignScan).
The ForeignScanState node has already been created, but
its fdw_state field is still NULL. Information about
the table to scan is accessible through the
ForeignScanState node (in particular, from the underlying
ForeignScan plan node, which contains any FDW-private
information provided by GetForeignPlan).
eflags contains flag bits describing the executor's
operating mode for this plan node.
Note that when (eflags & EXEC_FLAG_EXPLAIN_ONLY) is
true, this function should not perform any externally-visible actions;
it should only do the minimum required to make the node state valid
for ExplainForeignScan and EndForeignScan.
TupleTableSlot * IterateForeignScan(ForeignScanState *node);
Fetch one row from the foreign source, returning it in a tuple table slot
(the node's ScanTupleSlot should be used for this
purpose). Return NULL if no more rows are available. The tuple table
slot infrastructure allows either a physical or virtual tuple to be
returned; in most cases the latter choice is preferable from a
performance standpoint. Note that this is called in a short-lived memory
context that will be reset between invocations. Create a memory context
in BeginForeignScan if you need longer-lived storage, or use
the es_query_cxt of the node's EState.
The rows returned must match the fdw_scan_tlist target
list if one was supplied, otherwise they must match the row type of the
foreign table being scanned. If you choose to optimize away fetching
columns that are not needed, you should insert nulls in those column
positions, or else generate a fdw_scan_tlist list with
those columns omitted.
Note that PostgreSQL's executor doesn't care whether the rows returned violate any constraints that were defined on the foreign table — but the planner does care, and may optimize queries incorrectly if there are rows visible in the foreign table that do not satisfy a declared constraint. If a constraint is violated when the user has declared that the constraint should hold true, it may be appropriate to raise an error (just as you would need to do in the case of a data type mismatch).
void ReScanForeignScan(ForeignScanState *node);
Restart the scan from the beginning. Note that any parameters the scan depends on may have changed value, so the new scan does not necessarily return exactly the same rows.
void EndForeignScan(ForeignScanState *node);
End the scan and release resources. It is normally not important to release palloc'd memory, but for example open files and connections to remote servers should be cleaned up.
If an FDW supports performing foreign joins remotely (rather than by fetching both tables' data and doing the join locally), it should provide this callback function:
void
GetForeignJoinPaths(PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
RelOptInfo *innerrel,
JoinType jointype,
JoinPathExtraData *extra);
Create possible access paths for a join of two (or more) foreign tables
that all belong to the same foreign server. This optional
function is called during query planning. As
with GetForeignPaths, this function should
generate ForeignPath path(s) for the
supplied joinrel
(use create_foreign_join_path to build them),
and call add_path to add these
paths to the set of paths considered for the join. But unlike
GetForeignPaths, it is not necessary that this function
succeed in creating at least one path, since paths involving local
joining are always possible.
Note that this function will be invoked repeatedly for the same join relation, with different combinations of inner and outer relations; it is the responsibility of the FDW to minimize duplicated work.
If a ForeignPath path is chosen for the join, it will
represent the entire join process; paths generated for the component
tables and subsidiary joins will not be used. Subsequent processing of
the join path proceeds much as it does for a path scanning a single
foreign table. One difference is that the scanrelid of
the resulting ForeignScan plan node should be set to zero,
since there is no single relation that it represents; instead,
the fs_relids field of the ForeignScan
node represents the set of relations that were joined. (The latter field
is set up automatically by the core planner code, and need not be filled
by the FDW.) Another difference is that, because the column list for a
remote join cannot be found from the system catalogs, the FDW must
fill fdw_scan_tlist with an appropriate list
of TargetEntry nodes, representing the set of columns
it will supply at run time in the tuples it returns.
Beginning with PostgreSQL 16,
fs_relids includes the rangetable indexes
of outer joins, if any were involved in this join. The new field
fs_base_relids includes only base
relation indexes, and thus
mimics fs_relids's old semantics.
See Section 59.4 for additional information.
If an FDW supports performing remote post-scan/join processing, such as remote aggregation, it should provide this callback function:
void
GetForeignUpperPaths(PlannerInfo *root,
UpperRelationKind stage,
RelOptInfo *input_rel,
RelOptInfo *output_rel,
void *extra);
Create possible access paths for upper relation processing,
which is the planner's term for all post-scan/join query processing, such
as aggregation, window functions, sorting, and table updates. This
optional function is called during query planning. Currently, it is
called only if all base relation(s) involved in the query belong to the
same FDW. This function should generate ForeignPath
path(s) for any post-scan/join processing that the FDW knows how to
perform remotely
(use create_foreign_upper_path to build them),
and call add_path to add these paths to
the indicated upper relation. As with GetForeignJoinPaths,
it is not necessary that this function succeed in creating any paths,
since paths involving local processing are always possible.
The stage parameter identifies which post-scan/join step is
currently being considered. output_rel is the upper relation
that should receive paths representing computation of this step,
and input_rel is the relation representing the input to this
step. The extra parameter provides additional details,
currently, it is set only for UPPERREL_PARTIAL_GROUP_AGG
or UPPERREL_GROUP_AGG, in which case it points to a
GroupPathExtraData structure;
or for UPPERREL_FINAL, in which case it points to a
FinalPathExtraData structure.
(Note that ForeignPath paths added
to output_rel would typically not have any direct dependency
on paths of the input_rel, since their processing is expected
to be done externally. However, examining paths previously generated for
the previous processing step can be useful to avoid redundant planning
work.)
See Section 59.4 for additional information.
If an FDW supports writable foreign tables, it should provide some or all of the following callback functions depending on the needs and capabilities of the FDW: