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

59.2. カスタムスキャン計画の作成 #

<title>Creating Custom Scan Plans</title>

A custom scan is represented in a finished plan tree using the following structure: カスタムスキャンは完成した計画ツリー内で、以下の構造体を使って表現されます。

typedef struct CustomScan
{
    Scan      scan;
    uint32    flags;
    List     *custom_plans;
    List     *custom_exprs;
    List     *custom_private;
    List     *custom_scan_tlist;
    Bitmapset *custom_relids;
    const CustomScanMethods *methods;
} CustomScan;

<structfield>scan</structfield> must be initialized as for any other scan, including estimated costs, target lists, qualifications, and so on. <structfield>flags</structfield> is a bit mask with the same meaning as in <structname>CustomPath</structname>. <structfield>custom_plans</structfield> can be used to store child <structname>Plan</structname> nodes. <structfield>custom_exprs</structfield> should be used to store expression trees that will need to be fixed up by <filename>setrefs.c</filename> and <filename>subselect.c</filename>, while <structfield>custom_private</structfield> should be used to store other private data that is only used by the custom scan provider itself. <structfield>custom_scan_tlist</structfield> can be NIL when scanning a base relation, indicating that the custom scan returns scan tuples that match the base relation's row type. Otherwise it is a target list describing the actual scan tuples. <structfield>custom_scan_tlist</structfield> must be provided for joins, and could be provided for scans if the custom scan provider can compute some non-Var expressions. <structfield>custom_relids</structfield> is set by the core code to the set of relations (range table indexes) that this scan node handles; except when this scan is replacing a join, it will have only one member. <structfield>methods</structfield> must point to a (usually statically allocated) object implementing the required custom scan methods, which are further detailed below. scanは他のすべてのスキャンと同じく、推定コスト、対象のリスト、制約などを含めて初期化される必要があります。 flagsCustomPathと同じ意味のビットマスクです。 custom_plansは子のPlanノードを格納するために使うことができます。 custom_exprssetrefs.cおよびsubselect.cによって作成される必要がある式のツリーを格納するために使われます。 一方でcustom_privateはカスタムスキャンプロバイダ自体によってのみ使用されるその他のプライベートデータを格納するために使われます。 custom_scan_tlistはベースリレーションをスキャンするときはNILとすることができます。 これはカスタムスキャンがベースリレーションの行の型と一致するスキャンタプルを返すことを意味します。 それ以外の場合は、実際のスキャンタプルを表現する対象のリストとなります。 custom_scan_tlistは結合の場合には提供される必要があります。 また、カスタムスキャンプロバイダがVarでない式を計算できる場合はスキャン用に提供することができます。 custom_relidsは、コアコードにより、このスキャンノードが処理するリレーションの集合(範囲テーブルのインデックス)にセットされます。 ただし、このスキャンが結合を置換する場合は例外で、ただ1つのメンバだけになります。 methodsは必要なカスタムスキャンメソッドを実装しているオブジェクト(通常は静的に割り当てられる)を指していなければなりません。 これについては以下で詳しく説明します。

When a <structname>CustomScan</structname> scans a single relation, <structfield>scan.scanrelid</structfield> must be the range table index of the table to be scanned. When it replaces a join, <structfield>scan.scanrelid</structfield> should be zero. CustomScanがリレーションを1つだけスキャンするときは、scan.scanrelidはスキャンされるテーブルの範囲テーブルのインデックスである必要があります。 結合を置換するときはscan.scanrelidはゼロになります。

Plan trees must be able to be duplicated using <function>copyObject</function>, so all the data stored within the <quote>custom</quote> fields must consist of nodes that that function can handle. Furthermore, custom scan providers cannot substitute a larger structure that embeds a <structname>CustomScan</structname> for the structure itself, as would be possible for a <structname>CustomPath</structname> or <structname>CustomScanState</structname>. 計画ツリーはcopyObjectにより複製できる必要があるので、customフィールド内に格納されるすべてのデータは、その関数が処理できるノードから構成されていなければなりません。 また、カスタムスキャンプロバイダはCustomScanを組み込んでいる大きな構造体をCustomScanの構造体で代替することができません。 CustomPathCustomScanStateに対してはこれが可能です。

59.2.1. カスタムスキャン計画のコールバック #

<title>Custom Scan Plan Callbacks</title>

Node *(*CreateCustomScanState) (CustomScan *cscan);

Allocate a <structname>CustomScanState</structname> for this <structname>CustomScan</structname>. The actual allocation will often be larger than required for an ordinary <structname>CustomScanState</structname>, because many providers will wish to embed that as the first field of a larger structure. The value returned must have the node tag and <structfield>methods</structfield> set appropriately, but other fields should be left as zeroes at this stage; after <function>ExecInitCustomScan</function> performs basic initialization, the <function>BeginCustomScan</function> callback will be invoked to give the custom scan provider a chance to do whatever else is needed. このCustomScanCustomScanStateの領域を割り当てます。 多くのプロバイダは、より大きな構造体の最初のフィールドとしてこれを組み込もうとするので、実際の割り当ては通常のCustomScanStateが必要とするよりも多くくなることが多いでしょう。 戻り値では、ノードのタグとmethodsが適切に設定されている必要がありますが、その他のフィールドはこの段階ではゼロのままになっています。 ExecInitCustomScanが基本的な初期化をした後、BeginCustomScanコールバックが呼び出されることで、カスタムスキャンプロバイダがその他の必要なことを実行する機会が与えられます。