From 311bcfc6b3acdd6fd152798c7f287ddf74fa2a98 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Tue, 16 Apr 2024 21:46:48 +0200 Subject: Adding upstream version 15.4. Signed-off-by: Daniel Baumann --- doc/src/sgml/html/fdw-callbacks.html | 1257 ++++++++++++++++++++++++++++++++++ 1 file changed, 1257 insertions(+) create mode 100644 doc/src/sgml/html/fdw-callbacks.html (limited to 'doc/src/sgml/html/fdw-callbacks.html') diff --git a/doc/src/sgml/html/fdw-callbacks.html b/doc/src/sgml/html/fdw-callbacks.html new file mode 100644 index 0000000..c1b6f50 --- /dev/null +++ b/doc/src/sgml/html/fdw-callbacks.html @@ -0,0 +1,1257 @@ + +59.2. Foreign Data Wrapper Callback Routines

59.2. Foreign Data Wrapper Callback Routines

+ The FDW handler function returns a palloc'd FdwRoutine + struct containing pointers to the callback functions described below. + The scan-related functions are required, the rest are optional. +

+ The FdwRoutine struct type is declared in + src/include/foreign/fdwapi.h, which see for additional + details. +

59.2.1. FDW Routines for Scanning Foreign Tables

+

+void
+GetForeignRelSize(PlannerInfo *root,
+                  RelOptInfo *baserel,
+                  Oid foreigntableid);
+

