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;
scan
must be initialized as for any other scan, including
estimated costs, target lists, qualifications, and so on.
flags
is a bit mask with the same meaning as in
CustomPath
.
custom_plans
can be used to store child
Plan
nodes.
custom_exprs
should be used to
store expression trees that will need to be fixed up by
setrefs.c
and subselect.c
, while
custom_private
should be used to store other private data
that is only used by the custom scan provider itself.
custom_scan_tlist
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. custom_scan_tlist
must be
provided for joins, and could be provided for scans if the custom scan
provider can compute some non-Var expressions.
custom_relids
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.
methods
must point to a (usually statically allocated)
object implementing the required custom scan methods, which are further
detailed below.
When a CustomScan
scans a single relation,
scan.scanrelid
must be the range table index of the table
to be scanned. When it replaces a join, scan.scanrelid
should be zero.
Plan trees must be able to be duplicated using copyObject
,
so all the data stored within the “custom” fields must consist of
nodes that that function can handle. Furthermore, custom scan providers
cannot substitute a larger structure that embeds
a CustomScan
for the structure itself, as would be possible
for a CustomPath
or CustomScanState
.
Node *(*CreateCustomScanState) (CustomScan *cscan);
Allocate a CustomScanState
for this
CustomScan
. The actual allocation will often be larger than
required for an ordinary CustomScanState
, 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 methods
set appropriately, but other fields should be left as zeroes at this
stage; after ExecInitCustomScan
performs basic initialization,
the BeginCustomScan
callback will be invoked to give the
custom scan provider a chance to do whatever else is needed.