/* 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);
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);
+ }
}
/*
/*
* 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);
/*
4567890123456789 | -4567890123456789 | 4567890123456789 | -4567890123456789 |
(57 rows)
+-- lateral reference to a join alias variable
+select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
+ lateral (select x) ss2(y);
+ x | f1 | y
+---+----+---
+ 0 | 0 | 0
+(1 row)
+
+select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
+ lateral (values(x)) ss2(y);
+ x | f1 | y
+-------------+-------------+-------------
+ 0 | 0 | 0
+ 123456 | 123456 | 123456
+ -123456 | -123456 | -123456
+ 2147483647 | 2147483647 | 2147483647
+ -2147483647 | -2147483647 | -2147483647
+(5 rows)
+
+select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j,
+ lateral (select x) ss2(y);
+ x | f1 | y
+---+----+---
+ 0 | 0 | 0
+(1 row)
+
-- lateral references requiring pullup
select * from (values(1)) x(lb),
lateral generate_series(lb,4) x4;
int8_tbl x left join lateral (select a.q1 from int4_tbl y) ss(z)
on x.q2 = ss.z;
+-- lateral reference to a join alias variable
+select * from (select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
+ lateral (select x) ss2(y);
+select * from (select f1 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1,
+ lateral (values(x)) ss2(y);
+select * from ((select f1/2 as x from int4_tbl) ss1 join int4_tbl i4 on x = f1) j,
+ lateral (select x) ss2(y);
+
-- lateral references requiring pullup
select * from (values(1)) x(lb),
lateral generate_series(lb,4) x4;