From 9676b01028139ca399f2564f6c4cb40fffe2ec07 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 19 Aug 2010 18:57:57 +0000 Subject: [PATCH] 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. --- src/pl/plpgsql/src/gram.y | 53 +++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index 3a78fe69c7..2abc4aa8a7 100644 --- a/src/pl/plpgsql/src/gram.y +++ b/src/pl/plpgsql/src/gram.y @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.143 2010/06/25 16:40:13 tgl Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.144 2010/08/19 18:57:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1642,26 +1642,41 @@ stmt_dynexecute : K_EXECUTE 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, + NULL, &endtoken); + new->params = lappend(new->params, expr); + } while (endtoken == ','); + } + else if (endtoken == ';') + break; + else + yyerror("syntax error"); } $$ = (PLpgSQL_stmt *)new; -- 2.40.0