mirror of
https://github.com/postgres/postgres.git
synced 2025-05-01 01:04:50 +03:00
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.
This commit is contained in:
parent
fc68ac86b1
commit
bac95fd474
@ -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 :
|
|||||||
$$ = 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
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (tok != T_WORD)
|
if (tok == T_WORD)
|
||||||
|
new->condname = yylval.word.ident;
|
||||||
|
else if (plpgsql_token_is_unreserved_keyword(tok))
|
||||||
|
new->condname = pstrdup(yylval.keyword);
|
||||||
|
else
|
||||||
yyerror("syntax error");
|
yyerror("syntax error");
|
||||||
new->condname = yylval.word.ident;
|
|
||||||
plpgsql_recognize_err_condition(new->condname,
|
plpgsql_recognize_err_condition(new->condname,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
@ -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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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)
|
|||||||
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);
|
|||||||
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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user