diff options
| -rw-r--r-- | doc/src/sgml/custom-scan.sgml | 285 | ||||
| -rw-r--r-- | doc/src/sgml/filelist.sgml | 1 | ||||
| -rw-r--r-- | doc/src/sgml/postgres.sgml | 1 |
3 files changed, 287 insertions, 0 deletions
diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml new file mode 100644 index 00000000000..8a4a3dfcfeb --- /dev/null +++ b/doc/src/sgml/custom-scan.sgml @@ -0,0 +1,285 @@ +<!-- doc/src/sgml/custom-scan.sgml --> + +<chapter id="custom-scan"> + <title>Writing A Custom Scan Provider</title> + + <indexterm zone="custom-scan"> + <primary>custom scan provider</primary> + <secondary>handler for</secondary> + </indexterm> + + <para> + <productname>PostgreSQL</> supports a set of experimental facilities which + are intended to allow extension modules to add new scan types to the system. + Unlike a <link linkend="fdwhandler">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. + </para> + + <para> + 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. + </para> + + <sect1 id="custom-scan-path"> + <title>Implementing Custom Paths</title> + + <para> + 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. +<programlisting> +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; +</programlisting> + </para> + + <para> + 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 <structname>CustomPath</> objects and adding + them to <literal>rel</> using <function>add_path</>. The custom scan + provider is responsible for initializing the <structname>CustomPath</> + object, which is declared like this: +<programlisting> +typedef struct CustomPath +{ + Path path; + uint32 flags; + List *custom_private; + const CustomPathMethods *methods; +} CustomPath; +</programlisting> + </para> + + <para> + <structfield>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. <structfield>flags</> is a bitmask, which should include + <literal>CUSTOMPATH_SUPPORT_BACKWARD_SCAN</> if the custom path can support + a backward scan and <literal>CUSTOMPATH_SUPPORT_MARK_RESTORE</> if it + can support mark and restore. Both capabilities are optional. + <structfield>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 <literal>nodeToString</>, so that debugging routines which attempt to + print the custom path will work as designed. <structfield>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. + </para> + + <sect2 id="custom-scan-path-callbacks"> + <title>Custom Path Callbacks</title> + + <para> +<programlisting> +Plan *(*PlanCustomPath) (PlannerInfo *root, + RelOptInfo *rel, + CustomPath *best_path, + List *tlist, + List *clauses); +</programlisting> + Convert a custom path to a finished plan. The return value will generally + be a <literal>CustomScan</> object, which the callback must allocate and + initialize. See <xref linkend="custom-scan-plan"> for more details. + </para> + + <para> +<programlisting> +void (*TextOutCustomPath) (StringInfo str, + const CustomPath *node); +</programlisting> + Generate additional output when <function>nodeToString</> is invoked on + this custom path. This callback is optional. Since + <function>nodeToString</> will automatically dump all fields in the + structure that it can see, including <structfield>custom_private</>, this + is only useful if the <structname>CustomPath</> is actually embedded in a + larger struct containing additional fields. + </para> + </sect2> + </sect1> + + <sect1 id="custom-scan-plan"> + <title>Implementing Custom Plans</title> + + <para> + A custom scan is represented in a finished plan tree using the following + structure: +<programlisting> +typedef struct CustomScan +{ + Scan scan; + uint32 flags; + List *custom_exprs; + List *custom_private; + const CustomScanMethods *methods; +} CustomScan; +</programlisting> + </para> + + <para> + <structfield>scan</> must be initialized as for any other scan, including + estimated costs, target lists, qualifications, and so on. + <structfield>flags</> is a bitmask with the same meaning as in + <structname>CustomPath</>. <structfield>custom_exprs</> should be used to + store expression trees that will need to be fixed up by + <filename>setrefs.c</> and <filename>subselect.c</>, while + <literal>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 <function>copyObject</>, so all the data stored + within these two fields must consist of nodes that function can handle. + <structfield>methods</> must point to a (usually statically allocated) + object implementing the required custom scan methods, which are further + detailed below. + </para> + + <sect2 id="custom-scan-plan-callbacks"> + <title>Custom Scan Callbacks</title> + <para> +<programlisting> +Node *(*CreateCustomScanState) (CustomScan *cscan); +</programlisting> + Allocate a <structname>CustomScanState</> for this + <structname>CustomScan</>. The actual allocation will often be larger than + required for an ordinary <structname>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 <structfield>methods</> + set appropriately, but the other fields need not be initialized at this + stage; after <function>ExecInitCustomScan</> performs basic initialization, + the <function>BeginCustomScan</> callback will be invoked to give the + custom scan state a chance to do whatever else is needed. + </para> + + <para> +<programlisting> +void (*TextOutCustomScan) (StringInfo str, + const CustomScan *node); +</programlisting> + Generate additional output when <function>nodeToString</> is invoked on + this custom plan. This callback is optional. Since a + <structname>CustomScan</> must be copyable by <function>copyObject</>, + custom scan providers cannot substitute a larger structure that embeds a + <structname>CustomScan</> for the structure itself, as would be possible + for a <structname>CustomPath</> or <structname>CustomScanState</>. + Therefore, providing this callback is unlikely to be useful. + </para> + </sect2> + </sect1> + + <sect1 id="custom-scan-scan"> + <title>Implementing Custom Scans</title> + + <para> + When a <structfield>CustomScan</> is executed, its execution state is + represented by a <structfield>CustomScanState</>, which is declared as + follows. +<programlisting> +typedef struct CustomScanState +{ + ScanState ss; + uint32 flags; + const CustomExecMethods *methods; +} CustomScanState; +</programlisting> + </para> + + <para> + <structfield>ss</> must be initialized as for any other scanstate; + <structfield>flags</> is a bitmask with the same meaning as in + <structname>CustomPath</> and <structname>CustomScan</>. + <structfield>methods</> must point to a (usually statically allocated) + object implementing the required custom scan state methods, which are + further detailed below. Typically, a <structname>CustomScanState</>, which + need not support <function>copyObject</>, will actually be a larger + structure embedding the above as its first member. + </para> + + <sect2 id="custom-scan-scan-callbacks"> + <title>Custom Execution-Time Callbacks</title> + + <para> +<programlisting> +void (*BeginCustomScan) (CustomScanState *node, + EState *estate, + int eflags); +</programlisting> + Complete initialization of the supplied <structname>CustomScanState</>. + Some initialization is performed by <function>ExecInitCustomScan</>, but + any private fields should be initialized here. + </para> + + <para> +<programlisting> +TupleTableSlot *(*ExecCustomScan) (CustomScanState *node); +</programlisting> + Fetch the next scan tuple. If any tuples remain, it should fill + <literal>ps_ResultTupleSlot</> with the next tuple in the current scan + direction, and then return the tuple slot. If not, + <literal>NULL</> or an empty slot should be returned. + </para> + + <para> +<programlisting> +void (*EndCustomScan) (CustomScanState *node); +</programlisting> + Clean up any private data associated with the <literal>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. + </para> + + <para> +<programlisting> +void (*ReScanCustomScan) (CustomScanState *node); +</programlisting> + Rewind the current scan to the beginning and prepare to rescan the + relation. + </para> + + <para> +<programlisting> +void (*MarkPosCustomScan) (CustomScanState *node); +</programlisting> + Save the current scan position so that it can subsequently be restored + by the <function>RestrPosCustomScan</> callback. This calback is optional, + and need only be supplied if + <literal>CUSTOMPATH_SUPPORT_MARK_RESTORE</> flag is set. + </para> + + <para> +<programlisting> +void (*RestrPosCustomScan) (CustomScanState *node); +</programlisting> + Restore the previous scan position as saved by the + <function>MarkPosCustomScan</> callback. This callback is optional, + and need only be supplied if + <literal>CUSTOMPATH_SUPPORT_MARK_RESTORE</> flag is set. + </para> + + <para> +<programlisting> +void (*ExplainCustomScan) (CustomScanState *node, + List *ancestors, + ExplainState *es); +</programlisting> + Output additional information on <command>EXPLAIN</> that involves + custom-scan node. This callback is optional. Common data stored in the + <structname>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. + </para> + </sect2> + </sect1> +</chapter> diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index f03b72ab1db..89fff7739e1 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -93,6 +93,7 @@ <!ENTITY nls SYSTEM "nls.sgml"> <!ENTITY plhandler SYSTEM "plhandler.sgml"> <!ENTITY fdwhandler SYSTEM "fdwhandler.sgml"> +<!ENTITY custom-scan SYSTEM "custom-scan.sgml"> <!ENTITY logicaldecoding SYSTEM "logicaldecoding.sgml"> <!ENTITY protocol SYSTEM "protocol.sgml"> <!ENTITY sources SYSTEM "sources.sgml"> diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml index a648a4c5f64..e378d6978d0 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; |