+ + Obtain relation size estimates for a foreign table. This is called + at the beginning of planning for a query that scans a foreign table. + root is the planner's global information about the query; + baserel is the planner's information about this table; and + foreigntableid is the pg_class OID of the + foreign table. (foreigntableid could be obtained from the + planner data structures, but it's passed explicitly to save effort.) +

+ This function should update baserel->rows to be the + expected number of rows returned by the table scan, after accounting for + the filtering done by the restriction quals. The initial value of + baserel->rows is just a constant default estimate, which + should be replaced if at all possible. The function may also choose to + update baserel->width if it can compute a better estimate + of the average result row width. + (The initial value is based on column data types and on column + average-width values measured by the last ANALYZE.) + Also, this function may update baserel->tuples if + it can compute a better estimate of the foreign table's total row count. + (The initial value is + from pg_class.reltuples + which represents the total row count seen by the + last ANALYZE; it will be -1 if + no ANALYZE has been done on this foreign table.) +

+ See Section 59.4 for additional information. +

+

+void
+GetForeignPaths(PlannerInfo *root,
+                RelOptInfo *baserel,
+                Oid foreigntableid);
+

+ + Create possible access paths for a scan on a foreign table. + This is called during query planning. + The parameters are the same as for GetForeignRelSize, + which has already been called. +

+ This function must generate at least one access path + (ForeignPath node) for a scan on the foreign table and + must call add_path to add each such path to + baserel->pathlist. It's recommended to use + create_foreignscan_path to build the + ForeignPath nodes. The function can generate multiple + access paths, e.g., a path which has valid pathkeys to + represent a pre-sorted result. Each access path must contain cost + estimates, and can contain any FDW-private information that is needed to + identify the specific scan method intended. +

+ See Section 59.4 for additional information. +

+

+ForeignScan *
+GetForeignPlan(PlannerInfo *root,
+               RelOptInfo *baserel,
+               Oid foreigntableid,
+               ForeignPath *best_path,
+               List *tlist,
+               List *scan_clauses,
+               Plan *outer_plan);
+

+ + Create a ForeignScan plan node from the selected foreign + access path. This is called at the end of query planning. + The parameters are as for GetForeignRelSize, plus + the selected ForeignPath (previously produced by + GetForeignPaths, GetForeignJoinPaths, + or GetForeignUpperPaths), + the target list to be emitted by the plan node, + the restriction clauses to be enforced by the plan node, + and the outer subplan of the ForeignScan, + which is used for rechecks performed by RecheckForeignScan. + (If the path is for a join rather than a base + relation, foreigntableid is InvalidOid.) +

+ This function must create and return a ForeignScan plan + node; it's recommended to use make_foreignscan to build the + ForeignScan node. +

+ See Section 59.4 for additional information. +

+

+void
+BeginForeignScan(ForeignScanState *node,
+                 int eflags);
+

+ + Begin executing a foreign scan. This is called during executor startup. + It should perform any initialization needed before the scan can start, + but not start executing the actual scan (that should be done upon the + first call to IterateForeignScan). + The ForeignScanState node has already been created, but + its fdw_state field is still NULL. Information about + the table to scan is accessible through the + ForeignScanState node (in particular, from the underlying + ForeignScan plan node, which contains any FDW-private + information provided by GetForeignPlan). + eflags contains flag bits describing the executor's + operating mode for this plan node. +

+ Note that when (eflags & EXEC_FLAG_EXPLAIN_ONLY) is + true, this function should not perform any externally-visible actions; + it should only do the minimum required to make the node state valid + for ExplainForeignScan and EndForeignScan. +

+

+TupleTableSlot *
+IterateForeignScan(ForeignScanState *node);
+

+ + Fetch one row from the foreign source, returning it in a tuple table slot + (the node's ScanTupleSlot should be used for this + purpose). Return NULL if no more rows are available. The tuple table + slot infrastructure allows either a physical or virtual tuple to be + returned; in most cases the latter choice is preferable from a + performance standpoint. Note that this is called in a short-lived memory + context that will be reset between invocations. Create a memory context + in BeginForeignScan if you need longer-lived storage, or use + the es_query_cxt of the node's EState. +

+ The rows returned must match the fdw_scan_tlist target + list if one was supplied, otherwise they must match the row type of the + foreign table being scanned. If you choose to optimize away fetching + columns that are not needed, you should insert nulls in those column + positions, or else generate a fdw_scan_tlist list with + those columns omitted. +

+ Note that PostgreSQL's executor doesn't care + whether the rows returned violate any constraints that were defined on + the foreign table — but the planner does care, and may optimize + queries incorrectly if there are rows visible in the foreign table that + do not satisfy a declared constraint. If a constraint is violated when + the user has declared that the constraint should hold true, it may be + appropriate to raise an error (just as you would need to do in the case + of a data type mismatch). +

+

+void
+ReScanForeignScan(ForeignScanState *node);
+

+ + Restart the scan from the beginning. Note that any parameters the + scan depends on may have changed value, so the new scan does not + necessarily return exactly the same rows. +

+

+void
+EndForeignScan(ForeignScanState *node);
+

+ + End the scan and release resources. It is normally not important + to release palloc'd memory, but for example open files and connections + to remote servers should be cleaned up. +

59.2.2. FDW Routines for Scanning Foreign Joins

+ If an FDW supports performing foreign joins remotely (rather than + by fetching both tables' data and doing the join locally), it should + provide this callback function: +

+

+void
+GetForeignJoinPaths(PlannerInfo *root,
+                    RelOptInfo *joinrel,
+                    RelOptInfo *outerrel,
+                    RelOptInfo *innerrel,
+                    JoinType jointype,
+                    JoinPathExtraData *extra);
+

+ Create possible access paths for a join of two (or more) foreign tables + that all belong to the same foreign server. This optional + function is called during query planning. As + with GetForeignPaths, this function should + generate ForeignPath path(s) for the + supplied joinrel + (use create_foreign_join_path to build them), + and call add_path to add these + paths to the set of paths considered for the join. But unlike + GetForeignPaths, it is not necessary that this function + succeed in creating at least one path, since paths involving local + joining are always possible. +

+ Note that this function will be invoked repeatedly for the same join + relation, with different combinations of inner and outer relations; it is + the responsibility of the FDW to minimize duplicated work. +

+ If a ForeignPath path is chosen for the join, it will + represent the entire join process; paths generated for the component + tables and subsidiary joins will not be used. Subsequent processing of + the join path proceeds much as it does for a path scanning a single + foreign table. One difference is that the scanrelid of + the resulting ForeignScan plan node should be set to zero, + since there is no single relation that it represents; instead, + the fs_relids field of the ForeignScan + node represents the set of relations that were joined. (The latter field + is set up automatically by the core planner code, and need not be filled + by the FDW.) Another difference is that, because the column list for a + remote join cannot be found from the system catalogs, the FDW must + fill fdw_scan_tlist with an appropriate list + of TargetEntry nodes, representing the set of columns + it will supply at run time in the tuples it returns. +

+ See Section 59.4 for additional information. +

59.2.3. FDW Routines for Planning Post-Scan/Join Processing

+ If an FDW supports performing remote post-scan/join processing, such as + remote aggregation, it should provide this callback function: +

+

+void
+GetForeignUpperPaths(PlannerInfo *root,
+                     UpperRelationKind stage,
+                     RelOptInfo *input_rel,
+                     RelOptInfo *output_rel,
+                     void *extra);
+

+ Create possible access paths for upper relation processing, + which is the planner's term for all post-scan/join query processing, such + as aggregation, window functions, sorting, and table updates. This + optional function is called during query planning. Currently, it is + called only if all base relation(s) involved in the query belong to the + same FDW. This function should generate ForeignPath + path(s) for any post-scan/join processing that the FDW knows how to + perform remotely + (use create_foreign_upper_path to build them), + and call add_path to add these paths to + the indicated upper relation. As with GetForeignJoinPaths, + it is not necessary that this function succeed in creating any paths, + since paths involving local processing are always possible. +

+ The stage parameter identifies which post-scan/join step is + currently being considered. output_rel is the upper relation + that should receive paths representing computation of this step, + and input_rel is the relation representing the input to this + step. The extra parameter provides additional details, + currently, it is set only for UPPERREL_PARTIAL_GROUP_AGG + or UPPERREL_GROUP_AGG, in which case it points to a + GroupPathExtraData structure; + or for UPPERREL_FINAL, in which case it points to a + FinalPathExtraData structure. + (Note that ForeignPath paths added + to output_rel would typically not have any direct dependency + on paths of the input_rel, since their processing is expected + to be done externally. However, examining paths previously generated for + the previous processing step can be useful to avoid redundant planning + work.) +

+ See Section 59.4 for additional information. +

59.2.4. FDW Routines for Updating Foreign Tables

+ 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: +

+

+void
+AddForeignUpdateTargets(PlannerInfo *root,
+                        Index rtindex,
+                        RangeTblEntry *target_rte,
+                        Relation target_relation);
+

+ + UPDATE and DELETE 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 junk, target columns to the list of columns that are to be + retrieved from the foreign table during an UPDATE or + DELETE. +

+ To do that, construct a Var representing + an extra value you need, and pass it + to add_row_identity_var, 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 Var you need, except + that Vars that are identical except for + the varno field can and should share a + column name. + The core system uses the junk column names + tableoid for a + table's tableoid column, + ctid + or ctidN + for ctid, + wholerow + for a whole-row Var marked with + vartype = RECORD, + and wholerowN + for a whole-row Var with + vartype 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. +

+ If the AddForeignUpdateTargets pointer is set to + NULL, no extra target expressions are added. + (This will make it impossible to implement DELETE + operations, though UPDATE may still be feasible if the FDW + relies on an unchanging primary key to identify rows.) +

+

+List *
+PlanForeignModify(PlannerInfo *root,
+                  ModifyTable *plan,
+                  Index resultRelation,
+                  int subplan_index);
+

+ + 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 ModifyTable plan + node that performs the update action. This private information must + have the form of a List, and will be delivered to + BeginForeignModify during the execution stage. +

+ root is the planner's global information about the query. + plan is the ModifyTable plan node, which is + complete except for the fdwPrivLists field. + resultRelation identifies the target foreign table by its + range table index. subplan_index identifies which target of + the ModifyTable plan node this is, counting from zero; + use this if you want to index into per-target-relation substructures of the + plan node. +

+ See Section 59.4 for additional information. +

+ If the PlanForeignModify pointer is set to + NULL, no additional plan-time actions are taken, and the + fdw_private list delivered to + BeginForeignModify will be NIL. +

+

+void
+BeginForeignModify(ModifyTableState *mtstate,
+                   ResultRelInfo *rinfo,
+                   List *fdw_private,
+                   int subplan_index,
+                   int eflags);
+

+ + 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, + ExecForeignInsert/ExecForeignBatchInsert, + ExecForeignUpdate or + ExecForeignDelete will be called for tuple(s) to be + inserted, updated, or deleted. +

+ mtstate is the overall state of the + ModifyTable plan node being executed; global data about + the plan and execution state is available via this structure. + rinfo is the ResultRelInfo struct describing + the target foreign table. (The ri_FdwState field of + ResultRelInfo is available for the FDW to store any + private state it needs for this operation.) + fdw_private contains the private data generated by + PlanForeignModify, if any. + subplan_index identifies which target of + the ModifyTable plan node this is. + eflags contains flag bits describing the executor's + operating mode for this plan node. +

+ Note that when (eflags & EXEC_FLAG_EXPLAIN_ONLY) is + true, this function should not perform any externally-visible actions; + it should only do the minimum required to make the node state valid + for ExplainForeignModify and EndForeignModify. +

+ If the BeginForeignModify pointer is set to + NULL, no action is taken during executor startup. +

+

+TupleTableSlot *
+ExecForeignInsert(EState *estate,
+                  ResultRelInfo *rinfo,
+                  TupleTableSlot *slot,
+                  TupleTableSlot *planSlot);
+

+ + Insert one tuple into the foreign table. + estate is global execution state for the query. + rinfo is the ResultRelInfo struct describing + the target foreign table. + slot contains the tuple to be inserted; it will match the + row-type definition of the foreign table. + planSlot contains the tuple that was generated by the + ModifyTable plan node's subplan; it differs from + slot in possibly containing additional junk + columns. (The planSlot is typically of little interest + for INSERT cases, but is provided for completeness.) +

+ 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 + slot can be re-used for this purpose. +

+ The data in the returned slot is used only if the INSERT + statement has a RETURNING clause or involves a view + WITH CHECK OPTION; or if the foreign table has + an AFTER ROW trigger. Triggers require all columns, + but the FDW could choose to optimize away returning some or all columns + depending on the contents of the RETURNING clause or + WITH CHECK OPTION constraints. Regardless, some slot + must be returned to indicate success, or the query's reported row count + will be wrong. +

+ If the ExecForeignInsert pointer is set to + NULL, attempts to insert into the foreign table will fail + with an error message. +

+ Note that this function is also called when inserting routed tuples into + a foreign-table partition or executing COPY FROM on + a foreign table, in which case it is called in a different way than it + is in the INSERT case. See the callback functions + described below that allow the FDW to support that. +

+

+TupleTableSlot **
+ExecForeignBatchInsert(EState *estate,
+                       ResultRelInfo *rinfo,
+                       TupleTableSlot **slots,
+                       TupleTableSlot **planSlots,
+                       int *numSlots);
+

+ + Insert multiple tuples in bulk into the foreign table. + The parameters are the same for ExecForeignInsert + except slots and planSlots contain + multiple tuples and *numSlots specifies the number of + tuples in those arrays. +

+ 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 slots can be re-used for this purpose. + The number of successfully inserted tuples is returned in + *numSlots. +

+ The data in the returned slot is used only if the INSERT + statement involves a view + WITH CHECK OPTION; or if the foreign table has + an AFTER ROW trigger. Triggers require all columns, + but the FDW could choose to optimize away returning some or all columns + depending on the contents of the + WITH CHECK OPTION constraints. +

+ If the ExecForeignBatchInsert or + GetForeignModifyBatchSize pointer is set to + NULL, attempts to insert into the foreign table will + use ExecForeignInsert. + This function is not used if the INSERT has the + RETURNING clause. +

+ Note that this function is also called when inserting routed tuples into + a foreign-table partition. See the callback functions + described below that allow the FDW to support that. +

+

+int
+GetForeignModifyBatchSize(ResultRelInfo *rinfo);
+

+ + Report the maximum number of tuples that a single + ExecForeignBatchInsert call can handle for + the specified foreign table. The executor passes at most + the given number of tuples to ExecForeignBatchInsert. + rinfo is the ResultRelInfo 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. +

+ If the ExecForeignBatchInsert or + GetForeignModifyBatchSize pointer is set to + NULL, attempts to insert into the foreign table will + use ExecForeignInsert. +

+

+TupleTableSlot *
+ExecForeignUpdate(EState *estate,
+                  ResultRelInfo *rinfo,
+                  TupleTableSlot *slot,
+                  TupleTableSlot *planSlot);
+

+ + Update one tuple in the foreign table. + estate is global execution state for the query. + rinfo is the ResultRelInfo struct describing + the target foreign table. + slot contains the new data for the tuple; it will match the + row-type definition of the foreign table. + planSlot contains the tuple that was generated by the + ModifyTable plan node's subplan. Unlike + slot, 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 planSlot. + Also, planSlot typically contains + additional junk columns. In particular, any junk columns + that were requested by AddForeignUpdateTargets will + be available from this slot. +

+ 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 + slot can be re-used for this purpose. +

+ The data in the returned slot is used only if the UPDATE + statement has a RETURNING clause or involves a view + WITH CHECK OPTION; or if the foreign table has + an AFTER ROW trigger. Triggers require all columns, + but the FDW could choose to optimize away returning some or all columns + depending on the contents of the RETURNING clause or + WITH CHECK OPTION constraints. Regardless, some slot + must be returned to indicate success, or the query's reported row count + will be wrong. +

+ If the ExecForeignUpdate pointer is set to + NULL, attempts to update the foreign table will fail + with an error message. +

+

+TupleTableSlot *
+ExecForeignDelete(EState *estate,
+                  ResultRelInfo *rinfo,
+                  TupleTableSlot *slot,
+                  TupleTableSlot *planSlot);
+

+ + Delete one tuple from the foreign table. + estate is global execution state for the query. + rinfo is the ResultRelInfo struct describing + the target foreign table. + slot contains nothing useful upon call, but can be used to + hold the returned tuple. + planSlot contains the tuple that was generated by the + ModifyTable plan node's subplan; in particular, it will + carry any junk columns that were requested by + AddForeignUpdateTargets. The junk column(s) must be used + to identify the tuple to be deleted. +

+ 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 slot can be used to hold the tuple to be returned. +

+ The data in the returned slot is used only if the DELETE + query has a RETURNING clause or the foreign table has + an AFTER ROW trigger. Triggers require all columns, but the + FDW could choose to optimize away returning some or all columns depending + on the contents of the RETURNING clause. Regardless, some + slot must be returned to indicate success, or the query's reported row + count will be wrong. +

+ If the ExecForeignDelete pointer is set to + NULL, attempts to delete from the foreign table will fail + with an error message. +

+

+void
+EndForeignModify(EState *estate,
+                 ResultRelInfo *rinfo);
+

+ + 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. +

+ If the EndForeignModify pointer is set to + NULL, no action is taken during executor shutdown. +

+ Tuples inserted into a partitioned table by INSERT or + COPY FROM 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 + COPY FROM is executed on a foreign table. +

+

+void
+BeginForeignInsert(ModifyTableState *mtstate,
+                   ResultRelInfo *rinfo);
+

+ + 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 COPY FROM command. It should + perform any initialization needed prior to the actual insertion. + Subsequently, ExecForeignInsert or + ExecForeignBatchInsert will be called for + tuple(s) to be inserted into the foreign table. +

+ mtstate is the overall state of the + ModifyTable plan node being executed; global data about + the plan and execution state is available via this structure. + rinfo is the ResultRelInfo struct describing + the target foreign table. (The ri_FdwState field of + ResultRelInfo is available for the FDW to store any + private state it needs for this operation.) +

+ When this is called by a COPY FROM command, the + plan-related global data in mtstate is not provided + and the planSlot parameter of + ExecForeignInsert subsequently called for each + inserted tuple is NULL, whether the foreign table is + the partition chosen for tuple routing or the target specified in the + command. +

+ If the BeginForeignInsert pointer is set to + NULL, no action is taken for the initialization. +

+ Note that if the FDW does not support routable foreign-table partitions + and/or executing COPY FROM on foreign tables, this + function or ExecForeignInsert/ExecForeignBatchInsert + subsequently called must throw error as needed. +

+

+void
+EndForeignInsert(EState *estate,
+                 ResultRelInfo *rinfo);
+

+ + 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. +

+ If the EndForeignInsert pointer is set to + NULL, no action is taken for the termination. +

+

+int
+IsForeignRelUpdatable(Relation rel);
+

+ + 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 + CmdType enumeration; that is, + (1 << CMD_UPDATE) = 4 for UPDATE, + (1 << CMD_INSERT) = 8 for INSERT, and + (1 << CMD_DELETE) = 16 for DELETE. +

+ If the IsForeignRelUpdatable pointer is set to + NULL, foreign tables are assumed to be insertable, updatable, + or deletable if the FDW provides ExecForeignInsert, + ExecForeignUpdate, or ExecForeignDelete + 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 information_schema views.) +

+ 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 WITH CHECK OPTION + 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. +

+

+bool
+PlanDirectModify(PlannerInfo *root,
+                 ModifyTable *plan,
+                 Index resultRelation,
+                 int subplan_index);
+

+ + Decide whether it is safe to execute a direct modification + on the remote server. If so, return true after performing + planning actions needed for that. Otherwise, return false. + This optional function is called during query planning. + If this function succeeds, BeginDirectModify, + IterateDirectModify and EndDirectModify 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 PlanForeignModify. +

+ To execute the direct modification on the remote server, this function + must rewrite the target subplan with a ForeignScan plan + node that executes the direct modification on the remote server. The + operation and resultRelation fields + of the ForeignScan must be set appropriately. + operation must be set to the CmdType + enumeration corresponding to the statement kind (that is, + CMD_UPDATE for UPDATE, + CMD_INSERT for INSERT, and + CMD_DELETE for DELETE), and the + resultRelation argument must be copied to the + resultRelation field. +

+ See Section 59.4 for additional information. +

+ If the PlanDirectModify pointer is set to + NULL, no attempts to execute a direct modification on the + remote server are taken. +

+

+void
+BeginDirectModify(ForeignScanState *node,
+                  int eflags);
+

+ + 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 IterateDirectModify). + The ForeignScanState node has already been created, but + its fdw_state field is still NULL. Information about + the table to modify is accessible through the + ForeignScanState node (in particular, from the underlying + ForeignScan plan node, which contains any FDW-private + information provided by PlanDirectModify). + eflags contains flag bits describing the executor's + operating mode for this plan node. +

+ Note that when (eflags & EXEC_FLAG_EXPLAIN_ONLY) is + true, this function should not perform any externally-visible actions; + it should only do the minimum required to make the node state valid + for ExplainDirectModify and EndDirectModify. +

+ If the BeginDirectModify pointer is set to + NULL, no attempts to execute a direct modification on the + remote server are taken. +

+

+TupleTableSlot *
+IterateDirectModify(ForeignScanState *node);
+

+ + When the INSERT, UPDATE or DELETE + query doesn't have a RETURNING 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 RETURNING calculation, returning it in a + tuple table slot (the node's ScanTupleSlot should be + used for this purpose). The data that was actually inserted, updated + or deleted must be stored in + node->resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantuple. + 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 + BeginDirectModify if you need longer-lived storage, or use + the es_query_cxt of the node's EState. +

