|
9 | 9 | *
|
10 | 10 | *
|
11 | 11 | * 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 $ |
13 | 13 | *
|
14 | 14 | *-------------------------------------------------------------------------
|
15 | 15 | */
|
@@ -149,7 +149,7 @@ static List*read_raise_options(void);
|
149 | 149 | %type<loop_body>loop_body
|
150 | 150 | %type<stmt>proc_stmtpl_block
|
151 | 151 | %type<stmt>stmt_assignstmt_ifstmt_loopstmt_whilestmt_exit
|
152 |
| -%type<stmt>stmt_returnstmt_raisestmt_execsqlstmt_execsql_insert |
| 152 | +%type<stmt>stmt_returnstmt_raisestmt_execsql |
153 | 153 | %type<stmt>stmt_dynexecutestmt_forstmt_performstmt_getdiag
|
154 | 154 | %type<stmt>stmt_openstmt_fetchstmt_movestmt_closestmt_null
|
155 | 155 | %type<stmt>stmt_case
|
@@ -646,8 +646,6 @@ proc_stmt: pl_block ';'
|
646 | 646 | {$$ =$1; }
|
647 | 647 | |stmt_execsql
|
648 | 648 | {$$ =$1; }
|
649 |
| -|stmt_execsql_insert |
650 |
| -{$$ =$1; } |
651 | 649 | |stmt_dynexecute
|
652 | 650 | {$$ =$1; }
|
653 | 651 | |stmt_perform
|
@@ -1482,27 +1480,15 @@ stmt_execsql: execsql_start lno
|
1482 | 1480 | }
|
1483 | 1481 | ;
|
1484 | 1482 |
|
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 |
1487 | 1487 | {$$ = pstrdup(yytext); }
|
1488 | 1488 | |T_ERROR
|
1489 | 1489 | {$$ = pstrdup(yytext); }
|
1490 | 1490 | ;
|
1491 | 1491 |
|
1492 |
| -stmt_execsql_insert :K_INSERTlnoK_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 |
| - |
1506 | 1492 | stmt_dynexecute :K_EXECUTElno
|
1507 | 1493 | {
|
1508 | 1494 | PLpgSQL_stmt_dynexecute *new;
|
@@ -2156,20 +2142,36 @@ make_execsql_stmt(const char *sqlstart, int lineno)
|
2156 | 2142 | PLpgSQL_row*row =NULL;
|
2157 | 2143 | PLpgSQL_rec*rec =NULL;
|
2158 | 2144 | inttok;
|
| 2145 | +intprev_tok; |
2159 | 2146 | boolhave_into =false;
|
2160 | 2147 | boolhave_strict =false;
|
2161 | 2148 |
|
2162 | 2149 | plpgsql_dstring_init(&ds);
|
2163 | 2150 | plpgsql_dstring_append(&ds, sqlstart);
|
2164 | 2151 |
|
| 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 | + |
2165 | 2165 | for (;;)
|
2166 | 2166 | {
|
| 2167 | +prev_tok = tok; |
2167 | 2168 | tok =yylex();
|
2168 | 2169 | if (tok ==';')
|
2169 | 2170 | break;
|
2170 | 2171 | if (tok ==0)
|
2171 | 2172 | yyerror("unexpected end of function definition");
|
2172 |
| -if (tok == K_INTO) |
| 2173 | + |
| 2174 | +if (tok == K_INTO && prev_tok != K_INSERT) |
2173 | 2175 | {
|
2174 | 2176 | if (have_into)
|
2175 | 2177 | yyerror("INTO specified more than once");
|
|