* yytxt is the original token text; we need this to check for quoting,
* so that later checks for unreserved keywords work properly.
*
+ * We attempt to recognize the token as a variable only if lookup is true
+ * and the plpgsql_IdentifierLookup context permits it.
+ *
* If recognized as a variable, fill in *wdatum and return true;
* if not recognized, fill in *word and return false.
* (Note: those two pointers actually point to members of the same union,
* ----------
*/
bool
-plpgsql_parse_word(char *word1, const char *yytxt,
+plpgsql_parse_word(char *word1, const char *yytxt, bool lookup,
PLwdatum *wdatum, PLword *word)
{
PLpgSQL_nsitem *ns;
/*
- * We should do nothing in DECLARE sections. In SQL expressions, there's
- * no need to do anything either --- lookup will happen when the
- * expression is compiled.
+ * We should not lookup variables in DECLARE sections. In SQL
+ * expressions, there's no need to do so either --- lookup will happen
+ * when the expression is compiled.
*/
- if (plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
+ if (lookup && plpgsql_IdentifierLookup == IDENTIFIER_LOOKUP_NORMAL)
{
/*
* Do a lookup in the current namespace stack
push_back_token(tok2, &aux2);
if (plpgsql_parse_word(aux1.lval.str,
core_yy.scanbuf + aux1.lloc,
+ true,
&aux1.lval.wdatum,
&aux1.lval.word))
tok1 = T_DATUM;
push_back_token(tok2, &aux2);
/*
- * If we are at start of statement, prefer unreserved keywords
- * over variable names, unless the next token is assignment or
- * '[', in which case prefer variable names. (Note we need not
- * consider '.' as the next token; that case was handled above,
- * and we always prefer variable names in that case.) If we are
- * not at start of statement, always prefer variable names over
- * unreserved keywords.
+ * See if it matches a variable name, except in the context where
+ * we are at start of statement and the next token isn't
+ * assignment or '['. In that case, it couldn't validly be a
+ * variable name, and skipping the lookup allows variable names to
+ * be used that would conflict with plpgsql or core keywords that
+ * introduce statements (e.g., "comment"). Without this special
+ * logic, every statement-introducing keyword would effectively be
+ * reserved in PL/pgSQL, which would be unpleasant.
+ *
+ * If it isn't a variable name, try to match against unreserved
+ * plpgsql keywords. If not one of those either, it's T_WORD.
+ *
+ * Note: we must call plpgsql_parse_word even if we don't want to
+ * do variable lookup, because it sets up aux1.lval.word for the
+ * non-variable cases.
*/
- if (AT_STMT_START(plpgsql_yytoken) &&
- !(tok2 == '=' || tok2 == COLON_EQUALS || tok2 == '['))
+ if (plpgsql_parse_word(aux1.lval.str,
+ core_yy.scanbuf + aux1.lloc,
+ (!AT_STMT_START(plpgsql_yytoken) ||
+ (tok2 == '=' || tok2 == COLON_EQUALS ||
+ tok2 == '[')),
+ &aux1.lval.wdatum,
+ &aux1.lval.word))
+ tok1 = T_DATUM;
+ else if (!aux1.lval.word.quoted &&
+ (kw = ScanKeywordLookup(aux1.lval.word.ident,
+ unreserved_keywords,
+ num_unreserved_keywords)))
{
- /* try for unreserved keyword, then for variable name */
- if (core_yy.scanbuf[aux1.lloc] != '"' &&
- (kw = ScanKeywordLookup(aux1.lval.str,
- unreserved_keywords,
- num_unreserved_keywords)))
- {
- aux1.lval.keyword = kw->name;
- tok1 = kw->value;
- }
- else if (plpgsql_parse_word(aux1.lval.str,
- core_yy.scanbuf + aux1.lloc,
- &aux1.lval.wdatum,
- &aux1.lval.word))
- tok1 = T_DATUM;
- else
- tok1 = T_WORD;
+ aux1.lval.keyword = kw->name;
+ tok1 = kw->value;
}
else
- {
- /* try for variable name, then for unreserved keyword */
- if (plpgsql_parse_word(aux1.lval.str,
- core_yy.scanbuf + aux1.lloc,
- &aux1.lval.wdatum,
- &aux1.lval.word))
- tok1 = T_DATUM;
- else if (!aux1.lval.word.quoted &&
- (kw = ScanKeywordLookup(aux1.lval.word.ident,
- unreserved_keywords,
- num_unreserved_keywords)))
- {
- aux1.lval.keyword = kw->name;
- tok1 = kw->value;
- }
- else
- tok1 = T_WORD;
- }
+ tok1 = T_WORD;
}
}
else
extern PLpgSQL_function *plpgsql_compile_inline(char *proc_source);
extern void plpgsql_parser_setup(struct ParseState *pstate,
PLpgSQL_expr *expr);
-extern bool plpgsql_parse_word(char *word1, const char *yytxt,
+extern bool plpgsql_parse_word(char *word1, const char *yytxt, bool lookup,
PLwdatum *wdatum, PLword *word);
extern bool plpgsql_parse_dblword(char *word1, char *word2,
PLwdatum *wdatum, PLcword *cword);