バージョンごとのドキュメント一覧

59.2. 外部データラッパーのコールバックルーチン #

<title>Foreign Data Wrapper Callback Routines</title>

The FDW handler function returns a palloc'd <structname>FdwRoutine</structname> struct containing pointers to the callback functions described below. The scan-related functions are required, the rest are optional. FDWハンドラ関数は、以下で説明するコールバックの関数ポインタを含む、pallocされたFdwRoutine構造体を返します。 スキャンに関連した関数は必須で、それ以外は省略可能です。

The <structname>FdwRoutine</structname> struct type is declared in <filename>src/include/foreign/fdwapi.h</filename>, which see for additional details. FdwRoutine構造体はsrc/include/foreign/fdwapi.hで宣言されていますので、追加情報はそちらを参照してください。

59.2.1. 外部テーブルスキャンのためのFDWルーチン #

<title>FDW Routines for Scanning Foreign Tables</title>

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. <literal>root</literal> is the planner's global information about the query; <literal>baserel</literal> is the planner's information about this table; and <literal>foreigntableid</literal> is the <structname>pg_class</structname> OID of the foreign table. (<literal>foreigntableid</literal> could be obtained from the planner data structures, but it's passed explicitly to save effort.) 外部テーブルのリレーションサイズ見積もりを取得します。 この関数は、ある外部テーブルをスキャンする問い合わせのプラン作成の開始時に呼び出されます。 rootはその問い合わせに関するプランナのグローバル情報です。 baserelはそのテーブルに関するプランナの情報です。 そして、foreigntableidはその外部テーブルのpg_class OIDです。 (foreigntableidはプランナデータ構造体からも取得できますが、手間を省くために明示的に渡されます。)

This function should update <literal>baserel-&gt;rows</literal> 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 <literal>baserel-&gt;rows</literal> is just a constant default estimate, which should be replaced if at all possible. The function may also choose to update <literal>baserel-&gt;width</literal> 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 <command>ANALYZE</command>.) Also, this function may update <literal>baserel-&gt;tuples</literal> if it can compute a better estimate of the foreign table's total row count. (The initial value is from <structname>pg_class</structname>.<structfield>reltuples</structfield> which represents the total row count seen by the last <command>ANALYZE</command>; it will be <literal>-1</literal> if no <command>ANALYZE</command> has been done on this foreign table.) この関数は、検索条件によるフィルタリングも考慮に入れた、そのテーブルスキャンが返すと見込まれる件数にbaserel->rowsを更新するべきです。 baserel->rowsの初期値は固定のデフォルト見積もりなので、可能な限り置き換えられるべきです。この関数は、行の幅のよりよい見積もりを計算できるのであれば、baserel->widthを更新することも選択出来ます。 (初期値は列の型と最後に実行されたANALYZEから計測された平均列幅に基づいています。) また、外部テーブルの総行数の見積もりをより正しく計算できる場合、この関数は、baserel->tuplesを更新しても構いません。 (初期値はpg_class.reltuplesで、最後に実行されたANALYZEによって確認された総行数です。 もしこの外部テーブルにANALYZEが実行されていない場合は、-1になります。)

See <xref linkend="fdw-planning"/> for additional information. 追加情報については59.4を参照してください。

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 <function>GetForeignRelSize</function>, which has already been called. 外部テーブル対するスキャンとして可能なアクセスパスを作成します。 この関数は問い合わせのプラン作成中に呼び出されます。 引数は、先に呼ばれているGetForeignRelSizeと同じです。

This function must generate at least one access path (<structname>ForeignPath</structname> node) for a scan on the foreign table and must call <function>add_path</function> to add each such path to <literal>baserel-&gt;pathlist</literal>. It's recommended to use <function>create_foreignscan_path</function> to build the <structname>ForeignPath</structname> nodes. The function can generate multiple access paths, e.g., a path which has valid <literal>pathkeys</literal> 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. この関数は、少なくとも一つのアクセスパス(ForeignPathノード)を作成して、それぞれのパスをbaserel->pathlistに追加するためにadd_pathを呼ばなければなりません。 ForeignPathノードを構築するにはcreate_foreignscan_pathを使うことが推奨されています。 この関数は、たとえばソート済みの結果を表現する有効なpathkeysを持つパスのような複数のアクセスパスを作成することが出来ます。 それぞれのアクセスパスはコスト見積もりを含まねばならず、また意図した特定のスキャン方式を識別するのに必要なFDW固有の情報を持つことが出来ます。

See <xref linkend="fdw-planning"/> for additional information. 追加情報については59.4を参照してください。

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

Create a <structname>ForeignScan</structname> plan node from the selected foreign access path. This is called at the end of query planning. The parameters are as for <function>GetForeignRelSize</function>, plus the selected <structname>ForeignPath</structname> (previously produced by <function>GetForeignPaths</function>, <function>GetForeignJoinPaths</function>, or <function>GetForeignUpperPaths</function>), 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 <structname>ForeignScan</structname>, which is used for rechecks performed by <function>RecheckForeignScan</function>. (If the path is for a join rather than a base relation, <literal>foreigntableid</literal> is <literal>InvalidOid</literal>.) 選択された外部アクセスパスからForeignScanプランノードを作成します。 この関数は問い合わせのプラン作成の最後に呼び出されます。 引数は、GetForeignRelSizeと同じものに、選択されたForeignPath(事前にGetForeignPathsGetForeignJoinPathsまたはGetForeignUpperPathsによって作成されたもの)、そのプランノードによって出力されるターゲットリスト、そのプランノードで強制される条件句、およびRecheckForeignScanが実行する再検査で使用されるForeignScanの外側のサブプランが追加されます。 (パスがベースリレーションではなく結合のためのものの場合、foreigntableidInvalidOidになります。)

This function must create and return a <structname>ForeignScan</structname> plan node; it's recommended to use <function>make_foreignscan</function> to build the <structname>ForeignScan</structname> node. この関数はForeignScanプランノードを作成して返さなければなりません。ForeignScanノードを構築するにはmake_foreignscanを使うことが推奨されています。

See <xref linkend="fdw-planning"/> for additional information. 追加情報については59.4を参照してください。

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 <function>IterateForeignScan</function>). The <structname>ForeignScanState</structname> node has already been created, but its <structfield>fdw_state</structfield> field is still NULL. Information about the table to scan is accessible through the <structname>ForeignScanState</structname> node (in particular, from the underlying <structname>ForeignScan</structname> plan node, which contains any FDW-private information provided by <function>GetForeignPlan</function>). <literal>eflags</literal> contains flag bits describing the executor's operating mode for this plan node. 外部テーブルスキャンの実行を開始します。 この関数はエグゼキュータの起動中に呼び出されます。 スキャンを開始できるようになる前に、あらゆる必要な初期化を実行するべきですが、実際のスキャンの実行を始めるべきではありません(それは最初のIterateForeignScan呼び出しにおいて行われるべきです)。 ForeignScanStateノードは作成されていますが、そのfdw_stateフィールドはNULLのままです。 スキャンするテーブルの情報は、ForeignScanStateノード(特に、その先にあるGetForeignPlanから提供されたFDWプライベート情報を含む、ForeignScanプランノード)を通じてアクセス可能です。 eflagsは、このプランノードに関するエグゼキュータの操作モードを表すフラグビットを含みます。

Note that when <literal>(eflags &amp; EXEC_FLAG_EXPLAIN_ONLY)</literal> 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 <function>ExplainForeignScan</function> and <function>EndForeignScan</function>. (eflags & EXEC_FLAG_EXPLAIN_ONLY)が真の場合、この関数は外部に見える処理を実行すべきではないことに注意してください。 ExplainForeignScanEndForeignScan用にノード状態を有効にするのに必要とされる最小限のことだけをすべきです。

TupleTableSlot *
IterateForeignScan(ForeignScanState *node);

Fetch one row from the foreign source, returning it in a tuple table slot (the node's <structfield>ScanTupleSlot</structfield> 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 <function>BeginForeignScan</function> if you need longer-lived storage, or use the <structfield>es_query_cxt</structfield> of the node's <structname>EState</structname>. 外部ソースから一行を取り出して、それをタプルテーブルスロットに入れて返します(この用途にはノードのScanTupleSlotを使うべきです)。 利用可能な行がない場合は、NULLを返します。 タプルテーブルスロット機構を使うと、物理タプルと仮想タプルのどちらでも返せます。 ほとんどの場合、パフォーマンスの観点から後者を選ぶのが良いでしょう。 この関数は、呼出しごとにリセットされる短命なメモリコンテキスト内で呼び出されることに注意してください。 より長命なストレージが必要な場合は、BeginForeignScanでメモリコンテキストを作成するか、ノードのEStateに含まれるes_query_cxtを使用してください。

The rows returned must match the <structfield>fdw_scan_tlist</structfield> 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 <structfield>fdw_scan_tlist</structfield> list with those columns omitted. 返される行は、ターゲットリストfdw_scan_tlistが提供されたなら、それとマッチしなければならず、提供されていない場合はスキャンされている外部テーブルの行型とマッチしなければなりません。 不要な列を取り出さないように最適化することを選ぶなら、それらの列の位置にNULLを入れるか、あるいはそれらの列を除いたfdw_scan_tlistリストを生成するべきです。

Note that <productname>PostgreSQL</productname>'s executor doesn't care whether the rows returned violate any constraints that were defined on the foreign table &mdash; 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). PostgreSQLのエグゼキュータは返された行が外部テーブルに定義された制約に違反しているかどうかは気にしません。 しかし、プランナはそれに着目するので、宣言された制約に反する行が外部テーブル上にあった場合に、不正な最適化をするかもしれません。 ユーザが制約が成り立つと宣言したのに制約に違反した場合は(データ型が一致しなかった場合にする必要があるのと同様に)エラーを発生させるのが適切でしょう。

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. スキャンを終了しリソースを解放します。 通常、pallocされたメモリを解放することは重要ではありませんが、たとえば開いたファイルやリモートサーバへの接続などはクリーンアップするべきです。

59.2.2. 外部テーブルの結合をスキャンするためのFDWルーチン #

<title>FDW Routines for Scanning Foreign Joins</title>

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: FDWが外部テーブルの結合を(両方のテーブルのデータをフェッチして、ローカルで結合するのでなく)リモートで実行することをサポートする場合、次のコールバック関数を提供します。

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 <function>GetForeignPaths</function>, this function should generate <structname>ForeignPath</structname> path(s) for the supplied <literal>joinrel</literal> (use <function>create_foreign_join_path</function> to build them), and call <function>add_path</function> to add these paths to the set of paths considered for the join. But unlike <function>GetForeignPaths</function>, it is not necessary that this function succeed in creating at least one path, since paths involving local joining are always possible. 同じ外部サーバにある2つ(またはそれ以上)の外部テーブルの結合のための可能なアクセスパスを作成します。 このオプション関数は、問い合わせの計画時に呼び出されます。 GetForeignPathsと同じく、この関数は提供されたjoinrelのためのForeignPathパスを生成し(そのためにcreate_foreign_join_pathを使用します)、add_pathを呼んで、それらのパスを結合のために考慮されるパスの集合に追加します。 しかし、GetForeignPathsとは異なり、この関数が少なくとも1つのパスの作成に成功することは必要ではありません。 なぜなら、ローカルの結合を含んだパスはいつでも可能だからです。

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. この関数は、同じ結合のリレーションに対して、内側と外側のリレーションの異なる組み合わせで繰り返し呼び出されることに注意して下さい。 同じ作業の繰り返しを最小化することはFDWの責任です。

If a <structname>ForeignPath</structname> 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 <structfield>scanrelid</structfield> of the resulting <structname>ForeignScan</structname> plan node should be set to zero, since there is no single relation that it represents; instead, the <structfield>fs_relids</structfield> field of the <structname>ForeignScan</structname> 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 <structfield>fdw_scan_tlist</structfield> with an appropriate list of <structfield>TargetEntry</structfield> nodes, representing the set of columns it will supply at run time in the tuples it returns. ForeignPathパスが結合のために選択されると、それは結合プロセス全体を代表することになり、構成テーブルとその関連の結合のために生成されたパスは使われなくなります。 結合パスの以降の処理は、単一の外部テーブルをスキャンするパスとほぼ同様に進みます。 1つの相違点は、結果として作られるForeignScan計画ノードのscanrelidが0にセットされるべき、ということで、これはそれが表現する単一のリレーションがないためです。 その代わりに、ForeignScanノードのfs_relidsフィールドが結合されるリレーションの集合を表します。 (後者のフィールドはコアのプランナのコードによって自動的にセットされるので、FDWによって設定される必要はありません。) 他の相違点は、リモートの結合についての列リストがシステムカタログにはないため、FDWはfdw_scan_tlistに適切なTargetEntryノードのリストを入れて、実行時に返されるタプル内の列の集合を表すようにしなければならないということです。

注記

Beginning with <productname>PostgreSQL</productname> 16, <structfield>fs_relids</structfield> includes the rangetable indexes of outer joins, if any were involved in this join. The new field <structfield>fs_base_relids</structfield> includes only base relation indexes, and thus mimics <structfield>fs_relids</structfield>'s old semantics. PostgreSQL 16以降、fs_relidsには、この結合に関連する外部結合がある場合、その範囲テーブルの添字が含まれます。 新しいフィールドfs_base_relidsはベースリレーションの添字のみを含み、fs_relidsの古いセマンティクスを模倣しています。

See <xref linkend="fdw-planning"/> for additional information. 追加情報については59.4を参照してください。

59.2.3. スキャン/結合後の処理をプラン生成するためのFDWルーチン #

<title>FDW Routines for Planning Post-Scan/Join Processing</title>

If an FDW supports performing remote post-scan/join processing, such as remote aggregation, it should provide this callback function: FDWがリモート集約など、リモートでのスキャン/結合後の処理をサポートする場合、次のコールバック関数を提供します。

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

Create possible access paths for <firstterm>upper relation</firstterm> 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 <structname>ForeignPath</structname> path(s) for any post-scan/join processing that the FDW knows how to perform remotely (use <function>create_foreign_upper_path</function> to build them), and call <function>add_path</function> to add these paths to the indicated upper relation. As with <function>GetForeignJoinPaths</function>, it is not necessary that this function succeed in creating any paths, since paths involving local processing are always possible. 上位リレーション処理のための、ありうるアクセスパスを作成します。上位リレーションはプランナ用語で、ウィンドウ関数、ソート、テーブル更新など、全てのスキャン/結合後の問い合わせのことです。 この省略可能な関数は問い合わせのプラン作成時に呼ばれます。 今のところ、これは問い合わせに含まれる全てのベースリレーションが同じFDWに属する場合だけ呼ばれます。 この関数では、FDWがどのようにリモートで実行するか分かっている全てのスキャン/結合後の処理にForeignPathパスを生成し(そのためにcreate_foreign_upper_pathを使用します)、それらパスを指定された上位リレーションに加えるためにadd_pathを呼び出してください。 GetForeignJoinPathsの時と同様に、この関数が何らかのパス作成に成功する必要はありません。なぜなら、ローカル処理を含んでいるパスはいつでも可能だからです。

The <literal>stage</literal> parameter identifies which post-scan/join step is currently being considered. <literal>output_rel</literal> is the upper relation that should receive paths representing computation of this step, and <literal>input_rel</literal> is the relation representing the input to this step. The <literal>extra</literal> parameter provides additional details, currently, it is set only for <literal>UPPERREL_PARTIAL_GROUP_AGG</literal> or <literal>UPPERREL_GROUP_AGG</literal>, in which case it points to a <literal>GroupPathExtraData</literal> structure; or for <literal>UPPERREL_FINAL</literal>, in which case it points to a <literal>FinalPathExtraData</literal> structure. (Note that <structname>ForeignPath</structname> paths added to <literal>output_rel</literal> would typically not have any direct dependency on paths of the <literal>input_rel</literal>, 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.) stageパラメータはどのスキャン/結合後の処理が現在考慮されているかを定めます。 output_relは本処理の計算方法をあらわすパスを受け取るであろう上位リレーションで、input_relは本処理への入力をあらわすリレーションです。 extraパラメータは追加の詳細を指定し、今のところUPPERREL_PARTIAL_GROUP_AGGUPPERREL_GROUP_AGGに対して指定できて、この場合はGroupPathExtraData構造体へのポインタです。 さらにUPPERREL_FINALに対しても指定できて、この場合はFinalPathExtraData構造体へのポインタです。 (注意:これらの処理は外部で実行されると考えられるため、output_relに加えられるForeignPathパスは、一般的にinput_relのパスへの直接の依存を全く持たないでしょう。 しかしながら、手前の処理段階のために以前に生成されたパスを検査することは、冗長なプラン作成活動を回避するのに役立ちます。)

See <xref linkend="fdw-planning"/> for additional information. 追加情報については59.4を参照してください。

59.2.4. 外部テーブル更新のためのFDWルーチン #

<title>FDW Routines for Updating Foreign Tables</title>

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: もしFDWが更新可能な外部テーブルをサポートする場合、FDWのニーズと能力に応じて、以下のコールバック関数の一部または全てを提供する必要があります。

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

<command>UPDATE</command> and <command>DELETE</command> 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 <quote>junk</quote>, target columns to the list of columns that are to be retrieved from the foreign table during an <command>UPDATE</command> or <command>DELETE</command>. UPDATEDELETEの操作は、テーブルスキャン関数によって事前にフェッチされた行に対して実行されます。 FDWは、更新や削除の対象行を厳密に識別できるように行IDや主キー列の値といった追加情報を必要とするかもしれません。 それをサポートするために、この関数はUPDATEDELETEの間に外部テーブルから取得される列のリストに追加の隠された(またはジャンクの)ターゲット列を追加することができます。

To do that, construct a <structname>Var</structname> representing an extra value you need, and pass it to <function>add_row_identity_var</function>, 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 <structname>Var</structname> you need, except that <structname>Var</structname>s that are identical except for the <structfield>varno</structfield> field can and should share a column name. The core system uses the junk column names <literal>tableoid</literal> for a table's <structfield>tableoid</structfield> column, <literal>ctid</literal> or <literal>ctid<replaceable>N</replaceable></literal> for <structfield>ctid</structfield>, <literal>wholerow</literal> for a whole-row <structname>Var</structname> marked with <structfield>vartype</structfield> = <type>RECORD</type>, and <literal>wholerow<replaceable>N</replaceable></literal> for a whole-row <structname>Var</structname> with <structfield>vartype</structfield> 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. それを行うには、必要な追加の値を表すVarを作成し、それをジャンク列の名前とともにadd_row_identity_varに渡します。(複数の列が必要な場合は、これを二回以上実行できます。) 必要とするそれぞれのVarに個別のジャンク列名を選択する必要があります。ただし、Varvarnoフィールドを除いて同一である場合は、列名を共有することができるのでそうすべきです。 コアシステムは、テーブルのtableoid列をジャンク列名tableoidに、ctidまたはctidNctidに使用し、vartype = RECORDと記された行全体のVarwholerowに、vartypeを記された行全体のVarwholerowN使用しており、テーブルで宣言された行型が同じです。 できる限りこれらの名前を再利用してください(プランナは同一のジャンク列に対する重複したリクエストを結合します)。 もしこれらとは別の種類のジャンク列が必要なら、他のFDWとの衝突を避けるために拡張子名をプレフィックスとした名前を選ぶのが賢明かもしれません。

