Skip to content

Commit 7266d09

Browse files
committed
Allow functions-in-FROM to be pulled up if they reduce to constants.
This allows simplification of the plan tree in some common usage patterns: we can get rid of a join to the function RTE. In principle we could pull up any immutable expression, but restricting it to Consts avoids the risk that multiple evaluations of the expression might cost more than we can save. (Possibly this could be improved in future --- but we've more or less promised people that putting a function in FROM guarantees single evaluation, so we'd have to tread carefully.) To do this, we need to rearrange when eval_const_expressions() happens for expressions in function RTEs. I moved it to inline_set_returning_functions(), which already has to iterate over every function RTE, and in consequence renamed that function to preprocess_function_rtes(). A useful consequence is that inline_set_returning_function() no longer has to do this for itself, simplifying that code. In passing, break out pull_up_simple_subquery's code that knows where everything that needs pullup_replace_vars() processing is, so that the new pull_up_constant_function() routine can share it. We'd gotten away with one-and-a-half copies of that code so far, since pull_up_simple_values() could assume that a lot of cases didn't apply to it --- but I don't think pull_up_constant_function() can make any simplifying assumptions. Might as well make pull_up_simple_values() use it too. (Possibly this refactoring should go further: maybe we could share some of the code to fill in the pullup_replace_vars_context struct? For now, I left it that the callers fill that completely.) Note: the one existing test case that this patch changes has to be changed because inlining its function RTEs would destroy the point of the test, namely to check join order. Alexander Kuzmenkov and Aleksandr Parfenov, reviewed by Antonin Houska and Anastasia Lubennikova, and whacked around some more by me Discussion: https://postgr.es/m/[email protected]
1 parent a8d6a95 commit 7266d09

File tree

8 files changed

+499
-156
lines changed

8 files changed

+499
-156
lines changed

src/backend/optimizer/plan/planner.c

+11-6
Original file line numberDiff line numberDiff line change
@@ -659,11 +659,12 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
659659
pull_up_sublinks(root);
660660

661661
/*
662-
* Scan the rangetable for set-returning functions, and inline them if
663-
* possible (producing subqueries that might get pulled up next).
664-
* Recursion issues here are handled in the same way as for SubLinks.
662+
* Scan the rangetable for function RTEs, do const-simplification on them,
663+
* and then inline them if possible (producing subqueries that might get
664+
* pulled up next). Recursion issues here are handled in the same way as
665+
* for SubLinks.
665666
*/
666-
inline_set_returning_functions(root);
667+
preprocess_function_rtes(root);
667668

668669
/*
669670
* Check to see if any subqueries in the jointree can be merged into this
@@ -1071,7 +1072,9 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
10711072
expr = flatten_join_alias_vars(root->parse, expr);
10721073

10731074
/*
1074-
* Simplify constant expressions.
1075+
* Simplify constant expressions. For function RTEs, this was already
1076+
* done by preprocess_function_rtes ... but we have to do it again if the
1077+
* RTE is LATERAL and might have contained join alias variables.
10751078
*
10761079
* Note: an essential effect of this is to convert named-argument function
10771080
* calls to positional notation and insert the current actual values of
@@ -1085,7 +1088,9 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
10851088
* careful to maintain AND/OR flatness --- that is, do not generate a tree
10861089
* with AND directly under AND, nor OR directly under OR.
10871090
*/
1088-
expr = eval_const_expressions(root, expr);
1091+
if (!(kind == EXPRKIND_RTFUNC ||
1092+
(kind == EXPRKIND_RTFUNC_LATERAL && !root->hasJoinRTEs)))
1093+
expr = eval_const_expressions(root, expr);
10891094

10901095
/*
10911096
* If it's a qual or havingQual, canonicalize it.

0 commit comments

Comments
 (0)