Commit bac95fd4 authored by Tom Lane's avatar Tom Lane

Make plpgsql's unreserved keywords more unreserved.

There were assorted places where unreserved keywords were not treated the
same as T_WORD (that is, a random unrecognized identifier).  Fix them.
It might not always be possible to allow this, but it is in all these
places, so I don't see any downside.

Per gripe from Jim Wilson.  Arguably this is a bug fix, but given the lack
of other complaints and the ease of working around it (just quote the
word), I won't risk back-patching.
parent fc68ac86
...@@ -642,6 +642,21 @@ decl_aliasitem : T_WORD ...@@ -642,6 +642,21 @@ decl_aliasitem : T_WORD
parser_errposition(@1))); parser_errposition(@1)));
$$ = nsi; $$ = nsi;
} }
| unreserved_keyword
{
PLpgSQL_nsitem *nsi;
nsi = plpgsql_ns_lookup(plpgsql_ns_top(), false,
$1, NULL, NULL,
NULL);
if (nsi == NULL)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("variable \"%s\" does not exist",
$1),
parser_errposition(@1)));
$$ = nsi;
}
| T_CWORD | T_CWORD
{ {
PLpgSQL_nsitem *nsi; PLpgSQL_nsitem *nsi;
...@@ -722,6 +737,11 @@ decl_collate : ...@@ -722,6 +737,11 @@ decl_collate :
$$ = get_collation_oid(list_make1(makeString($2.ident)), $$ = get_collation_oid(list_make1(makeString($2.ident)),
false); false);
} }
| K_COLLATE unreserved_keyword
{
$$ = get_collation_oid(list_make1(makeString(pstrdup($2))),
false);
}
| K_COLLATE T_CWORD | K_COLLATE T_CWORD
{ {
$$ = get_collation_oid($2.idents, false); $$ = get_collation_oid($2.idents, false);
...@@ -1720,9 +1740,12 @@ stmt_raise : K_RAISE ...@@ -1720,9 +1740,12 @@ stmt_raise : K_RAISE
} }
else else
{ {
if (tok != T_WORD) if (tok == T_WORD)
yyerror("syntax error");
new->condname = yylval.word.ident; new->condname = yylval.word.ident;
else if (plpgsql_token_is_unreserved_keyword(tok))
new->condname = pstrdup(yylval.keyword);
else
yyerror("syntax error");
plpgsql_recognize_err_condition(new->condname, plpgsql_recognize_err_condition(new->condname,
false); false);
} }
...@@ -2185,12 +2208,16 @@ opt_exitcond : ';' ...@@ -2185,12 +2208,16 @@ opt_exitcond : ';'
; ;
/* /*
* need both options because scanner will have tried to resolve as variable * need to allow DATUM because scanner will have tried to resolve as variable
*/ */
any_identifier : T_WORD any_identifier : T_WORD
{ {
$$ = $1.ident; $$ = $1.ident;
} }
| unreserved_keyword
{
$$ = pstrdup($1);
}
| T_DATUM | T_DATUM
{ {
if ($1.ident == NULL) /* composite name not OK */ if ($1.ident == NULL) /* composite name not OK */
...@@ -2513,6 +2540,30 @@ read_datatype(int tok) ...@@ -2513,6 +2540,30 @@ read_datatype(int tok)
} }
} }
} }
else if (plpgsql_token_is_unreserved_keyword(tok))
{
char *dtname = pstrdup(yylval.keyword);
tok = yylex();
if (tok == '%')
{
tok = yylex();
if (tok_is_keyword(tok, &yylval,
K_TYPE, "type"))
{
result = plpgsql_parse_wordtype(dtname);
if (result)
return result;
}
else if (tok_is_keyword(tok, &yylval,
K_ROWTYPE, "rowtype"))
{
result = plpgsql_parse_wordrowtype(dtname);
if (result)
return result;
}
}
}
else if (tok == T_CWORD) else if (tok == T_CWORD)
{ {
List *dtnames = yylval.cword.idents; List *dtnames = yylval.cword.idents;
......
...@@ -410,6 +410,25 @@ plpgsql_push_back_token(int token) ...@@ -410,6 +410,25 @@ plpgsql_push_back_token(int token)
push_back_token(token, &auxdata); push_back_token(token, &auxdata);
} }
/*
* Tell whether a token is an unreserved keyword.
*
* (If it is, its lowercased form was returned as the token value, so we
* do not need to offer that data here.)
*/
bool
plpgsql_token_is_unreserved_keyword(int token)
{
int i;
for (i = 0; i < num_unreserved_keywords; i++)
{
if (unreserved_keywords[i].value == token)
return true;
}
return false;
}
/* /*
* Append the function text starting at startlocation and extending to * Append the function text starting at startlocation and extending to
* (not including) endlocation onto the existing contents of "buf". * (not including) endlocation onto the existing contents of "buf".
......
...@@ -973,6 +973,7 @@ extern void plpgsql_dumptree(PLpgSQL_function *func); ...@@ -973,6 +973,7 @@ extern void plpgsql_dumptree(PLpgSQL_function *func);
extern int plpgsql_base_yylex(void); extern int plpgsql_base_yylex(void);
extern int plpgsql_yylex(void); extern int plpgsql_yylex(void);
extern void plpgsql_push_back_token(int token); extern void plpgsql_push_back_token(int token);
extern bool plpgsql_token_is_unreserved_keyword(int token);
extern void plpgsql_append_source_text(StringInfo buf, extern void plpgsql_append_source_text(StringInfo buf,
int startlocation, int endlocation); int startlocation, int endlocation);
extern void plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc, extern void plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment