|
- <?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>56.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 V1.79.1" /><link rel="prev" href="fdw-functions.html" title="56.1. Foreign Data Wrapper Functions" /><link rel="next" href="fdw-helpers.html" title="56.3. Foreign Data Wrapper Helper Functions" /></head><body><div xmlns="http://www.w3.org/TR/xhtml1/transitional" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="5" align="center">56.2. Foreign Data Wrapper Callback Routines</th></tr><tr><td width="10%" align="left"><a accesskey="p" href="fdw-functions.html" title="56.1. Foreign Data Wrapper Functions">Prev</a> </td><td width="10%" align="left"><a accesskey="u" href="fdwhandler.html" title="Chapter 56. Writing a Foreign Data Wrapper">Up</a></td><th width="60%" align="center">Chapter 56. Writing a Foreign Data Wrapper</th><td width="10%" align="right"><a accesskey="h" href="index.html" title="PostgreSQL 12.4 Documentation">Home</a></td><td width="10%" align="right"> <a accesskey="n" href="fdw-helpers.html" title="56.3. Foreign Data Wrapper Helper Functions">Next</a></td></tr></table><hr></hr></div><div class="sect1" id="FDW-CALLBACKS"><div class="titlepage"><div><div><h2 class="title" style="clear: both">56.2. Foreign Data Wrapper Callback Routines</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-SCAN">56.2.1. FDW Routines for Scanning Foreign Tables</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-JOIN-SCAN">56.2.2. FDW Routines for Scanning Foreign Joins</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-UPPER-PLANNING">56.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">56.2.4. FDW Routines for Updating Foreign Tables</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-ROW-LOCKING">56.2.5. FDW Routines for Row Locking</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-EXPLAIN">56.2.6. FDW Routines for <code class="command">EXPLAIN</code></a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-ANALYZE">56.2.7. FDW Routines for <code class="command">ANALYZE</code></a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-IMPORT">56.2.8. 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">56.2.9. FDW Routines for Parallel Execution</a></span></dt><dt><span class="sect2"><a href="fdw-callbacks.html#FDW-CALLBACKS-REPARAMETERIZE-PATHS">56.2.10. 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">56.2.1. FDW Routines for Scanning Foreign Tables</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->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->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->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->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>.)
- </p><p>
- See <a class="xref" href="fdw-planning.html" title="56.4. Foreign Data Wrapper Query Planning">Section 56.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->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="56.4. Foreign Data Wrapper Query Planning">Section 56.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="56.4. Foreign Data Wrapper Query Planning">Section 56.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 & 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">56.2.2. FDW Routines for Scanning Foreign Joins</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><p>
- See <a class="xref" href="fdw-planning.html" title="56.4. Foreign Data Wrapper Query Planning">Section 56.4</a> for additional information.
- </p></div><div class="sect2" id="FDW-CALLBACKS-UPPER-PLANNING"><div class="titlepage"><div><div><h3 class="title">56.2.3. FDW Routines for Planning Post-Scan/Join Processing</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="56.4. Foreign Data Wrapper Query Planning">Section 56.4</a> for additional information.
- </p></div><div class="sect2" id="FDW-CALLBACKS-UPDATE"><div class="titlepage"><div><div><h3 class="title">56.2.4. FDW Routines for Updating Foreign Tables</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(Query *parsetree,
- 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, add <code class="structname">TargetEntry</code> items to
- <code class="literal">parsetree->targetList</code>, containing expressions for the
- extra values to be fetched. Each such entry must be marked
- <code class="structfield">resjunk</code> = <code class="literal">true</code>, and must have a distinct
- <code class="structfield">resname</code> that will identify it at execution time.
- Avoid using names matching <code class="literal">ctid<em class="replaceable"><code>N</code></em></code>,
- <code class="literal">wholerow</code>, or
- <code class="literal">wholerow<em class="replaceable"><code>N</code></em></code>, as the core system can
- generate junk columns of these names.
- If the extra expressions are more complex than simple Vars, they
- must be run through <code class="function">eval_const_expressions</code>
- before adding them to the targetlist.
- </p><p>
- Although this function is called during planning, the
- information provided is a bit different from that available to other
- planning routines.
- <code class="literal">parsetree</code> is the parse tree for the <code class="command">UPDATE</code> or
- <code class="command">DELETE</code> command, while <code class="literal">target_rte</code> and
- <code class="literal">target_relation</code> describe the target foreign table.
- </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 <code class="literal">plan->plans</code> or other
- substructure of the <code class="literal">plan</code> node.
- </p><p>
- See <a class="xref" href="fdw-planning.html" title="56.4. Foreign Data Wrapper Query Planning">Section 56.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</code>, <code class="function">ExecForeignUpdate</code> or
- <code class="function">ExecForeignDelete</code> will be called for each tuple 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 & 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 *
- 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; it differs from
- <code class="literal">slot</code> in possibly containing 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> will be called for
- each tuple 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</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 << CMD_UPDATE) = 4</code> for <code class="command">UPDATE</code>,
- <code class="literal">(1 << CMD_INSERT) = 8</code> for <code class="command">INSERT</code>, and
- <code class="literal">(1 << 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> field of the <code class="structname">ForeignScan</code> must
- be set to the <code class="literal">CmdType</code> enumeration appropriately; 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>.
- </p><p>
- See <a class="xref" href="fdw-planning.html" title="56.4. Foreign Data Wrapper Query Planning">Section 56.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 & 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 the
- <code class="literal">es_result_relation_info->ri_projectReturning->pi_exprContext->ecxt_scantuple</code>
- of the node's <code class="structname">EState</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-ROW-LOCKING"><div class="titlepage"><div><div><h3 class="title">56.2.5. FDW Routines for Row Locking</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="56.5. Row Locking in Foreign Data Wrappers">Section 56.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="56.5. Row Locking in Foreign Data Wrappers">Section 56.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->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->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="56.5. Row Locking in Foreign Data Wrappers">Section 56.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">56.2.6. FDW Routines for <code class="command">EXPLAIN</code></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">56.2.7. FDW Routines for <code class="command">ANALYZE</code></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">56.2.8. FDW Routines for <code class="command">IMPORT FOREIGN SCHEMA</code></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">56.2.9. FDW Routines for Parallel Execution</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-REPARAMETERIZE-PATHS"><div class="titlepage"><div><div><h3 class="title">56.2.10. FDW Routines for Reparameterization of Paths</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">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="fdwhandler.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="fdw-helpers.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">56.1. Foreign Data Wrapper Functions </td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top"> 56.3. Foreign Data Wrapper Helper Functions</td></tr></table></div></body></html>
|