Re: factorial function/phase out postfix operators? - Mailing list pgsql-hackers

From Tom Lane
Subject Re: factorial function/phase out postfix operators?
Date
Msg-id 28461.1589932031@sss.pgh.pa.us
Whole thread Raw
In response to Re: factorial function/phase out postfix operators?  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: factorial function/phase out postfix operators?
Re: factorial function/phase out postfix operators?
Re: factorial function/phase out postfix operators?
List pgsql-hackers
I wrote:
> However, we do have to have a benefit to show those people whose
> queries we break.  Hence my insistence on having a working AS fix
> (or some other benefit) before not after.

I experimented with this a bit more, and came up with the attached.
It's not a working patch, just a set of grammar changes that Bison
is happy with.  (Getting to a working patch would require fixing the
various build infrastructure that knows about the keyword classification,
which seems straightforward but tedious.)

As Robert theorized, it works to move a fairly-small number of unreserved
keywords into a new slightly-reserved category.  However, as the patch
stands, only the remaining fully-unreserved keywords can be used as bare
column labels.  I'd hoped to be able to also use col_name keywords in that
way (which'd make the set of legal bare column labels mostly the same as
ColId).  The col_name keywords that cause problems are, it appears,
only PRECISION, CHARACTER, and CHAR_P.  So in principle we could move
those three into yet another keyword category and then let the remaining
col_name keywords be included in BareColLabel.  I kind of think that
that's more complication than it's worth, though.

            regards, tom lane

diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a24b30f..0b034b6 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -542,13 +542,14 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <str>        Sconst comment_text notify_payload
 %type <str>        RoleId opt_boolean_or_string
 %type <list>    var_list
-%type <str>        ColId ColLabel var_name type_function_name param_name
+%type <str>        ColId ColLabel BareColLabel
 %type <str>        NonReservedWord NonReservedWord_or_Sconst
+%type <str>        var_name type_function_name param_name
 %type <str>        createdb_opt_name
 %type <node>    var_value zone_value
 %type <rolespec> auth_ident RoleSpec opt_granted_by

-%type <keyword> unreserved_keyword type_func_name_keyword
+%type <keyword> unreserved_keyword non_label_keyword type_func_name_keyword
 %type <keyword> col_name_keyword reserved_keyword

 %type <node>    TableConstraint TableLikeClause
@@ -744,7 +745,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %nonassoc    '<' '>' '=' LESS_EQUALS GREATER_EQUALS NOT_EQUALS
 %nonassoc    BETWEEN IN_P LIKE ILIKE SIMILAR NOT_LA
 %nonassoc    ESCAPE            /* ESCAPE must be just above LIKE/ILIKE/SIMILAR */
-%left        POSTFIXOP        /* dummy for postfix Op rules */
 /*
  * To support target_el without AS, we must give IDENT an explicit priority
  * between POSTFIXOP and Op.  We can safely assign the same priority to
@@ -3908,6 +3908,7 @@ PartitionSpec: PARTITION BY part_strategy '(' part_params ')'

 part_strategy:    IDENT                    { $$ = $1; }
                 | unreserved_keyword    { $$ = pstrdup($1); }
+                | non_label_keyword        { $$ = pstrdup($1); }
         ;

 part_params:    part_elem                        { $$ = list_make1($1); }
@@ -13230,8 +13231,6 @@ a_expr:        c_expr                                    { $$ = $1; }
                 { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }
             | qual_Op a_expr                    %prec Op
                 { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); }
-            | a_expr qual_Op                    %prec POSTFIXOP
-                { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); }

             | a_expr AND a_expr
                 { $$ = makeAndExpr($1, $3, @2); }
@@ -13645,8 +13644,6 @@ b_expr:        c_expr
                 { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, $3, @2); }
             | qual_Op b_expr                    %prec Op
                 { $$ = (Node *) makeA_Expr(AEXPR_OP, $1, NULL, $2, @1); }
-            | b_expr qual_Op                    %prec POSTFIXOP
-                { $$ = (Node *) makeA_Expr(AEXPR_OP, $2, $1, NULL, @2); }
             | b_expr IS DISTINCT FROM b_expr        %prec IS
                 {
                     $$ = (Node *) makeSimpleA_Expr(AEXPR_DISTINCT, "=", $1, $5, @2);
@@ -14910,7 +14907,7 @@ target_el:    a_expr AS ColLabel
              * as an infix expression, which we accomplish by assigning
              * IDENT a precedence higher than POSTFIXOP.
              */
