diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2010-08-19 18:58:11 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2010-08-19 18:58:11 +0000 |
commit | affcd50e4090a420fb235b11af007ca3f9ccf967 (patch) | |
tree | e1f6543fc8dc3b9b703ee3a861033543d7c34047 | |
parent | a1bde80db45fe9f123abb2a493b9dfcb755d427d (diff) | |
download | postgresql-affcd50e4090a420fb235b11af007ca3f9ccf967.tar.gz postgresql-affcd50e4090a420fb235b11af007ca3f9ccf967.zip |
Allow USING and INTO clauses of plpgsql's EXECUTE to appear in either order.
Aside from being more forgiving, this prevents a rather surprising misbehavior
when the "wrong" order was used: the old code didn't throw a syntax error,
but absorbed the INTO clause into the last USING expression, which then did
strange things downstream.
Intentionally not changing the documentation; we'll continue to advertise
only the "standard" clause order.
Backpatch to 8.4, where the USING clause was added to EXECUTE.
-rw-r--r-- | src/pl/plpgsql/src/gram.y | 53 |
1 files changed, 34 insertions, 19 deletions
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 90369ead08f..4215def73e9 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.125 2009/06/18 10:22:09 petere Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.125.2.1 2010/08/19 18:58:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1525,26 +1525,41 @@ stmt_dynexecute : K_EXECUTE lno new->row = NULL; new->params = NIL; - /* If we found "INTO", collect the argument */ - if (endtoken == K_INTO) - { - new->into = true; - read_into_target(&new->rec, &new->row, &new->strict); - endtoken = yylex(); - if (endtoken != ';' && endtoken != K_USING) - yyerror("syntax error"); - } - - /* If we found "USING", collect the argument(s) */ - if (endtoken == K_USING) + /* + * We loop to allow the INTO and USING clauses to + * appear in either order, since people easily get + * that wrong. This coding also prevents "INTO foo" + * from getting absorbed into a USING expression, + * which is *really* confusing. + */ + for (;;) { - do + if (endtoken == K_INTO) + { + if (new->into) /* multiple INTO */ + yyerror("syntax error"); + new->into = true; + read_into_target(&new->rec, &new->row, &new->strict); + endtoken = yylex(); + } + else if (endtoken == K_USING) { - expr = read_sql_expression2(',', ';', - ", or ;", - &endtoken); - new->params = lappend(new->params, expr); - } while (endtoken == ','); + if (new->params) /* multiple USING */ + yyerror("syntax error"); + do + { + expr = read_sql_construct(',', ';', K_INTO, + ", or ; or INTO", + "SELECT ", + true, true, + &endtoken); + new->params = lappend(new->params, expr); + } while (endtoken == ','); + } + else if (endtoken == ';') + break; + else + yyerror("syntax error"); } $$ = (PLpgSQL_stmt *)new; |