@@ -287,6 +287,7 @@ static void check_raise_parameters(PLpgSQL_stmt_raise *stmt);
287287%token <keyword> K_GET
288288%token <keyword> K_HINT
289289%token <keyword> K_IF
290+ %token <keyword> K_IMPORT
290291%token <keyword> K_IN
291292%token <keyword> K_INFO
292293%token <keyword> K_INSERT
@@ -1929,7 +1930,11 @@ loop_body : proc_sect K_END K_LOOP opt_label ';'
19291930 * assignment. Give an appropriate complaint for that, instead of letting
19301931 * the core parser throw an unhelpful "syntax error".
19311932 */
1932- stmt_execsql : K_INSERT
1933+ stmt_execsql : K_IMPORT
1934+ {
1935+ $$ = make_execsql_stmt (K_IMPORT, @1 );
1936+ }
1937+ | K_INSERT
19331938 {
19341939 $$ = make_execsql_stmt (K_INSERT, @1 );
19351940 }
@@ -2418,6 +2423,7 @@ unreserved_keyword :
24182423 | K_FORWARD
24192424 | K_GET
24202425 | K_HINT
2426+ | K_IMPORT
24212427 | K_INFO
24222428 | K_INSERT
24232429 | K_IS
@@ -2843,12 +2849,32 @@ make_execsql_stmt(int firsttoken, int location)
28432849 plpgsql_IdentifierLookup = IDENTIFIER_LOOKUP_EXPR;
28442850
28452851 /*
2846- * We have to special-case the sequence INSERT INTO, because we don't want
2847- * that to be taken as an INTO-variables clause. Fortunately, this is the
2848- * only valid use of INTO in a pl/pgsql SQL command, and INTO is already a
2849- * fully reserved word in the main grammar. We have to treat it that way
2850- * anywhere in the string, not only at the start; consider CREATE RULE
2851- * containing an INSERT statement.
2852+ * Scan to the end of the SQL command. Identify any INTO-variables
2853+ * clause lurking within it, and parse that via read_into_target().
2854+ *
2855+ * Because INTO is sometimes used in the main SQL grammar, we have to be
2856+ * careful not to take any such usage of INTO as a pl/pgsql INTO clause.
2857+ * There are currently three such cases:
2858+ *
2859+ * 1. SELECT ... INTO. We don't care, we just override that with the
2860+ * pl/pgsql definition.
2861+ *
2862+ * 2. INSERT INTO. This is relatively easy to recognize since the words
2863+ * must appear adjacently; but we can't assume INSERT starts the command,
2864+ * because it can appear in CREATE RULE or WITH. Unfortunately, INSERT is
2865+ * *not* fully reserved, so that means there is a chance of a false match;
2866+ * but it's not very likely.
2867+ *
2868+ * 3. IMPORT FOREIGN SCHEMA ... INTO. This is not allowed in CREATE RULE
2869+ * or WITH, so we just check for IMPORT as the command's first token.
2870+ * (If IMPORT FOREIGN SCHEMA returned data someone might wish to capture
2871+ * with an INTO-variables clause, we'd have to work much harder here.)
2872+ *
2873+ * Fortunately, INTO is a fully reserved word in the main grammar, so
2874+ * at least we need not worry about it appearing as an identifier.
2875+ *
2876+ * Any future additional uses of INTO in the main grammar will doubtless
2877+ * break this logic again ... beware!
28522878 */
28532879 tok = firsttoken;
28542880 for (;;)
@@ -2861,9 +2887,12 @@ make_execsql_stmt(int firsttoken, int location)
28612887 break;
28622888 if (tok == 0)
28632889 yyerror("unexpected end of function definition");
2864-
2865- if (tok == K_INTO && prev_tok != K_INSERT)
2890+ if (tok == K_INTO)
28662891 {
2892+ if (prev_tok == K_INSERT)
2893+ continue; /* INSERT INTO is not an INTO-target */
2894+ if (firsttoken == K_IMPORT)
2895+ continue; /* IMPORT ... INTO is not an INTO-target */
28672896 if (have_into)
28682897 yyerror("INTO specified more than once");
28692898 have_into = true;
0 commit comments