]> granicus.if.org Git - postgresql/commitdiff
Make plpgsql's unreserved keywords more unreserved.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 27 Sep 2012 02:27:36 +0000 (22:27 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 27 Sep 2012 02:27:36 +0000 (22:27 -0400)
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.

src/pl/plpgsql/src/gram.y
src/pl/plpgsql/src/pl_scanner.c
src/pl/plpgsql/src/plpgsql.h

index 4967a2a6a79eef7509790989fb3c7537a72750cc..9c3d254a0f7866374ead593362e7cd908247fbd2 100644 (file)
@@ -642,6 +642,21 @@ decl_aliasitem     : T_WORD
                                                                         parser_errposition(@1)));
                                                $$ = 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
                                        {
                                                PLpgSQL_nsitem *nsi;
@@ -722,6 +737,11 @@ decl_collate       :
                                                $$ = get_collation_oid(list_make1(makeString($2.ident)),
                                                                                           false);
                                        }
+                               | K_COLLATE unreserved_keyword
+                                       {
+                                               $$ = get_collation_oid(list_make1(makeString(pstrdup($2))),
+                                                                                          false);
+                                       }
                                | K_COLLATE T_CWORD
                                        {
                                                $$ = get_collation_oid($2.idents, false);
@@ -1720,9 +1740,12 @@ stmt_raise               : K_RAISE
                                                                }
                                                                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");
-                                                                       new->condname = yylval.word.ident;
                                                                        plpgsql_recognize_err_condition(new->condname,
                                                                                                                                        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
                                        {
                                                $$ = $1.ident;
                                        }
+                               | unreserved_keyword
+                                       {
+                                               $$ = pstrdup($1);
+                                       }
                                | T_DATUM
                                        {
                                                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)
        {
                List   *dtnames = yylval.cword.idents;
index ebce3fd860beaa06264a909cfa1844a01b0b060b..c78527c309a1936b2ebaa8736546f9b6635dfb35 100644 (file)
@@ -410,6 +410,25 @@ plpgsql_push_back_token(int token)
        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
  * (not including) endlocation onto the existing contents of "buf".
index dcf80743b88babc4b16fc5ca401b9dda7bb688ee..7ea696033bbfad22a5afe6dbbadc0dd8fbdac4b3 100644 (file)
@@ -973,6 +973,7 @@ extern void plpgsql_dumptree(PLpgSQL_function *func);
 extern int     plpgsql_base_yylex(void);
 extern int     plpgsql_yylex(void);
 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,
                                                   int startlocation, int endlocation);
 extern void plpgsql_peek2(int *tok1_p, int *tok2_p, int *tok1_loc,