-            | a_expr IDENT
+            | a_expr BareColLabel
                 {
                     $$ = makeNode(ResTarget);
                     $$->name = $2;
@@ -15228,6 +15225,7 @@ role_list:    RoleSpec
  */
 ColId:        IDENT                                    { $$ = $1; }
             | unreserved_keyword                    { $$ = pstrdup($1); }
+            | non_label_keyword                        { $$ = pstrdup($1); }
             | col_name_keyword                        { $$ = pstrdup($1); }
         ;

@@ -15235,6 +15233,7 @@ ColId:        IDENT                                    { $$ = $1; }
  */
 type_function_name:    IDENT                            { $$ = $1; }
             | unreserved_keyword                    { $$ = pstrdup($1); }
+            | non_label_keyword                        { $$ = pstrdup($1); }
             | type_func_name_keyword                { $$ = pstrdup($1); }
         ;

@@ -15242,15 +15241,23 @@ type_function_name:    IDENT                            { $$ = $1; }
  */
 NonReservedWord:    IDENT                            { $$ = $1; }
             | unreserved_keyword                    { $$ = pstrdup($1); }
+            | non_label_keyword                        { $$ = pstrdup($1); }
             | col_name_keyword                        { $$ = pstrdup($1); }
             | type_func_name_keyword                { $$ = pstrdup($1); }
         ;

+/* Bare column label --- names that can be column labels without writing "AS".
+ */
+BareColLabel:    IDENT                                { $$ = $1; }
+            | unreserved_keyword                    { $$ = pstrdup($1); }
+        ;
+
 /* Column label --- allowed labels in "AS" clauses.
  * This presently includes *all* Postgres keywords.
  */
 ColLabel:    IDENT                                    { $$ = $1; }
             | unreserved_keyword                    { $$ = pstrdup($1); }
+            | non_label_keyword                        { $$ = pstrdup($1); }
             | col_name_keyword                        { $$ = pstrdup($1); }
             | type_func_name_keyword                { $$ = pstrdup($1); }
             | reserved_keyword                        { $$ = pstrdup($1); }
@@ -15326,7 +15333,6 @@ unreserved_keyword:
             | CYCLE
             | DATA_P
             | DATABASE
-            | DAY_P
             | DEALLOCATE
             | DECLARE
             | DEFAULTS
@@ -15360,7 +15366,6 @@ unreserved_keyword:
             | EXTENSION
             | EXTERNAL
             | FAMILY
-            | FILTER
             | FIRST_P
             | FOLLOWING
             | FORCE
@@ -15374,7 +15379,6 @@ unreserved_keyword:
             | HANDLER
             | HEADER_P
             | HOLD
-            | HOUR_P
             | IDENTITY_P
             | IF_P
             | IMMEDIATE
@@ -15414,10 +15418,8 @@ unreserved_keyword:
             | MATERIALIZED
             | MAXVALUE
             | METHOD
-            | MINUTE_P
             | MINVALUE
             | MODE
-            | MONTH_P
             | MOVE
             | NAME_P
             | NAMES
@@ -15443,7 +15445,6 @@ unreserved_keyword:
             | OPTIONS
             | ORDINALITY
             | OTHERS
-            | OVER
             | OVERRIDING
             | OWNED
             | OWNER
@@ -15499,7 +15500,6 @@ unreserved_keyword:
             | SCHEMAS
             | SCROLL
             | SEARCH
-            | SECOND_P
             | SECURITY
             | SEQUENCE
             | SEQUENCES
@@ -15557,23 +15557,36 @@ unreserved_keyword:
             | VALIDATE
             | VALIDATOR
             | VALUE_P
-            | VARYING
             | VERSION_P
             | VIEW
             | VIEWS
             | VOLATILE
             | WHITESPACE_P
-            | WITHIN
-            | WITHOUT
             | WORK
             | WRAPPER
             | WRITE
             | XML_P
-            | YEAR_P
             | YES_P
             | ZONE
         ;

+/* "Non label" keywords --- cannot be a bare column label in a SELECT list
+ * (you have to write AS in front).  Otherwise usable for anything.
+ */
+non_label_keyword:
+            DAY_P
+            | FILTER
+            | HOUR_P
+            | MINUTE_P
+            | MONTH_P
+            | OVER
+            | SECOND_P
+            | VARYING
+            | WITHIN
+            | WITHOUT
+            | YEAR_P
+        ;
+
 /* Column identifier --- keywords that can be column, table, etc names.
  *
  * Many of these keywords will in fact be recognized as type or function

pgsql-hackers by date:

Previous
From: Michael Paquier
Date:
Subject: Re: pg_stat_wal_receiver and flushedUpto/writtenUpto
Next
From: Fujii Masao
Date:
Subject: Re: pg_stat_wal_receiver and flushedUpto/writtenUpto