<!-- 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</productname> 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</link>, 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>Creating Custom Scan Paths</title>
<para>
A custom scan provider will typically add paths for a base relation by
setting the following hook, which is called after the core code has
generated all the access paths it can for the relation (except for
Gather and Gather Merge paths, which are made after this call so that
they can use partial paths added by the hook):
<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</structname> objects and adding
them to <literal>rel</literal> using <function>add_path</function>, or
<function>add_partial_path</function> if they are partial paths. The
custom scan provider is responsible for initializing the
<structname>CustomPath</structname> object, which is declared like this:
<programlisting>
typedef struct CustomPath
{
Path path;
uint32 flags;
List *custom_paths;
List *custom_restrictinfo;
List *custom_private;
const CustomPathMethods *methods;
} CustomPath;
</programlisting>
</para>
<para>
<structfield>path</structfield> 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</structfield> is a bit mask, which
specifies whether the scan provider can support certain optional
capabilities. <structfield>flags</structfield> should include
<literal>CUSTOMPATH_SUPPORT_BACKWARD_SCAN</literal> if the custom path can support
a backward scan, <literal>CUSTOMPATH_SUPPORT_MARK_RESTORE</literal> if it
can support mark and restore,
and <literal>CUSTOMPATH_SUPPORT_PROJECTION</literal> if it can perform
projections. (If <literal>CUSTOMPATH_SUPPORT_PROJECTION</literal> is not
set, the scan node will only be asked to produce Vars of the scanned
relation; while if that flag is set, the scan node must be able to
evaluate scalar expressions over these Vars.)