Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)