If the <function>AddForeignUpdateTargets</function> pointer is set to <literal>NULL</literal>, no extra target expressions are added. (This will make it impossible to implement <command>DELETE</command> operations, though <command>UPDATE</command> may still be feasible if the FDW relies on an unchanging primary key to identify rows.) もしAddForeignUpdateTargetsポインタがNULLに設定されている場合は、追加のターゲット式は追加されません。 (FDWが行を識別するのに不変の主キーに依存するのであればUPDATEは依然として実現可能かもしれませんが、DELETE操作を実装することは不可能になるでしょう。)

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 <structname>ModifyTable</structname> plan node that performs the update action. This private information must have the form of a <literal>List</literal>, and will be delivered to <function>BeginForeignModify</function> during the execution stage. 外部テーブルに対する挿入、更新、削除に必要となる、追加のプラン生成アクションを実行します。 この関数は、更新処理を実行するModifyTableプランノードに追加されるFDW固有の情報を生成します。この固有情報はList形式でなければならず、また実行段階の間にBeginForeignModifyに渡されます。

<literal>root</literal> is the planner's global information about the query. <literal>plan</literal> is the <structname>ModifyTable</structname> plan node, which is complete except for the <structfield>fdwPrivLists</structfield> field. <literal>resultRelation</literal> identifies the target foreign table by its range table index. <literal>subplan_index</literal> identifies which target of the <structname>ModifyTable</structname> plan node this is, counting from zero; use this if you want to index into per-target-relation substructures of the <literal>plan</literal> node. rootはその問い合わせに関するプランナのグローバル情報です。 planfdwPrivListsフィールドを除いて完成しているModifyTableプランノードです。 resultRelationは対象の外部テーブルをレンジテーブルの添字で識別します。 subplan_indexModifyTableプランノードの対象がどれであるかを0始まりで識別します。 これは、planノードのターゲットリレーションごとのサブ構造にインデックスを付けたい場合に使用してください。

See <xref linkend="fdw-planning"/> for additional information. 追加情報は59.4を参照してください。

If the <function>PlanForeignModify</function> pointer is set to <literal>NULL</literal>, no additional plan-time actions are taken, and the <literal>fdw_private</literal> list delivered to <function>BeginForeignModify</function> will be NIL. もしPlanForeignModifyポインタがNULLに設定されている場合は、追加のプラン作成時処理は実行されず、BeginForeignModifyに渡されるfdw_privateリストは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, <function>ExecForeignInsert/ExecForeignBatchInsert</function>, <function>ExecForeignUpdate</function> or <function>ExecForeignDelete</function> will be called for tuple(s) to be inserted, updated, or deleted. 外部テーブルへの変更操作の実行を開始します。 このルーチンはエグゼキュータの起動中に呼び出されます。 実際のテーブル変更に先立って必要なあらゆる初期化処理を実行する必要があります。 その後、各タプルが挿入、更新、削除されるようにExecForeignInsert/ExecForeignBatchInsertExecForeignUpdateExecForeignDeleteのいずれかが呼ばれます。

<literal>mtstate</literal> is the overall state of the <structname>ModifyTable</structname> plan node being executed; global data about the plan and execution state is available via this structure. <literal>rinfo</literal> is the <structname>ResultRelInfo</structname> struct describing the target foreign table. (The <structfield>ri_FdwState</structfield> field of <structname>ResultRelInfo</structname> is available for the FDW to store any private state it needs for this operation.) <literal>fdw_private</literal> contains the private data generated by <function>PlanForeignModify</function>, if any. <literal>subplan_index</literal> identifies which target of the <structname>ModifyTable</structname> plan node this is. <literal>eflags</literal> contains flag bits describing the executor's operating mode for this plan node. mtstateは実行されているModifyTableプランノード全体の状態です。プランに関する全般的なデータと実行状態はこの構造体経由で利用可能です。 rinfoは対象の外部テーブルを表すResultRelInfo構造体です。 (ResultRelInfori_FdwStateフィールドはこの操作で必要となる固有の状態をFDWが格納するのに利用できます。) fdw_privateは、もしあればPlanForeignModifyで生成された固有データを含みます。 subplan_indexは、これがModifyTableプランノードのどのターゲットであるかを識別します。 eflagsは、このプランノードに関するエグゼキュータの操作モードを表すフラグビットを含みます。

Note that when <literal>(eflags &amp; EXEC_FLAG_EXPLAIN_ONLY)</literal> 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 <function>ExplainForeignModify</function> and <function>EndForeignModify</function>. (eflags & EXEC_FLAG_EXPLAIN_ONLY)が真の場合、この関数は外部に見える処理を実行すべきではないことに注意してください。 ExplainForeignModifyEndForeignModify用にノード状態を有効にするのに必要な最小限のことだけを実行するべきです。

If the <function>BeginForeignModify</function> pointer is set to <literal>NULL</literal>, no action is taken during executor startup. もしBeginForeignModifyポインタがNULLに設定されている場合は、エグゼキュータ起動時には追加処理は何も実行されません。

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

Insert one tuple into the foreign table. <literal>estate</literal> is global execution state for the query. <literal>rinfo</literal> is the <structname>ResultRelInfo</structname> struct describing the target foreign table. <literal>slot</literal> contains the tuple to be inserted; it will match the row-type definition of the foreign table. <literal>planSlot</literal> contains the tuple that was generated by the <structname>ModifyTable</structname> plan node's subplan; it differs from <literal>slot</literal> in possibly containing additional <quote>junk</quote> columns. (The <literal>planSlot</literal> is typically of little interest for <command>INSERT</command> cases, but is provided for completeness.) 外部テーブルにタプルを一つ挿入します。 estateはその問い合わせのグローバルな実行状態です。 rinfoは対象の外部テーブルを表すResultRelInfo構造体です。 slotには挿入されるタプルが含まれます。その行型定義は外部テーブルと一致します。 planSlotにはModifyTableプランノードのサブプランが生成したタプルが含まれます。追加のジャンク列を含みうる点において、slotとは異なります。(planSlotは一般的にINSERTのケースにおいてはそれほど意味を持ちませんが、完全性のために提供されます。)

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 <literal>slot</literal> can be re-used for this purpose. 戻り値は実際に挿入されたデータ(例えばトリガー処理の結果などにより、提供されたデータとは異なるかもしれません)を含むスロットか、または(こちらも一般的にトリガーの結果)実際には挿入されなかった場合はNULLです。 渡されたslotはこの用途に再利用可能です。

The data in the returned slot is used only if the <command>INSERT</command> statement has a <literal>RETURNING</literal> clause or involves a view <literal>WITH CHECK OPTION</literal>; or if the foreign table has an <literal>AFTER ROW</literal> trigger. Triggers require all columns, but the FDW could choose to optimize away returning some or all columns depending on the contents of the <literal>RETURNING</literal> clause or <literal>WITH CHECK OPTION</literal> constraints. Regardless, some slot must be returned to indicate success, or the query's reported row count will be wrong. 返却されたスロット内のデータはINSERT文がRETURNING句を持っているか、WITH CHECK OPTIONを伴うビューに影響を及ぼす場合、もしくは、外部テーブルがAFTER ROWトリガを持っていた場合にのみ使われます。 トリガは全列を必要としますが、FDWはRETURNING句やWITH CHECK OPTIONの制約の内容に応じて、返却する列を一部にするかすべてにするかを最適化する余地があります。 それとは関係なく、処理成功を表すためになんらかのスロットは返却しなければなりません。さもないと、報告される問い合わせの結果行数が誤った値になってしまいます。

If the <function>ExecForeignInsert</function> pointer is set to <literal>NULL</literal>, attempts to insert into the foreign table will fail with an error message. もしExecForeignInsertポインタがNULLに設定されている場合は、外部テーブルへの挿入の試みはエラーメッセージとともに失敗します。

Note that this function is also called when inserting routed tuples into a foreign-table partition or executing <command>COPY FROM</command> on a foreign table, in which case it is called in a different way than it is in the <command>INSERT</command> case. See the callback functions described below that allow the FDW to support that. この関数は外部テーブルパーティションに転送対象のタプルを挿入する際、あるいはCOPY FROMを外部テーブルに対して実行する際にも呼び出されることに注意してください。 COPY FROMの場合、INSERTとはこの関数の呼び出され方は異なります。 FDWがそれをサポートすることを可能にする以下で説明するコールバック関数をご覧ください。

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 <function>ExecForeignInsert</function> except <literal>slots</literal> and <literal>planSlots</literal> contain multiple tuples and <literal>*numSlots</literal> specifies the number of tuples in those arrays. 外部テーブルに一括で複数のタプルを挿入します。 slotsplanSlotsが複数のタプルを含むことと*numSlotsがそれらの配列のタプルの数を指定すること以外はExecForeignInsertとパラメータは同じです。

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 <literal>slots</literal> can be re-used for this purpose. The number of successfully inserted tuples is returned in <literal>*numSlots</literal>. 戻り値は実際に挿入されたデータを含んだスロットの配列です。(これは例えばトリガー実行の結果として、提供された結果と異なるかもしれません。) 渡されたslotsは、この目的のために再利用できます。 挿入に成功したタプルの数は、*numSlotsに返されます。

The data in the returned slot is used only if the <command>INSERT</command> statement involves a view <literal>WITH CHECK OPTION</literal>; or if the foreign table has an <literal>AFTER ROW</literal> trigger. Triggers require all columns, but the FDW could choose to optimize away returning some or all columns depending on the contents of the <literal>WITH CHECK OPTION</literal> constraints. 返却されたスロット内のデータはINSERT文がビューWITH CHECK OPTIONを含む場合、または外部テーブルにAFTER ROWトリガーがある場合にのみ、使用されます。 トリガーはすべての列を必要としますが、FDWはWITH CHECK OPTION制約の内容に応じて、一部またはすべての列を返さないように最適化することを選択することができます。

