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 <da...@fetter.org> http://fetter.org/
Phone: +1 415 235 3778  AIM: dfetter666  Yahoo!: dfetter
Skype: davidfetter      XMPP: david.fet...@gmail.com
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 (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to