diff options
author | Tom Lane | 2009-02-02 20:25:43 +0000 |
---|---|---|
committer | Tom Lane | 2009-02-02 20:25:43 +0000 |
commit | 09406122347f04025b03bab3daa248a9004c1e4b (patch) | |
tree | c9ea319b16f1320d797bdfa60c73a1d0c2e744fe | |
parent | b1abb3340b02d77227d9419f424ef936d7cde1d8 (diff) |
Fix plpgsql to not treat INSERT INTO as an INTO-variables clause anywhereREL8_3_6
in the string, not just at the start. Per bug #4629 from Martin Blazek.
Back-patch to 8.2; prior versions don't have the problem, at least not in
the reported case, because they don't try to recognize INTO in non-SELECT
statements. (IOW, this is really fallout from the RETURNING patch.)
-rw-r--r-- | src/pl/plpgsql/src/gram.y | 44 |
1 files changed, 23 insertions, 21 deletions
diff --git a/src/pl/plpgsql/src/gram.y b/src/pl/plpgsql/src/gram.y index c9ffb8f18b6..02b8dbfb336 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.108 2008/01/01 19:46:00 momjian Exp $ + * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.108.2.1 2009/02/02 20:25:43 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -125,7 +125,7 @@ static void check_labels(const char *start_label, %type <loop_body> loop_body %type <stmt> proc_stmt pl_block %type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit -%type <stmt> stmt_return stmt_raise stmt_execsql stmt_execsql_insert +%type <stmt> stmt_return stmt_raise stmt_execsql %type <stmt> stmt_dynexecute stmt_for stmt_perform stmt_getdiag %type <stmt> stmt_open stmt_fetch stmt_move stmt_close stmt_null @@ -625,8 +625,6 @@ proc_stmt : pl_block ';' { $$ = $1; } | stmt_execsql { $$ = $1; } - | stmt_execsql_insert - { $$ = $1; } | stmt_dynexecute { $$ = $1; } | stmt_perform @@ -1280,27 +1278,15 @@ stmt_execsql : execsql_start lno } ; -/* this matches any otherwise-unrecognized starting keyword */ -execsql_start : T_WORD +/* T_WORD+T_ERROR match any otherwise-unrecognized starting keyword */ +execsql_start : K_INSERT + { $$ = pstrdup(yytext); } + | T_WORD { $$ = pstrdup(yytext); } | T_ERROR { $$ = pstrdup(yytext); } ; -stmt_execsql_insert : K_INSERT lno K_INTO - { - /* - * We have to special-case INSERT so that its INTO - * won't be treated as an INTO-variables clause. - * - * Fortunately, this is the only valid use of INTO - * in a pl/pgsql SQL command, and INTO is already - * a fully reserved word in the main grammar. - */ - $$ = make_execsql_stmt("INSERT INTO", $2); - } - ; - stmt_dynexecute : K_EXECUTE lno { PLpgSQL_stmt_dynexecute *new; @@ -1942,20 +1928,36 @@ make_execsql_stmt(const char *sqlstart, int lineno) PLpgSQL_row *row = NULL; PLpgSQL_rec *rec = NULL; int tok; + int prev_tok; bool have_into = false; bool have_strict = false; plpgsql_dstring_init(&ds); plpgsql_dstring_append(&ds, sqlstart); + /* + * We have to special-case the sequence INSERT INTO, because we don't want + * that to be taken as an INTO-variables clause. Fortunately, this is the + * only valid use of INTO in a pl/pgsql SQL command, and INTO is already a + * fully reserved word in the main grammar. We have to treat it that way + * anywhere in the string, not only at the start; consider CREATE RULE + * containing an INSERT statement. + */ + if (pg_strcasecmp(sqlstart, "insert") == 0) + tok = K_INSERT; + else + tok = 0; + for (;;) { + prev_tok = tok; tok = yylex(); if (tok == ';') break; if (tok == 0) yyerror("unexpected end of function definition"); - if (tok == K_INTO) + + if (tok == K_INTO && prev_tok != K_INSERT) { if (have_into) yyerror("INTO specified more than once"); |