If the <function>ExecForeignBatchInsert</function> or <function>GetForeignModifyBatchSize</function> pointer is set to <literal>NULL</literal>, attempts to insert into the foreign table will use <function>ExecForeignInsert</function>. This function is not used if the <command>INSERT</command> has the <literal>RETURNING</literal> clause. ExecForeignBatchInsertまたはGetForeignModifyBatchSizeポインタにNULLが設定された場合、外部テーブルにはExecForeignInsertを使って挿入を試みます。 この関数はRETURNING句をもつINSERTの場合、使用されません。

Note that this function is also called when inserting routed tuples into a foreign-table partition or executing <command>COPY FROM</command> on a foreign table, in which case it is called in a different way than it is in the <command>INSERT</command> case. See the callback functions described below that allow the FDW to support that. この関数は外部テーブルパーティションに転送対象のタプルを挿入する際、あるいはCOPY FROMを外部テーブルに対して実行する際にも呼び出されることに注意してください。 COPY FROMの場合、INSERTとはこの関数の呼び出され方は異なります。 FDWがそれをサポートすることを可能にする以下で説明するコールバック関数をご覧ください。

int
GetForeignModifyBatchSize(ResultRelInfo *rinfo);

Report the maximum number of tuples that a single <function>ExecForeignBatchInsert</function> call can handle for the specified foreign table. The executor passes at most the given number of tuples to <function>ExecForeignBatchInsert</function>. <literal>rinfo</literal> is the <structname>ResultRelInfo</structname> 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. 指定された外部テーブルに対して、単一のExecForeignBatchInsert呼び出しが処理できる最大のタプル数を報告します。 エグゼキュータは、最大で指定された数のタプルをExecForeignBatchInsertに渡します。 rinfoには、対象の外部テーブルを記述したResultRelInfo構造体を指定します。 FDWは、ユーザーがこの値またはハードコードされた値を設定するための外部サーバや外部テーブルオプションを提供することを想定しています。

If the <function>ExecForeignBatchInsert</function> or <function>GetForeignModifyBatchSize</function> pointer is set to <literal>NULL</literal>, attempts to insert into the foreign table will use <function>ExecForeignInsert</function>. ExecForeignBatchInsertまたはGetForeignModifyBatchSizeポインタにNULLが設定された場合、外部テーブルにはExecForeignInsertを使って挿入を試みます。

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

Update one tuple in the foreign table. <literal>estate</literal> is global execution state for the query. <literal>rinfo</literal> is the <structname>ResultRelInfo</structname> struct describing the target foreign table. <literal>slot</literal> contains the new data for the tuple; it will match the row-type definition of the foreign table. <literal>planSlot</literal> contains the tuple that was generated by the <structname>ModifyTable</structname> plan node's subplan. Unlike <literal>slot</literal>, 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 <literal>planSlot</literal>. Also, <literal>planSlot</literal> typically contains additional <quote>junk</quote> columns. In particular, any junk columns that were requested by <function>AddForeignUpdateTargets</function> will be available from this slot. 外部テーブル内のタプルを一つ更新します。 estateはその問い合わせのグローバルな実行状態です。 rinfoは対象の外部テーブルを表すResultRelInfo構造体です。 slotにはタプルの新しいデータが含まれます。その行型定義は外部テーブルと一致します。 planSlotにはModifyTableプランノードのサブプランが生成したタプルが含まれます。 slotとは異なり、このタプルは問い合わせによって変更された列の新しい値のみを含むので、planSlotにインデックスを付けるために外部テーブルの属性番号に依存しないようにしましょう。 また、planSlotは通常、追加のジャンク列を含んでいます。 特に、AddForeignUpdateTargetsによって要求されたジャンク列は、このスロットから利用できるようになります。

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 <literal>slot</literal> can be re-used for this purpose. 戻り値は実際に更新されたデータ(例えばトリガー処理の結果などにより、提供されたデータとは異なるかもしれません)を含むスロットか、または(こちらも一般的にトリガーの結果)実際には更新されなかった場合はNULLです。 渡されたslotはこの用途に再利用可能です。

The data in the returned slot is used only if the <command>UPDATE</command> statement has a <literal>RETURNING</literal> clause or involves a view <literal>WITH CHECK OPTION</literal>; or if the foreign table has an <literal>AFTER ROW</literal> trigger. Triggers require all columns, but the FDW could choose to optimize away returning some or all columns depending on the contents of the <literal>RETURNING</literal> clause or <literal>WITH CHECK OPTION</literal> constraints. Regardless, some slot must be returned to indicate success, or the query's reported row count will be wrong. 返却されたスロット内のデータはUPDATE文がRETURNING句を持っているか、WITH CHECK OPTIONを伴うビューに影響を及ぼす場合、もしくは外部テーブルがAFTER ROWトリガを持っていた場合にのみ使われます。 トリガは全列を必要としますが、FDWはRETURNING句やWITH CHECK OPTIONの制約の内容に応じて返却する列を一部にするか全てにするかを最適化する余地があります。 それとは関係なく、処理成功を表すためになんらかのスロットは返却しなければなりません。さもないと、報告される問い合わせの結果行数が誤った値になってしまいます。

If the <function>ExecForeignUpdate</function> pointer is set to <literal>NULL</literal>, attempts to update the foreign table will fail with an error message. もしExecForeignUpdateポインタがNULLに設定されている場合は、外部テーブルへの更新の試みはエラーメッセージとともに失敗します。

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

Delete one tuple from the foreign table. <literal>estate</literal> is global execution state for the query. <literal>rinfo</literal> is the <structname>ResultRelInfo</structname> struct describing the target foreign table. <literal>slot</literal> contains nothing useful upon call, but can be used to hold the returned tuple. <literal>planSlot</literal> contains the tuple that was generated by the <structname>ModifyTable</structname> plan node's subplan; in particular, it will carry any junk columns that were requested by <function>AddForeignUpdateTargets</function>. The junk column(s) must be used to identify the tuple to be deleted. 外部テーブルからタプルを一つ削除します。 estateはその問い合わせのグローバルな実行状態です。 rinfoは対象の外部テーブルを表すResultRelInfo構造体です。 slotにはタプルの新しいデータが含まれます。その行型定義は外部テーブルと一致します。 planSlotにはModifyTableプランノードのサブプランが生成したタプルが含まれます。実際、AddForeignUpdateTargetsが要求するジャンク列はこのスロットが運びます。ジャンク列は削除されるタプルを識別するために使用しなければなりません。

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 <literal>slot</literal> can be used to hold the tuple to be returned. 戻り値は実際に削除されたデータを含むスロットか、または(一般的にトリガーの結果)実際には削除されなかった場合はNULLです。 渡されたslotは返却するタプルを保持する用途に利用可能です。

The data in the returned slot is used only if the <command>DELETE</command> query has a <literal>RETURNING</literal> clause or the foreign table has an <literal>AFTER ROW</literal> trigger. Triggers require all columns, but the FDW could choose to optimize away returning some or all columns depending on the contents of the <literal>RETURNING</literal> clause. Regardless, some slot must be returned to indicate success, or the query's reported row count will be wrong. 返却されたスロット内のデータはDELETE問い合わせがRETURNING句を持っていた場合もしくは外部テーブルがAFTER ROWトリガを持っていた場合にのみ使われます。 トリガは全列を必要としますが、FDWはRETURNING句の内容に応じて返却する列を一部にするか全てにするかを最適化する余地があります。 それとは関係なく、処理成功を表すためになんらかのスロットは返却しなければなりません。さもないと、報告される問い合わせの結果行数が誤った値になってしまいます。

If the <function>ExecForeignDelete</function> pointer is set to <literal>NULL</literal>, attempts to delete from the foreign table will fail with an error message. もしExecForeignDeleteポインタがNULLに設定されている場合は、外部テーブルからの削除の試みはエラーメッセージとともに失敗します。

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. テーブル更新を終えてリソースを解放します。 通常、pallocされたメモリを解放することは重要ではありませんが、たとえば開いたファイルやリモートサーバへの接続などはクリーンアップするべきです。

If the <function>EndForeignModify</function> pointer is set to <literal>NULL</literal>, no action is taken during executor shutdown. もしEndForeignModifyポインタがNULLに設定されている場合は、エグゼキュータ終了時には追加処理は何も実行されません。

Tuples inserted into a partitioned table by <command>INSERT</command> or <command>COPY FROM</command> 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 <command>COPY FROM</command> is executed on a foreign table. INSERTあるいはCOPY FROMでパーティション化テーブルに挿入されたタプルはパーティションに転送されます。 FDWが外部テーブルのパーティションへの転送をサポートしているなら、以下のコールバック関数も提供すべきです。 これらの関数は、外部テーブルでCOPY FROMが実行された時に呼び出されます。

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 <command>COPY FROM</command> command. It should perform any initialization needed prior to the actual insertion. Subsequently, <function>ExecForeignInsert</function> or <function>ExecForeignBatchInsert</function> will be called for tuple(s) to be inserted into the foreign table. 外部テーブルへの挿入操作の実行を開始します。 このルーチンは、タプル転送のためにパーティションが選択された場合か、COPY FROMコマンドでターゲットが指定された場合に、最初の行が外部テーブルに挿入される直前に呼び出されます。 この関数は、実際の挿入に先立つすべての必要な初期化を実行すべきです。 続いて、ExecForeignInsertまたはExecForeignBatchInsertが外部テーブルにタブルを挿入するために呼び出されます。

<literal>mtstate</literal> is the overall state of the <structname>ModifyTable</structname> plan node being executed; global data about the plan and execution state is available via this structure. <literal>rinfo</literal> is the <structname>ResultRelInfo</structname> struct describing the target foreign table. (The <structfield>ri_FdwState</structfield> field of <structname>ResultRelInfo</structname> is available for the FDW to store any private state it needs for this operation.) mtstateは、実行中のModifyTableプランノードの全体的な状態です。 プランのグローバルデータと実行状態がこの構造体を通じて得られます。 rinfoResultRelInfo構造体で、ターゲットの外部テーブルを記述します。 (この操作中に必要なFDWのプライベート状態を保存するためにResultRelInfori_FdwStateフィールドが利用可能です。)

