diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-02-09 18:08:48 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-02-09 18:08:48 -0500 |
commit | 1fb57af92069ee104c09e2016af9e0e620681be3 (patch) | |
tree | 8bb9db8431972a220f6bd6f8b13e663049172583 /doc/src | |
parent | 1a8d5afb0dfc5d0dcc6eda0656a34cb1f0cf0bdf (diff) | |
download | postgresql-1fb57af92069ee104c09e2016af9e0e620681be3.tar.gz postgresql-1fb57af92069ee104c09e2016af9e0e620681be3.zip |
Create the infrastructure for planner support functions.
Rename/repurpose pg_proc.protransform as "prosupport". The idea is
still that it names an internal function that provides knowledge to
the planner about the behavior of the function it's attached to;
but redesign the API specification so that it's not limited to doing
just one thing, but can support an extensible set of requests.
The original purpose of simplifying a function call is handled by
the first request type to be invented, SupportRequestSimplify.
Adjust all the existing transform functions to handle this API,
and rename them fron "xxx_transform" to "xxx_support" to reflect
the potential generalization of what they do. (Since we never
previously provided any way for extensions to add transform functions,
this change doesn't create an API break for them.)
Also add DDL and pg_dump support for attaching a support function to a
user-defined function. Unfortunately, DDL access has to be restricted
to superusers, at least for now; but seeing that support functions
will pretty much have to be written in C, that limitation is just
theoretical. (This support is untested in this patch, but a follow-on
patch will add cases that exercise it.)
Discussion: https://postgr.es/m/15193.1548028093@sss.pgh.pa.us
Diffstat (limited to 'doc/src')
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 6 | ||||
-rw-r--r-- | doc/src/sgml/keywords.sgml | 7 | ||||
-rw-r--r-- | doc/src/sgml/ref/alter_function.sgml | 19 | ||||
-rw-r--r-- | doc/src/sgml/ref/create_function.sgml | 14 | ||||
-rw-r--r-- | doc/src/sgml/xfunc.sgml | 120 | ||||
-rw-r--r-- | doc/src/sgml/xoper.sgml | 12 |
6 files changed, 141 insertions, 37 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index af4d0625eab..6dd0700da75 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -5146,11 +5146,11 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </row> <row> - <entry><structfield>protransform</structfield></entry> + <entry><structfield>prosupport</structfield></entry> <entry><type>regproc</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> - <entry>Calls to this function can be simplified by this other function - (see <xref linkend="xfunc-transform-functions"/>)</entry> + <entry>Optional planner support function for this function + (see <xref linkend="xfunc-optimization"/>)</entry> </row> <row> diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml index a37d0b756bd..fa32a88b8e2 100644 --- a/doc/src/sgml/keywords.sgml +++ b/doc/src/sgml/keywords.sgml @@ -4522,6 +4522,13 @@ <entry>reserved</entry> </row> <row> + <entry><token>SUPPORT</token></entry> + <entry>non-reserved</entry> + <entry></entry> + <entry></entry> + <entry></entry> + </row> + <row> <entry><token>SYMMETRIC</token></entry> <entry>reserved</entry> <entry>reserved</entry> diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml index d8747e07482..03ffa5945a2 100644 --- a/doc/src/sgml/ref/alter_function.sgml +++ b/doc/src/sgml/ref/alter_function.sgml @@ -40,6 +40,7 @@ ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="param PARALLEL { UNSAFE | RESTRICTED | SAFE } COST <replaceable class="parameter">execution_cost</replaceable> ROWS <replaceable class="parameter">result_rows</replaceable> + SUPPORT <replaceable class="parameter">support_function</replaceable> SET <replaceable class="parameter">configuration_parameter</replaceable> { TO | = } { <replaceable class="parameter">value</replaceable> | DEFAULT } SET <replaceable class="parameter">configuration_parameter</replaceable> FROM CURRENT RESET <replaceable class="parameter">configuration_parameter</replaceable> @@ -248,6 +249,24 @@ ALTER FUNCTION <replaceable>name</replaceable> [ ( [ [ <replaceable class="param </listitem> </varlistentry> + <varlistentry> + <term><literal>SUPPORT</literal> <replaceable class="parameter">support_function</replaceable></term> + + <listitem> + <para> + Set or change the planner support function to use for this function. + See <xref linkend="xfunc-optimization"/> for details. You must be + superuser to use this option. + </para> + + <para> + This option cannot be used to remove the support function altogether, + since it must name a new support function. Use <command>CREATE OR + REPLACE FUNCTION</command> if you need to do that. + </para> + </listitem> + </varlistentry> + <varlistentry> <term><replaceable>configuration_parameter</replaceable></term> <term><replaceable>value</replaceable></term> diff --git a/doc/src/sgml/ref/create_function.sgml b/doc/src/sgml/ref/create_function.sgml index 40725431842..dd6a2f73049 100644 --- a/doc/src/sgml/ref/create_function.sgml +++ b/doc/src/sgml/ref/create_function.sgml @@ -33,6 +33,7 @@ CREATE [ OR REPLACE ] FUNCTION | PARALLEL { UNSAFE | RESTRICTED | SAFE } | COST <replaceable class="parameter">execution_cost</replaceable> | ROWS <replaceable class="parameter">result_rows</replaceable> + | SUPPORT <replaceable class="parameter">support_function</replaceable> | SET <replaceable class="parameter">configuration_parameter</replaceable> { TO <replaceable class="parameter">value</replaceable> | = <replaceable class="parameter">value</replaceable> | FROM CURRENT } | AS '<replaceable class="parameter">definition</replaceable>' | AS '<replaceable class="parameter">obj_file</replaceable>', '<replaceable class="parameter">link_symbol</replaceable>' @@ -478,6 +479,19 @@ CREATE [ OR REPLACE ] FUNCTION </varlistentry> <varlistentry> + <term><literal>SUPPORT</literal> <replaceable class="parameter">support_function</replaceable></term> + + <listitem> + <para> + The name (optionally schema-qualified) of a <firstterm>planner support + function</firstterm> to use for this function. See + <xref linkend="xfunc-optimization"/> for details. + You must be superuser to use this option. + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><replaceable>configuration_parameter</replaceable></term> <term><replaceable>value</replaceable></term> <listitem> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index e18272c33a1..d70aa6eed78 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3241,40 +3241,6 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray </para> </sect2> - <sect2 id="xfunc-transform-functions"> - <title>Transform Functions</title> - - <para> - Some function calls can be simplified during planning based on - properties specific to the function. For example, - <literal>int4mul(n, 1)</literal> could be simplified to just <literal>n</literal>. - To define such function-specific optimizations, write a - <firstterm>transform function</firstterm> and place its OID in the - <structfield>protransform</structfield> field of the primary function's - <structname>pg_proc</structname> entry. The transform function must have the SQL - signature <literal>protransform(internal) RETURNS internal</literal>. The - argument, actually <type>FuncExpr *</type>, is a dummy node representing a - call to the primary function. If the transform function's study of the - expression tree proves that a simplified expression tree can substitute - for all possible concrete calls represented thereby, build and return - that simplified expression. Otherwise, return a <literal>NULL</literal> - pointer (<emphasis>not</emphasis> a SQL null). - </para> - - <para> - We make no guarantee that <productname>PostgreSQL</productname> will never call the - primary function in cases that the transform function could simplify. - Ensure rigorous equivalence between the simplified expression and an - actual call to the primary function. - </para> - - <para> - Currently, this facility is not exposed to users at the SQL level - because of security concerns, so it is only practical to use for - optimizing built-in functions. - </para> - </sect2> - <sect2> <title>Shared Memory and LWLocks</title> @@ -3388,3 +3354,89 @@ if (!ptr) </sect2> </sect1> + + <sect1 id="xfunc-optimization"> + <title>Function Optimization Information</title> + + <indexterm zone="xfunc-optimization"> + <primary>optimization information</primary> + <secondary>for functions</secondary> + </indexterm> + + <para> + By default, a function is just a <quote>black box</quote> that the + database system knows very little about the behavior of. However, + that means that queries using the function may be executed much less + efficiently than they could be. It is possible to supply additional + knowledge that helps the planner optimize function calls. + </para> + + <para> + Some basic facts can be supplied by declarative annotations provided in + the <xref linkend="sql-createfunction"/> command. Most important of + these is the function's <link linkend="xfunc-volatility">volatility + category</link> (<literal>IMMUTABLE</literal>, <literal>STABLE</literal>, + or <literal>VOLATILE</literal>); one should always be careful to + specify this correctly when defining a function. + The parallel safety property (<literal>PARALLEL + UNSAFE</literal>, <literal>PARALLEL RESTRICTED</literal>, or + <literal>PARALLEL SAFE</literal>) must also be specified if you hope + to use the function in parallelized queries. + It can also be useful to specify the function's estimated execution + cost, and/or the number of rows a set-returning function is estimated + to return. However, the declarative way of specifying those two + facts only allows specifying a constant value, which is often + inadequate. + </para> + + <para> + It is also possible to attach a <firstterm>planner support + function</firstterm> to a SQL-callable function (called + its <firstterm>target function</firstterm>), and thereby provide + knowledge about the target function that is too complex to be + represented declaratively. Planner support functions have to be + written in C (although their target functions might not be), so this is + an advanced feature that relatively few people will use. + </para> + + <para> + A planner support function must have the SQL signature +<programlisting> +supportfn(internal) returns internal +</programlisting> + It is attached to its target function by specifying + the <literal>SUPPORT</literal> clause when creating the target function. + </para> + + <para> + The details of the API for planner support functions can be found in + file <filename>src/include/nodes/supportnodes.h</filename> in the + <productname>PostgreSQL</productname> source code. Here we provide + just an overview of what planner support functions can do. + The set of possible requests to a support function is extensible, + so more things might be possible in future versions. + </para> + + <para> + Some function calls can be simplified during planning based on + properties specific to the function. For example, + <literal>int4mul(n, 1)</literal> could be simplified to + just <literal>n</literal>. This type of transformation can be + performed by a planner support function, by having it implement + the <literal>SupportRequestSimplify</literal> request type. + The support function will be called for each instance of its target + function found in a query parse tree. If it finds that the particular + call can be simplified into some other form, it can build and return a + parse tree representing that expression. This will automatically work + for operators based on the function, too — in the example just + given, <literal>n * 1</literal> would also be simplified to + <literal>n</literal>. + (But note that this is just an example; this particular + optimization is not actually performed by + standard <productname>PostgreSQL</productname>.) + We make no guarantee that <productname>PostgreSQL</productname> will + never call the target function in cases that the support function could + simplify. Ensure rigorous equivalence between the simplified + expression and an actual execution of the target function. + </para> + </sect1> diff --git a/doc/src/sgml/xoper.sgml b/doc/src/sgml/xoper.sgml index 2f5560ac505..260e43c6459 100644 --- a/doc/src/sgml/xoper.sgml +++ b/doc/src/sgml/xoper.sgml @@ -78,6 +78,11 @@ SELECT (a + b) AS c FROM test_complex; <sect1 id="xoper-optimization"> <title>Operator Optimization Information</title> + <indexterm zone="xoper-optimization"> + <primary>optimization information</primary> + <secondary>for operators</secondary> + </indexterm> + <para> A <productname>PostgreSQL</productname> operator definition can include several optional clauses that tell the system useful things about how @@ -97,6 +102,13 @@ SELECT (a + b) AS c FROM test_complex; the ones that release &version; understands. </para> + <para> + It is also possible to attach a planner support function to the function + that underlies an operator, providing another way of telling the system + about the behavior of the operator. + See <xref linkend="xfunc-optimization"/> for more information. + </para> + <sect2> <title><literal>COMMUTATOR</literal></title> |