+ The rows returned must match the fdw_scan_tlist target + list if one was supplied, otherwise they must match the row type of the + foreign table being updated. If you choose to optimize away fetching + columns that are not needed for the RETURNING calculation, + you should insert nulls in those column positions, or else generate a + fdw_scan_tlist list with those columns omitted. +

+ 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 + ForeignScanState node in the EXPLAIN ANALYZE + case. +

+ If the IterateDirectModify pointer is set to + NULL, no attempts to execute a direct modification on the + remote server are taken. +

+

+void
+EndDirectModify(ForeignScanState *node);
+

+ + 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. +

+ If the EndDirectModify pointer is set to + NULL, no attempts to execute a direct modification on the + remote server are taken. +

59.2.5. FDW Routines for TRUNCATE

+

+void
+ExecForeignTruncate(List *rels,
+                    DropBehavior behavior,
+                    bool restart_seqs);
+

+ + Truncate foreign tables. This function is called when + TRUNCATE is executed on a foreign table. + rels is a list of Relation + data structures of foreign tables to truncate. +

+ behavior is either DROP_RESTRICT + or DROP_CASCADE indicating that the + RESTRICT or CASCADE option was + requested in the original TRUNCATE command, + respectively. +

+ If restart_seqs is true, + the original TRUNCATE command requested the + RESTART IDENTITY behavior, otherwise the + CONTINUE IDENTITY behavior was requested. +

