aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c59
1 files changed, 41 insertions, 18 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 0540afaced0..4284eed47b9 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -49,13 +49,15 @@ planner_hook_type planner_hook = NULL;
/* Expression kind codes for preprocess_expression */
-#define EXPRKIND_QUAL 0
-#define EXPRKIND_TARGET 1
-#define EXPRKIND_RTFUNC 2
-#define EXPRKIND_VALUES 3
-#define EXPRKIND_LIMIT 4
-#define EXPRKIND_APPINFO 5
-#define EXPRKIND_PHV 6
+#define EXPRKIND_QUAL 0
+#define EXPRKIND_TARGET 1
+#define EXPRKIND_RTFUNC 2
+#define EXPRKIND_RTFUNC_LATERAL 3
+#define EXPRKIND_VALUES 4
+#define EXPRKIND_VALUES_LATERAL 5
+#define EXPRKIND_LIMIT 6
+#define EXPRKIND_APPINFO 7
+#define EXPRKIND_PHV 8
static Node *preprocess_expression(PlannerInfo *root, Node *expr, int kind);
@@ -438,18 +440,38 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
preprocess_expression(root, (Node *) root->append_rel_list,
EXPRKIND_APPINFO);
- /* Also need to preprocess expressions for function and values RTEs */
+ /* Also need to preprocess expressions within RTEs */
foreach(l, parse->rtable)
{
RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
+ int kind;
- if (rte->rtekind == RTE_FUNCTION)
- rte->funcexpr = preprocess_expression(root, rte->funcexpr,
- EXPRKIND_RTFUNC);
+ if (rte->rtekind == RTE_SUBQUERY)
+ {
+ /*
+ * We don't want to do all preprocessing yet on the subquery's
+ * expressions, since that will happen when we plan it. But if it
+ * contains any join aliases of our level, those have to get
+ * expanded now, because planning of the subquery won't do it.
+ * That's only possible if the subquery is LATERAL.
+ */
+ if (rte->lateral && root->hasJoinRTEs)
+ rte->subquery = (Query *)
+ flatten_join_alias_vars(root, (Node *) rte->subquery);
+ }
+ else if (rte->rtekind == RTE_FUNCTION)
+ {
+ /* Preprocess the function expression fully */
+ kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
+ rte->funcexpr = preprocess_expression(root, rte->funcexpr, kind);
+ }
else if (rte->rtekind == RTE_VALUES)
+ {
+ /* Preprocess the values lists fully */
+ kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
rte->values_lists = (List *)
- preprocess_expression(root, (Node *) rte->values_lists,
- EXPRKIND_VALUES);
+ preprocess_expression(root, (Node *) rte->values_lists, kind);
+ }
}
/*
@@ -593,12 +615,13 @@ preprocess_expression(PlannerInfo *root, Node *expr, int kind)
/*
* If the query has any join RTEs, replace join alias variables with
- * base-relation variables. We must do this before sublink processing,
- * else sublinks expanded out from join aliases wouldn't get processed. We
- * can skip it in VALUES lists, however, since they can't contain any Vars
- * at all.
+ * base-relation variables. We must do this before sublink processing,
+ * else sublinks expanded out from join aliases would not get processed.
+ * We can skip it in non-lateral RTE functions and VALUES lists, however,
+ * since they can't contain any Vars of the current query level.
*/
- if (root->hasJoinRTEs && kind != EXPRKIND_VALUES)
+ if (root->hasJoinRTEs &&
+ !(kind == EXPRKIND_RTFUNC || kind == EXPRKIND_VALUES))
expr = flatten_join_alias_vars(root, expr);
/*