From c32a09320a6320bcc8a681829c03690556760ffe Mon Sep 17 00:00:00 2001
From: "Paul A. Jungwirth" <pj@illuminatedcomputing.com>
Date: Tue, 1 Jul 2025 20:10:18 -0700
Subject: [PATCH v1 1/2] Split Function Optimization section into parts

We already separate declarative function annotations from dynamic
information provided by support functions. We can make these
sub-sections for better clarity and linkability. And this structure will
help keep things accessible when we introduce a new section about
function inlining.

Author: Paul A. Jungwirth <pj@illuminatedcomputing.com>
---
 doc/src/sgml/xfunc.sgml | 200 ++++++++++++++++++++++------------------
 1 file changed, 108 insertions(+), 92 deletions(-)

diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 2d81afce8cb..74740b4e345 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -4097,107 +4097,123 @@ extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind,
     knowledge that helps the planner optimize function calls.
    </para>
 
-   <para>
-    Some basic facts can be supplied by declarative annotations provided in
-    the <link linkend="sql-createfunction"><command>CREATE FUNCTION</command></link> 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>
+   <sect2 id="xfunc-annotations">
+    <title>Function Annotations</title>
+    <indexterm>
+     <primary>function</primary>
+     <secondary>annotations</secondary>
+    </indexterm>
 
-   <para>
-    It is also possible to attach a <firstterm>planner support
-    function</firstterm> to an 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>
+     Some basic facts can be supplied by declarative annotations provided in
+     the <link linkend="sql-createfunction"><command>CREATE FUNCTION</command></link> 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>
+   </sect2>
 
-   <para>
-    A planner support function must have the SQL signature
+   <sect2 id="xfunc-support-functions">
+    <title>Function Support Functions</title>
+    <indexterm>
+     <primary>function</primary>
+     <secondary>support functions</secondary>
+    </indexterm>
+
+    <para>
+     It is also possible to attach a <firstterm>planner support
+     function</firstterm> to an 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>
+     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>
+     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 &mdash; 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>
+    <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 &mdash; 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>
 
-   <para>
-    For target functions that return <type>boolean</type>, it is often useful to estimate
-    the fraction of rows that will be selected by a <literal>WHERE</literal> clause using that
-    function.  This can be done by a support function that implements
-    the <literal>SupportRequestSelectivity</literal> request type.
-   </para>
+    <para>
+     For target functions that return <type>boolean</type>, it is often useful to estimate
+     the fraction of rows that will be selected by a <literal>WHERE</literal> clause using that
+     function.  This can be done by a support function that implements
+     the <literal>SupportRequestSelectivity</literal> request type.
+    </para>
 
-   <para>
-    If the target function's run time is highly dependent on its inputs,
-    it may be useful to provide a non-constant cost estimate for it.
-    This can be done by a support function that implements
-    the <literal>SupportRequestCost</literal> request type.
-   </para>
+    <para>
+     If the target function's run time is highly dependent on its inputs,
+     it may be useful to provide a non-constant cost estimate for it.
+     This can be done by a support function that implements
+     the <literal>SupportRequestCost</literal> request type.
+    </para>
 
-   <para>
-    For target functions that return sets, it is often useful to provide
-    a non-constant estimate for the number of rows that will be returned.
-    This can be done by a support function that implements
-    the <literal>SupportRequestRows</literal> request type.
-   </para>
+    <para>
+     For target functions that return sets, it is often useful to provide
+     a non-constant estimate for the number of rows that will be returned.
+     This can be done by a support function that implements
+     the <literal>SupportRequestRows</literal> request type.
+    </para>
 
-   <para>
-    For target functions that return <type>boolean</type>, it may be possible to
-    convert a function call appearing in <literal>WHERE</literal> into an indexable operator
-    clause or clauses.  The converted clauses might be exactly equivalent
-    to the function's condition, or they could be somewhat weaker (that is,
-    they might accept some values that the function condition does not).
-    In the latter case the index condition is said to
-    be <firstterm>lossy</firstterm>; it can still be used to scan an index,
-    but the function call will have to be executed for each row returned by
-    the index to see if it really passes the <literal>WHERE</literal> condition or not.
-    To create such conditions, the support function must implement
-    the <literal>SupportRequestIndexCondition</literal> request type.
-   </para>
+    <para>
+     For target functions that return <type>boolean</type>, it may be possible to
+     convert a function call appearing in <literal>WHERE</literal> into an indexable operator
+     clause or clauses.  The converted clauses might be exactly equivalent
+     to the function's condition, or they could be somewhat weaker (that is,
+     they might accept some values that the function condition does not).
+     In the latter case the index condition is said to
+     be <firstterm>lossy</firstterm>; it can still be used to scan an index,
+     but the function call will have to be executed for each row returned by
+     the index to see if it really passes the <literal>WHERE</literal> condition or not.
+     To create such conditions, the support function must implement
+     the <literal>SupportRequestIndexCondition</literal> request type.
+    </para>
+   </sect2>
   </sect1>
-- 
2.45.0