+ Note that the ONLY options specified + in the original TRUNCATE command are not passed to + ExecForeignTruncate. This behavior is similar to + the callback functions of SELECT, + UPDATE and DELETE on + a foreign table. +

+ ExecForeignTruncate is invoked once per + foreign server for which foreign tables are to be truncated. + This means that all foreign tables included in rels + must belong to the same server. +

+ If the ExecForeignTruncate pointer is set to + NULL, attempts to truncate foreign tables will + fail with an error message. +

59.2.6. FDW Routines for Row Locking

+ If an FDW wishes to support late row locking (as described + in Section 59.5), it must provide the following + callback functions: +

+

+RowMarkType
+GetForeignRowMarkType(RangeTblEntry *rte,
+                      LockClauseStrength strength);
+

+ + Report which row-marking option to use for a foreign table. + rte is the RangeTblEntry node for the table + and strength describes the lock strength requested by the + relevant FOR UPDATE/SHARE clause, if any. The result must be + a member of the RowMarkType enum type. +

+ This function is called during query planning for each foreign table that + appears in an UPDATE, DELETE, or SELECT + FOR UPDATE/SHARE query and is not the target of UPDATE + or DELETE. +

+ If the GetForeignRowMarkType pointer is set to + NULL, the ROW_MARK_COPY option is always used. + (This implies that RefetchForeignRow will never be called, + so it need not be provided either.) +