When this is called by a <command>COPY FROM</command> command, the plan-related global data in <literal>mtstate</literal> is not provided and the <literal>planSlot</literal> parameter of <function>ExecForeignInsert</function> subsequently called for each inserted tuple is <literal>NULL</literal>, whether the foreign table is the partition chosen for tuple routing or the target specified in the command. この関数がCOPY FROMコマンドで呼ばれると、外部テーブルがタプル転送で選択された対象なのか、あるいはコマンドがターゲットを指定したのかに関わらず、mtstate中のプランに関係するグローバルデータは提供されず、次に個々の挿入されるタプルに対して呼び出されるExecForeignInsertplanSlotパラメータはNULLとなります。

If the <function>BeginForeignInsert</function> pointer is set to <literal>NULL</literal>, no action is taken for the initialization. BeginForeignInsertポインターがNULLなら、初期化処理は実施されません。

Note that if the FDW does not support routable foreign-table partitions and/or executing <command>COPY FROM</command> on foreign tables, this function or <function>ExecForeignInsert/ExecForeignBatchInsert</function> subsequently called must throw error as needed. FDWが外部テーブルパーティションのタプル転送をサポートしていないか、または外部テーブルに対してCOPY FROMの実行をサポートしていないか、あるいはその両方なら、この関数あるいは以後呼ばれたExecForeignInsert/ExecForeignBatchInsertは、必ず必要なだけエラーを引き起こします。

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. 挿入操作を終了してリソースを解放します。 通常、pallocされたメモリを解放することは重要ではありませんが、たとえば開いたファイルやリモートサーバへの接続などはクリーンアップするべきです。

If the <function>EndForeignInsert</function> pointer is set to <literal>NULL</literal>, no action is taken for the termination. EndForeignInsertポインターがNULLなら、終了処理は実施されません。

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 <literal>CmdType</literal> enumeration; that is, <literal>(1 &lt;&lt; CMD_UPDATE) = 4</literal> for <command>UPDATE</command>, <literal>(1 &lt;&lt; CMD_INSERT) = 8</literal> for <command>INSERT</command>, and <literal>(1 &lt;&lt; CMD_DELETE) = 16</literal> for <command>DELETE</command>. 指定された外部テーブルがどの更新処理をサポートしているかを報告します。 戻り値は、その外部テーブルがサポートする操作を表すルールイベント番号のビットマスクである必要があります。 UPDATE用の(1 << CMD_UPDATE) = 4INSERT用の(1 << CMD_INSERT) = 8DELETE用の(1 << CMD_DELETE) = 16といったCmdType列挙値を使います。

If the <function>IsForeignRelUpdatable</function> pointer is set to <literal>NULL</literal>, foreign tables are assumed to be insertable, updatable, or deletable if the FDW provides <function>ExecForeignInsert</function>, <function>ExecForeignUpdate</function>, or <function>ExecForeignDelete</function> 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 <literal>information_schema</literal> views.) もしIsForeignRelUpdatableポインタがNULLに設定されていると、外部テーブルはExecForeignInsertExecForeignUpdateExecForeignDeleteを提供していると、それぞれ挿入、更新、削除をサポートしていると判断します。 この関数は、FDWが一部のテーブルについてのみ更新をサポートする場合にのみ必要です。 (そのような場合でも、この関数でチェックする代わりに問い合わせ実行関数でエラーにしても構いません。しかしながら、この関数はinformation_schemaのビューの表示で更新可否を判定するのに使用されます。)

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 <literal>WITH CHECK OPTION</literal> 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. 外部テーブルへの挿入、更新、削除は、代替インタフェース一式を実装することで最適化できます。 通常の挿入、更新、削除のインタフェースは行をリモートサーバから取得し、その後、それらの行を一つずつ変更します。 一部の場合にはこの一行ごとのやり方は必要ですが、非効率とも言えます。 外部サーバについて行が本当はそれらを引き出すことなしに変更されるべきと判断できて、操作に影響を与える仕組み(行レベルのローカルトリガ、格納生成列、あるいは、親ビューからのWITH CHECK OPTIONの制約)が無いならば、操作全体がリモートサーバで実行されるように計画することができます。 以下に示すインタフェースはこれを可能にします。

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 <literal>true</literal> after performing planning actions needed for that. Otherwise, return <literal>false</literal>. This optional function is called during query planning. If this function succeeds, <function>BeginDirectModify</function>, <function>IterateDirectModify</function> and <function>EndDirectModify</function> 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 <function>PlanForeignModify</function>. リモートサーバ上で直接変更を実行することが安全かを判断します。 そうであれば、そのために必要なプラン作成の動作を実行した後にtrueを返します。 さもなくば、falseを返します。 この省略可能な関数は問い合わせのプラン作成時に呼ばれます。 この関数が成功すると、BeginDirectModifyIterateDirectModifyEndDirectModifyが実行段階で代わりに呼び出されます。 成功しなければ、テーブルの変更は前述のテーブル更新関数を使って実行されます。 パラメータはPlanForeignModifyに対するものと同じです。

To execute the direct modification on the remote server, this function must rewrite the target subplan with a <structname>ForeignScan</structname> plan node that executes the direct modification on the remote server. The <structfield>operation</structfield> and <structfield>resultRelation</structfield> fields of the <structname>ForeignScan</structname> must be set appropriately. <structfield>operation</structfield> must be set to the <literal>CmdType</literal> enumeration corresponding to the statement kind (that is, <literal>CMD_UPDATE</literal> for <command>UPDATE</command>, <literal>CMD_INSERT</literal> for <command>INSERT</command>, and <literal>CMD_DELETE</literal> for <command>DELETE</command>), and the <literal>resultRelation</literal> argument must be copied to the <structfield>resultRelation</structfield> field. リモートサーバで直接変更を実行するには、本関数は対象サブプランをリモートサーバ上で直接変更するForeignScanプランノードで書き換えしなければなりません。 ForeignScanoperationresultRelationフィールドは適切にセットされる必要があります。 operationは文の種類に対応するCmdType列挙値にセットする必要があり(すなわちUPDATEにはCMD_UPDATEINSERTにはCMD_INSERTDELETEにはCMD_DELETE)、そして、resultRelation引数はresultRelationフィールドにコピーされる必要があります。

See <xref linkend="fdw-planning"/> for additional information. 追加情報は59.4を参照してください。

If the <function>PlanDirectModify</function> pointer is set to <literal>NULL</literal>, no attempts to execute a direct modification on the remote server are taken. PlanDirectModifyポインタにNULLが設定されている場合、 リモートサーバでの直接変更の実行は試みられません。

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 <function>IterateDirectModify</function>). The <structname>ForeignScanState</structname> node has already been created, but its <structfield>fdw_state</structfield> field is still NULL. Information about the table to modify is accessible through the <structname>ForeignScanState</structname> node (in particular, from the underlying <structname>ForeignScan</structname> plan node, which contains any FDW-private information provided by <function>PlanDirectModify</function>). <literal>eflags</literal> contains flag bits describing the executor's operating mode for this plan node. リモートサーバでの直接変更を実行する準備をします。 この関数はエグゼキュータが開始するときに呼び出されます。 この関数は(最初のIterateDirectModify呼び出しで実行されるであろう)直接変更より前に必要とされる全ての初期化を実行するべきです。 ForeignScanStateノードはすでに作られていますが、fdw_stateがフィールドはまだNULLです。 変更するテーブルに関する情報はForeignScanStateノードを通して(具体的にはPlanDirectModifyで提供されるFDWプライベート情報を含む、元となるForeignScanプランノードから)入手可能です。 eflagsは、このプランノードに関するエグゼキュータの操作モードを表すフラグビットを含みます。

Note that when <literal>(eflags &amp; EXEC_FLAG_EXPLAIN_ONLY)</literal> 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 <function>ExplainDirectModify</function> and <function>EndDirectModify</function>. (eflags & EXEC_FLAG_EXPLAIN_ONLY)が真の場合、この関数は外部に見える処理を実行すべきではないことに注意してください。 ExplainDirectModifyEndDirectModify用にノード状態を有効にするのに必要な最小限のことだけを実行するべきです。

If the <function>BeginDirectModify</function> pointer is set to <literal>NULL</literal>, no attempts to execute a direct modification on the remote server are taken. BeginDirectModifyポインタがNULLに設定されている場合、リモートサーバでの直接変更の実行は試みられません。

TupleTableSlot *
IterateDirectModify(ForeignScanState *node);

When the <command>INSERT</command>, <command>UPDATE</command> or <command>DELETE</command> query doesn't have a <literal>RETURNING</literal> 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 <literal>RETURNING</literal> calculation, returning it in a tuple table slot (the node's <structfield>ScanTupleSlot</structfield> should be used for this purpose). The data that was actually inserted, updated or deleted must be stored in <literal>node->resultRelInfo->ri_projectReturning-&gt;pi_exprContext-&gt;ecxt_scantuple</literal>. 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 <function>BeginDirectModify</function> if you need longer-lived storage, or use the <structfield>es_query_cxt</structfield> of the node's <structname>EState</structname>. INSERTUPDATE、または、DELETEの問い合わせがRETURNING句を持たないときには、リモートサーバでの直接変更の後、単にNULLが返ります。 問い合わせがRETURNING句を持つときには、RETURNING計算に必要なデータを含む結果を一つ取り出し、タプルテーブルスロットでそれを返します(この用途にはノードのScanTupleSlotを使うべきです)。 実際に挿入、更新、削除されたデータはnode->resultRelInfo->ri_projectReturning->pi_exprContext->ecxt_scantupleに格納されなければなりません。 有効な行がそれ以上なければNULLを返します。 これは呼び出しの間でリセットされる寿命の短いメモリコンテキストで呼び出されることに注意してください。 より長命な格納場所を必要とするなら、BeginDirectModifyでメモリコンテキストを作るか、ノードのEStatees_query_cxtを使ってください。

