diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index 04bf919b3438..3055f32f1375 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -4090,107 +4090,173 @@ extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind,
knowledge that helps the planner optimize function calls.
-
- Some basic facts can be supplied by declarative annotations provided in
- the CREATE FUNCTION command. Most important of
- these is the function's volatility
- category (IMMUTABLE, STABLE,
- or VOLATILE); one should always be careful to
- specify this correctly when defining a function.
- The parallel safety property (PARALLEL
- UNSAFE, PARALLEL RESTRICTED, or
- PARALLEL SAFE) 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.
-
+
+ Function Inlining
+
+ function
+ inlining
+
-
- It is also possible to attach a planner support
- function to an SQL-callable function (called
- its target function), 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.
-
+
+ Even with no extra information, the planner may be able to inline the function
+ into the calling query. The rules vary depending on whether the function returns
+ a single result or is a set-returning function.
+ But in all cases the function must be implemented in SQL (not PL/pgSQL).
+ It must not be SECURITY DEFINER.
+ And if an extension has hooked function entry/exit,
+ then inlining must be skipped.
+
+
+
+ For single-result functions, the function body must be a single
+ SELECT expression statement
+ returning a single column.
+ It must not return a RECORD.
+ It must return a type that matches the function declaration.
+ It cannot recurse. It must not include CTEs, a FROM clause,
+ references to tables or table-like objects, DISTINCT,
+ GROUP BY, HAVING,
+ aggregate functions, window functions,
+ ORDER BY, LIMIT, OFFSET,
+ UNION, INTERSECT, or EXCEPT.
+ Its arguments, if used more than once in its body, cannot include VOLATILE functions.
+ The hypothetical inlined expression must be no more volatile than the original function
+ (so an IMMUTABLE function must inline to an IMMUTABLE
+ expression, and a STABLE function must inline to STABLE or IMMUTABLE).
+ If the original function was STRICT, then any called functions must be STRICT.
+ For more control, see SupportRequestSimplify.
+
+
+
+ For set-returning functions, inlining lets the planner merge the query into the
+ outer query, enabling optimizations like qual pushdown, constant folding, etc.
+ The function body must be a single SELECT statement.
+ It must be declared STABLE or IMMUTABLE.
+ It must not be STRICT.
+ In addition its arguments may not include volatile function calls or
+ sub-queries. The function must be called from the FROM clause,
+ not the SELECT clause, nor with ORDINALITY or
+ ROWS FROM.
+
+
-
- A planner support function must have the SQL signature
+
+ Function Annotations
+
+ function
+ annotations
+
+
+
+ Some basic facts can be supplied by declarative annotations provided in
+ the CREATE FUNCTION command. Most important of
+ these is the function's volatility
+ category (IMMUTABLE, STABLE,
+ or VOLATILE); one should always be careful to
+ specify this correctly when defining a function.
+ The parallel safety property (PARALLEL
+ UNSAFE, PARALLEL RESTRICTED, or
+ PARALLEL SAFE) 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.
+
+
+
+
+ Function Support Functions
+
+ function
+ support functions
+
+
+
+ It is also possible to attach a planner support
+ function to an SQL-callable function (called
+ its target function), 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.
+
+
+
+ A planner support function must have the SQL signature
supportfn(internal) returns internal
- It is attached to its target function by specifying
- the SUPPORT clause when creating the target function.
-
+ It is attached to its target function by specifying
+ the SUPPORT clause when creating the target function.
+
-
- The details of the API for planner support functions can be found in
- file src/include/nodes/supportnodes.h in the
- PostgreSQL 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.
-
+
+ The details of the API for planner support functions can be found in
+ file src/include/nodes/supportnodes.h in the
+ PostgreSQL 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.
+
-
- Some function calls can be simplified during planning based on
- properties specific to the function. For example,
- int4mul(n, 1) could be simplified to
- just n. This type of transformation can be
- performed by a planner support function, by having it implement
- the SupportRequestSimplify 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, n * 1 would also be simplified to
- n.
- (But note that this is just an example; this particular
- optimization is not actually performed by
- standard PostgreSQL.)
- We make no guarantee that PostgreSQL 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.
-
+
+ Some function calls can be simplified during planning based on
+ properties specific to the function. For example,
+ int4mul(n, 1) could be simplified to
+ just n. This type of transformation can be
+ performed by a planner support function, by having it implement
+ the SupportRequestSimplify 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, n * 1 would also be simplified to
+ n.
+ (But note that this is just an example; this particular
+ optimization is not actually performed by
+ standard PostgreSQL.)
+ We make no guarantee that PostgreSQL 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.
+
-
- For target functions that return boolean, it is often useful to estimate
- the fraction of rows that will be selected by a WHERE clause using that
- function. This can be done by a support function that implements
- the SupportRequestSelectivity request type.
-
+
+ For target functions that return boolean, it is often useful to estimate
+ the fraction of rows that will be selected by a WHERE clause using that
+ function. This can be done by a support function that implements
+ the SupportRequestSelectivity request type.
+
-
- 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 SupportRequestCost request type.
-
+
+ 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 SupportRequestCost request type.
+
-
- 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 SupportRequestRows request type.
-
+
+ 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 SupportRequestRows request type.
+
-
- For target functions that return boolean, it may be possible to
- convert a function call appearing in WHERE 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 lossy; 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 WHERE condition or not.
- To create such conditions, the support function must implement
- the SupportRequestIndexCondition request type.
-
+
+ For target functions that return boolean, it may be possible to
+ convert a function call appearing in WHERE 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 lossy; 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 WHERE condition or not.
+ To create such conditions, the support function must implement
+ the SupportRequestIndexCondition request type.
+
+