+ See Section 59.5 for more information. +

+

+void
+RefetchForeignRow(EState *estate,
+                  ExecRowMark *erm,
+                  Datum rowid,
+                  TupleTableSlot *slot,
+                  bool *updated);
+

+ + Re-fetch one tuple slot from the foreign table, after locking it if required. + estate is global execution state for the query. + erm is the ExecRowMark struct describing + the target foreign table and the row lock type (if any) to acquire. + rowid identifies the tuple to be fetched. + slot contains nothing useful upon call, but can be used to + hold the returned tuple. updated is an output parameter. +

+ 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 erm->markType, which is the value + previously returned by GetForeignRowMarkType. + (ROW_MARK_REFERENCE means to just re-fetch the tuple + without acquiring any lock, and ROW_MARK_COPY will + never be seen by this routine.) +

+ In addition, *updated should be set to true + 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 true is recommended.) +

+ 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 SKIP LOCKED option is specified + by erm->waitPolicy. +

+ The rowid is the ctid value previously read + for the row to be re-fetched. Although the rowid value is + passed as a Datum, it can currently only be a tid. The + function API is chosen in hopes that it may be possible to allow other + data types for row IDs in future. +

+ If the RefetchForeignRow pointer is set to + NULL, attempts to re-fetch rows will fail + with an error message. +