The rows returned must match the <structfield>fdw_scan_tlist</structfield> 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 <literal>RETURNING</literal> calculation, you should insert nulls in those column positions, or else generate a <structfield>fdw_scan_tlist</structfield> list with those columns omitted. 返される行は、ターゲットリストfdw_scan_tlistが提供されたなら、それとマッチしなければならず、提供されていない場合は変更されている外部テーブルの行型とマッチしなければなりません。 RETURNING計算に不要な列を取り出さないように最適化することを選ぶなら、それらの列の位置にNULLを入れるか、あるいはそれらの列を除いたfdw_scan_tlistリストを生成するべきです。

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 <structname>ForeignScanState</structname> node in the <command>EXPLAIN ANALYZE</command> case. 問い合わせが句をもつかどうかによらず、問い合わせが報告する行数はFDW自身によって増加されなければなりません。 問い合わせが句を持たないときも、FDWはEXPLAIN ANALYZEの場合のForeignScanState nodeむけに行数を増加させなければなりません。

If the <function>IterateDirectModify</function> pointer is set to <literal>NULL</literal>, no attempts to execute a direct modification on the remote server are taken. IterateDirectModifyポインタがNULLに設定されている場合、リモートサーバでの直接変更の実行は試みられません。

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. リモートサーバでの直接変更の後、クリーンアップします。 通常、pallocされたメモリを解放することは重要ではありませんが、たとえば開いたファイルやリモートサーバへの接続などはクリーンアップするべきです。

If the <function>EndDirectModify</function> pointer is set to <literal>NULL</literal>, no attempts to execute a direct modification on the remote server are taken. EndDirectModifyポインタがNULLに設定されている場合、リモートサーバでの直接変更の実行は試みられません。

59.2.5. TRUNCATEのためのFDWルーチン #

<title>FDW Routines for <command>TRUNCATE</command></title>

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

Truncate foreign tables. This function is called when <xref linkend="sql-truncate"/> is executed on a foreign table. <literal>rels</literal> is a list of <structname>Relation</structname> data structures of foreign tables to truncate. 外部テーブルを切り捨てます。 この関数はTRUNCATEが外部テーブルに対して実行されたときに呼び出されます。 relsは切り捨てられる外部テーブルのRelationデータ構造のリストです。

<literal>behavior</literal> is either <literal>DROP_RESTRICT</literal> or <literal>DROP_CASCADE</literal> indicating that the <literal>RESTRICT</literal> or <literal>CASCADE</literal> option was requested in the original <command>TRUNCATE</command> command, respectively. behaviorDROP_RESTRICTDROP_CASCADEのいずれかで、それぞれ元のTRUNCATEコマンドでRESTRICTまたCASCADEオプションが要求されたことを表しています。

If <literal>restart_seqs</literal> is <literal>true</literal>, the original <command>TRUNCATE</command> command requested the <literal>RESTART IDENTITY</literal> behavior, otherwise the <literal>CONTINUE IDENTITY</literal> behavior was requested. restart_seqstrue の場合、元のTRUNCATEコマンドがRESTART IDENTITY動作が要求され、それ以外の場合はCONTINUE IDENTITY動作が要求されていたことになります。

Note that the <literal>ONLY</literal> options specified in the original <command>TRUNCATE</command> command are not passed to <function>ExecForeignTruncate</function>. This behavior is similar to the callback functions of <command>SELECT</command>, <command>UPDATE</command> and <command>DELETE</command> on a foreign table. 元のTRUNCATEコマンドで指定されたONLYオプションはExecForeignTruncateに渡されないことに注意してください。 この動作は外部テーブルに対するSELECTUPDATEDELETEのコールバック関数と同様です。

<function>ExecForeignTruncate</function> is invoked once per foreign server for which foreign tables are to be truncated. This means that all foreign tables included in <literal>rels</literal> must belong to the same server. ExecForeignTruncateは、外部テーブルが切り捨てられる外部サーバごとに一度呼び出されます。 これは、relsに含まれるすべての外部テーブルが同じサーバーに所属していなければならないことを意味しています。

If the <function>ExecForeignTruncate</function> pointer is set to <literal>NULL</literal>, attempts to truncate foreign tables will fail with an error message. ExecForeignTruncateポインタがNULLに設定されている場合、外部テーブルを切り捨てる試みはエラーメッセージとともに失敗します。

59.2.6. 行ロックのためのFDWルーチン #

<title>FDW Routines for Row Locking</title>

If an FDW wishes to support <firstterm>late row locking</firstterm> (as described in <xref linkend="fdw-row-locking"/>), it must provide the following callback functions: FDWが(59.5で説明される)遅延行ロックをサポートする場合は、以下のコールバック関数を提供する必要があります。

RowMarkType
GetForeignRowMarkType(RangeTblEntry *rte,
                      LockClauseStrength strength);

Report which row-marking option to use for a foreign table. <literal>rte</literal> is the <structname>RangeTblEntry</structname> node for the table and <literal>strength</literal> describes the lock strength requested by the relevant <literal>FOR UPDATE/SHARE</literal> clause, if any. The result must be a member of the <literal>RowMarkType</literal> enum type. 行の印付けでどのオプションを外部テーブルに使うかを報告します。 rteはテーブルのRangeTblEntryノードで、strengthは関連するFOR UPDATE/SHARE句があれば、それが要求するロックの強さを表します。 その結果は、RowMarkType列挙型のメンバーでなければなりません。

This function is called during query planning for each foreign table that appears in an <command>UPDATE</command>, <command>DELETE</command>, or <command>SELECT FOR UPDATE/SHARE</command> query and is not the target of <command>UPDATE</command> or <command>DELETE</command>. この関数はUPDATEDELETESELECT FOR UPDATE/SHAREの問い合わせに現れ、かつUPDATEあるいはDELETEの対象ではない各外部テーブルについて、問い合わせの計画時に呼び出されます。

If the <function>GetForeignRowMarkType</function> pointer is set to <literal>NULL</literal>, the <literal>ROW_MARK_COPY</literal> option is always used. (This implies that <function>RefetchForeignRow</function> will never be called, so it need not be provided either.) GetForeignRowMarkTypeのポインタがNULLに設定されていると、必ずROW_MARK_COPYオプションが使われます。 (これはRefetchForeignRowが決して呼び出されないので、それを提供する必要もない、ということを意味します。)

See <xref linkend="fdw-row-locking"/> for more information. さらなる情報については59.5を参照してください。

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. <literal>estate</literal> is global execution state for the query. <literal>erm</literal> is the <structname>ExecRowMark</structname> struct describing the target foreign table and the row lock type (if any) to acquire. <literal>rowid</literal> identifies the tuple to be fetched. <literal>slot</literal> contains nothing useful upon call, but can be used to hold the returned tuple. <literal>updated</literal> is an output parameter. 必要ならロックした後で、外部テーブルから1つのタプルスロットを再フェッチします。 estateは問い合わせのグローバルな実行状態です。 ermは対象の外部テーブルおよび獲得する行ロックの種別(あれば)を記述するExecRowMark構造体です。 rowidはフェッチするタプルを特定するものです。 slotは呼び出しで役立つ内容は含みませんが、返されたタプルを保持するために使用できます。 updatedは出力パラメータです。

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 <literal>erm-&gt;markType</literal>, which is the value previously returned by <function>GetForeignRowMarkType</function>. (<literal>ROW_MARK_REFERENCE</literal> means to just re-fetch the tuple without acquiring any lock, and <literal>ROW_MARK_COPY</literal> will never be seen by this routine.) この関数はタプルを与えられたスロットに格納するか、あるいは行ロックが取得できなければタプルをクリアします。 獲得する行ロックの種別はerm->markTypeで指定されます。この値は事前にGetForeignRowMarkTypeから返されたものです。 (ROW_MARK_REFERENCEは行のロックを獲得せずに、単にタプルを再フェッチすることを意味し、また、ROW_MARK_COPYはこのルーチンで使われることはありません。)

In addition, <literal>*updated</literal> should be set to <literal>true</literal> 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 <literal>true</literal> is recommended.) そして、*updatedはフェッチしたタプルが、以前に取得したものと同じではなく、更新されたバージョンであったときにtrueにセットされます。 (どちらなのかFDWが判断できない場合は、trueを返すことが推奨されます)。

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 <literal>SKIP LOCKED</literal> option is specified by <literal>erm-&gt;waitPolicy</literal>. デフォルトでは、行ロックの獲得に失敗したときはエラーを発生させるべきであることに注意してください。 空スロットを返すのが適切なのは、erm->waitPolicySKIP LOCKEDオプションが指定されている場合だけです。

The <literal>rowid</literal> is the <structfield>ctid</structfield> value previously read for the row to be re-fetched. Although the <literal>rowid</literal> value is passed as a <type>Datum</type>, it can currently only be a <type>tid</type>. The function API is chosen in hopes that it may be possible to allow other data types for row IDs in future. rowidは、再フェッチする行を以前読んだ時のctid値です。 rowid値はDatumとして渡されますが、現在はtidにしかなりません。 将来は行ID以外のデータ型が可能になることを期待して、関数APIとすることが選択されました。

If the <function>RefetchForeignRow</function> pointer is set to <literal>NULL</literal>, attempts to re-fetch rows will fail with an error message. RefetchForeignRowポインタがNULLの場合、行を再フェッチする試みは失敗し、エラーメッセージを発行します。

