57.2. Creating Custom Scan Plans#
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 inCustomPath
.custom_plans
can be used to store childPlan
nodes.custom_exprs
should be used to store expression trees that will need to be fixed up bysetrefs.c
andsubselect.c
, whilecustom_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 aCustomScan
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 usingcopyObject
, 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 aCustomScan
for the structure itself, as would be possible for aCustomPath
orCustomScanState
.
57.2.1. Custom Scan Plan Callbacks#
Node *(*CreateCustomScanState) (CustomScan *cscan);
Allocate aCustomScanState
for thisCustomScan
. The actual allocation will often be larger than required for an ordinaryCustomScanState
, because many providers will wish to embed that as the first field of a larger structure. The value returned must have the node tag andmethods
set appropriately, but other fields should be left as zeroes at this stage; afterExecInitCustomScan
performs basic initialization, theBeginCustomScan
callback will be invoked to give the custom scan provider a chance to do whatever else is needed.