@@ -286,6 +286,7 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt);
286286%token <keyword> K_GET
287287%token <keyword> K_HINT
288288%token <keyword> K_IF
289+ %token <keyword> K_IMPORT
289290%token <keyword> K_IN
290291%token <keyword> K_INFO
291292%token <keyword> K_INSERT
@@ -1891,7 +1892,11 @@ loop_body : proc_sect K_END K_LOOP opt_label ';'
18911892 * assignment. Give an appropriate complaint for that, instead of letting
18921893 * the core parser throw an unhelpful "syntax error".
18931894 */
1894- stmt_execsql : K_INSERT
1895+ stmt_execsql : K_IMPORT
1896+ {
1897+ $$ = make_execsql_stmt (K_IMPORT, @1 );
1898+ }
1899+ | K_INSERT
18951900 {
18961901 $$ = make_execsql_stmt (K_INSERT, @1 );
18971902 }
@@ -2369,6 +2374,7 @@ unreserved_keyword :
23692374 | K_FORWARD
23702375 | K_GET
23712376 | K_HINT
2377+ | K_IMPORT
23722378 | K_INFO
23732379 | K_INSERT
23742380 | K_IS
@@ -2794,12 +2800,32 @@ make_execsql_stmt(int firsttoken, int location)
27942800 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
27952801
27962802 /*
2797- * We have to special-case the sequence INSERT INTO, because we don't want
2798- * that to be taken as an INTO-variables clause. Fortunately, this is the
2799- * only valid use of INTO in a pl/pgsql SQL command, and INTO is already a
2800- * fully reserved word in the main grammar. We have to treat it that way
2801- * anywhere in the string, not only at the start; consider CREATE RULE
2802- * containing an INSERT statement.
2803+ * Scan to the end of the SQL command. Identify any INTO-variables
2804+ * clause lurking within it, and parse that via read_into_target().
2805+ *
2806+ * Because INTO is sometimes used in the main SQL grammar, we have to be
2807+ * careful not to take any such usage of INTO as a pl/pgsql INTO clause.
2808+ * There are currently three such cases:
2809+ *
2810+ * 1. SELECT ... INTO. We don't care, we just override that with the
2811+ * pl/pgsql definition.
2812+ *
2813+ * 2. INSERT INTO. This is relatively easy to recognize since the words
2814+ * must appear adjacently; but we can't assume INSERT starts the command,
2815+ * because it can appear in CREATE RULE or WITH. Unfortunately, INSERT is
2816+ * *not* fully reserved, so that means there is a chance of a false match;
2817+ * but it's not very likely.
2818+ *
2819+ * 3. IMPORT FOREIGN SCHEMA ... INTO. This is not allowed in CREATE RULE
2820+ * or WITH, so we just check for IMPORT as the command's first token.
2821+ * (If IMPORT FOREIGN SCHEMA returned data someone might wish to capture
2822+ * with an INTO-variables clause, we'd have to work much harder here.)
2823+ *
2824+ * Fortunately, INTO is a fully reserved word in the main grammar, so
2825+ * at least we need not worry about it appearing as an identifier.
2826+ *
2827+ * Any future additional uses of INTO in the main grammar will doubtless
2828+ * break this logic again ... beware!
28032829 */
28042830 tok = firsttoken;
28052831 for (;;)
@@ -2812,9 +2838,12 @@ make_execsql_stmt(int firsttoken, int location)
28122838 break;
28132839 if (tok == 0)
28142840 yyerror("unexpected end of function definition");
2815-
2816- if (tok == K_INTO && prev_tok != K_INSERT)
2841+ if (tok == K_INTO)
28172842 {
2843+ if (prev_tok == K_INSERT)
2844+ continue; /* INSERT INTO is not an INTO-target */
2845+ if (firsttoken == K_IMPORT)
2846+ continue; /* IMPORT ... INTO is not an INTO-target */
28182847 if (have_into)
28192848 yyerror("INTO specified more than once");
28202849 have_into = true;
0 commit comments