286 lines
11 KiB
Plaintext
286 lines
11 KiB
Plaintext
|
<!-- 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>
|