他のバージョンの文書10 | 9.6 | 9.5 | 9.4 | 9.3 | 9.2 | 9.1 | 9.0 | 8.4 | 8.3 | 8.2 | 8.1 | 8.0 | 7.4 | 7.3 | 7.2

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

FDWハンドラ関数は、以下のコールバック関数へのポインタを含む、pallocされたFdwRoutine構造体を返します。

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

外部テーブルのリレーションサイズ見積もりを取得します。この関数は、ある外部テーブルを使用するクエリのプラン作成の開始時に呼び出されます。rootはそのクエリに関するプランナのグローバル情報です。baserelはそのテーブルに関するプランナの情報です。そして、foreigntableidはその外部テーブルのpg_class OIDです。(foreigntableidはプランナデータ構造体からも取得できますが、手間を省くために明示的に渡されます。)

この関数は、制約条件によるフィルタリングも考慮に入れた、そのテーブルスキャンが返すと見込まれる件数にbaserel->rowsを更新するべきです。 baserel->rowsの初期値は固定のデフォルト見積もりなので、可能な限り置き換えられるべきです。この関数は、行の幅のよりよい見積もりを計算できるのであれば、baserel->widthを更新することも選択出来ます。

追加情報については項50.4を参照してください。

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

外部テーブル対するスキャンとしてありえるアクセスパスを作成します。 この関数はクエリのプラン作成中に呼び出されます。 引数は、先に呼ばれているGetForeignRelSizeと同じです。

この関数は、少なくとも一つのアクセスパス(ForeignPathノード)を作成して、それぞれのパスをbaserel->pathlistに追加するためにadd_pathを呼ばなければなりません。 ForeignPathノードを構築するにはcreate_foreignscan_pathを使うことが推奨されています。 この関数は、たとえばソート済みの結果を表現する有効なpathkeysを持つパスのような複数のアクセスパスを作成することが出来ます。 それぞれのアクセスパスはコスト見積もりを含まねばならず、また意図する特定のスキャン方式を識別するのに必要なFDW固有の情報を持つことが出来ます。

追加情報については項50.4を参照してください。

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

選択された外部アクセスパスからForeignScanプランノードを作成します。 この関数はクエリプラン作成の最後に呼び出されます。 引数は、GetForeignRelSizeと同じものに、選択されたForeignPath(事前にGetForeignPathsによって作成されたもの)と、そのプランノードによって出力されるターゲットリスト、およびそのプランノードで強制される制限句が追加されます。

この関数はForeignScanプランノードを作成して返さなければなりません。ForeignScanノードを構築するにはmake_foreignscanを使うことが推奨されています。

追加情報については項50.4を参照してください。

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

外部テーブルスキャンの追加のEXPLAIN出力を表示します。 何も表示する必要がないのであれば、単にリターンすることもできます。 もしくは、EXPLAIN出力にフィールドを追加するためにExplainPropertyTextや関連する関数を呼び出すべきです。 esの中のフラグフィールドは何を表示するかを決めるのに使用できます。また、EXPLAIN ANALYZEの場合には、実行時統計情報を提供するためにForeignScanStateノードの状態を調べることができます。

void
BeginForeignScan (ForeignScanState *node,
                  int eflags);

外部テーブルスキャンの実行を開始します。 この関数はエグゼキュータのスタートアップ中に呼び出されます。 スキャンを開始できるようになる前に、あらゆる必要な初期化を実行するべきですが、実際のスキャンの実行を始めるべきではありません(それは最初のIterateForeignScan呼び出しにおいて行われるべきです)。 ForeignScanStateノードは作成されていますが、そのfdw_stateフィールドはNULLのままです。 スキャンするテーブルの情報は、ForeignScanStateノード(実際にはその先にある、PlanForeignScanから返されたFdwPlan構造体へのポインタを含む、ForeignScanプランノード)を通じてアクセス可能です。

(eflags & EXEC_FLAG_EXPLAIN_ONLY)が真の場合、この関数は外部に見えるアクションを起こすべきではないことに注意してください。 ExplainForeignScanEndForeignScan用にノード状態を有効にするのに必要とされる最小限のことだけをすべきです。

TupleTableSlot *
IterateForeignScan (ForeignScanState *node);

外部ソースから一行を取り出して、それをタプルテーブルスロットに入れて返します(この用途にはノードのScanTupleSlotを使うべきです)。 利用可能な行がない場合は、NULLを返します。 タプルテーブルスロット機構を使うと、物理タプルと仮想タプルのどちらでも返せます。 ほとんどの場合、パフォーマンスの観点から後者を選ぶのが良いでしょう。 この関数は、呼出しごとにリセットされる短命なメモリコンテキスト内で呼び出されることに注意してください。 より長命なストレージが必要な場合は、BeginForeignScanでメモリコンテキストを作成するか、ノードのEStateに含まれるes_query_cxtを使用してください。

返される行はスキャンされている外部テーブルのカラムシグネチャと一致しなければなりません。 不要なカラムを取り出さないように最適化することを選ぶなら、それらのカラム位置にNULLを入れるべきです。

PostgreSQLのエグゼキュータは返された行が外部テーブルの列に定義されたNOT NULL制約に違反しているかどうかは気にしませんが、プランナはそれに関心を持ち、NULL値を含まないと宣言された列にNULL値が現れた場合に不正なクエリ最適化をしてしまう場合があることに注意してください。 ユーザがあってはならないと宣言したのにNULL値に遭遇した場合は(データ型が一致しなかった場合にする必要があるのと同様に)エラーを発生させるのが適切でしょう。

void
ReScanForeignScan (ForeignScanState *node);

先頭からスキャンを再開します。 スキャンが依存するいずれかのパラメータが値を変更しているかもしれないので、新しいスキャンが必ずしも厳密に同じ行を返すとは限らないことに注意してください。

void
EndForeignScan (ForeignScanState *node);

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

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

この関数はANALYZEが外部テーブルに対して実行されたときに呼び出されます。 もしFDWがこの外部テーブルの統計情報を収集できる場合は、そのテーブルからサンプル行を集める関数のポインタとテーブルサイズのページ単位での見積もりをそれぞれfunctotalpagesに渡しtrueを返す必要があります。 そうでない場合は、falseを返します。 もしFDWが統計情報の収集をどのテーブルについてもサポートしない場合は、AnalyzeForeignTableポインターをNULLにすることもできます。

もし提供される場合は、サンプル収集関数はこのようなシグネチャを持つ必要があります。

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

最大targrows行のランダムサンプルをテーブルから収集し、呼び出し元が提供するrows配列に格納する必要があります。 実際に収集された行の数を返す必要があります。 さらに、テーブルに含まれる有効行と不要行の合計数の見積もりを出力パラメータのtotalrowstotaldeadrowsに返す必要があります。(もしFDWが不要行という概念を持たない場合はtotaldeadrowsを0に設定してください。)

FdwRoutine構造体はさらなる情報を含むsrc/include/foreign/fdwapi.hで宣言されています。

FdwRoutineFdwPlanの構造体型はsrc/include/foreign/fdwapi.hで宣言されているので、さらなる詳細はそちらを見て下さい。