See <xref linkend="fdw-row-locking"/> for more information. さらなる情報については59.5を参照してください。

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 <literal>NULL</literal> and instead set <structfield>fdw_recheck_quals</structfield> 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. <literal>RecheckForeignScan</literal> 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. 以前に戻されたタプルが、関連するスキャンおよび結合の制約とまだ一致しているか再検査し、更新されたバージョンのタプルを提供する場合もあります。 結合のプッシュダウンを行わない外部データラッパーでは、通常は、これをNULLにセットし、代わりにfdw_recheck_qualsを適切にセットする方が便利でしょう。 しかし、外部結合をプッシュダウンする場合、すべてのベーステーブルに関する検査を結果のタプルに適用するだけでは、たとえすべての必要な属性がそこにあったとしても十分ではありません。 なぜなら一部の制約が一致しないことで、タプルが戻されない代わりに、一部の属性がNULLになってしまうかもしれないからです。 RecheckForeignScan制約を再検査し、それが依然として満たされていれば真を、そうでなければ偽を返すことができます。 それだけでなく、置換されたタプルを提供されたスロットに格納することもできます。

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 <literal>ForeignScan</literal>. 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 <literal>GetExistingLocalJoinPath</literal> may be used to search existing paths for a suitable local join path, which can be used as the alternative local join plan. <literal>GetExistingLocalJoinPath</literal> 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.) 結合のプッシュダウンを実装する場合、外部データラッパーは通常、再検査のためだけに使用される代替のローカル結合プランを構築します。 これがForeignScanの外部サブプランとなります。 再検査が必要な時は、このサブプランを実行して、結果のタプルをスロットに格納することができます。 どのベーステーブルも最大で1行しか返さないので、このプランは効率的である必要はありません。 例えば、すべての結合をネステッドループで実装することもできます。 関数GetExistingLocalJoinPathは、存在するパスから代替ローカルの結合プランとして使用可能な適当なローカル結合パスを検索するのに使われるかもしれません。 GetExistingLocalJoinPathは指定された結合リレーションのパスリストのパラメータ化されていないパスを検索します。 (そのようなパスが見つからなかった場合はNULLを返します。この場合、外部データラッパーはそれ自身によりローカルパスを構築するかもしれず、あるいは、その結合むけのアクセスパスを作らないことを選択するかもしれません。)

59.2.7. EXPLAINのためのFDWルーチン #

<title>FDW Routines for <command>EXPLAIN</command></title>

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

Print additional <command>EXPLAIN</command> output for a foreign table scan. This function can call <function>ExplainPropertyText</function> and related functions to add fields to the <command>EXPLAIN</command> output. The flag fields in <literal>es</literal> can be used to determine what to print, and the state of the <structname>ForeignScanState</structname> node can be inspected to provide run-time statistics in the <command>EXPLAIN ANALYZE</command> case. 外部テーブルスキャンの追加のEXPLAIN出力を表示します。 EXPLAIN出力にフィールドを追加するためにExplainPropertyTextや関連する関数を呼び出すことができます。 esの中のフラグフィールドは何を表示するかを決めるのに使用できます。また、EXPLAIN ANALYZEの場合には、実行時統計情報を提供するためにForeignScanStateノードの状態を調べることができます。

If the <function>ExplainForeignScan</function> pointer is set to <literal>NULL</literal>, no additional information is printed during <command>EXPLAIN</command>. もしExplainForeignScanポインタがNULLに設定されている場合は、EXPLAIN中に追加情報は表示されません。

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

Print additional <command>EXPLAIN</command> output for a foreign table update. This function can call <function>ExplainPropertyText</function> and related functions to add fields to the <command>EXPLAIN</command> output. The flag fields in <literal>es</literal> can be used to determine what to print, and the state of the <structname>ModifyTableState</structname> node can be inspected to provide run-time statistics in the <command>EXPLAIN ANALYZE</command> case. The first four arguments are the same as for <function>BeginForeignModify</function>. 外部テーブル更新の追加のEXPLAIN出力を表示します。 EXPLAIN出力にフィールドを追加するためにExplainPropertyTextや関連する関数を呼び出すことができます。 esの中のフラグフィールドは何を表示するかを決めるのに使用できます。また、EXPLAIN ANALYZEの場合には、実行時統計情報を提供するためにModifyTableStateノードの状態を調べることができます。 最初の4つの引数はBeginForeignModifyと同じです。

If the <function>ExplainForeignModify</function> pointer is set to <literal>NULL</literal>, no additional information is printed during <command>EXPLAIN</command>. もしExplainForeignModifyポインタがNULLに設定されている場合は、EXPLAIN中に追加情報は表示されません。

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

Print additional <command>EXPLAIN</command> output for a direct modification on the remote server. This function can call <function>ExplainPropertyText</function> and related functions to add fields to the <command>EXPLAIN</command> output. The flag fields in <literal>es</literal> can be used to determine what to print, and the state of the <structname>ForeignScanState</structname> node can be inspected to provide run-time statistics in the <command>EXPLAIN ANALYZE</command> case. リモートサーバでの直接変更について追加EXPLAIN出力を表示します。 この関数はEXPLAIN出力にフィールドを加えるためにExplainPropertyTextと関連の関数を呼ぶことができます。 esの中のフラグフィールドは何を表示するかを決めるのに使用できます。また、EXPLAIN ANALYZEの場合には、実行時統計情報を提供するためにForeignScanStateノードの状態を調べることができます。

If the <function>ExplainDirectModify</function> pointer is set to <literal>NULL</literal>, no additional information is printed during <command>EXPLAIN</command>. ExplainDirectModifyポインタがNULLに設定されている場合は、EXPLAIN中に追加情報は表示されません。

59.2.8. ANALYZEのためのFDWルーチン #

<title>FDW Routines for <command>ANALYZE</command></title>

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

This function is called when <xref linkend="sql-analyze"/> is executed on a foreign table. If the FDW can collect statistics for this foreign table, it should return <literal>true</literal>, and provide a pointer to a function that will collect sample rows from the table in <parameter>func</parameter>, plus the estimated size of the table in pages in <parameter>totalpages</parameter>. Otherwise, return <literal>false</literal>. この関数はANALYZEが外部テーブルに対して実行されたときに呼び出されます。 もしFDWがこの外部テーブルの統計情報を収集できる場合は、そのテーブルからサンプル行を集める関数のポインタとページ単位でのテーブルサイズの見積もりをそれぞれfunctotalpagesに渡しtrueを返す必要があります。 そうでない場合は、falseを返します。

If the FDW does not support collecting statistics for any tables, the <function>AnalyzeForeignTable</function> pointer can be set to <literal>NULL</literal>. もしFDWが統計情報の収集をどのテーブルについてもサポートしない場合は、AnalyzeForeignTableポインタを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 <parameter>targrows</parameter> rows should be collected from the table and stored into the caller-provided <parameter>rows</parameter> 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 <parameter>totalrows</parameter> and <parameter>totaldeadrows</parameter>. (Set <parameter>totaldeadrows</parameter> to zero if the FDW does not have any concept of dead rows.) 最大targrows行のランダムサンプルをテーブルから収集し、呼び出し元が提供するrows配列に格納する必要があります。 実際に収集された行の数を返す必要があります。 さらに、テーブルに含まれる有効行と不要行の合計数の見積もりを出力パラメータのtotalrowstotaldeadrowsに返す必要があります。(もしFDWが不要行という概念を持たない場合はtotaldeadrowsを0に設定してください。)

59.2.9. IMPORT FOREIGN SCHEMAのためのFDWルーチン #

<title>FDW Routines for <command>IMPORT FOREIGN SCHEMA</command></title>

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

Obtain a list of foreign table creation commands. This function is called when executing <xref linkend="sql-importforeignschema"/>, 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 <xref linkend="sql-createforeigntable"/> command. These strings will be parsed and executed by the core server. 外部テーブル作成コマンドのリストを取得します。 この関数はIMPORT FOREIGN SCHEMAを実行する時に呼び出され、その文の解析木と外部サーバが使用するOIDとを渡されます。 C文字列のリストを返し、その各文字列はCREATE FOREIGN TABLEコマンドを含んでいる必要があります。 これらの文字列はコアサーバが解析して実行します。

Within the <structname>ImportForeignSchemaStmt</structname> struct, <structfield>remote_schema</structfield> is the name of the remote schema from which tables are to be imported. <structfield>list_type</structfield> identifies how to filter table names: <literal>FDW_IMPORT_SCHEMA_ALL</literal> means that all tables in the remote schema should be imported (in this case <structfield>table_list</structfield> is empty), <literal>FDW_IMPORT_SCHEMA_LIMIT_TO</literal> means to include only tables listed in <structfield>table_list</structfield>, and <literal>FDW_IMPORT_SCHEMA_EXCEPT</literal> means to exclude the tables listed in <structfield>table_list</structfield>. <structfield>options</structfield> 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 <literal>NOT NULL</literal> attributes of columns should be imported. These options need not have anything to do with those supported by the FDW as database object options. ImportForeignSchemaStmt構造体において、remote_schemaはリモートスキーマの名前で、そこからテーブルがインポートされます。 list_typeはテーブル名のフィルタ方法を指定します。 ここで、FDW_IMPORT_SCHEMA_ALLはリモートスキーマのすべてのテーブルをインポートすること(この場合、table_listは空にします)、 FDW_IMPORT_SCHEMA_LIMIT_TOtable_listに列挙されたテーブルだけを含めること、 そしてFDW_IMPORT_SCHEMA_EXCEPTtable_listに列挙されたテーブルを除外することを意味します。 optionsはインポートのプロセスで使用されるオプションのリストです。 オプションの意味はFDWに依存します。 例えば、FDWは列のNOT NULL属性をインポートするかどうかを定めるオプションを使うことができます。 これらのオプションはFDWがデータベースオブジェクトのオプションとしてサポートするものと何ら関係ある必要はありません。

The FDW may ignore the <structfield>local_schema</structfield> field of the <structname>ImportForeignSchemaStmt</structname>, because the core server will automatically insert that name into the parsed <command>CREATE FOREIGN TABLE</command> commands. FDWはImportForeignSchemaStmtlocal_schemaフィールドを無視しても良いです。 なぜなら、コアサーバは解析されたCREATE FOREIGN TABLEコマンドにその名前を自動的に挿入するからです。

The FDW does not have to concern itself with implementing the filtering specified by <structfield>list_type</structfield> and <structfield>table_list</structfield>, 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 <function>IsImportableForeignTable()</function> may be useful to test whether a given foreign-table name will pass the filter. FDWはlist_typeおよびtable_listで指定されるフィルタの実装にも注意する必要はありません。 なぜなら、コアサーバはそれらのオプションによって除外されるテーブルに対して戻されたコマンドをすべて自動的にスキップするからです。 しかし、除外されるテーブルについてコマンドを作成する作業を回避するのは、そもそも役立つことが多いです。 関数IsImportableForeignTable()は指定の外部テーブル名がフィルタを通るかどうかの検査に役立つかもしれません。

If the FDW does not support importing table definitions, the <function>ImportForeignSchema</function> pointer can be set to <literal>NULL</literal>. FDWがテーブル定義のインポートをサポートしない場合は、ImportForeignSchemaポインタをNULLにセットすることができます。

59.2.10. パラレル実行のためのFDWルーチン #

<title>FDW Routines for Parallel Execution</title>

A <structname>ForeignScan</structname> node can, optionally, support parallel execution. A parallel <structname>ForeignScan</structname> 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. ForeignScanノードは、オプションとして、パラレル実行をサポートします。 並列ForeignScanは複数プロセスで実行され、全ての協調プロセスにわたって各行が一度だけ返るようにしなければなりません。 これを行うため、プロセスは動的共有メモリの固定サイズチャンクを通して調整をはかることができます。 この共有メモリは全プロセスで同じアドレスに割り当てされることが保証されませんので、ポインタを含まないようにしなければなりません。 以下のコールバックは一般に全て省略可能ですが、パラレル実行をサポートするためには必要です。

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. 並列操作に必要とされるであろう動的共有メモリ量を推定します。 これは実際に使われる量よりも大きくてよいですが、小さくてはいけません。 戻り値はバイト単位です。 この関数はオプションであり、必要でない場合は省略することができます。 しかし省略された場合、FDWの使用のために共有メモリが割り当てられないため、次の3つの関数も省略しなければなりません。

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

Initialize the dynamic shared memory that will be required for parallel operation. <literal>coordinate</literal> points to a shared memory area of size equal to the return value of <function>EstimateDSMForeignScan</function>. This function is optional, and can be omitted if not needed. 並列処理で必要とされる動的共有メモリを初期化します。 coordinateEstimateDSMForeignScanの戻り値に等しいサイズの共有メモリ領域へのポインタです。 この関数はオプションであり、必要でない場合は省略することができます。

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 <function>ReScanForeignScan</function> function resets only local state. Currently, this function will be called before <function>ReScanForeignScan</function>, but it's best not to rely on that ordering. 外部スキャンプランノードが再スキャンされようとしているときに、並列操作に必要な動的共有メモリーを再初期化します。 この関数はオプションであり、必要でない場合は省略することができます。 ReScanForeignScan関数はローカル状態のみをリセットし、この関数は共有状態のみをリセットすることをお勧めします。 現在、この関数はReScanForeignScanより前に呼び出されますが、その順序に依存しないようにする方が良いでしょう。

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 <function>InitializeDSMForeignScan</function>. This function is optional, and can be omitted if not needed. InitializeDSMForeignScanでリーダーがセットアップした共有状態に基づくパラレルワーカーのローカル状態を初期化します。 この関数はオプションであり、必要でない場合は省略することができます。

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, <literal>EndForeignScan</literal> 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. ノードが完了するまで実行されないことが予想されるときにリソースを解放します。 これはすべてのケースで呼ばれるわけではありません。 EndForeignScanは、この関数が最初に呼び出されなくても呼び出されることがあります。 このコールバックが呼び出された直後に、パラレルクエリで使用されるDSM(動的共有メモリ)セグメントが破棄されるため、DSMセグメントがなくなる前に何らかのアクションを実行する外部データラッパーがこのメソッドを実装する必要があります。

59.2.11. 非同期実行のためのFDWルーチン #

<title>FDW Routines for Asynchronous Execution</title>

A <structname>ForeignScan</structname> node can, optionally, support asynchronous execution as described in <filename>src/backend/executor/README</filename>. The following functions are all optional, but are all required if asynchronous execution is to be supported. ForeignScanノードは、オプションとしてsrc/backend/executor/READMEに記述されているように、非同期実行をサポートすることが可能です。 以下の関数はすべてオプションですが、非同期実行をサポートする場合はすべて必須です。

bool
IsForeignPathAsyncCapable(ForeignPath *path);

Test whether a given <structname>ForeignPath</structname> 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 <structname>AppendPath</structname> 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. 与えられたForeignPathパスが、そもそも外部リレーションを非同期でスキャンできるかどうかをテストします。 この関数は与えられたパスがAppendPathパスの直接の子であり、プランナが非同期実行が性能を向上させると考える場合にのみ、問い合わせ計画の最後で呼ばれ、与えられたパスが外部リレーションを非同期にスキャンできる場合に真を返さなければなりません。

If this function is not defined, it is assumed that the given path scans the foreign relation using <function>IterateForeignScan</function>. (This implies that the callback functions described below will never be called, so they need not be provided either.) この関数が定義されていない場合、与えられたパスはIterateForeignScanを使用して外部リレーションをスキャンすることが想定されます。 (これは以下で説明されるコールバック関数が決して呼ばれないことを意味します。呼ばれないことを意味するので、それらも提供される必要はありません。)

void
ForeignAsyncRequest(AsyncRequest *areq);

Produce one tuple asynchronously from the <structname>ForeignScan</structname> node. <literal>areq</literal> is the <structname>AsyncRequest</structname> struct describing the <structname>ForeignScan</structname> node and the parent <structname>Append</structname> node that requested the tuple from it. This function should store the tuple into the slot specified by <literal>areq-&gt;result</literal>, and set <literal>areq-&gt;request_complete</literal> to <literal>true</literal>; 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 <literal>false</literal>, and set <literal>areq-&gt;callback_pending</literal> to <literal>true</literal> for the <structname>ForeignScan</structname> 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 <literal>areq-&gt;request_complete</literal> flag to <literal>true</literal>. It's recommended to use <function>ExecAsyncRequestDone</function> or <function>ExecAsyncRequestPending</function> to set the output parameters in the <literal>areq</literal>. ForeignScanノードから非同期に1つのタプルを生成します。 areqForeignScanノードと、そこからタプルを要求した親Appendノードを記述するAsyncRequest構造体です。 areq->resultで指定されたスロットにタプルを格納し、areq->request_completetrueを設定します。 または、ネットワークI/Oなどコアサーバの外部のイベントを待つ必要があり、すぐにタプルを生成できない場合は、フラグをfalseに、areq->callback_pendingtrueに設定して、ForeignScanノードが後述のコールバック関数からコールバックを取得するようにします。 それ以上のタプルがない場合、スロットにNULLまたは空のスロットを設定し、areq->request_completeフラグにtrueを設定します。 ExecAsyncRequestDoneExecAsyncRequestPendingを使ってareqに出力パラメータを設定することが推奨されています。

void
ForeignAsyncConfigureWait(AsyncRequest *areq);

Configure a file descriptor event for which the <structname>ForeignScan</structname> node wishes to wait. This function will only be called when the <structname>ForeignScan</structname> node has the <literal>areq-&gt;callback_pending</literal> flag set, and should add the event to the <structfield>as_eventset</structfield> of the parent <structname>Append</structname> node described by the <literal>areq</literal>. See the comments for <function>ExecAsyncConfigureWait</function> in <filename>src/backend/executor/execAsync.c</filename> for additional information. When the file descriptor event occurs, <function>ForeignAsyncNotify</function> will be called. ForeignScanノードが待機したいファイル記述子イベントを設定します。 この関数は、ForeignScanノードにareq->callback_pendingフラグが設定されている場合にのみ呼び出され、areqで記述された親ノードAppendas_eventsetにイベントを追加しなければなりません。 詳細はsrc/backend/executor/execAsync.cExecAsyncConfigureWaitに対するコメントを参照してください。 ファイルディスクリプタのイベントが発生すると、ForeignAsyncNotifyが呼ばれます。

void
ForeignAsyncNotify(AsyncRequest *areq);

Process a relevant event that has occurred, then produce one tuple asynchronously from the <structname>ForeignScan</structname> node. This function should set the output parameters in the <literal>areq</literal> in the same way as <function>ForeignAsyncRequest</function>. 発生した関連イベントを処理し、ForeignScanノードから非同期に1つのタプルを生成します。 この関数はForeignAsyncRequestと同じようにareqに出力パラメータを設定する必要があります。

59.2.12. パスの再パラメータ化のためのFDWルーチン #

<title>FDW Routines for Reparameterization of Paths</title>

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 <literal>child_rel</literal> to be parameterized by the child relation. The function is used to reparameterize any paths or translate any expression nodes saved in the given <literal>fdw_private</literal> member of a <structname>ForeignPath</structname>. The callback may use <literal>reparameterize_path_by_child</literal>, <literal>adjust_appendrel_attrs</literal> or <literal>adjust_appendrel_attrs_multilevel</literal> as required. この関数は、child_relで指定された子リレーションの最上位の親によってパラメータ化されたパスを、子リレーションによってパラメータ化されたパスに変換する際に呼び出されます。 この関数はパスをパラメータ化する、あるいはForeignPathfdw_privateメンバーに保存されている式ノードを変換するために使用されます。 このコールバックは必要に応じて、reparameterize_path_by_childadjust_appendrel_attrsあるいはadjust_appendrel_attrs_multilevelを呼び出すことができます。