Skip to content

Commit c401a5c

Browse files
committed
Fix plpgsql to not treat INSERT INTO as an INTO-variables clause anywhere
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.)
1 parent 775f1b3 commit c401a5c

File tree

1 file changed

+23
-21
lines changed

1 file changed

+23
-21
lines changed

src/pl/plpgsql/src/gram.y

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.119 2009/01/07 13:44:37 tgl Exp $
12+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.120 2009/02/02 20:25:38 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -149,7 +149,7 @@ static List *read_raise_options(void);
149149
%type <loop_body> loop_body
150150
%type <stmt> proc_stmt pl_block
151151
%type <stmt> stmt_assign stmt_if stmt_loop stmt_while stmt_exit
152-
%type <stmt> stmt_return stmt_raise stmt_execsql stmt_execsql_insert
152+
%type <stmt> stmt_return stmt_raise stmt_execsql
153153
%type <stmt> stmt_dynexecute stmt_for stmt_perform stmt_getdiag
154154
%type <stmt> stmt_open stmt_fetch stmt_move stmt_close stmt_null
155155
%type <stmt> stmt_case
@@ -646,8 +646,6 @@ proc_stmt : pl_block ';'
646646
{ $$ = $1; }
647647
| stmt_execsql
648648
{ $$ = $1; }
649-
| stmt_execsql_insert
650-
{ $$ = $1; }
651649
| stmt_dynexecute
652650
{ $$ = $1; }
653651
| stmt_perform
@@ -1482,27 +1480,15 @@ stmt_execsql : execsql_start lno
14821480
}
14831481
;
14841482

1485-
/* this matches any otherwise-unrecognized starting keyword */
1486-
execsql_start : T_WORD
1483+
/* T_WORD+T_ERROR match any otherwise-unrecognized starting keyword */
1484+
execsql_start : K_INSERT
1485+
{ $$ = pstrdup(yytext); }
1486+
| T_WORD
14871487
{ $$ = pstrdup(yytext); }
14881488
| T_ERROR
14891489
{ $$ = pstrdup(yytext); }
14901490
;
14911491

1492-
stmt_execsql_insert : K_INSERT lno K_INTO
1493-
{
1494-
/*
1495-
* We have to special-case INSERT so that its INTO
1496-
* won't be treated as an INTO-variables clause.
1497-
*
1498-
* Fortunately, this is the only valid use of INTO
1499-
* in a pl/pgsql SQL command, and INTO is already
1500-
* a fully reserved word in the main grammar.
1501-
*/
1502-
$$ = make_execsql_stmt("INSERT INTO", $2);
1503-
}
1504-
;
1505-
15061492
stmt_dynexecute : K_EXECUTE lno
15071493
{
15081494
PLpgSQL_stmt_dynexecute *new;
@@ -2156,20 +2142,36 @@ make_execsql_stmt(const char *sqlstart, int lineno)
21562142
PLpgSQL_row *row = NULL;
21572143
PLpgSQL_rec *rec = NULL;
21582144
int tok;
2145+
int prev_tok;
21592146
bool have_into = false;
21602147
bool have_strict = false;
21612148

21622149
plpgsql_dstring_init(&ds);
21632150
plpgsql_dstring_append(&ds, sqlstart);
21642151

2152+
/*
2153+
* We have to special-case the sequence INSERT INTO, because we don't want
2154+
* that to be taken as an INTO-variables clause. Fortunately, this is the
2155+
* only valid use of INTO in a pl/pgsql SQL command, and INTO is already a
2156+
* fully reserved word in the main grammar. We have to treat it that way
2157+
* anywhere in the string, not only at the start; consider CREATE RULE
2158+
* containing an INSERT statement.
2159+
*/
2160+
if (pg_strcasecmp(sqlstart, "insert") == 0)
2161+
tok = K_INSERT;
2162+
else
2163+
tok = 0;
2164+
21652165
for (;;)
21662166
{
2167+
prev_tok = tok;
21672168
tok = yylex();
21682169
if (tok == ';')
21692170
break;
21702171
if (tok == 0)
21712172
yyerror("unexpected end of function definition");
2172-
if (tok == K_INTO)
2173+
2174+
if (tok == K_INTO && prev_tok != K_INSERT)
21732175
{
21742176
if (have_into)
21752177
yyerror("INTO specified more than once");

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy