PostgreSQL 9.5.4文書 | |||
---|---|---|---|
前のページ | 上に戻る | 第 54章外部データラッパの作成 | 次のページ |
FDWハンドラ関数は、以下で説明するコールバック関数へのポインタを含む、pallocされたFdwRoutine構造体を返します。 スキャンに関連した関数は必須で、それ以外は省略可能です。
FdwRoutine構造体はsrc/include/foreign/fdwapi.hで宣言されていますので、追加情報はそちらを参照してください。
void GetForeignRelSize (PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid);
外部テーブルのリレーションサイズ見積もりを取得します。この関数は、ある外部テーブルをスキャンするクエリのプラン作成の開始時に呼び出されます。rootはそのクエリに関するプランナのグローバル情報です。baserelはそのテーブルに関するプランナの情報です。そして、foreigntableidはその外部テーブルのpg_class OIDです。(foreigntableidはプランナデータ構造体からも取得できますが、手間を省くために明示的に渡されます。)
この関数は、制約条件によるフィルタリングも考慮に入れた、そのテーブルスキャンが返すと見込まれる件数にbaserel->rowsを更新するべきです。 baserel->rowsの初期値は固定のデフォルト見積もりなので、可能な限り置き換えられるべきです。この関数は、行の幅のよりよい見積もりを計算できるのであれば、baserel->widthを更新することも選択出来ます。
追加情報については項54.4を参照してください。
void GetForeignPaths (PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid);
外部テーブル対するスキャンとしてありえるアクセスパスを作成します。
この関数はクエリのプラン作成中に呼び出されます。
引数は、先に呼ばれているGetForeignRelSize
と同じです。
この関数は、少なくとも一つのアクセスパス(ForeignPathノード)を作成して、それぞれのパスをbaserel->pathlistに追加するためにadd_path
を呼ばなければなりません。
ForeignPathノードを構築するにはcreate_foreignscan_path
を使うことが推奨されています。
この関数は、たとえばソート済みの結果を表現する有効なpathkeysを持つパスのような複数のアクセスパスを作成することが出来ます。
それぞれのアクセスパスはコスト見積もりを含まねばならず、また意図した特定のスキャン方式を識別するのに必要なFDW固有の情報を持つことが出来ます。
追加情報については項54.4を参照してください。
ForeignScan * GetForeignPlan (PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid, ForeignPath *best_path, List *tlist, List *scan_clauses, Plan *outer_plan);
選択された外部アクセスパスからForeignScanプランノードを作成します。
この関数はクエリプラン作成の最後に呼び出されます。
引数は、GetForeignRelSize
と同じものに、選択されたForeignPath(事前にGetForeignPaths
またはGetForeignJoinPaths
によって作成されたもの)、そのプランノードによって出力されるターゲットリスト、そのプランノードで強制される条件句、およびRecheckForeignScan
が実行する再検査で使用されるForeignScanの外側のサブプランが追加されます。
(パスがベースリレーションではなく結合のためのものの場合、foreigntableidはInvalidOidになります。)
この関数はForeignScanプランノードを作成して返さなければなりません。ForeignScanノードを構築するにはmake_foreignscan
を使うことが推奨されています。
追加情報については項54.4を参照してください。
void BeginForeignScan (ForeignScanState *node, int eflags);
外部テーブルスキャンの実行を開始します。
この関数はエグゼキュータの起動中に呼び出されます。
スキャンを開始できるようになる前に、あらゆる必要な初期化を実行するべきですが、実際のスキャンの実行を始めるべきではありません(それは最初のIterateForeignScan
呼び出しにおいて行われるべきです)。
ForeignScanStateノードは作成されていますが、そのfdw_stateフィールドはNULLのままです。
スキャンするテーブルの情報は、ForeignScanStateノード(実際にはその先にある、PlanForeignScan
から返されたFdwPlan構造体へのポインタを含む、ForeignScanプランノード)を通じてアクセス可能です。
eflagsは、このプランノードに関するエグゼキュータの操作モードを表すフラグビットを含みます。
(eflags & EXEC_FLAG_EXPLAIN_ONLY)が真の場合、この関数は外部に見える処理を実行すべきではないことに注意してください。
ExplainForeignScan
やEndForeignScan
用にノード状態を有効にするのに必要とされる最小限のことだけをすべきです。
TupleTableSlot * IterateForeignScan (ForeignScanState *node);
外部ソースから一行を取り出して、それをタプルテーブルスロットに入れて返します(この用途にはnodeのScanTupleSlotを使うべきです)。
利用可能な行がない場合は、NULLを返します。
タプルテーブルスロット機構を使うと、物理タプルと仮想タプルのどちらでも返せます。
ほとんどの場合、パフォーマンスの観点から後者を選ぶのが良いでしょう。
この関数は、呼出しごとにリセットされる短命なメモリコンテキスト内で呼び出されることに注意してください。
より長命なストレージが必要な場合は、BeginForeignScan
でメモリコンテキストを作成するか、ノードのEStateに含まれるes_query_cxtを使用してください。
返される行は、ターゲットリストfdw_scan_tlistが提供されたなら、それとマッチしなければならず、提供されていない場合はスキャンされている外部テーブルの行型とマッチしなければなりません。 不要なカラムを取り出さないように最適化することを選ぶなら、それらのカラム位置にNULLを入れるか、あるいはそれらの列を除いたfdw_scan_tlistリストを生成するべきです。
PostgreSQLのエグゼキュータは返された行が外部テーブルに定義された制約に違反しているかどうかは気にしません。 しかし、プランナはそれに着目するので、宣言された制約に反する行が外部テーブル上にあった場合に、不正な最適化をするかもしれません。 ユーザが制約が成り立つと宣言したのに制約に違反した場合は(データ型が一致しなかった場合にする必要があるのと同様に)エラーを発生させるのが適切でしょう。
void ReScanForeignScan (ForeignScanState *node);
先頭からスキャンを再開します。 スキャンが依存するいずれかのパラメータが値を変更しているかもしれないので、新しいスキャンが必ずしも厳密に同じ行を返すとは限らないことに注意してください。
void EndForeignScan (ForeignScanState *node);
スキャンを終了しリソースを解放します。 通常、pallocされたメモリを解放することは重要ではありませんが、開いたファイルやリモートサーバへの接続などはクリーンアップするべきです。
FDWが外部テーブルの結合を(両方のテーブルのデータをフェッチして、ローカルで結合するのでなく)リモートで実行することをサポートする場合、次のコールバック関数を提供します。
void GetForeignJoinPaths (PlannerInfo *root, RelOptInfo *joinrel, RelOptInfo *outerrel, RelOptInfo *innerrel, JoinType jointype, JoinPathExtraData *extra);
同じ外部サーバにある2つ(またはそれ以上)の外部テーブルの結合のための可能なアクセスパスを作成します。
このオプション関数は、問い合わせの計画時に呼び出されます。
GetForeignPaths
と同じく、この関数は提供されたjoinrelのためのForeignPathパスを生成し、add_path
を呼んで、それらのパスを結合のために考慮されるパスの集合に追加します。
しかし、GetForeignPaths
とは異なり、この関数が少なくとも1つのパスの作成に成功することは必要ではありません。
なぜなら、ローカルの結合を含んだパスはいつでも可能だからです。
この関数は、同じ結合のリレーションに対して、内側と外側のリレーションの異なる組み合わせで繰り返し呼び出されることに注意して下さい。 同じ作業の繰り返しを最小化することはFDWの責任です。
ForeignPathパスが結合のために選択されると、それは結合プロセス全体を代表することになり、構成テーブルとその関連の結合のために生成されたパスは使われなくなります。 結合パスの以降の処理は、単一の外部テーブルをスキャンするパスとほぼ同様に進みます。 1つの相違点は、結果として作られるForeignScan計画ノードのscanrelidが0にセットされるべき、ということで、これはそれが表現する単一のリレーションがないためです。 その代わりに、ForeignScanノードのfs_relidsフィールドが結合されるリレーションの集合を表します。 (後者のフィールドはコアのプランナのコードによって自動的にセットされるので、FDWによって設定される必要はありません。) 他の相違点は、リモートの結合についての列リストがシステムカタログにはないため、FDWはfdw_scan_tlistに適切なTargetEntryノードのリストを入れて、実行時に返されるタプル内の列の集合を表すようにしなければならないということです。
追加情報については項54.4を参照してください。
もしFDWが更新可能な外部テーブルをサポートする場合、FDWのニーズと能力に応じて、以下のコールバック関数の一部または全てを提供する必要があります。
void AddForeignUpdateTargets (Query *parsetree, RangeTblEntry *target_rte, Relation target_relation);
UPDATEとDELETEの操作は、テーブルスキャン関数によって事前にフェッチされた行に対して実行されます。 FDWは、更新や削除の対象行を厳密に識別できるように行IDや主キー列の値といった追加情報を必要とするかもしれません。 それをサポートするために、この関数はUPDATEやDELETEの間に外部テーブルから取得される列のリストに追加の隠された(または"ジャンクの")ターゲット列を追加することができます。
これを実行するには、フェッチする追加の値の式を含むTargetEntryエントリをparsetree->targetListに追加します。 それぞれのエントリはresjunk = trueとマークされなければならず、また実行時にエントリを識別できる異なるresnameを持つ必要があります。 コアシステムがそのような名前のジャンク列を生成できるように、ctidNやwholerow、wholerowNと一致する名前は使用しないでください。
この関数はプランナでなくリライタで呼ばれるので、利用可能な情報はプラン生成ルーチンで利用可能なものとは少し異なります。 parsetreeはUPDATEやDELETEコマンドのパース木で、target_rteとtarget_relationは対象の外部テーブルを表します。
もしAddForeignUpdateTargets
ポインターがNULLに設定されている場合は、追加のターゲット式は追加されません。
(FDWが行を識別するのに不変の主キーに依存するのであればUPDATEは依然として実現可能かもしれませんが、DELETE操作を実装することは不可能になるでしょう。)
List * PlanForeignModify (PlannerInfo *root, ModifyTable *plan, Index resultRelation, int subplan_index);
外部テーブルに対する挿入、更新、削除に必要となる、追加のプラン生成アクションを実行します。
この関数は、更新処理を実行するModifyTableプランノードに追加されるFDW固有の情報を生成します。この固有情報はList形式でなければならず、また実行段階の間にBeginForeignModify
に渡されます。
rootはそのクエリに関するプランナのグローバル情報です。 planはfdwPrivListsフィールドを除いて完成しているModifyTableプランノードです。 resultRelationは対象の外部テーブルをレンジテーブルの添字で識別します。 subplan_indexはModifyTableプランノードの対象がどれであるかを0始まりで識別します。この情報はplan->plansなどのplanの下位構造を指定したい場合に使用してください。
追加情報は項54.4を参照してください。
もしAddForeignUpdateTargets
ポインターがNULLに設定されている場合は、追加のプラン作成時処理は実行されず、BeginForeignModify
に渡されるfdw_privateリストはNILになります。
void BeginForeignModify (ModifyTableState *mtstate, ResultRelInfo *rinfo, List *fdw_private, int subplan_index, int eflags);
外部テーブルへの変更操作の実行を開始します。
このルーチンはエグゼキュータの起動中に呼び出されます。
実際のテーブル変更に先立って必要なあらゆる初期化処理を実行する必要があります。
その後、各タプルが挿入、更新、削除されるようにExecForeignInsert
、ExecForeignUpdate
、ExecForeignDelete
のいずれかが呼ばれます。
mtstateは実行されているModifyTableプランノード全体の状態です。プランに関する全般的なデータと実行状態はこの構造体経由で利用可能です。
rinfoは対象の外部テーブルを表すResultRelInfo構造体です。(ResultRelInfoのri_FdwStateフィールドはこの操作で必要となる固有の状態をFDWが格納するのに利用できます。)
fdw_privateはもしあればPlanForeignModify
で生成された固有データを含みます。
eflagsは、このプランノードに関するエグゼキュータの操作モードを表すフラグビットを含みます。
(eflags & EXEC_FLAG_EXPLAIN_ONLY)が真の場合、この関数は外部に見える処理を実行すべきではないことに注意してください。
ExplainForeignModify
やEndForeignModify
用にノード状態を有効するのに必要な最小限のことだけを実行するべきです。
もしBeginForeignModify
ポインターがNULLに設定されている場合は、エグゼキュータ起動時には追加処理は何も実行されません。
TupleTableSlot * ExecForeignInsert (EState *estate, ResultRelInfo *rinfo, TupleTableSlot *slot, TupleTableSlot *planSlot);
外部テーブルにタプルを一つ挿入します。 estateはそのクエリのグローバルな実行状態です。 rinfoは対象の外部テーブルを表すResultRelInfo構造体です。 slotには挿入されるタプルが含まれます。その行型定義は外部テーブルと一致します。 planSlotにはModifyTableプランノードのサブプランが生成したタプルが含まれます。追加の"ジャンク"列を含みうる点において、slotとは異なります。(planSlotは一般的にINSERTのケースにおいてはそれほど意味を持ちませんが、完全さのために提供されます。)
戻り値は実際に挿入されたデータ(例えばトリガー処理の結果などにより、提供されたデータとは異なるかもしれません)を含むスロットか、または(こちらも一般的にトリガーの結果)実際には挿入されなかった場合はNULLです。 渡されたslotはこの用途に再利用可能です。
返却されたスロット内のデータはINSERTクエリがRETURNING句を持っていた場合もしくは外部テーブルがAFTER ROWトリガを持っていた場合にのみ使われます。 トリガは全列を必要としますが、FDWはRETURNING句の内容に応じて返却する列を一部にするかすべてにするかを最適化する余地があります。 それとは関係なく、処理成功を表すためになんらかのスロットは返却しなければなりません。さもないと、報告されるクエリの結果行数が誤った値になってしまいます。
もしExecForeignInsert
ポインターがNULLに設定されている場合は、外部テーブルへの挿入の試みはエラーメッセージとともに失敗します。
TupleTableSlot * ExecForeignUpdate (EState *estate, ResultRelInfo *rinfo, TupleTableSlot *slot, TupleTableSlot *planSlot);
外部テーブル内のタプルを一つ更新します。
estateはそのクエリのグローバルな実行状態です。
rinfoは対象の外部テーブルを表すResultRelInfo構造体です。
slotにはタプルの新しいデータが含まれます。その行型定義は外部テーブルと一致します。
planSlotにはModifyTableプランノードのサブプランが生成したタプルが含まれます。追加の"ジャンク"列を含みうる点において、slotとは異なります。実際、AddForeignUpdateTargets
が要求するジャンク列はこのスロットから利用可能です。
戻り値は実際に更新されたデータ(例えばトリガー処理の結果などにより、提供されたデータとは異なるかもしれません)を含むスロットか、または(こちらも一般的にトリガーの結果)実際には更新されなかった場合はNULLです。 渡されたslotはこの用途に再利用可能です。
返却されたスロット内のデータはUPDATEクエリがRETURNING句を持っていた場合もしくは外部テーブルがAFTER ROWトリガを持っていた場合にのみ使われます。 トリガは全列を必要としますが、FDWはRETURNING句の内容に応じて返却する列を一部にするか全てにするかを最適化する余地があります。 それとは関係なく、処理成功を表すためになんらかのスロットは返却しなければなりません。さもないと、報告されるクエリの結果行数が誤った値になってしまいます。
もしExecForeignUpdate
ポインターがNULLに設定されている場合は、外部テーブルへの更新の試みはエラーメッセージとともに失敗します。
TupleTableSlot * ExecForeignDelete (EState *estate, ResultRelInfo *rinfo, TupleTableSlot *slot, TupleTableSlot *planSlot);
外部テーブルからタプルを一つ削除します。
estateはそのクエリのグローバルな実行状態です。
rinfoは対象の外部テーブルを表すResultRelInfo構造体です。
slotにはタプルの新しいデータが含まれます。その行型定義は外部テーブルと一致します。
planSlotにはModifyTableプランノードのサブプランが生成したタプルが含まれます。実際、AddForeignUpdateTargets
が要求するジャンク列はこのスロットが運びます。ジャンク列は削除されるタプルを識別するために使用しなければなりません。
戻り値は実際に削除されたデータを含むスロットか、または(一般的にトリガーの結果)実際には削除されなかった場合はNULLです。 渡されたslotは返却するタプルを保持する用途に利用可能です。
返却されたスロット内のデータはDELETEクエリがRETURNING句を持っていた場合もしくは外部テーブルがAFTER ROWトリガを持っていた場合にのみ使われます。 トリガは全列を必要としますが、FDWはRETURNING句の内容に応じて返却する列を一部にするか全てにするかを最適化する余地があります。 それとは関係なく、処理成功を表すためになんらかのスロットは返却しなければなりません。さもないと、報告されるクエリの結果行数が誤った値になってしまいます。
もしExecForeignDelete
ポインターがNULLに設定されている場合は、外部テーブルからの削除の試みはエラーメッセージとともに失敗します。
void EndForeignModify (EState *estate, ResultRelInfo *rinfo);
テーブル更新を終えてリソースを解放します。pallocされたメモリの解放は通常重要ではありませんが、開いたファイルやリモートサーバへの接続はクリーンアップするべきです。
もしEndForeignModify
ポインターがNULLに設定されている場合は、エグゼキュータ終了時には追加処理は何も実行されません。
int IsForeignRelUpdatable (Relation rel);
指定された外部テーブルがどの更新処理をサポートしているかを報告します。 戻り値は、その外部テーブルがサポートする操作を表すルールイベント番号のビットマスクである必要があります。 UPDATE用の(1 << CMD_UPDATE) = 4、INSERT用の(1 << CMD_INSERT) = 8、DELETE用の(1 << CMD_DELETE) = 16といったCmdType列挙値を使います。
もしIsForeignRelUpdatable
ポインターがNULLに設定されていると、外部テーブルはExecForeignInsert
、ExecForeignUpdate
、ExecForeignDelete
を提供していると、それぞれ挿入、更新、削除をサポートしていると判断します。
この関数は、FDWが一部のテーブルについてのみ更新をサポートする場合にのみ必要です。
(そのような場合でも、この関数でチェックする代わりにクエリ実行関数でエラーにしても構いません。しかしながら、この関数はinformation_schemaのビューの表示で更新可否を判定するのに使用されます。)
FDWが(項54.5で説明される)遅延行ロックをサポートする場合は、以下のコールバック関数を提供する必要があります。
RowMarkType GetForeignRowMarkType (RangeTblEntry *rte, LockClauseStrength strength);
行の印付けでどのオプションを外部テーブルに使うかを報告します。 rteはテーブルのRangeTblEntryノードで、strengthは関連するFOR UPDATE/SHARE句があれば、それが要求するロックの強さを表します。 その結果は、RowMarkType列挙型のメンバーでなければなりません。
この関数はUPDATE、DELETE、SELECT FOR UPDATE/SHAREの問い合わせに現れ、かつUPDATEあるいはDELETEの対象ではない各外部テーブルについて、問い合わせの計画時に呼び出されます。
GetForeignRowMarkType
のポインタがNULLに設定されていると、必ずROW_MARK_COPYオプションが使われます。
(これはRefetchForeignRow
が決して呼び出されないので、それを提供する必要もない、ということを意味します。)
さらなる情報については項54.5を参照してください。
HeapTuple RefetchForeignRow (EState *estate, ExecRowMark *erm, Datum rowid, bool *updated);
必要ならロックした後で、外部テーブルから1つのタプルを再フェッチします。 estateは問い合わせのグローバルな実行状態です。 ermは対象の外部テーブルおよび獲得する行ロックの種別(あれば)を記述するExecRowMark構造体です。 rowidはフェッチするタプルを特定するものです。 updatedは出力パラメータです。
この関数は、フェッチしたタプルをpallocして複製したものを返すか、あるいは行ロックが取得できなければNULLを返します。
獲得する行ロックの種別はerm->markTypeで指定されますが、この値は事前にGetForeignRowMarkType
から返されたものです。
(ROW_MARK_REFERENCEは行のロックを獲得せずに、単にタプルを再フェッチすることを意味し、また、ROW_MARK_COPYはこのルーチンで使われることはありません。)
そして、*updatedはフェッチしたタプルが、以前に取得したものと同じではなく、更新されたバージョンであったときにtrueにセットされます。 (どちらなのかFDWが判断できない場合は、trueを返すことが推奨されます)。
デフォルトでは、行ロックの獲得に失敗したときはエラーを発生させるべきであることに注意してください。 NULLを返すのが適切なのは、erm->waitPolicyでSKIP LOCKEDオプションが指定されている場合だけです。
rowidは、再フェッチする行を以前読んだ時のctid値です。 rowid値はDatumとして渡されますが、現在はtidにしかなりません。 将来は行ID以外のデータ型が可能になることを期待して、関数APIとすることが選択されました。
RefetchForeignRow
ポインタがNULLの場合、行を再フェッチする試みは失敗し、エラーメッセージを発行します。
さらなる情報については項54.5を参照してください。
bool RecheckForeignScan (ForeignScanState *node, TupleTableSlot *slot);
以前に戻されたタプルが、関連するスキャンおよび結合の制約とまだ一致しているか再検査し、更新されたバージョンのタプルを提供する場合もあります。 結合のプッシュダウンを行わない外部データラッパでは、通常は、これをNULLにセットし、代わりにfdw_recheck_qualsを適切にセットする方が便利でしょう。 しかし、外部結合をプッシュダウンする場合、すべてのベーステーブルに関する検査を結果のタプルに適用するだけでは、たとえすべての必要な属性がそこにあったとしても十分ではありません。 なぜなら一部の制約が一致しないことで、タプルが戻されない代わりに、一部の属性がNULLになってしまうかもしれないからです。 RecheckForeignScan制約を再検査し、それが依然として満たされていれば真を、そうでなければ偽を返すことができます。 それだけでなく、置換されたタプルを提供されたスロットに格納することもできます。
結合のプッシュダウンを実装する場合、外部データラッパは通常、再検査のためだけに使用される代替のローカル結合プランを構築します。 これがForeignScanの外部サブプランとなります。 再検査が必要な時は、このサブプランを実行して、結果のタプルをスロットに格納することができます。 どのベーステーブルも最大で1行しか返さないので、このプランは効率的である必要はありません。 例えば、すべての結合をネストループで実装することもできます。
void ExplainForeignScan (ForeignScanState *node, ExplainState *es);
外部テーブルスキャンの追加のEXPLAIN出力を表示します。
EXPLAIN出力にフィールドを追加するためにExplainPropertyText
や関連する関数を呼び出すことができます。
esの中のフラグフィールドは何を表示するかを決めるのに使用できます。また、EXPLAIN ANALYZEの場合には、実行時統計情報を提供するためにForeignScanStateノードの状態を調べることができます。
もしExplainForeignScan
ポインターがNULLに設定されている場合は、EXPLAIN中に追加情報は表示されません。
void ExplainForeignModify (ModifyTableState *mtstate, ResultRelInfo *rinfo, List *fdw_private, int subplan_index, struct ExplainState *es);
外部テーブル更新の追加のEXPLAIN出力を表示します。
EXPLAIN出力にフィールドを追加するためにExplainPropertyText
や関連する関数を呼び出すことができます。
esの中のフラグフィールドは何を表示するかを決めるのに使用できます。また、EXPLAIN ANALYZEの場合には、実行時統計情報を提供するためにForeignScanStateノードの状態を調べることができます。
最初の4つの引数はBeginForeignModify
と同じです。
もしExplainForeignModify
ポインターがNULLに設定されている場合は、EXPLAIN中に追加情報は表示されません。
bool AnalyzeForeignTable (Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages);
この関数はANALYZEが外部テーブルに対して実行されたときに呼び出されます。 もしFDWがこの外部テーブルの統計情報を収集できる場合は、そのテーブルからサンプル行を集める関数のポインタとページ単位でのテーブルサイズの見積もりをそれぞれfuncとtotalpagesに渡しtrueを返す必要があります。 そうでない場合は、falseを返します。
もしFDWが統計情報の収集をどのテーブルについてもサポートしない場合は、AnalyzeForeignTable
ポインターをNULLにすることもできます。
もし提供される場合は、サンプル収集関数はこのようなシグネチャを持つ必要があります。
int AcquireSampleRowsFunc (Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows);
最大targrows行のランダムサンプルをテーブルから収集し、呼び出し元が提供するrows配列に格納する必要があります。 実際に収集された行の数を返す必要があります。 さらに、テーブルに含まれる有効行と不要行の合計数の見積もりを出力パラメータのtotalrowsとtotaldeadrowsに返す必要があります。(もしFDWが不要行という概念を持たない場合はtotaldeadrowsを0に設定してください。)
List * ImportForeignSchema (ImportForeignSchemaStmt *stmt, Oid serverOid);
外部テーブル作成コマンドのリストを取得します。 この関数はIMPORT FOREIGN SCHEMAを実行する時に呼び出され、その文の解析木と外部サーバが使用するOIDとを渡されます。 C文字列のリストを返し、その各文字列はCREATE FOREIGN TABLEコマンドを含んでいる必要があります。 これらの文字列はコアサーバが解析して実行します。
ImportForeignSchemaStmt構造体において、remote_schemaはリモートスキーマの名前で、そこからテーブルがインポートされます。 list_typeはテーブル名のフィルタ方法を指定します。 ここで、FDW_IMPORT_SCHEMA_ALLはリモートスキーマのすべてのテーブルをインポートすること(この場合、table_listは空にします)、 FDW_IMPORT_SCHEMA_LIMIT_TOはtable_listに列挙されたテーブルだけを含めること、 そしてFDW_IMPORT_SCHEMA_EXCEPTはtable_listに列挙されたテーブルを除外することを意味します。 optionsはインポートのプロセスで使用されるオプションのリストです。 オプションの意味はFDWに依存します。 例えば、FDWは列のNOT NULL属性をインポートするかどうかを定めるオプションを使うことができます。 これらのオプションはFDWがデータベースオブジェクトのオプションとしてサポートするものと何ら関係ある必要はありません。
FDWはImportForeignSchemaStmtのlocal_schemaフィールドを無視しても良いです。 なぜなら、コアサーバは解析されたCREATE FOREIGN TABLEコマンドにその名前を自動的に挿入するからです。
FDWはlist_typeおよびtable_listで指定されるフィルタの実装にも注意する必要はありません。
なぜなら、コアサーバはそれらのオプションによって除外されるテーブルに対して戻されたコマンドをすべて自動的にスキップするからです。
しかし、除外されるテーブルについてコマンドを作成する作業を回避するのは、そもそも役立つことが多いです。
関数IsImportableForeignTable()
は指定の外部テーブル名がフィルタを通るかどうかの検査に役立つかもしれません。
FDWがテーブル定義のインポートをサポートしない場合は、ImportForeignSchema
ポインタをNULLにセットすることができます。