summaryrefslogtreecommitdiffstats
path: root/doc/src/sgml/html/fdw-callbacks.html
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--doc/src/sgml/html/fdw-callbacks.html1266
1 files changed, 1266 insertions, 0 deletions
diff --git a/doc/src/sgml/html/fdw-callbacks.html b/doc/src/sgml/html/fdw-callbacks.html
new file mode 100644
index 0000000..a339a8f
--- /dev/null
+++ b/doc/src/sgml/html/fdw-callbacks.html
@@ -0,0 +1,1266 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>59.2. Foreign Data Wrapper Callback Routines</title><link rel="stylesheet" type="text/css" href="stylesheet.css" /><link rev="made" href="pgsql-docs@lists.postgresql.org" /><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot" /><link rel="prev" href="fdw-functions.html" title="59.1. Foreign Data Wrapper Functions" /><link rel="next" href="fdw-helpers.html" title="59.3. Foreign Data Wrapper Helper Functions" /></head><body id="docContent" class="container-fluid col-10"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">59.2. Foreign Data Wrapper Callback Routines</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="fdw-functions.html" title="59.1. Foreign Data Wrapper Functions">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="fdwhandler.html" title="Chapter 59. Writing a Foreign Data Wrapper">Up</a></td><th width="60%" align="center">Chapter 59. Writing a Foreign Data Wrapper</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 16.2 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="fdw-helpers.html" title="59.3. Foreign Data Wrapper Helper Functions">Next</a></td></tr></table><hr /></div><div class="sect1" id="FDW-CALLBACKS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">59.2. Foreign Data Wrapper Callback Routines <a href="#FDW-CALLBACKS" class="id_link">#</a></h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-SCAN">59.2.1. FDW Routines for Scanning Foreign Tables</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-JOIN-SCAN">59.2.2. FDW Routines for Scanning Foreign Joins</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-UPPER-PLANNING">59.2.3. FDW Routines for Planning Post-Scan/Join Processing</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-UPDATE">59.2.4. FDW Routines for Updating Foreign Tables</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-TRUNCATE">59.2.5. FDW Routines for <code class="command">TRUNCATE</code></a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-ROW-LOCKING">59.2.6. FDW Routines for Row Locking</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-EXPLAIN">59.2.7. FDW Routines for <code class="command">EXPLAIN</code></a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-ANALYZE">59.2.8. FDW Routines for <code class="command">ANALYZE</code></a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-IMPORT">59.2.9. FDW Routines for <code class="command">IMPORT FOREIGN SCHEMA</code></a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-PARALLEL">59.2.10. FDW Routines for Parallel Execution</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-ASYNC">59.2.11. FDW Routines for Asynchronous Execution</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-REPARAMETERIZE-PATHS">59.2.12. FDW Routines for Reparameterization of Paths</a></span></dt></dl></div><p>
+ The FDW handler function returns a palloc'd <code class="structname">FdwRoutine</code>
+ struct containing pointers to the callback functions described below.
+ The scan-related functions are required, the rest are optional.
+ </p><p>
+ The <code class="structname">FdwRoutine</code> struct type is declared in
+ <code class="filename">src/include/foreign/fdwapi.h</code>, which see for additional
+ details.
+ </p><div class="sect2" id="FDW-CALLBACKS-SCAN"><div class="titlepage"><div><div><h3 class="title">59.2.1. FDW Routines for Scanning Foreign Tables <a href="#FDW-CALLBACKS-SCAN" class="id_link">#</a></h3></div></div></div><p>
+</p><pre class="programlisting">
+void
+GetForeignRelSize(PlannerInfo *root,
+ RelOptInfo *baserel,
+ Oid foreigntableid);
+</pre><p>
+
+ Obtain relation size estimates for a foreign table. This is called
+ at the beginning of planning for a query that scans a foreign table.
+ <code class="literal">root</code> is the planner's global information about the query;
+ <code class="literal">baserel</code> is the planner's information about this table; and
+ <code class="literal">foreigntableid</code> is the <code class="structname">pg_class</code> OID of the
+ foreign table. (<code class="literal">foreigntableid</code> could be obtained from the
+ planner data structures, but it's passed explicitly to save effort.)
+ </p><p>
+ This function should update <code class="literal">baserel-&gt;rows</code> 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
+ <code class="literal">baserel-&gt;rows</code> is just a constant default estimate, which
+ should be replaced if at all possible. The function may also choose to
+ update <code class="literal">baserel-&gt;width</code> 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 <code class="command">ANALYZE</code>.)
+ Also, this function may update <code class="literal">baserel-&gt;tuples</code> if
+ it can compute a better estimate of the foreign table's total row count.
+ (The initial value is
+ from <code class="structname">pg_class</code>.<code class="structfield">reltuples</code>
+ which represents the total row count seen by the
+ last <code class="command">ANALYZE</code>; it will be <code class="literal">-1</code> if
+ no <code class="command">ANALYZE</code> has been done on this foreign table.)
+ </p><p>
+ See <a class="xref" href="fdw-planning.html" title="59.4. Foreign Data Wrapper Query Planning">Section 59.4</a> for additional information.
+ </p><p>
+</p><pre class="programlisting">
+void
+GetForeignPaths(PlannerInfo *root,
+ RelOptInfo *baserel,
+ Oid foreigntableid);
+</pre><p>
+
+ Create possible access paths for a scan on a foreign table.
+ This is called during query planning.
+ The parameters are the same as for <code class="function">GetForeignRelSize</code>,
+ which has already been called.
+ </p><p>
+ This function must generate at least one access path
+ (<code class="structname">ForeignPath</code> node) for a scan on the foreign table and
+ must call <code class="function">add_path</code> to add each such path to
+ <code class="literal">baserel-&gt;pathlist</code>. It's recommended to use
+ <code class="function">create_foreignscan_path</code> to build the
+ <code class="structname">ForeignPath</code> nodes. The function can generate multiple
+ access paths, e.g., a path which has valid <code class="literal">pathkeys</code> 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.
+ </p><p>
+ See <a class="xref" href="fdw-planning.html" title="59.4. Foreign Data Wrapper Query Planning">Section 59.4</a> for additional information.
+ </p><p>
+</p><pre class="programlisting">
+ForeignScan *
+GetForeignPlan(PlannerInfo *root,
+ RelOptInfo *baserel,
+ Oid foreigntableid,
+ ForeignPath *best_path,
+ List *tlist,
+ List *scan_clauses,
+ Plan *outer_plan);
+</pre><p>
+
+ Create a <code class="structname">ForeignScan</code> plan node from the selected foreign
+ access path. This is called at the end of query planning.
+ The parameters are as for <code class="function">GetForeignRelSize</code>, plus
+ the selected <code class="structname">ForeignPath</code> (previously produced by
+ <code class="function">GetForeignPaths</code>, <code class="function">GetForeignJoinPaths</code>,
+ or <code class="function">GetForeignUpperPaths</code>),
+ 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 <code class="structname">ForeignScan</code>,
+ which is used for rechecks performed by <code class="function">RecheckForeignScan</code>.
+ (If the path is for a join rather than a base
+ relation, <code class="literal">foreigntableid</code> is <code class="literal">InvalidOid</code>.)
+ </p><p>
+ This function must create and return a <code class="structname">ForeignScan</code> plan
+ node; it's recommended to use <code class="function">make_foreignscan</code> to build the
+ <code class="structname">ForeignScan</code> node.
+ </p><p>
+ See <a class="xref" href="fdw-planning.html" title="59.4. Foreign Data Wrapper Query Planning">Section 59.4</a> for additional information.
+ </p><p>
+</p><pre class="programlisting">
+void
+BeginForeignScan(ForeignScanState *node,
+ int eflags);
+</pre><p>
+
+ 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 <code class="function">IterateForeignScan</code>).
+ The <code class="structname">ForeignScanState</code> node has already been created, but
+ its <code class="structfield">fdw_state</code> field is still NULL. Information about
+ the table to scan is accessible through the
+ <code class="structname">ForeignScanState</code> node (in particular, from the underlying
+ <code class="structname">ForeignScan</code> plan node, which contains any FDW-private
+ information provided by <code class="function">GetForeignPlan</code>).
+ <code class="literal">eflags</code> contains flag bits describing the executor's
+ operating mode for this plan node.
+ </p><p>
+ Note that when <code class="literal">(eflags &amp; EXEC_FLAG_EXPLAIN_ONLY)</code> 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 <code class="function">ExplainForeignScan</code> and <code class="function">EndForeignScan</code>.
+ </p><p>
+</p><pre class="programlisting">
+TupleTableSlot *
+IterateForeignScan(ForeignScanState *node);
+</pre><p>
+
+ Fetch one row from the foreign source, returning it in a tuple table slot
+ (the node's <code class="structfield">ScanTupleSlot</code> 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 <code class="function">BeginForeignScan</code> if you need longer-lived storage, or use
+ the <code class="structfield">es_query_cxt</code> of the node's <code class="structname">EState</code>.
+ </p><p>
+ The rows returned must match the <code class="structfield">fdw_scan_tlist</code> 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 <code class="structfield">fdw_scan_tlist</code> list with
+ those columns omitted.
+ </p><p>
+ Note that <span class="productname">PostgreSQL</span>'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).
+ </p><p>
+</p><pre class="programlisting">
+void
+ReScanForeignScan(ForeignScanState *node);
+</pre><p>
+
+ 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.
+ </p><p>
+</p><pre class="programlisting">
+void
+EndForeignScan(ForeignScanState *node);
+</pre><p>
+
+ 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.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-JOIN-SCAN"><div class="titlepage"><div><div><h3 class="title">59.2.2. FDW Routines for Scanning Foreign Joins <a href="#FDW-CALLBACKS-JOIN-SCAN" class="id_link">#</a></h3></div></div></div><p>
+ 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:
+ </p><p>
+</p><pre class="programlisting">
+void
+GetForeignJoinPaths(PlannerInfo *root,
+ RelOptInfo *joinrel,
+ RelOptInfo *outerrel,
+ RelOptInfo *innerrel,
+ JoinType jointype,
+ JoinPathExtraData *extra);
+</pre><p>
+ 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 <code class="function">GetForeignPaths</code>, this function should
+ generate <code class="structname">ForeignPath</code> path(s) for the
+ supplied <code class="literal">joinrel</code>
+ (use <code class="function">create_foreign_join_path</code> to build them),
+ and call <code class="function">add_path</code> to add these
+ paths to the set of paths considered for the join. But unlike
+ <code class="function">GetForeignPaths</code>, it is not necessary that this function
+ succeed in creating at least one path, since paths involving local
+ joining are always possible.
+ </p><p>
+ 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.
+ </p><p>
+ If a <code class="structname">ForeignPath</code> 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 <code class="structfield">scanrelid</code> of
+ the resulting <code class="structname">ForeignScan</code> plan node should be set to zero,
+ since there is no single relation that it represents; instead,
+ the <code class="structfield">fs_relids</code> field of the <code class="structname">ForeignScan</code>
+ 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 <code class="structfield">fdw_scan_tlist</code> with an appropriate list
+ of <code class="structfield">TargetEntry</code> nodes, representing the set of columns
+ it will supply at run time in the tuples it returns.
+ </p><div class="note"><h3 class="title">Note</h3><p>
+ Beginning with <span class="productname">PostgreSQL</span> 16,
+ <code class="structfield">fs_relids</code> includes the rangetable indexes
+ of outer joins, if any were involved in this join. The new field
+ <code class="structfield">fs_base_relids</code> includes only base
+ relation indexes, and thus
+ mimics <code class="structfield">fs_relids</code>'s old semantics.
+ </p></div><p>
+ See <a class="xref" href="fdw-planning.html" title="59.4. Foreign Data Wrapper Query Planning">Section 59.4</a> for additional information.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-UPPER-PLANNING"><div class="titlepage"><div><div><h3 class="title">59.2.3. FDW Routines for Planning Post-Scan/Join Processing <a href="#FDW-CALLBACKS-UPPER-PLANNING" class="id_link">#</a></h3></div></div></div><p>
+ If an FDW supports performing remote post-scan/join processing, such as
+ remote aggregation, it should provide this callback function:
+ </p><p>
+</p><pre class="programlisting">
+void
+GetForeignUpperPaths(PlannerInfo *root,
+ UpperRelationKind stage,
+ RelOptInfo *input_rel,
+ RelOptInfo *output_rel,
+ void *extra);
+</pre><p>
+ Create possible access paths for <em class="firstterm">upper relation</em> 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 <code class="structname">ForeignPath</code>
+ path(s) for any post-scan/join processing that the FDW knows how to
+ perform remotely
+ (use <code class="function">create_foreign_upper_path</code> to build them),
+ and call <code class="function">add_path</code> to add these paths to
+ the indicated upper relation. As with <code class="function">GetForeignJoinPaths</code>,
+ it is not necessary that this function succeed in creating any paths,
+ since paths involving local processing are always possible.
+ </p><p>
+ The <code class="literal">stage</code> parameter identifies which post-scan/join step is
+ currently being considered. <code class="literal">output_rel</code> is the upper relation
+ that should receive paths representing computation of this step,
+ and <code class="literal">input_rel</code> is the relation representing the input to this
+ step. The <code class="literal">extra</code> parameter provides additional details,
+ currently, it is set only for <code class="literal">UPPERREL_PARTIAL_GROUP_AGG</code>
+ or <code class="literal">UPPERREL_GROUP_AGG</code>, in which case it points to a
+ <code class="literal">GroupPathExtraData</code> structure;
+ or for <code class="literal">UPPERREL_FINAL</code>, in which case it points to a
+ <code class="literal">FinalPathExtraData</code> structure.
+ (Note that <code class="structname">ForeignPath</code> paths added
+ to <code class="literal">output_rel</code> would typically not have any direct dependency
+ on paths of the <code class="literal">input_rel</code>, 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.)
+ </p><p>
+ See <a class="xref" href="fdw-planning.html" title="59.4. Foreign Data Wrapper Query Planning">Section 59.4</a> for additional information.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-UPDATE"><div class="titlepage"><div><div><h3 class="title">59.2.4. FDW Routines for Updating Foreign Tables <a href="#FDW-CALLBACKS-UPDATE" class="id_link">#</a></h3></div></div></div><p>
+ 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:
+ </p><p>
+</p><pre class="programlisting">
+void
+AddForeignUpdateTargets(PlannerInfo *root,
+ Index rtindex,
+ RangeTblEntry *target_rte,
+ Relation target_relation);
+</pre><p>
+
+ <code class="command">UPDATE</code> and <code class="command">DELETE</code> operations are performed
+ against rows previously fetched by the table-scanning functions. The
+ FDW may need extra information, such as a row ID or the values of
+ primary-key columns, to ensure that it can identify the exact row to
+ update or delete. To support that, this function can add extra hidden,
+ or <span class="quote">“<span class="quote">junk</span>”</span>, target columns to the list of columns that are to be
+ retrieved from the foreign table during an <code class="command">UPDATE</code> or
+ <code class="command">DELETE</code>.
+ </p><p>
+ To do that, construct a <code class="structname">Var</code> representing
+ an extra value you need, and pass it
+ to <code class="function">add_row_identity_var</code>, along with a name for
+ the junk column. (You can do this more than once if several columns
+ are needed.) You must choose a distinct junk column name for each
+ different <code class="structname">Var</code> you need, except
+ that <code class="structname">Var</code>s that are identical except for
+ the <code class="structfield">varno</code> field can and should share a
+ column name.
+ The core system uses the junk column names
+ <code class="literal">tableoid</code> for a
+ table's <code class="structfield">tableoid</code> column,
+ <code class="literal">ctid</code>
+ or <code class="literal">ctid<em class="replaceable"><code>N</code></em></code>
+ for <code class="structfield">ctid</code>,
+ <code class="literal">wholerow</code>
+ for a whole-row <code class="structname">Var</code> marked with
+ <code class="structfield">vartype</code> = <code class="type">RECORD</code>,
+ and <code class="literal">wholerow<em class="replaceable"><code>N</code></em></code>
+ for a whole-row <code class="structname">Var</code> with
+ <code class="structfield">vartype</code> equal to the table's declared row type.
+ Re-use these names when you can (the planner will combine duplicate
+ requests for identical junk columns). If you need another kind of
+ junk column besides these, it might be wise to choose a name prefixed
+ with your extension name, to avoid conflicts against other FDWs.
+ </p><p>
+ If the <code class="function">AddForeignUpdateTargets</code> pointer is set to
+ <code class="literal">NULL</code>, no extra target expressions are added.
+ (This will make it impossible to implement <code class="command">DELETE</code>
+ operations, though <code class="command">UPDATE</code> may still be feasible if the FDW
+ relies on an unchanging primary key to identify rows.)
+ </p><p>
+</p><pre class="programlisting">
+List *
+PlanForeignModify(PlannerInfo *root,
+ ModifyTable *plan,
+ Index resultRelation,
+ int subplan_index);
+</pre><p>
+
+ Perform any additional planning actions needed for an insert, update, or
+ delete on a foreign table. This function generates the FDW-private
+ information that will be attached to the <code class="structname">ModifyTable</code> plan
+ node that performs the update action. This private information must
+ have the form of a <code class="literal">List</code>, and will be delivered to
+ <code class="function">BeginForeignModify</code> during the execution stage.
+ </p><p>
+ <code class="literal">root</code> is the planner's global information about the query.
+ <code class="literal">plan</code> is the <code class="structname">ModifyTable</code> plan node, which is
+ complete except for the <code class="structfield">fdwPrivLists</code> field.
+ <code class="literal">resultRelation</code> identifies the target foreign table by its
+ range table index. <code class="literal">subplan_index</code> identifies which target of
+ the <code class="structname">ModifyTable</code> plan node this is, counting from zero;
+ use this if you want to index into per-target-relation substructures of the
+ <code class="literal">plan</code> node.
+ </p><p>
+ See <a class="xref" href="fdw-planning.html" title="59.4. Foreign Data Wrapper Query Planning">Section 59.4</a> for additional information.
+ </p><p>
+ If the <code class="function">PlanForeignModify</code> pointer is set to
+ <code class="literal">NULL</code>, no additional plan-time actions are taken, and the
+ <code class="literal">fdw_private</code> list delivered to
+ <code class="function">BeginForeignModify</code> will be NIL.
+ </p><p>
+</p><pre class="programlisting">
+void
+BeginForeignModify(ModifyTableState *mtstate,
+ ResultRelInfo *rinfo,
+ List *fdw_private,
+ int subplan_index,
+ int eflags);
+</pre><p>
+
+ Begin executing a foreign table modification operation. This routine is
+ called during executor startup. It should perform any initialization
+ needed prior to the actual table modifications. Subsequently,
+ <code class="function">ExecForeignInsert/ExecForeignBatchInsert</code>,
+ <code class="function">ExecForeignUpdate</code> or
+ <code class="function">ExecForeignDelete</code> will be called for tuple(s) to be
+ inserted, updated, or deleted.
+ </p><p>
+ <code class="literal">mtstate</code> is the overall state of the
+ <code class="structname">ModifyTable</code> plan node being executed; global data about
+ the plan and execution state is available via this structure.
+ <code class="literal">rinfo</code> is the <code class="structname">ResultRelInfo</code> struct describing
+ the target foreign table. (The <code class="structfield">ri_FdwState</code> field of
+ <code class="structname">ResultRelInfo</code> is available for the FDW to store any
+ private state it needs for this operation.)
+ <code class="literal">fdw_private</code> contains the private data generated by
+ <code class="function">PlanForeignModify</code>, if any.
+ <code class="literal">subplan_index</code> identifies which target of
+ the <code class="structname">ModifyTable</code> plan node this is.
+ <code class="literal">eflags</code> contains flag bits describing the executor's
+ operating mode for this plan node.
+ </p><p>
+ Note that when <code class="literal">(eflags &amp; EXEC_FLAG_EXPLAIN_ONLY)</code> 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 <code class="function">ExplainForeignModify</code> and <code class="function">EndForeignModify</code>.
+ </p><p>
+ If the <code class="function">BeginForeignModify</code> pointer is set to
+ <code class="literal">NULL</code>, no action is taken during executor startup.
+ </p><p>
+</p><pre class="programlisting">
+TupleTableSlot *
+ExecForeignInsert(EState *estate,
+ ResultRelInfo *rinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *planSlot);
+</pre><p>
+
+ Insert one tuple into the foreign table.
+ <code class="literal">estate</code> is global execution state for the query.
+ <code class="literal">rinfo</code> is the <code class="structname">ResultRelInfo</code> struct describing
+ the target foreign table.
+ <code class="literal">slot</code> contains the tuple to be inserted; it will match the
+ row-type definition of the foreign table.
+ <code class="literal">planSlot</code> contains the tuple that was generated by the
+ <code class="structname">ModifyTable</code> plan node's subplan; it differs from
+ <code class="literal">slot</code> in possibly containing additional <span class="quote">“<span class="quote">junk</span>”</span>
+ columns. (The <code class="literal">planSlot</code> is typically of little interest
+ for <code class="command">INSERT</code> cases, but is provided for completeness.)
+ </p><p>
+ The return value is either a slot containing the data that was actually
+ inserted (this might differ from the data supplied, for example as a
+ result of trigger actions), or NULL if no row was actually inserted
+ (again, typically as a result of triggers). The passed-in
+ <code class="literal">slot</code> can be re-used for this purpose.
+ </p><p>
+ The data in the returned slot is used only if the <code class="command">INSERT</code>
+ statement has a <code class="literal">RETURNING</code> clause or involves a view
+ <code class="literal">WITH CHECK OPTION</code>; or if the foreign table has
+ an <code class="literal">AFTER ROW</code> trigger. Triggers require all columns,
+ but the FDW could choose to optimize away returning some or all columns
+ depending on the contents of the <code class="literal">RETURNING</code> clause or
+ <code class="literal">WITH CHECK OPTION</code> constraints. Regardless, some slot
+ must be returned to indicate success, or the query's reported row count
+ will be wrong.
+ </p><p>
+ If the <code class="function">ExecForeignInsert</code> pointer is set to
+ <code class="literal">NULL</code>, attempts to insert into the foreign table will fail
+ with an error message.
+ </p><p>
+ Note that this function is also called when inserting routed tuples into
+ a foreign-table partition or executing <code class="command">COPY FROM</code> on
+ a foreign table, in which case it is called in a different way than it
+ is in the <code class="command">INSERT</code> case. See the callback functions
+ described below that allow the FDW to support that.
+ </p><p>
+</p><pre class="programlisting">
+TupleTableSlot **
+ExecForeignBatchInsert(EState *estate,
+ ResultRelInfo *rinfo,
+ TupleTableSlot **slots,
+ TupleTableSlot **planSlots,
+ int *numSlots);
+</pre><p>
+
+ Insert multiple tuples in bulk into the foreign table.
+ The parameters are the same for <code class="function">ExecForeignInsert</code>
+ except <code class="literal">slots</code> and <code class="literal">planSlots</code> contain
+ multiple tuples and <code class="literal">*numSlots</code> specifies the number of
+ tuples in those arrays.
+ </p><p>
+ The return value is an array of slots containing the data that was
+ actually inserted (this might differ from the data supplied, for
+ example as a result of trigger actions.)
+ The passed-in <code class="literal">slots</code> can be re-used for this purpose.
+ The number of successfully inserted tuples is returned in
+ <code class="literal">*numSlots</code>.
+ </p><p>
+ The data in the returned slot is used only if the <code class="command">INSERT</code>
+ statement involves a view
+ <code class="literal">WITH CHECK OPTION</code>; or if the foreign table has
+ an <code class="literal">AFTER ROW</code> trigger. Triggers require all columns,
+ but the FDW could choose to optimize away returning some or all columns
+ depending on the contents of the
+ <code class="literal">WITH CHECK OPTION</code> constraints.
+ </p><p>
+ If the <code class="function">ExecForeignBatchInsert</code> or
+ <code class="function">GetForeignModifyBatchSize</code> pointer is set to
+ <code class="literal">NULL</code>, attempts to insert into the foreign table will
+ use <code class="function">ExecForeignInsert</code>.
+ This function is not used if the <code class="command">INSERT</code> has the
+ <code class="literal">RETURNING</code> clause.
+ </p><p>
+ Note that this function is also called when inserting routed tuples into
+ a foreign-table partition or executing <code class="command">COPY FROM</code> on
+ a foreign table, in which case it is called in a different way than it
+ is in the <code class="command">INSERT</code> case. See the callback functions
+ described below that allow the FDW to support that.
+ </p><p>
+</p><pre class="programlisting">
+int
+GetForeignModifyBatchSize(ResultRelInfo *rinfo);
+</pre><p>
+
+ Report the maximum number of tuples that a single
+ <code class="function">ExecForeignBatchInsert</code> call can handle for
+ the specified foreign table. The executor passes at most
+ the given number of tuples to <code class="function">ExecForeignBatchInsert</code>.
+ <code class="literal">rinfo</code> is the <code class="structname">ResultRelInfo</code> struct describing
+ the target foreign table.
+ The FDW is expected to provide a foreign server and/or foreign
+ table option for the user to set this value, or some hard-coded value.
+ </p><p>
+ If the <code class="function">ExecForeignBatchInsert</code> or
+ <code class="function">GetForeignModifyBatchSize</code> pointer is set to
+ <code class="literal">NULL</code>, attempts to insert into the foreign table will
+ use <code class="function">ExecForeignInsert</code>.
+ </p><p>
+</p><pre class="programlisting">
+TupleTableSlot *
+ExecForeignUpdate(EState *estate,
+ ResultRelInfo *rinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *planSlot);
+</pre><p>
+
+ Update one tuple in the foreign table.
+ <code class="literal">estate</code> is global execution state for the query.
+ <code class="literal">rinfo</code> is the <code class="structname">ResultRelInfo</code> struct describing
+ the target foreign table.
+ <code class="literal">slot</code> contains the new data for the tuple; it will match the
+ row-type definition of the foreign table.
+ <code class="literal">planSlot</code> contains the tuple that was generated by the
+ <code class="structname">ModifyTable</code> plan node's subplan. Unlike
+ <code class="literal">slot</code>, this tuple contains only the new values for
+ columns changed by the query, so do not rely on attribute numbers of the
+ foreign table to index into <code class="literal">planSlot</code>.
+ Also, <code class="literal">planSlot</code> typically contains
+ additional <span class="quote">“<span class="quote">junk</span>”</span> columns. In particular, any junk columns
+ that were requested by <code class="function">AddForeignUpdateTargets</code> will
+ be available from this slot.
+ </p><p>
+ The return value is either a slot containing the row as it was actually
+ updated (this might differ from the data supplied, for example as a
+ result of trigger actions), or NULL if no row was actually updated
+ (again, typically as a result of triggers). The passed-in
+ <code class="literal">slot</code> can be re-used for this purpose.
+ </p><p>
+ The data in the returned slot is used only if the <code class="command">UPDATE</code>
+ statement has a <code class="literal">RETURNING</code> clause or involves a view
+ <code class="literal">WITH CHECK OPTION</code>; or if the foreign table has
+ an <code class="literal">AFTER ROW</code> trigger. Triggers require all columns,
+ but the FDW could choose to optimize away returning some or all columns
+ depending on the contents of the <code class="literal">RETURNING</code> clause or
+ <code class="literal">WITH CHECK OPTION</code> constraints. Regardless, some slot
+ must be returned to indicate success, or the query's reported row count
+ will be wrong.
+ </p><p>
+ If the <code class="function">ExecForeignUpdate</code> pointer is set to
+ <code class="literal">NULL</code>, attempts to update the foreign table will fail
+ with an error message.
+ </p><p>
+</p><pre class="programlisting">
+TupleTableSlot *
+ExecForeignDelete(EState *estate,
+ ResultRelInfo *rinfo,
+ TupleTableSlot *slot,
+ TupleTableSlot *planSlot);
+</pre><p>
+
+ Delete one tuple from the foreign table.
+ <code class="literal">estate</code> is global execution state for the query.
+ <code class="literal">rinfo</code> is the <code class="structname">ResultRelInfo</code> struct describing
+ the target foreign table.
+ <code class="literal">slot</code> contains nothing useful upon call, but can be used to
+ hold the returned tuple.
+ <code class="literal">planSlot</code> contains the tuple that was generated by the
+ <code class="structname">ModifyTable</code> plan node's subplan; in particular, it will
+ carry any junk columns that were requested by
+ <code class="function">AddForeignUpdateTargets</code>. The junk column(s) must be used
+ to identify the tuple to be deleted.
+ </p><p>
+ The return value is either a slot containing the row that was deleted,
+ or NULL if no row was deleted (typically as a result of triggers). The
+ passed-in <code class="literal">slot</code> can be used to hold the tuple to be returned.
+ </p><p>
+ The data in the returned slot is used only if the <code class="command">DELETE</code>
+ query has a <code class="literal">RETURNING</code> clause or the foreign table has
+ an <code class="literal">AFTER ROW</code> trigger. Triggers require all columns, but the
+ FDW could choose to optimize away returning some or all columns depending
+ on the contents of the <code class="literal">RETURNING</code> clause. Regardless, some
+ slot must be returned to indicate success, or the query's reported row
+ count will be wrong.
+ </p><p>
+ If the <code class="function">ExecForeignDelete</code> pointer is set to
+ <code class="literal">NULL</code>, attempts to delete from the foreign table will fail
+ with an error message.
+ </p><p>
+</p><pre class="programlisting">
+void
+EndForeignModify(EState *estate,
+ ResultRelInfo *rinfo);
+</pre><p>
+
+ End the table update 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.
+ </p><p>
+ If the <code class="function">EndForeignModify</code> pointer is set to
+ <code class="literal">NULL</code>, no action is taken during executor shutdown.
+ </p><p>
+ Tuples inserted into a partitioned table by <code class="command">INSERT</code> or
+ <code class="command">COPY FROM</code> are routed to partitions. If an FDW
+ supports routable foreign-table partitions, it should also provide the
+ following callback functions. These functions are also called when
+ <code class="command">COPY FROM</code> is executed on a foreign table.
+ </p><p>
+</p><pre class="programlisting">
+void
+BeginForeignInsert(ModifyTableState *mtstate,
+ ResultRelInfo *rinfo);
+</pre><p>
+
+ Begin executing an insert operation on a foreign table. This routine is
+ called right before the first tuple is inserted into the foreign table
+ in both cases when it is the partition chosen for tuple routing and the
+ target specified in a <code class="command">COPY FROM</code> command. It should
+ perform any initialization needed prior to the actual insertion.
+ Subsequently, <code class="function">ExecForeignInsert</code> or
+ <code class="function">ExecForeignBatchInsert</code> will be called for
+ tuple(s) to be inserted into the foreign table.
+ </p><p>
+ <code class="literal">mtstate</code> is the overall state of the
+ <code class="structname">ModifyTable</code> plan node being executed; global data about
+ the plan and execution state is available via this structure.
+ <code class="literal">rinfo</code> is the <code class="structname">ResultRelInfo</code> struct describing
+ the target foreign table. (The <code class="structfield">ri_FdwState</code> field of
+ <code class="structname">ResultRelInfo</code> is available for the FDW to store any
+ private state it needs for this operation.)
+ </p><p>
+ When this is called by a <code class="command">COPY FROM</code> command, the
+ plan-related global data in <code class="literal">mtstate</code> is not provided
+ and the <code class="literal">planSlot</code> parameter of
+ <code class="function">ExecForeignInsert</code> subsequently called for each
+ inserted tuple is <code class="literal">NULL</code>, whether the foreign table is
+ the partition chosen for tuple routing or the target specified in the
+ command.
+ </p><p>
+ If the <code class="function">BeginForeignInsert</code> pointer is set to
+ <code class="literal">NULL</code>, no action is taken for the initialization.
+ </p><p>
+ Note that if the FDW does not support routable foreign-table partitions
+ and/or executing <code class="command">COPY FROM</code> on foreign tables, this
+ function or <code class="function">ExecForeignInsert/ExecForeignBatchInsert</code>
+ subsequently called must throw error as needed.
+ </p><p>
+</p><pre class="programlisting">
+void
+EndForeignInsert(EState *estate,
+ ResultRelInfo *rinfo);
+</pre><p>
+
+ End the insert operation 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.
+ </p><p>
+ If the <code class="function">EndForeignInsert</code> pointer is set to
+ <code class="literal">NULL</code>, no action is taken for the termination.
+ </p><p>
+</p><pre class="programlisting">
+int
+IsForeignRelUpdatable(Relation rel);
+</pre><p>
+
+ Report which update operations the specified foreign table supports.
+ The return value should be a bit mask of rule event numbers indicating
+ which operations are supported by the foreign table, using the
+ <code class="literal">CmdType</code> enumeration; that is,
+ <code class="literal">(1 &lt;&lt; CMD_UPDATE) = 4</code> for <code class="command">UPDATE</code>,
+ <code class="literal">(1 &lt;&lt; CMD_INSERT) = 8</code> for <code class="command">INSERT</code>, and
+ <code class="literal">(1 &lt;&lt; CMD_DELETE) = 16</code> for <code class="command">DELETE</code>.
+ </p><p>
+ If the <code class="function">IsForeignRelUpdatable</code> pointer is set to
+ <code class="literal">NULL</code>, foreign tables are assumed to be insertable, updatable,
+ or deletable if the FDW provides <code class="function">ExecForeignInsert</code>,
+ <code class="function">ExecForeignUpdate</code>, or <code class="function">ExecForeignDelete</code>
+ respectively. This function is only needed if the FDW supports some
+ tables that are updatable and some that are not. (Even then, it's
+ permissible to throw an error in the execution routine instead of
+ checking in this function. However, this function is used to determine
+ updatability for display in the <code class="literal">information_schema</code> views.)
+ </p><p>
+ Some inserts, updates, and deletes to foreign tables can be optimized
+ by implementing an alternative set of interfaces. The ordinary
+ interfaces for inserts, updates, and deletes fetch rows from the remote
+ server and then modify those rows one at a time. In some cases, this
+ row-by-row approach is necessary, but it can be inefficient. If it is
+ possible for the foreign server to determine which rows should be
+ modified without actually retrieving them, and if there are no local
+ structures which would affect the operation (row-level local triggers,
+ stored generated columns, or <code class="literal">WITH CHECK OPTION</code>
+ constraints from parent views), then it is possible to arrange things
+ so that the entire operation is performed on the remote server. The
+ interfaces described below make this possible.
+ </p><p>
+</p><pre class="programlisting">
+bool
+PlanDirectModify(PlannerInfo *root,
+ ModifyTable *plan,
+ Index resultRelation,
+ int subplan_index);
+</pre><p>
+
+ Decide whether it is safe to execute a direct modification
+ on the remote server. If so, return <code class="literal">true</code> after performing
+ planning actions needed for that. Otherwise, return <code class="literal">false</code>.
+ This optional function is called during query planning.
+ If this function succeeds, <code class="function">BeginDirectModify</code>,
+ <code class="function">IterateDirectModify</code> and <code class="function">EndDirectModify</code> will
+ be called at the execution stage, instead. Otherwise, the table
+ modification will be executed using the table-updating functions
+ described above.
+ The parameters are the same as for <code class="function">PlanForeignModify</code>.
+ </p><p>
+ To execute the direct modification on the remote server, this function
+ must rewrite the target subplan with a <code class="structname">ForeignScan</code> plan
+ node that executes the direct modification on the remote server. The
+ <code class="structfield">operation</code> and <code class="structfield">resultRelation</code> fields
+ of the <code class="structname">ForeignScan</code> must be set appropriately.
+ <code class="structfield">operation</code> must be set to the <code class="literal">CmdType</code>
+ enumeration corresponding to the statement kind (that is,
+ <code class="literal">CMD_UPDATE</code> for <code class="command">UPDATE</code>,
+ <code class="literal">CMD_INSERT</code> for <code class="command">INSERT</code>, and
+ <code class="literal">CMD_DELETE</code> for <code class="command">DELETE</code>), and the
+ <code class="literal">resultRelation</code> argument must be copied to the
+ <code class="structfield">resultRelation</code> field.
+ </p><p>
+ See <a class="xref" href="fdw-planning.html" title="59.4. Foreign Data Wrapper Query Planning">Section 59.4</a> for additional information.
+ </p><p>
+ If the <code class="function">PlanDirectModify</code> pointer is set to
+ <code class="literal">NULL</code>, no attempts to execute a direct modification on the
+ remote server are taken.
+ </p><p>
+</p><pre class="programlisting">
+void
+BeginDirectModify(ForeignScanState *node,
+ int eflags);
+</pre><p>
+
+ Prepare to execute a direct modification on the remote server.
+ This is called during executor startup. It should perform any
+ initialization needed prior to the direct modification (that should be
+ done upon the first call to <code class="function">IterateDirectModify</code>).
+ The <code class="structname">ForeignScanState</code> node has already been created, but
+ its <code class="structfield">fdw_state</code> field is still NULL. Information about
+ the table to modify is accessible through the
+ <code class="structname">ForeignScanState</code> node (in particular, from the underlying
+ <code class="structname">ForeignScan</code> plan node, which contains any FDW-private
+ information provided by <code class="function">PlanDirectModify</code>).
+ <code class="literal">eflags</code> contains flag bits describing the executor's
+ operating mode for this plan node.
+ </p><p>
+ Note that when <code class="literal">(eflags &amp; EXEC_FLAG_EXPLAIN_ONLY)</code> 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 <code class="function">ExplainDirectModify</code> and <code class="function">EndDirectModify</code>.
+ </p><p>
+ If the <code class="function">BeginDirectModify</code> pointer is set to
+ <code class="literal">NULL</code>, no attempts to execute a direct modification on the
+ remote server are taken.
+ </p><p>
+</p><pre class="programlisting">
+TupleTableSlot *
+IterateDirectModify(ForeignScanState *node);
+</pre><p>
+
+ When the <code class="command">INSERT</code>, <code class="command">UPDATE</code> or <code class="command">DELETE</code>
+ query doesn't have a <code class="literal">RETURNING</code> clause, just return NULL
+ after a direct modification on the remote server.
+ When the query has the clause, fetch one result containing the data
+ needed for the <code class="literal">RETURNING</code> calculation, returning it in a
+ tuple table slot (the node's <code class="structfield">ScanTupleSlot</code> should be
+ used for this purpose). The data that was actually inserted, updated
+ or deleted must be stored in
+ <code class="literal">node-&gt;resultRelInfo-&gt;ri_projectReturning-&gt;pi_exprContext-&gt;ecxt_scantuple</code>.
+ Return NULL if no more rows are available.
+ Note that this is called in a short-lived memory context that will be
+ reset between invocations. Create a memory context in
+ <code class="function">BeginDirectModify</code> if you need longer-lived storage, or use
+ the <code class="structfield">es_query_cxt</code> of the node's <code class="structname">EState</code>.
+ </p><p>
+ The rows returned must match the <code class="structfield">fdw_scan_tlist</code> target
+ list if one was supplied, otherwise they must match the row type of the
+ foreign table being updated. If you choose to optimize away fetching
+ columns that are not needed for the <code class="literal">RETURNING</code> calculation,
+ you should insert nulls in those column positions, or else generate a
+ <code class="structfield">fdw_scan_tlist</code> list with those columns omitted.
+ </p><p>
+ Whether the query has the clause or not, the query's reported row count
+ must be incremented by the FDW itself. When the query doesn't have the
+ clause, the FDW must also increment the row count for the
+ <code class="structname">ForeignScanState</code> node in the <code class="command">EXPLAIN ANALYZE</code>
+ case.
+ </p><p>
+ If the <code class="function">IterateDirectModify</code> pointer is set to
+ <code class="literal">NULL</code>, no attempts to execute a direct modification on the
+ remote server are taken.
+ </p><p>
+</p><pre class="programlisting">
+void
+EndDirectModify(ForeignScanState *node);
+</pre><p>
+
+ Clean up following a direct modification on the remote server. It is
+ normally not important to release palloc'd memory, but for example open
+ files and connections to the remote server should be cleaned up.
+ </p><p>
+ If the <code class="function">EndDirectModify</code> pointer is set to
+ <code class="literal">NULL</code>, no attempts to execute a direct modification on the
+ remote server are taken.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-TRUNCATE"><div class="titlepage"><div><div><h3 class="title">59.2.5. FDW Routines for <code class="command">TRUNCATE</code> <a href="#FDW-CALLBACKS-TRUNCATE" class="id_link">#</a></h3></div></div></div><p>
+</p><pre class="programlisting">
+void
+ExecForeignTruncate(List *rels,
+ DropBehavior behavior,
+ bool restart_seqs);
+</pre><p>
+
+ Truncate foreign tables. This function is called when
+ <a class="xref" href="sql-truncate.html" title="TRUNCATE"><span class="refentrytitle">TRUNCATE</span></a> is executed on a foreign table.
+ <code class="literal">rels</code> is a list of <code class="structname">Relation</code>
+ data structures of foreign tables to truncate.
+ </p><p>
+ <code class="literal">behavior</code> is either <code class="literal">DROP_RESTRICT</code>
+ or <code class="literal">DROP_CASCADE</code> indicating that the
+ <code class="literal">RESTRICT</code> or <code class="literal">CASCADE</code> option was
+ requested in the original <code class="command">TRUNCATE</code> command,
+ respectively.
+ </p><p>
+ If <code class="literal">restart_seqs</code> is <code class="literal">true</code>,
+ the original <code class="command">TRUNCATE</code> command requested the
+ <code class="literal">RESTART IDENTITY</code> behavior, otherwise the
+ <code class="literal">CONTINUE IDENTITY</code> behavior was requested.
+ </p><p>
+ Note that the <code class="literal">ONLY</code> options specified
+ in the original <code class="command">TRUNCATE</code> command are not passed to
+ <code class="function">ExecForeignTruncate</code>. This behavior is similar to
+ the callback functions of <code class="command">SELECT</code>,
+ <code class="command">UPDATE</code> and <code class="command">DELETE</code> on
+ a foreign table.
+ </p><p>
+ <code class="function">ExecForeignTruncate</code> is invoked once per
+ foreign server for which foreign tables are to be truncated.
+ This means that all foreign tables included in <code class="literal">rels</code>
+ must belong to the same server.
+ </p><p>
+ If the <code class="function">ExecForeignTruncate</code> pointer is set to
+ <code class="literal">NULL</code>, attempts to truncate foreign tables will
+ fail with an error message.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-ROW-LOCKING"><div class="titlepage"><div><div><h3 class="title">59.2.6. FDW Routines for Row Locking <a href="#FDW-CALLBACKS-ROW-LOCKING" class="id_link">#</a></h3></div></div></div><p>
+ If an FDW wishes to support <em class="firstterm">late row locking</em> (as described
+ in <a class="xref" href="fdw-row-locking.html" title="59.5. Row Locking in Foreign Data Wrappers">Section 59.5</a>), it must provide the following
+ callback functions:
+ </p><p>
+</p><pre class="programlisting">
+RowMarkType
+GetForeignRowMarkType(RangeTblEntry *rte,
+ LockClauseStrength strength);
+</pre><p>
+
+ Report which row-marking option to use for a foreign table.
+ <code class="literal">rte</code> is the <code class="structname">RangeTblEntry</code> node for the table
+ and <code class="literal">strength</code> describes the lock strength requested by the
+ relevant <code class="literal">FOR UPDATE/SHARE</code> clause, if any. The result must be
+ a member of the <code class="literal">RowMarkType</code> enum type.
+ </p><p>
+ This function is called during query planning for each foreign table that
+ appears in an <code class="command">UPDATE</code>, <code class="command">DELETE</code>, or <code class="command">SELECT
+ FOR UPDATE/SHARE</code> query and is not the target of <code class="command">UPDATE</code>
+ or <code class="command">DELETE</code>.
+ </p><p>
+ If the <code class="function">GetForeignRowMarkType</code> pointer is set to
+ <code class="literal">NULL</code>, the <code class="literal">ROW_MARK_COPY</code> option is always used.
+ (This implies that <code class="function">RefetchForeignRow</code> will never be called,
+ so it need not be provided either.)
+ </p><p>
+ See <a class="xref" href="fdw-row-locking.html" title="59.5. Row Locking in Foreign Data Wrappers">Section 59.5</a> for more information.
+ </p><p>
+</p><pre class="programlisting">
+void
+RefetchForeignRow(EState *estate,
+ ExecRowMark *erm,
+ Datum rowid,
+ TupleTableSlot *slot,
+ bool *updated);
+</pre><p>
+
+ Re-fetch one tuple slot from the foreign table, after locking it if required.
+ <code class="literal">estate</code> is global execution state for the query.
+ <code class="literal">erm</code> is the <code class="structname">ExecRowMark</code> struct describing
+ the target foreign table and the row lock type (if any) to acquire.
+ <code class="literal">rowid</code> identifies the tuple to be fetched.
+ <code class="literal">slot</code> contains nothing useful upon call, but can be used to
+ hold the returned tuple. <code class="literal">updated</code> is an output parameter.
+ </p><p>
+ This function should store the tuple into the provided slot, or clear it if
+ the row lock couldn't be obtained. The row lock type to acquire is
+ defined by <code class="literal">erm-&gt;markType</code>, which is the value
+ previously returned by <code class="function">GetForeignRowMarkType</code>.
+ (<code class="literal">ROW_MARK_REFERENCE</code> means to just re-fetch the tuple
+ without acquiring any lock, and <code class="literal">ROW_MARK_COPY</code> will
+ never be seen by this routine.)
+ </p><p>
+ In addition, <code class="literal">*updated</code> should be set to <code class="literal">true</code>
+ if what was fetched was an updated version of the tuple rather than
+ the same version previously obtained. (If the FDW cannot be sure about
+ this, always returning <code class="literal">true</code> is recommended.)
+ </p><p>
+ Note that by default, failure to acquire a row lock should result in
+ raising an error; returning with an empty slot is only appropriate if
+ the <code class="literal">SKIP LOCKED</code> option is specified
+ by <code class="literal">erm-&gt;waitPolicy</code>.
+ </p><p>
+ The <code class="literal">rowid</code> is the <code class="structfield">ctid</code> value previously read
+ for the row to be re-fetched. Although the <code class="literal">rowid</code> value is
+ passed as a <code class="type">Datum</code>, it can currently only be a <code class="type">tid</code>. The
+ function API is chosen in hopes that it may be possible to allow other
+ data types for row IDs in future.
+ </p><p>
+ If the <code class="function">RefetchForeignRow</code> pointer is set to
+ <code class="literal">NULL</code>, attempts to re-fetch rows will fail
+ with an error message.
+ </p><p>
+ See <a class="xref" href="fdw-row-locking.html" title="59.5. Row Locking in Foreign Data Wrappers">Section 59.5</a> for more information.
+ </p><p>
+</p><pre class="programlisting">
+bool
+RecheckForeignScan(ForeignScanState *node,
+ TupleTableSlot *slot);
+</pre><p>
+ Recheck that a previously-returned tuple still matches the relevant
+ scan and join qualifiers, and possibly provide a modified version of
+ the tuple. For foreign data wrappers which do not perform join pushdown,
+ it will typically be more convenient to set this to <code class="literal">NULL</code> and
+ instead set <code class="structfield">fdw_recheck_quals</code> appropriately.
+ When outer joins are pushed down, however, it isn't sufficient to
+ reapply the checks relevant to all the base tables to the result tuple,
+ even if all needed attributes are present, because failure to match some
+ qualifier might result in some attributes going to NULL, rather than in
+ no tuple being returned. <code class="literal">RecheckForeignScan</code> can recheck
+ qualifiers and return true if they are still satisfied and false
+ otherwise, but it can also store a replacement tuple into the supplied
+ slot.
+ </p><p>
+ To implement join pushdown, a foreign data wrapper will typically
+ construct an alternative local join plan which is used only for
+ rechecks; this will become the outer subplan of the
+ <code class="literal">ForeignScan</code>. When a recheck is required, this subplan
+ can be executed and the resulting tuple can be stored in the slot.
+ This plan need not be efficient since no base table will return more
+ than one row; for example, it may implement all joins as nested loops.
+ The function <code class="literal">GetExistingLocalJoinPath</code> may be used to search
+ existing paths for a suitable local join path, which can be used as the
+ alternative local join plan. <code class="literal">GetExistingLocalJoinPath</code>
+ searches for an unparameterized path in the path list of the specified
+ join relation. (If it does not find such a path, it returns NULL, in
+ which case a foreign data wrapper may build the local path by itself or
+ may choose not to create access paths for that join.)
+ </p></div><div class="sect2" id="FDW-CALLBACKS-EXPLAIN"><div class="titlepage"><div><div><h3 class="title">59.2.7. FDW Routines for <code class="command">EXPLAIN</code> <a href="#FDW-CALLBACKS-EXPLAIN" class="id_link">#</a></h3></div></div></div><p>
+</p><pre class="programlisting">
+void
+ExplainForeignScan(ForeignScanState *node,
+ ExplainState *es);
+</pre><p>
+
+ Print additional <code class="command">EXPLAIN</code> output for a foreign table scan.
+ This function can call <code class="function">ExplainPropertyText</code> and
+ related functions to add fields to the <code class="command">EXPLAIN</code> output.
+ The flag fields in <code class="literal">es</code> can be used to determine what to
+ print, and the state of the <code class="structname">ForeignScanState</code> node
+ can be inspected to provide run-time statistics in the <code class="command">EXPLAIN
+ ANALYZE</code> case.
+ </p><p>
+ If the <code class="function">ExplainForeignScan</code> pointer is set to
+ <code class="literal">NULL</code>, no additional information is printed during
+ <code class="command">EXPLAIN</code>.
+ </p><p>
+</p><pre class="programlisting">
+void
+ExplainForeignModify(ModifyTableState *mtstate,
+ ResultRelInfo *rinfo,
+ List *fdw_private,
+ int subplan_index,
+ struct ExplainState *es);
+</pre><p>
+
+ Print additional <code class="command">EXPLAIN</code> output for a foreign table update.
+ This function can call <code class="function">ExplainPropertyText</code> and
+ related functions to add fields to the <code class="command">EXPLAIN</code> output.
+ The flag fields in <code class="literal">es</code> can be used to determine what to
+ print, and the state of the <code class="structname">ModifyTableState</code> node
+ can be inspected to provide run-time statistics in the <code class="command">EXPLAIN
+ ANALYZE</code> case. The first four arguments are the same as for
+ <code class="function">BeginForeignModify</code>.
+ </p><p>
+ If the <code class="function">ExplainForeignModify</code> pointer is set to
+ <code class="literal">NULL</code>, no additional information is printed during
+ <code class="command">EXPLAIN</code>.
+ </p><p>
+</p><pre class="programlisting">
+void
+ExplainDirectModify(ForeignScanState *node,
+ ExplainState *es);
+</pre><p>
+
+ Print additional <code class="command">EXPLAIN</code> output for a direct modification
+ on the remote server.
+ This function can call <code class="function">ExplainPropertyText</code> and
+ related functions to add fields to the <code class="command">EXPLAIN</code> output.
+ The flag fields in <code class="literal">es</code> can be used to determine what to
+ print, and the state of the <code class="structname">ForeignScanState</code> node
+ can be inspected to provide run-time statistics in the <code class="command">EXPLAIN
+ ANALYZE</code> case.
+ </p><p>
+ If the <code class="function">ExplainDirectModify</code> pointer is set to
+ <code class="literal">NULL</code>, no additional information is printed during
+ <code class="command">EXPLAIN</code>.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-ANALYZE"><div class="titlepage"><div><div><h3 class="title">59.2.8. FDW Routines for <code class="command">ANALYZE</code> <a href="#FDW-CALLBACKS-ANALYZE" class="id_link">#</a></h3></div></div></div><p>
+</p><pre class="programlisting">
+bool
+AnalyzeForeignTable(Relation relation,
+ AcquireSampleRowsFunc *func,
+ BlockNumber *totalpages);
+</pre><p>
+
+ This function is called when <a class="xref" href="sql-analyze.html" title="ANALYZE"><span class="refentrytitle">ANALYZE</span></a> is executed on
+ a foreign table. If the FDW can collect statistics for this
+ foreign table, it should return <code class="literal">true</code>, and provide a pointer
+ to a function that will collect sample rows from the table in
+ <em class="parameter"><code>func</code></em>, plus the estimated size of the table in pages in
+ <em class="parameter"><code>totalpages</code></em>. Otherwise, return <code class="literal">false</code>.
+ </p><p>
+ If the FDW does not support collecting statistics for any tables, the
+ <code class="function">AnalyzeForeignTable</code> pointer can be set to <code class="literal">NULL</code>.
+ </p><p>
+ If provided, the sample collection function must have the signature
+</p><pre class="programlisting">
+int
+AcquireSampleRowsFunc(Relation relation,
+ int elevel,
+ HeapTuple *rows,
+ int targrows,
+ double *totalrows,
+ double *totaldeadrows);
+</pre><p>
+
+ A random sample of up to <em class="parameter"><code>targrows</code></em> rows should be collected
+ from the table and stored into the caller-provided <em class="parameter"><code>rows</code></em>
+ array. The actual number of rows collected must be returned. In
+ addition, store estimates of the total numbers of live and dead rows in
+ the table into the output parameters <em class="parameter"><code>totalrows</code></em> and
+ <em class="parameter"><code>totaldeadrows</code></em>. (Set <em class="parameter"><code>totaldeadrows</code></em> to zero
+ if the FDW does not have any concept of dead rows.)
+ </p></div><div class="sect2" id="FDW-CALLBACKS-IMPORT"><div class="titlepage"><div><div><h3 class="title">59.2.9. FDW Routines for <code class="command">IMPORT FOREIGN SCHEMA</code> <a href="#FDW-CALLBACKS-IMPORT" class="id_link">#</a></h3></div></div></div><p>
+</p><pre class="programlisting">
+List *
+ImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid);
+</pre><p>
+
+ Obtain a list of foreign table creation commands. This function is
+ called when executing <a class="xref" href="sql-importforeignschema.html" title="IMPORT FOREIGN SCHEMA"><span class="refentrytitle">IMPORT FOREIGN SCHEMA</span></a>, and is
+ passed the parse tree for that statement, as well as the OID of the
+ foreign server to use. It should return a list of C strings, each of
+ which must contain a <a class="xref" href="sql-createforeigntable.html" title="CREATE FOREIGN TABLE"><span class="refentrytitle">CREATE FOREIGN TABLE</span></a> command.
+ These strings will be parsed and executed by the core server.
+ </p><p>
+ Within the <code class="structname">ImportForeignSchemaStmt</code> struct,
+ <code class="structfield">remote_schema</code> is the name of the remote schema from
+ which tables are to be imported.
+ <code class="structfield">list_type</code> identifies how to filter table names:
+ <code class="literal">FDW_IMPORT_SCHEMA_ALL</code> means that all tables in the remote
+ schema should be imported (in this case <code class="structfield">table_list</code> is
+ empty), <code class="literal">FDW_IMPORT_SCHEMA_LIMIT_TO</code> means to include only
+ tables listed in <code class="structfield">table_list</code>,
+ and <code class="literal">FDW_IMPORT_SCHEMA_EXCEPT</code> means to exclude the tables
+ listed in <code class="structfield">table_list</code>.
+ <code class="structfield">options</code> is a list of options used for the import process.
+ The meanings of the options are up to the FDW.
+ For example, an FDW could use an option to define whether the
+ <code class="literal">NOT NULL</code> attributes of columns should be imported.
+ These options need not have anything to do with those supported by the
+ FDW as database object options.
+ </p><p>
+ The FDW may ignore the <code class="structfield">local_schema</code> field of
+ the <code class="structname">ImportForeignSchemaStmt</code>, because the core server
+ will automatically insert that name into the parsed <code class="command">CREATE
+ FOREIGN TABLE</code> commands.
+ </p><p>
+ The FDW does not have to concern itself with implementing the filtering
+ specified by <code class="structfield">list_type</code> and <code class="structfield">table_list</code>,
+ either, as the core server will automatically skip any returned commands
+ for tables excluded according to those options. However, it's often
+ useful to avoid the work of creating commands for excluded tables in the
+ first place. The function <code class="function">IsImportableForeignTable()</code> may be
+ useful to test whether a given foreign-table name will pass the filter.
+ </p><p>
+ If the FDW does not support importing table definitions, the
+ <code class="function">ImportForeignSchema</code> pointer can be set to <code class="literal">NULL</code>.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-PARALLEL"><div class="titlepage"><div><div><h3 class="title">59.2.10. FDW Routines for Parallel Execution <a href="#FDW-CALLBACKS-PARALLEL" class="id_link">#</a></h3></div></div></div><p>
+ A <code class="structname">ForeignScan</code> node can, optionally, support parallel
+ execution. A parallel <code class="structname">ForeignScan</code> will be executed
+ in multiple processes and must return each row exactly once across
+ all cooperating processes. To do this, processes can coordinate through
+ fixed-size chunks of dynamic shared memory. This shared memory is not
+ guaranteed to be mapped at the same address in every process, so it
+ must not contain pointers. The following functions are all optional,
+ but most are required if parallel execution is to be supported.
+ </p><p>
+</p><pre class="programlisting">
+bool
+IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
+ RangeTblEntry *rte);
+</pre><p>
+ Test whether a scan can be performed within a parallel worker. This
+ function will only be called when the planner believes that a parallel
+ plan might be possible, and should return true if it is safe for that scan
+ to run within a parallel worker. This will generally not be the case if
+ the remote data source has transaction semantics, unless the worker's
+ connection to the data can somehow be made to share the same transaction
+ context as the leader.
+ </p><p>
+ If this function is not defined, it is assumed that the scan must take
+ place within the parallel leader. Note that returning true does not mean
+ that the scan itself can be done in parallel, only that the scan can be
+ performed within a parallel worker. Therefore, it can be useful to define
+ this method even when parallel execution is not supported.
+ </p><p>
+</p><pre class="programlisting">
+Size
+EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
+</pre><p>
+ Estimate the amount of dynamic shared memory that will be required
+ for parallel operation. This may be higher than the amount that will
+ actually be used, but it must not be lower. The return value is in bytes.
+ This function is optional, and can be omitted if not needed; but if it
+ is omitted, the next three functions must be omitted as well, because
+ no shared memory will be allocated for the FDW's use.
+ </p><p>
+</p><pre class="programlisting">
+void
+InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
+ void *coordinate);
+</pre><p>
+ Initialize the dynamic shared memory that will be required for parallel
+ operation. <code class="literal">coordinate</code> points to a shared memory area of
+ size equal to the return value of <code class="function">EstimateDSMForeignScan</code>.
+ This function is optional, and can be omitted if not needed.
+ </p><p>
+</p><pre class="programlisting">
+void
+ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
+ void *coordinate);
+</pre><p>
+ Re-initialize the dynamic shared memory required for parallel operation
+ when the foreign-scan plan node is about to be re-scanned.
+ This function is optional, and can be omitted if not needed.
+ Recommended practice is that this function reset only shared state,
+ while the <code class="function">ReScanForeignScan</code> function resets only local
+ state. Currently, this function will be called
+ before <code class="function">ReScanForeignScan</code>, but it's best not to rely on
+ that ordering.
+ </p><p>
+</p><pre class="programlisting">
+void
+InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
+ void *coordinate);
+</pre><p>
+ Initialize a parallel worker's local state based on the shared state
+ set up by the leader during <code class="function">InitializeDSMForeignScan</code>.
+ This function is optional, and can be omitted if not needed.
+ </p><p>
+</p><pre class="programlisting">
+void
+ShutdownForeignScan(ForeignScanState *node);
+</pre><p>
+ Release resources when it is anticipated the node will not be executed
+ to completion. This is not called in all cases; sometimes,
+ <code class="literal">EndForeignScan</code> may be called without this function having
+ been called first. Since the DSM segment used by parallel query is
+ destroyed just after this callback is invoked, foreign data wrappers that
+ wish to take some action before the DSM segment goes away should implement
+ this method.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-ASYNC"><div class="titlepage"><div><div><h3 class="title">59.2.11. FDW Routines for Asynchronous Execution <a href="#FDW-CALLBACKS-ASYNC" class="id_link">#</a></h3></div></div></div><p>
+ A <code class="structname">ForeignScan</code> node can, optionally, support
+ asynchronous execution as described in
+ <code class="filename">src/backend/executor/README</code>. The following
+ functions are all optional, but are all required if asynchronous
+ execution is to be supported.
+ </p><p>
+</p><pre class="programlisting">
+bool
+IsForeignPathAsyncCapable(ForeignPath *path);
+</pre><p>
+ Test whether a given <code class="structname">ForeignPath</code> path can scan
+ the underlying foreign relation asynchronously.
+ This function will only be called at the end of query planning when the
+ given path is a direct child of an <code class="structname">AppendPath</code>
+ path and when the planner believes that asynchronous execution improves
+ performance, and should return true if the given path is able to scan the
+ foreign relation asynchronously.
+ </p><p>
+ If this function is not defined, it is assumed that the given path scans
+ the foreign relation using <code class="function">IterateForeignScan</code>.
+ (This implies that the callback functions described below will never be
+ called, so they need not be provided either.)
+ </p><p>
+</p><pre class="programlisting">
+void
+ForeignAsyncRequest(AsyncRequest *areq);
+</pre><p>
+ Produce one tuple asynchronously from the
+ <code class="structname">ForeignScan</code> node. <code class="literal">areq</code> is
+ the <code class="structname">AsyncRequest</code> struct describing the
+ <code class="structname">ForeignScan</code> node and the parent
+ <code class="structname">Append</code> node that requested the tuple from it.
+ This function should store the tuple into the slot specified by
+ <code class="literal">areq-&gt;result</code>, and set
+ <code class="literal">areq-&gt;request_complete</code> to <code class="literal">true</code>;
+ or if it needs to wait on an event external to the core server such as
+ network I/O, and cannot produce any tuple immediately, set the flag to
+ <code class="literal">false</code>, and set
+ <code class="literal">areq-&gt;callback_pending</code> to <code class="literal">true</code>
+ for the <code class="structname">ForeignScan</code> node to get a callback from
+ the callback functions described below. If no more tuples are available,
+ set the slot to NULL or an empty slot, and the
+ <code class="literal">areq-&gt;request_complete</code> flag to
+ <code class="literal">true</code>. It's recommended to use
+ <code class="function">ExecAsyncRequestDone</code> or
+ <code class="function">ExecAsyncRequestPending</code> to set the output parameters
+ in the <code class="literal">areq</code>.
+ </p><p>
+</p><pre class="programlisting">
+void
+ForeignAsyncConfigureWait(AsyncRequest *areq);
+</pre><p>
+ Configure a file descriptor event for which the
+ <code class="structname">ForeignScan</code> node wishes to wait.
+ This function will only be called when the
+ <code class="structname">ForeignScan</code> node has the
+ <code class="literal">areq-&gt;callback_pending</code> flag set, and should add
+ the event to the <code class="structfield">as_eventset</code> of the parent
+ <code class="structname">Append</code> node described by the
+ <code class="literal">areq</code>. See the comments for
+ <code class="function">ExecAsyncConfigureWait</code> in
+ <code class="filename">src/backend/executor/execAsync.c</code> for additional
+ information. When the file descriptor event occurs,
+ <code class="function">ForeignAsyncNotify</code> will be called.
+ </p><p>
+</p><pre class="programlisting">
+void
+ForeignAsyncNotify(AsyncRequest *areq);
+</pre><p>
+ Process a relevant event that has occurred, then produce one tuple
+ asynchronously from the <code class="structname">ForeignScan</code> node.
+ This function should set the output parameters in the
+ <code class="literal">areq</code> in the same way as
+ <code class="function">ForeignAsyncRequest</code>.
+ </p></div><div class="sect2" id="FDW-CALLBACKS-REPARAMETERIZE-PATHS"><div class="titlepage"><div><div><h3 class="title">59.2.12. FDW Routines for Reparameterization of Paths <a href="#FDW-CALLBACKS-REPARAMETERIZE-PATHS" class="id_link">#</a></h3></div></div></div><p>
+</p><pre class="programlisting">
+List *
+ReparameterizeForeignPathByChild(PlannerInfo *root, List *fdw_private,
+ RelOptInfo *child_rel);
+</pre><p>
+ This function is called while converting a path parameterized by the
+ top-most parent of the given child relation <code class="literal">child_rel</code> to be
+ parameterized by the child relation. The function is used to reparameterize
+ any paths or translate any expression nodes saved in the given
+ <code class="literal">fdw_private</code> member of a <code class="structname">ForeignPath</code>. The
+ callback may use <code class="literal">reparameterize_path_by_child</code>,
+ <code class="literal">adjust_appendrel_attrs</code> or
+ <code class="literal">adjust_appendrel_attrs_multilevel</code> as required.
+ </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="fdw-functions.html" title="59.1. Foreign Data Wrapper Functions">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="fdwhandler.html" title="Chapter 59. Writing a Foreign Data Wrapper">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="fdw-helpers.html" title="59.3. Foreign Data Wrapper Helper Functions">Next</a></td></tr><tr><td width="40%" align="left" valign="top">59.1. Foreign Data Wrapper Functions </td><td width="20%" align="center"><a accesskey="h" href="index.html" title="PostgreSQL 16.2 Documentation">Home</a></td><td width="40%" align="right" valign="top"> 59.3. Foreign Data Wrapper Helper Functions</td></tr></table></div></body></html> \ No newline at end of file