*** a/src/backend/parser/gram.y --- b/src/backend/parser/gram.y *************** *** 9391,9397 **** table_ref: relation_expr opt_alias_clause | func_table func_alias_clause { RangeFunction *n = makeNode(RangeFunction); ! n->lateral = false; n->funccallnode = $1; n->alias = linitial($2); n->coldeflist = lsecond($2); --- 9391,9397 ---- | func_table func_alias_clause { RangeFunction *n = makeNode(RangeFunction); ! n->lateral = true; n->funccallnode = $1; n->alias = linitial($2); n->coldeflist = lsecond($2); *** a/src/backend/utils/adt/ruleutils.c --- b/src/backend/utils/adt/ruleutils.c *************** *** 7928,7934 **** get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) deparse_columns *colinfo = deparse_columns_fetch(varno, dpns); bool printalias; ! if (rte->lateral) appendStringInfoString(buf, "LATERAL "); /* Print the FROM item proper */ --- 7928,7934 ---- deparse_columns *colinfo = deparse_columns_fetch(varno, dpns); bool printalias; ! if (rte->lateral && rte->rtekind != RTE_FUNCTION) appendStringInfoString(buf, "LATERAL "); /* Print the FROM item proper */ *** a/src/test/regress/expected/join.out --- b/src/test/regress/expected/join.out *************** *** 3577,3603 **** select * from Output: (COALESCE((COALESCE(b.q2, 42::bigint)), d.q2)) (26 rows) - -- test some error cases where LATERAL should have been used but wasn't - select f1,g from int4_tbl a, generate_series(0, f1) g; - ERROR: column "f1" does not exist - LINE 1: select f1,g from int4_tbl a, generate_series(0, f1) g; - ^ - HINT: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. - select f1,g from int4_tbl a, generate_series(0, a.f1) g; - ERROR: invalid reference to FROM-clause entry for table "a" - LINE 1: select f1,g from int4_tbl a, generate_series(0, a.f1) g; - ^ - HINT: There is an entry for table "a", but it cannot be referenced from this part of the query. - select f1,g from int4_tbl a cross join generate_series(0, f1) g; - ERROR: column "f1" does not exist - LINE 1: ...ct f1,g from int4_tbl a cross join generate_series(0, f1) g; - ^ - HINT: There is a column named "f1" in table "a", but it cannot be referenced from this part of the query. - select f1,g from int4_tbl a cross join generate_series(0, a.f1) g; - ERROR: invalid reference to FROM-clause entry for table "a" - LINE 1: ... f1,g from int4_tbl a cross join generate_series(0, a.f1) g; - ^ - HINT: There is an entry for table "a", but it cannot be referenced from this part of the query. -- SQL:2008 says the left table is in scope but illegal to access here select f1,g from int4_tbl a right join lateral generate_series(0, a.f1) g on true; ERROR: invalid reference to FROM-clause entry for table "a" --- 3577,3582 ---- *** a/src/test/regress/expected/rangefuncs.out --- b/src/test/regress/expected/rangefuncs.out *************** *** 21,30 **** INSERT INTO foo2 VALUES(1, 111); CREATE FUNCTION foot(int) returns setof foo2 as 'SELECT * FROM foo2 WHERE fooid = $1;' LANGUAGE SQL; -- supposed to fail with ERROR select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2; ! ERROR: invalid reference to FROM-clause entry for table "foo2" ! LINE 1: select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2; ! ^ ! HINT: There is an entry for table "foo2", but it cannot be referenced from this part of the query. -- function in subselect select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = foo2.fooid) ORDER BY 1,2; fooid | f2 --- 21,33 ---- CREATE FUNCTION foot(int) returns setof foo2 as 'SELECT * FROM foo2 WHERE fooid = $1;' LANGUAGE SQL; -- supposed to fail with ERROR select * from foo2, foot(foo2.fooid) z where foo2.f2 = z.f2; ! fooid | f2 | fooid | f2 ! -------+-----+-------+----- ! 1 | 11 | 1 | 11 ! 2 | 22 | 2 | 22 ! 1 | 111 | 1 | 111 ! (3 rows) ! -- function in subselect select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = foo2.fooid) ORDER BY 1,2; fooid | f2 *** a/src/test/regress/sql/join.sql --- b/src/test/regress/sql/join.sql *************** *** 986,996 **** select * from ) on c.q2 = ss2.q1, lateral (select ss2.y) ss3; - -- test some error cases where LATERAL should have been used but wasn't - select f1,g from int4_tbl a, generate_series(0, f1) g; - select f1,g from int4_tbl a, generate_series(0, a.f1) g; - select f1,g from int4_tbl a cross join generate_series(0, f1) g; - select f1,g from int4_tbl a cross join generate_series(0, a.f1) g; -- SQL:2008 says the left table is in scope but illegal to access here select f1,g from int4_tbl a right join lateral generate_series(0, a.f1) g on true; select f1,g from int4_tbl a full join lateral generate_series(0, a.f1) g on true; --- 986,991 ----