+ See Section 59.5 for more information. +

+

+bool
+RecheckForeignScan(ForeignScanState *node,
+                   TupleTableSlot *slot);
+

+ 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 NULL and + instead set fdw_recheck_quals 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. RecheckForeignScan 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. +

+ 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 + ForeignScan. 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 GetExistingLocalJoinPath may be used to search + existing paths for a suitable local join path, which can be used as the + alternative local join plan. GetExistingLocalJoinPath + 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.) +

59.2.7. FDW Routines for EXPLAIN

+

+void
+ExplainForeignScan(ForeignScanState *node,
+                   ExplainState *es);
+

+ + Print additional EXPLAIN output for a foreign table scan. + This function can call ExplainPropertyText and + related functions to add fields to the EXPLAIN output. + The flag fields in es can be used to determine what to + print, and the state of the ForeignScanState node + can be inspected to provide run-time statistics in the EXPLAIN + ANALYZE case. +

+ If the ExplainForeignScan pointer is set to + NULL, no additional information is printed during + EXPLAIN. +

+

+void
+ExplainForeignModify(ModifyTableState *mtstate,
+                     ResultRelInfo *rinfo,
+                     List *fdw_private,
+                     int subplan_index,
+                     struct ExplainState *es);
+

+ + Print additional EXPLAIN output for a foreign table update. + This function can call ExplainPropertyText and + related functions to add fields to the EXPLAIN output. + The flag fields in es can be used to determine what to + print, and the state of the ModifyTableState node + can be inspected to provide run-time statistics in the EXPLAIN + ANALYZE case. The first four arguments are the same as for + BeginForeignModify. +

