*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.138 2010/01/10 17:15:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/pl/plpgsql/src/gram.y,v 1.139 2010/01/10 17:56:50 tgl Exp $
*
*-------------------------------------------------------------------------
*/
static bool tok_is_keyword(int token, union YYSTYPE *lval,
int kw_token, const char *kw_str);
-static void token_is_not_variable(int tok);
+static void word_is_not_variable(PLword *word, int location);
+static void cword_is_not_variable(PLcword *cword, int location);
+static void current_token_is_not_variable(int tok);
static PLpgSQL_expr *read_sql_construct(int until,
int until2,
int until3,
| T_WORD
{
/* just to give a better message than "syntax error" */
- token_is_not_variable(T_WORD);
+ word_is_not_variable(&($1), @1);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
- token_is_not_variable(T_CWORD);
+ cword_is_not_variable(&($1), @1);
}
;
tok = yylex();
plpgsql_push_back_token(tok);
if (tok == ',')
- {
- /* can't use token_is_not_variable here */
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("\"%s\" is not a known variable",
- $1.ident),
- parser_errposition(@1)));
- }
+ word_is_not_variable(&($1), @1);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
- token_is_not_variable(T_CWORD);
+ cword_is_not_variable(&($1), @1);
}
;
/*
* T_WORD+T_CWORD match any initial identifier that is not a known plpgsql
- * variable. The composite case is probably a syntax error, but we'll let
- * the core parser decide that.
+ * variable. (The composite case is probably a syntax error, but we'll let
+ * the core parser decide that.) Normally, we should assume that such a
+ * word is a SQL statement keyword that isn't also a plpgsql keyword.
+ * However, if the next token is assignment or '[', it can't be a valid
+ * SQL statement, and what we're probably looking at is an intended variable
+ * assignment. Give an appropriate complaint for that, instead of letting
+ * the core parser throw an unhelpful "syntax error".
*/
stmt_execsql : K_INSERT
- { $$ = make_execsql_stmt(K_INSERT, @1); }
+ {
+ $$ = make_execsql_stmt(K_INSERT, @1);
+ }
| T_WORD
- { $$ = make_execsql_stmt(T_WORD, @1); }
+ {
+ int tok;
+
+ tok = yylex();
+ plpgsql_push_back_token(tok);
+ if (tok == '=' || tok == COLON_EQUALS || tok == '[')
+ word_is_not_variable(&($1), @1);
+ $$ = make_execsql_stmt(T_WORD, @1);
+ }
| T_CWORD
- { $$ = make_execsql_stmt(T_CWORD, @1); }
+ {
+ int tok;
+
+ tok = yylex();
+ plpgsql_push_back_token(tok);
+ if (tok == '=' || tok == COLON_EQUALS || tok == '[')
+ cword_is_not_variable(&($1), @1);
+ $$ = make_execsql_stmt(T_CWORD, @1);
+ }
;
stmt_dynexecute : K_EXECUTE
| T_WORD
{
/* just to give a better message than "syntax error" */
- token_is_not_variable(T_WORD);
+ word_is_not_variable(&($1), @1);
}
| T_CWORD
{
/* just to give a better message than "syntax error" */
- token_is_not_variable(T_CWORD);
+ cword_is_not_variable(&($1), @1);
}
;
return false; /* not the keyword */
}
+/*
+ * Convenience routine to complain when we expected T_DATUM and got T_WORD,
+ * ie, unrecognized variable.
+ */
+static void
+word_is_not_variable(PLword *word, int location)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("\"%s\" is not a known variable",
+ word->ident),
+ parser_errposition(location)));
+}
+
+/* Same, for a CWORD */
+static void
+cword_is_not_variable(PLcword *cword, int location)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("\"%s\" is not a known variable",
+ NameListToString(cword->idents)),
+ parser_errposition(location)));
+}
+
/*
* Convenience routine to complain when we expected T_DATUM and got
* something else. "tok" must be the current token, since we also
* look at yylval and yylloc.
*/
static void
-token_is_not_variable(int tok)
+current_token_is_not_variable(int tok)
{
if (tok == T_WORD)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("\"%s\" is not a known variable",
- yylval.word.ident),
- parser_errposition(yylloc)));
+ word_is_not_variable(&(yylval.word), yylloc);
else if (tok == T_CWORD)
- ereport(ERROR,
- (errcode(ERRCODE_SYNTAX_ERROR),
- errmsg("\"%s\" is not a known variable",
- NameListToString(yylval.cword.idents)),
- parser_errposition(yylloc)));
+ cword_is_not_variable(&(yylval.cword), yylloc);
else
yyerror("syntax error");
}
default:
/* just to give a better message than "syntax error" */
- token_is_not_variable(tok);
+ current_token_is_not_variable(tok);
}
}
default:
/* just to give a better message than "syntax error" */
- token_is_not_variable(tok);
+ current_token_is_not_variable(tok);
}
}