From 82fe8b1119e4187f3d991564274607b0b4089aca Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 13 Mar 2015 07:55:39 -0400 Subject: [PATCH] Document the new custom scan APIs. These APIs changed somewhat subsequent to the initial commit, and may change further in the future, but let's document what we have today. KaiGai Kohei and Robert Haas, reviewed by Tom Lane and Thom Brown --- doc/src/sgml/custom-scan.sgml | 285 ++++++++++++++++++++++++++++++++++ doc/src/sgml/filelist.sgml | 1 + doc/src/sgml/postgres.sgml | 1 + 3 files changed, 287 insertions(+) create mode 100644 doc/src/sgml/custom-scan.sgml diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml new file mode 100644 index 0000000000..8a4a3dfcfe --- /dev/null +++ b/doc/src/sgml/custom-scan.sgml @@ -0,0 +1,285 @@ + + + + Writing A Custom Scan Provider + + + custom scan provider + handler for + + + + PostgreSQL supports a set of experimental facilities which + are intended to allow extension modules to add new scan types to the system. + Unlike a foreign data wrapper, which is only + responsible for knowing how to scan its own foreign tables, a custom scan + provider can provide an alternative method of scanning any relation in the + system. Typically, the motivation for writing a custom scan provider will + be to allow the use of some optimization not supported by the core + system, such as caching or some form of hardware acceleration. This chapter + outlines how to write a new custom scan provider. + + + + Implementing a new type of custom scan is a three-step process. First, + during planning, it is necessary to generate access paths representing a + scan using the proposed strategy. Second, if one of those access paths + is selected by the planner as the optimal strategy for scanning a + particular relation, the access path must be converted to a plan. + Finally, it must be possible to execute the plan and generate the same + results that would have been generated for any other access path targeting + the same relation. + + + + Implementing Custom Paths + + + A custom scan provider will typically add paths by setting the following + hook, which is called after the core code has generated what it believes + to be the complete and correct set of access paths for the relation. + +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; + + + + + Although this hook function can be used to examine, modify, or remove + paths generated by the core system, a custom scan provider will typically + confine itself to generating CustomPath objects and adding + them to rel using add_path. The custom scan + provider is responsible for initializing the CustomPath + object, which is declared like this: + +typedef struct CustomPath +{ + Path path; + uint32 flags; + List *custom_private; + const CustomPathMethods *methods; +} CustomPath; + + + + + path must be initialized as for any other path, including + the row-count estimate, start and total cost, and sort ordering provided + by this path. flags is a bitmask, which should include + CUSTOMPATH_SUPPORT_BACKWARD_SCAN if the custom path can support + a backward scan and CUSTOMPATH_SUPPORT_MARK_RESTORE if it + can support mark and restore. Both capabilities are optional. + custom_private can be used to store the custom path's + private data. Private data should be stored in a form that can be handled + by nodeToString, so that debugging routines which attempt to + print the custom path will work as designed. methods must + point to a (usually statically allocated) object implementing the required + custom path methods, of which there are currently only two, as further + detailed below. + + + + Custom Path Callbacks + + + +Plan *(*PlanCustomPath) (PlannerInfo *root, + RelOptInfo *rel, + CustomPath *best_path, + List *tlist, + List *clauses); + + Convert a custom path to a finished plan. The return value will generally + be a CustomScan object, which the callback must allocate and + initialize. See for more details. + + + + +void (*TextOutCustomPath) (StringInfo str, + const CustomPath *node); + + Generate additional output when nodeToString is invoked on + this custom path. This callback is optional. Since + nodeToString will automatically dump all fields in the + structure that it can see, including custom_private, this + is only useful if the CustomPath is actually embedded in a + larger struct containing additional fields. + + + + + + Implementing Custom Plans + + + A custom scan is represented in a finished plan tree using the following + structure: + +typedef struct CustomScan +{ + Scan scan; + uint32 flags; + List *custom_exprs; + List *custom_private; + 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 bitmask with the same meaning as in + CustomPath. 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. Plan trees must be able + to be duplicated using copyObject, so all the data stored + within these two fields must consist of nodes that function can handle. + methods must point to a (usually statically allocated) + object implementing the required custom scan methods, which are further + detailed below. + + + + Custom Scan Callbacks + + +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 + scan types will wish to embed that as the first field of a large structure. + The value returned must have the node tag and methods + set appropriately, but the other fields need not be initialized at this + stage; after ExecInitCustomScan performs basic initialization, + the BeginCustomScan callback will be invoked to give the + custom scan state a chance to do whatever else is needed. + + + + +void (*TextOutCustomScan) (StringInfo str, + const CustomScan *node); + + Generate additional output when nodeToString is invoked on + this custom plan. This callback is optional. Since a + CustomScan must be copyable by copyObject, + 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. + Therefore, providing this callback is unlikely to be useful. + + + + + + Implementing Custom Scans + + + When a CustomScan is executed, its execution state is + represented by a CustomScanState, which is declared as + follows. + +typedef struct CustomScanState +{ + ScanState ss; + uint32 flags; + const CustomExecMethods *methods; +} CustomScanState; + + + + + ss must be initialized as for any other scanstate; + flags is a bitmask with the same meaning as in + CustomPath and CustomScan. + methods must point to a (usually statically allocated) + object implementing the required custom scan state methods, which are + further detailed below. Typically, a CustomScanState, which + need not support copyObject, will actually be a larger + structure embedding the above as its first member. + + + + Custom Execution-Time Callbacks + + + +void (*BeginCustomScan) (CustomScanState *node, + EState *estate, + int eflags); + + Complete initialization of the supplied CustomScanState. + Some initialization is performed by ExecInitCustomScan, but + any private fields should be initialized here. + + + + +TupleTableSlot *(*ExecCustomScan) (CustomScanState *node); + + Fetch the next scan tuple. If any tuples remain, it should fill + ps_ResultTupleSlot with the next tuple in the current scan + direction, and then return the tuple slot. If not, + NULL or an empty slot should be returned. + + + + +void (*EndCustomScan) (CustomScanState *node); + + Clean up any private data associated with the CustomScanState. + This method is required, but may not need to do anything if the associated + data does not exist or will be cleaned up automatically. + + + + +void (*ReScanCustomScan) (CustomScanState *node); + + Rewind the current scan to the beginning and prepare to rescan the + relation. + + + + +void (*MarkPosCustomScan) (CustomScanState *node); + + Save the current scan position so that it can subsequently be restored + by the RestrPosCustomScan callback. This calback is optional, + and need only be supplied if + CUSTOMPATH_SUPPORT_MARK_RESTORE flag is set. + + + + +void (*RestrPosCustomScan) (CustomScanState *node); + + Restore the previous scan position as saved by the + MarkPosCustomScan callback. This callback is optional, + and need only be supplied if + CUSTOMPATH_SUPPORT_MARK_RESTORE flag is set. + + + + +void (*ExplainCustomScan) (CustomScanState *node, + List *ancestors, + ExplainState *es); + + Output additional information on EXPLAIN that involves + custom-scan node. This callback is optional. Common data stored in the + ScanState, such as the target list and scan relation, will + be shown even without this callback, but the callback allows the display + of additional, private state. + + + + diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index f03b72ab1d..89fff7739e 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -93,6 +93,7 @@ + diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index a648a4c5f6..e378d6978d 100644 --- a/doc/src/sgml/postgres.sgml +++ b/doc/src/sgml/postgres.sgml @@ -242,6 +242,7 @@ &nls; &plhandler; &fdwhandler; + &custom-scan; &geqo; &indexam; &gist; -- 2.40.0