+ If the ExplainForeignModify pointer is set to + NULL, no additional information is printed during + EXPLAIN. +

+

+void
+ExplainDirectModify(ForeignScanState *node,
+                    ExplainState *es);
+

+ + Print additional EXPLAIN output for a direct modification + on the remote server. + This function can call ExplainPropertyText and + related functions to add fields to the EXPLAIN output. + The flag fields in es can be used to determine what to + print, and the state of the ForeignScanState node + can be inspected to provide run-time statistics in the EXPLAIN + ANALYZE case. +

+ If the ExplainDirectModify pointer is set to + NULL, no additional information is printed during + EXPLAIN. +

59.2.8. FDW Routines for ANALYZE

+

+bool
+AnalyzeForeignTable(Relation relation,
+                    AcquireSampleRowsFunc *func,
+                    BlockNumber *totalpages);
+

+ + This function is called when ANALYZE is executed on + a foreign table. If the FDW can collect statistics for this + foreign table, it should return true, and provide a pointer + to a function that will collect sample rows from the table in + func, plus the estimated size of the table in pages in + totalpages. Otherwise, return false. +

+ If the FDW does not support collecting statistics for any tables, the + AnalyzeForeignTable pointer can be set to NULL. +

+ If provided, the sample collection function must have the signature +

+int
+AcquireSampleRowsFunc(Relation relation,
+                      int elevel,
+                      HeapTuple *rows,
+                      int targrows,
+                      double *totalrows,
+                      double *totaldeadrows);
+

+ + A random sample of up to targrows rows should be collected + from the table and stored into the caller-provided rows + 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 totalrows and + totaldeadrows. (Set totaldeadrows to zero + if the FDW does not have any concept of dead rows.) +

59.2.9. FDW Routines for IMPORT FOREIGN SCHEMA

+

+List *
+ImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid);
+

+ + Obtain a list of foreign table creation commands. This function is + called when executing IMPORT FOREIGN SCHEMA, 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 CREATE FOREIGN TABLE command. + These strings will be parsed and executed by the core server. +

+ Within the ImportForeignSchemaStmt struct, + remote_schema is the name of the remote schema from + which tables are to be imported. + list_type identifies how to filter table names: + FDW_IMPORT_SCHEMA_ALL means that all tables in the remote + schema should be imported (in this case table_list is + empty), FDW_IMPORT_SCHEMA_LIMIT_TO means to include only + tables listed in table_list, + and FDW_IMPORT_SCHEMA_EXCEPT means to exclude the tables + listed in table_list. + options 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 + NOT NULL attributes of columns should be imported. + These options need not have anything to do with those supported by the + FDW as database object options. +

