2011-02-20 06:17:18 +01:00
|
|
|
<!-- doc/src/sgml/fdwhandler.sgml -->
|
|
|
|
|
|
|
|
<chapter id="fdwhandler">
|
|
|
|
<title>Writing A Foreign Data Wrapper</title>
|
|
|
|
|
|
|
|
<indexterm zone="fdwhandler">
|
|
|
|
<primary>foreign data wrapper</primary>
|
|
|
|
<secondary>handler for</secondary>
|
|
|
|
</indexterm>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
All operations on a foreign table are handled through its foreign data
|
|
|
|
wrapper, which consists of a set of functions that the planner and
|
|
|
|
executor call. The foreign data wrapper is responsible for fetching
|
|
|
|
data from the remote data source and returning it to the
|
|
|
|
<productname>PostgreSQL</productname> executor. This chapter outlines how
|
|
|
|
to write a new foreign data wrapper.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The foreign data wrappers included in the standard distribution are good
|
|
|
|
references when trying to write your own. Look into the
|
|
|
|
<filename>contrib/file_fdw</> subdirectory of the source tree.
|
|
|
|
The <xref linkend="sql-createforeigndatawrapper"> reference page also has
|
|
|
|
some useful details.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
The SQL standard specifies an interface for writing foreign data wrappers.
|
|
|
|
However, PostgreSQL does not implement that API, because the effort to
|
|
|
|
accommodate it into PostgreSQL would be large, and the standard API hasn't
|
|
|
|
gained wide adoption anyway.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
2011-07-05 21:54:00 +02:00
|
|
|
<sect1 id="fdw-functions">
|
|
|
|
<title>Foreign Data Wrapper Functions</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The FDW author needs to implement a handler function, and optionally
|
|
|
|
a validator function. Both functions must be written in a compiled
|
|
|
|
language such as C, using the version-1 interface.
|
|
|
|
For details on C language calling conventions and dynamic loading,
|
|
|
|
see <xref linkend="xfunc-c">.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The handler function simply returns a struct of function pointers to
|
|
|
|
callback functions that will be called by the planner and executor.
|
|
|
|
Most of the effort in writing an FDW is in implementing these callback
|
|
|
|
functions.
|
|
|
|
The handler function must be registered with
|
|
|
|
<productname>PostgreSQL</productname> as taking no arguments and
|
|
|
|
returning the special pseudo-type <type>fdw_handler</type>. The
|
|
|
|
callback functions are plain C functions and are not visible or
|
|
|
|
callable at the SQL level. The callback functions are described in
|
|
|
|
<xref linkend="fdw-callbacks">.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The validator function is responsible for validating options given in
|
|
|
|
<command>CREATE</command> and <command>ALTER</command> commands for its
|
|
|
|
foreign data wrapper, as well as foreign servers, user mappings, and
|
|
|
|
foreign tables using the wrapper.
|
|
|
|
The validator function must be registered as taking two arguments, a
|
|
|
|
text array containing the options to be validated, and an OID
|
|
|
|
representing the type of object the options are associated with (in
|
|
|
|
the form of the OID of the system catalog the object would be stored
|
|
|
|
in, either
|
|
|
|
<literal>ForeignDataWrapperRelationId</>,
|
|
|
|
<literal>ForeignServerRelationId</>,
|
|
|
|
<literal>UserMappingRelationId</>,
|
|
|
|
or <literal>ForeignTableRelationId</>).
|
|
|
|
If no validator function is supplied, options are not checked at object
|
|
|
|
creation time or object alteration time.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
</sect1>
|
|
|
|
|
|
|
|
<sect1 id="fdw-callbacks">
|
2011-02-20 06:17:18 +01:00
|
|
|
<title>Foreign Data Wrapper Callback Routines</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The FDW handler function returns a palloc'd <structname>FdwRoutine</>
|
|
|
|
struct containing pointers to the following callback functions:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
2012-03-05 22:15:59 +01:00
|
|
|
void
|
2011-02-20 06:17:18 +01:00
|
|
|
PlanForeignScan (Oid foreigntableid,
|
|
|
|
PlannerInfo *root,
|
|
|
|
RelOptInfo *baserel);
|
|
|
|
</programlisting>
|
|
|
|
|
2012-03-05 22:15:59 +01:00
|
|
|
Create possible access paths for a scan on a foreign table. This is
|
|
|
|
called when a query is planned.
|
2011-02-20 06:17:18 +01:00
|
|
|
<literal>foreigntableid</> is the <structname>pg_class</> OID of the
|
|
|
|
foreign table. <literal>root</> is the planner's global information
|
|
|
|
about the query, and <literal>baserel</> is the planner's information
|
|
|
|
about this table.
|
2012-03-05 22:15:59 +01:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The function must generate at least one access path (ForeignPath node)
|
|
|
|
for a scan on the foreign table and must call <function>add_path</> to
|
|
|
|
add the path to <literal>baserel->pathlist</>. It's recommended to
|
|
|
|
use <function>create_foreignscan_path</> to build the ForeignPath node.
|
|
|
|
The function may generate multiple access paths, e.g., a path which has
|
|
|
|
valid <literal>pathkeys</> to represent a pre-sorted result. Each access
|
|
|
|
path must contain cost estimates, and can contain any FDW-private
|
|
|
|
information that is needed to execute the foreign scan at a later time.
|
|
|
|
(Note that the private information must be represented in a form that
|
|
|
|
<function>copyObject</> knows how to copy.)
|
2011-02-20 06:17:18 +01:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The information in <literal>root</> and <literal>baserel</> can be used
|
|
|
|
to reduce the amount of information that has to be fetched from the
|
|
|
|
foreign table (and therefore reduce the cost estimate).
|
|
|
|
<literal>baserel->baserestrictinfo</> is particularly interesting, as
|
|
|
|
it contains restriction quals (<literal>WHERE</> clauses) that can be
|
|
|
|
used to filter the rows to be fetched. (The FDW is not required to
|
|
|
|
enforce these quals, as the finished plan will recheck them anyway.)
|
|
|
|
<literal>baserel->reltargetlist</> can be used to determine which
|
|
|
|
columns need to be fetched.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
In addition to returning cost estimates, the function should update
|
|
|
|
<literal>baserel->rows</> to be the expected number of rows returned
|
|
|
|
by the scan, after accounting for the filtering done by the restriction
|
|
|
|
quals. The initial value of <literal>baserel->rows</> is just a
|
|
|
|
constant default estimate, which should be replaced if at all possible.
|
|
|
|
The function may also choose to update <literal>baserel->width</> if
|
|
|
|
it can compute a better estimate of the average result row width.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
void
|
|
|
|
ExplainForeignScan (ForeignScanState *node,
|
|
|
|
ExplainState *es);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
Print additional <command>EXPLAIN</> output for a foreign table scan.
|
|
|
|
This can just return if there is no need to print anything.
|
|
|
|
Otherwise, it should call <function>ExplainPropertyText</> and
|
|
|
|
related functions to add fields to the <command>EXPLAIN</> output.
|
|
|
|
The flag fields in <literal>es</> can be used to determine what to
|
|
|
|
print, and the state of the <structname>ForeignScanState</> node
|
|
|
|
can be inspected to provide runtime statistics in the <command>EXPLAIN
|
|
|
|
ANALYZE</> case.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
void
|
|
|
|
BeginForeignScan (ForeignScanState *node,
|
|
|
|
int eflags);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
Begin executing a foreign scan. This is called during executor startup.
|
2011-07-25 15:37:06 +02:00
|
|
|
It should perform any initialization needed before the scan can start,
|
|
|
|
but not start executing the actual scan (that should be done upon the
|
|
|
|
first call to <function>IterateForeignScan</>).
|
2011-02-20 06:17:18 +01:00
|
|
|
The <structname>ForeignScanState</> node has already been created, but
|
|
|
|
its <structfield>fdw_state</> field is still NULL. Information about
|
|
|
|
the table to scan is accessible through the
|
|
|
|
<structname>ForeignScanState</> node (in particular, from the underlying
|
2012-03-05 22:15:59 +01:00
|
|
|
<structname>ForeignScan</> plan node, which contains any FDW-private
|
|
|
|
information provided by <function>PlanForeignScan</>).
|
2011-02-20 06:17:18 +01:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Note that when <literal>(eflags & EXEC_FLAG_EXPLAIN_ONLY)</> is
|
|
|
|
true, this function should not perform any externally-visible actions;
|
|
|
|
it should only do the minimum required to make the node state valid
|
|
|
|
for <function>ExplainForeignScan</> and <function>EndForeignScan</>.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
TupleTableSlot *
|
|
|
|
IterateForeignScan (ForeignScanState *node);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
Fetch one row from the foreign source, returning it in a tuple table slot
|
|
|
|
(the node's <structfield>ScanTupleSlot</> should be used for this
|
|
|
|
purpose). Return NULL if no more rows are available. The tuple table
|
|
|
|
slot infrastructure allows either a physical or virtual tuple to be
|
|
|
|
returned; in most cases the latter choice is preferable from a
|
|
|
|
performance standpoint. Note that this is called in a short-lived memory
|
|
|
|
context that will be reset between invocations. Create a memory context
|
|
|
|
in <function>BeginForeignScan</> if you need longer-lived storage, or use
|
|
|
|
the <structfield>es_query_cxt</> of the node's <structname>EState</>.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The rows returned must match the column signature of the foreign table
|
|
|
|
being scanned. If you choose to optimize away fetching columns that
|
|
|
|
are not needed, you should insert nulls in those column positions.
|
|
|
|
</para>
|
|
|
|
|
2011-06-13 14:28:41 +02:00
|
|
|
<para>
|
|
|
|
Note that <productname>PostgreSQL</productname>'s executor doesn't care
|
|
|
|
whether the rows returned violate the <literal>NOT NULL</literal>
|
|
|
|
constraints which were defined on the foreign table columns - but the
|
|
|
|
planner does care, and may optimize queries incorrectly if
|
|
|
|
<literal>NULL</> values are present in a column declared not to contain
|
|
|
|
them. If a <literal>NULL</> value is encountered when the user has
|
|
|
|
declared that none should be present, it may be appropriate to raise an
|
|
|
|
error (just as you would need to do in the case of a data type mismatch).
|
|
|
|
</para>
|
|
|
|
|
2011-02-20 06:17:18 +01:00
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
void
|
|
|
|
ReScanForeignScan (ForeignScanState *node);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
Restart the scan from the beginning. Note that any parameters the
|
|
|
|
scan depends on may have changed value, so the new scan does not
|
|
|
|
necessarily return exactly the same rows.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
void
|
|
|
|
EndForeignScan (ForeignScanState *node);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
End the scan and release resources. It is normally not important
|
|
|
|
to release palloc'd memory, but for example open files and connections
|
|
|
|
to remote servers should be cleaned up.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2012-03-05 22:15:59 +01:00
|
|
|
The <structname>FdwRoutine</> struct type is declared in
|
|
|
|
<filename>src/include/foreign/fdwapi.h</>, which see for additional
|
|
|
|
details.
|
2011-02-20 06:17:18 +01:00
|
|
|
</para>
|
|
|
|
|
|
|
|
</sect1>
|
|
|
|
|
2012-03-08 00:20:58 +01:00
|
|
|
<sect1 id="fdw-helpers">
|
|
|
|
<title>Foreign Data Wrapper Helper Functions</title>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Several helper functions are exported from the core server so that
|
|
|
|
authors of foreign data wrappers can get easy access to attributes of
|
|
|
|
FDW-related objects, such as FDW options.
|
|
|
|
To use any of these functions, you need to include the header file
|
|
|
|
<filename>foreign/foreign.h</filename> in your source file.
|
|
|
|
That header also defines the struct types that are returned by
|
|
|
|
these functions.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
ForeignDataWrapper *
|
|
|
|
GetForeignDataWrapper(Oid fdwid);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
This function returns a <structname>ForeignDataWrapper</structname>
|
|
|
|
object for the foreign-data wrapper with the given OID. A
|
|
|
|
<structname>ForeignDataWrapper</structname> object contains properties
|
|
|
|
of the FDW (see <filename>foreign/foreign.h</filename> for details).
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
ForeignServer *
|
|
|
|
GetForeignServer(Oid serverid);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
This function returns a <structname>ForeignServer</structname> object
|
|
|
|
for the foreign server with the given OID. A
|
|
|
|
<structname>ForeignServer</structname> object contains properties
|
|
|
|
of the server (see <filename>foreign/foreign.h</filename> for details).
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
UserMapping *
|
|
|
|
GetUserMapping(Oid userid, Oid serverid);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
This function returns a <structname>UserMapping</structname> object for
|
|
|
|
the user mapping of the given role on the given server. (If there is no
|
|
|
|
mapping for the specific user, it will return the mapping for
|
|
|
|
<literal>PUBLIC</>, or throw error if there is none.) A
|
|
|
|
<structname>UserMapping</structname> object contains properties of the
|
|
|
|
user mapping (see <filename>foreign/foreign.h</filename> for details).
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
ForeignTable *
|
|
|
|
GetForeignTable(Oid relid);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
This function returns a <structname>ForeignTable</structname> object for
|
|
|
|
the foreign table with the given OID. A
|
|
|
|
<structname>ForeignTable</structname> object contains properties of the
|
|
|
|
foreign table (see <filename>foreign/foreign.h</filename> for details).
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
List *
|
|
|
|
GetForeignTableColumnOptions(Oid relid, AttrNumber attnum);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
This function returns the per-column FDW options for the column with the
|
|
|
|
given foreign table OID and attribute number, in the form of a list of
|
|
|
|
<structname>DefElem</structname>. NIL is returned if the column has no
|
|
|
|
options.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Some object types have name-based lookup functions in addition to the
|
|
|
|
OID-based ones:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
ForeignDataWrapper *
|
|
|
|
GetForeignDataWrapperByName(const char *name, bool missing_ok);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
This function returns a <structname>ForeignDataWrapper</structname>
|
|
|
|
object for the foreign-data wrapper with the given name. If the wrapper
|
|
|
|
is not found, return NULL if missing_ok is true, otherwise raise an
|
|
|
|
error.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<programlisting>
|
|
|
|
ForeignServer *
|
|
|
|
GetForeignServerByName(const char *name, bool missing_ok);
|
|
|
|
</programlisting>
|
|
|
|
|
|
|
|
This function returns a <structname>ForeignServer</structname> object
|
|
|
|
for the foreign server with the given name. If the server is not found,
|
|
|
|
return NULL if missing_ok is true, otherwise raise an error.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
</sect1>
|
|
|
|
|
2011-02-20 06:17:18 +01:00
|
|
|
</chapter>
|