On Thu, Jan 24, 2013 at 09:12:41PM -0800, David Fetter wrote:
> On Thu, Jan 24, 2013 at 09:51:46AM -0800, David Fetter wrote:
> > Folks,
> >
> > Andrew Gierth asked me to send this out as his email is in a parlous
> > state at the moment. My comments will follow in replies. Without
> > further ado:
> > [snip]
> >
> > As I see it, the current options are:
> >
> > 1. Do nothing, and insist on non-standard use of the LATERAL keyword.
> >
> > 2. Add UNNEST to the grammar (or parse analysis) as a special case, making
> > it implicitly LATERAL.
> >
> > (This would make implementing S301 easier, but special cases are ugly.)
> >
> > 3. Make all cases of SRFs in the FROM-clause implicitly LATERAL.
> >
> > (As far as I can tell, those cases whose behaviour would be changed by
> > this actually produce errors in versions prior to 9.3, so no working
> > code should be affected.)
> >
> > Since LATERAL is new in 9.3, I think the pros and cons of these choices
> > should be considered now, rather than being allowed to slide by unexamined.
>
> Please find attached a patch which implements approach 3. The vast
> majority of it is changes to the regression tests. The removed
> regression tests in join.{sql,out} are no longer errors, although some
> of them are pretty standard DoS attacks, hence they're all removed.
>
> Cheers,
> David.
Oops. Misspelled rtekind in the previous patch. Here's a corrected
one, much shorter.
Cheers,
David.
--
David Fetter <[email protected]> http://fetter.org/
Phone: +1 415 235 3778 AIM: dfetter666 Yahoo!: dfetter
Skype: davidfetter XMPP: [email protected]
iCal: webcal://www.tripit.com/feed/ical/people/david74/tripit.ics
Remember to vote!
Consider donating to Postgres: http://www.postgresql.org/about/donate
*** 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 ----
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers