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
は他のすべてのスキャンと同じく、推定コスト、対象のリスト、制約などを含めて初期化される必要があります。
flags
はCustomPath
と同じ意味のビットマスクです。
custom_plans
は子のPlan
ノードを格納するために使うことができます。
custom_exprs
はsetrefs.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
の構造体で代替することができません。
CustomPath
やCustomScanState
に対してはこれが可能です。
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.
このCustomScan
にCustomScanState
の領域を割り当てます。
多くのプロバイダは、より大きな構造体の最初のフィールドとしてこれを組み込もうとするので、実際の割り当ては通常のCustomScanState
が必要とするよりも多くくなることが多いでしょう。
戻り値では、ノードのタグとmethods
が適切に設定されている必要がありますが、その他のフィールドはこの段階ではゼロのままになっています。
ExecInitCustomScan
が基本的な初期化をした後、BeginCustomScan
コールバックが呼び出されることで、カスタムスキャンプロバイダがその他の必要なことを実行する機会が与えられます。