+ The FDW may ignore the local_schema field of + the ImportForeignSchemaStmt, because the core server + will automatically insert that name into the parsed CREATE + FOREIGN TABLE commands. +

+ The FDW does not have to concern itself with implementing the filtering + specified by list_type and table_list, + 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 IsImportableForeignTable() may be + useful to test whether a given foreign-table name will pass the filter. +

+ If the FDW does not support importing table definitions, the + ImportForeignSchema pointer can be set to NULL. +

59.2.10. FDW Routines for Parallel Execution

+ A ForeignScan node can, optionally, support parallel + execution. A parallel ForeignScan 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. +

+

+bool
+IsForeignScanParallelSafe(PlannerInfo *root, RelOptInfo *rel,
+                          RangeTblEntry *rte);
+

+ 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. +

+ 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. +

+

+Size
+EstimateDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt);
+

+ 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. +

+

+void
+InitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
+                         void *coordinate);
+

+ Initialize the dynamic shared memory that will be required for parallel + operation. coordinate points to a shared memory area of + size equal to the return value of EstimateDSMForeignScan. + This function is optional, and can be omitted if not needed. +

+

+void
+ReInitializeDSMForeignScan(ForeignScanState *node, ParallelContext *pcxt,
+                           void *coordinate);
+

+ 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 ReScanForeignScan function resets only local + state. Currently, this function will be called + before ReScanForeignScan, but it's best not to rely on + that ordering. +

+

+void
+InitializeWorkerForeignScan(ForeignScanState *node, shm_toc *toc,
+                            void *coordinate);
+

+ Initialize a parallel worker's local state based on the shared state + set up by the leader during InitializeDSMForeignScan. + This function is optional, and can be omitted if not needed. +

+

+void
+ShutdownForeignScan(ForeignScanState *node);
+

+ Release resources when it is anticipated the node will not be executed + to completion. This is not called in all cases; sometimes, + EndForeignScan 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. +

59.2.11. FDW Routines for Asynchronous Execution

+ A ForeignScan node can, optionally, support + asynchronous execution as described in + src/backend/executor/README. The following + functions are all optional, but are all required if asynchronous + execution is to be supported. +

+

+bool
+IsForeignPathAsyncCapable(ForeignPath *path);
+

+ Test whether a given ForeignPath 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 AppendPath + 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. +

+ If this function is not defined, it is assumed that the given path scans + the foreign relation using IterateForeignScan. + (This implies that the callback functions described below will never be + called, so they need not be provided either.) +

+

+void
+ForeignAsyncRequest(AsyncRequest *areq);
+

+ Produce one tuple asynchronously from the + ForeignScan node. areq is + the AsyncRequest struct describing the + ForeignScan node and the parent + Append node that requested the tuple from it. + This function should store the tuple into the slot specified by + areq->result, and set + areq->request_complete to true; + 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 + false, and set + areq->callback_pending to true + for the ForeignScan 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 + areq->request_complete flag to + true. It's recommended to use + ExecAsyncRequestDone or + ExecAsyncRequestPending to set the output parameters + in the areq. +

+

+void
+ForeignAsyncConfigureWait(AsyncRequest *areq);
+

+ Configure a file descriptor event for which the + ForeignScan node wishes to wait. + This function will only be called when the + ForeignScan node has the + areq->callback_pending flag set, and should add + the event to the as_eventset of the parent + Append node described by the + areq. See the comments for + ExecAsyncConfigureWait in + src/backend/executor/execAsync.c for additional + information. When the file descriptor event occurs, + ForeignAsyncNotify will be called. +

+

+void
+ForeignAsyncNotify(AsyncRequest *areq);
+

+ Process a relevant event that has occurred, then produce one tuple + asynchronously from the ForeignScan node. + This function should set the output parameters in the + areq in the same way as + ForeignAsyncRequest. +

59.2.12. FDW Routines for Reparameterization of Paths

+

+List *
+ReparameterizeForeignPathByChild(PlannerInfo *root, List *fdw_private,
+                                 RelOptInfo *child_rel);
+

+ This function is called while converting a path parameterized by the + top-most parent of the given child relation child_rel to be + parameterized by the child relation. The function is used to reparameterize + any paths or translate any expression nodes saved in the given + fdw_private member of a ForeignPath. The + callback may use reparameterize_path_by_child, + adjust_appendrel_attrs or + adjust_appendrel_attrs_multilevel as required. +

\ No newline at end of file -- cgit v1.2.3