カスタムスキャンプロバイダは、典型的には、以下のフックを設定することでベースリレーションのためのパスを追加します。 このフックはコアのコードがそのリレーションへのすべてのアクセスパスを生成した後で呼び出されます。 (フックの呼び出しの後に作成されるギャザーパス(Gather path)を除きます。フックが追加した部分パスをギャザーパスが利用できるようにするためです。)
typedef void (*set_rel_pathlist_hook_type) (PlannerInfo *root,
RelOptInfo *rel,
Index rti,
RangeTblEntry *rte);
extern PGDLLIMPORT set_rel_pathlist_hook_type set_rel_pathlist_hook;
このフックはコアシステムが生成したパスを検査し、修正し、あるいは削除するために使うことができますが、カスタムスキャンプロバイダは、典型的にはCustomPathオブジェクトを生成し、add_pathを使ってそれをrelに追加することのみを行います。
カスタムスキャンプロバイダはCustomPathオブジェクトの初期化を担当します。
このオブジェクトは以下のように宣言されています。
typedef struct CustomPath
{
Path path;
uint32 flags;
List *custom_paths;
List *custom_private;
const CustomPathMethods *methods;
} CustomPath;
pathは、他のすべてのパスと同じく、行数の推定値、開始とトータルのコスト、このパスで提供されるソート順を含めて初期化される必要があります。
flagsはビットマスクで、カスタムパスが逆向きスキャンをサポートできるならCUSTOMPATH_SUPPORT_BACKWARD_SCANを、マークとリストアがサポートできるならCUSTOMPATH_SUPPORT_MARK_RESTOREを含めます。
いずれの機能も必須ではありません。
オプションのcustom_pathsはこのカスタムパスのノードで使用されるPathのノードのリストです。
プランナがこれをPlanのノードに変換します。
custom_privateはカスタムパスのプライベートデータを格納するために使うことができます。
プライベートデータはnodeToStringが処理できるような形式で格納してください。
そうすることで、カスタムパスを出力するデバッグルーチンが設計通りに動作します。
methodsは要求されるカスタムパスのメソッドのオブジェクト(通常は静的に割り当てられる)を指している必要があり、現在は1つのみとなります。
LibraryNameフィールドとSymbolNameフィールドは、動的ローダがそれらのメソッドテーブルの位置を解決できるように、初期化されていなければなりません。
カスタムスキャンプロバイダは結合(join)のパスを提供することもできます。
ベースのリレーションの場合と同様、そのようなパスは置換される結合が普通に生成したであろうものと同じ結果を生成しなければなりません。
そのために、結合のプロバイダは以下のフックをセットし、フック関数内で結合リレーション用にCustomPathのパスを作成します。
typedef void (*set_join_pathlist_hook_type) (PlannerInfo *root,
RelOptInfo *joinrel,
RelOptInfo *outerrel,
RelOptInfo *innerrel,
JoinType jointype,
JoinPathExtraData *extra);
extern PGDLLIMPORT set_join_pathlist_hook_type set_join_pathlist_hook;
このフックは、同じ結合リレーションについて、内側あるいは外側のリレーションとの様々な組み合わせで繰り返し呼び出されます。 繰り返しの作業を最小化するのはフック側の責任です。
Plan *(*PlanCustomPath) (PlannerInfo *root,
RelOptInfo *rel,
CustomPath *best_path,
List *tlist,
List *clauses,
List *custom_plans);
カスタムパスを完成した計画に変換します。
戻り値は一般的にはCustomScanオブジェクトで、その領域はコールバックが割り当てて初期化しなければなりません。
詳しくは59.2を参照してください。