Make the OVER keyword unreserved.
authorRobert Haas <rhaas@postgresql.org>
Fri, 28 Jun 2013 14:18:00 +0000 (10:18 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 28 Jun 2013 15:11:00 +0000 (11:11 -0400)
This results in a slightly less specific error message when OVER
is used in a context where we don't accept window functions, but
per discussion, it's worth it to get the benefit of not needing
to reserve this keyword any more.  This same refactoring will
also let us avoid reserving some other keywords that we expect
to add in upcoming patches (specifically, IGNORE, RESPECT, and
FILTER).

Troels Nielsen, with minor changes by me

src/backend/parser/gram.y
src/include/parser/kwlist.h
src/test/regress/expected/window.out

index 509422675001e25ee7f3a2a2b52988473bf8874b..c41f1b512f6b3a1da605bcfce37583c98aad6512 100644 (file)
@@ -401,7 +401,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <node>   columnDef columnOptions
 %type <defelt> def_elem reloption_elem old_aggr_elem
 %type <node>   def_arg columnElem where_clause where_or_current_clause
-               a_expr b_expr c_expr func_expr AexprConst indirection_el
+               a_expr b_expr c_expr AexprConst indirection_el
                columnref in_expr having_clause func_table array_expr
                ExclusionWhereClause
 %type <list>   ExclusionConstraintList ExclusionConstraintElem
@@ -481,6 +481,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <ival>   document_or_content
 %type <boolean> xml_whitespace_option
 
+%type <node>   func_application func_expr_common_subexpr
+%type <node>   func_expr func_expr_windowless
 %type <node>   common_table_expr
 %type <with>   with_clause opt_with_clause
 %type <list>   cte_list
@@ -6132,7 +6134,7 @@ index_elem:   ColId opt_collate opt_class opt_asc_desc opt_nulls_order
                    $$->ordering = $4;
                    $$->nulls_ordering = $5;
                }
-           | func_expr opt_collate opt_class opt_asc_desc opt_nulls_order
+           | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order
                {
                    $$ = makeNode(IndexElem);
                    $$->name = NULL;
@@ -9894,8 +9896,7 @@ relation_expr_opt_alias: relation_expr                    %prec UMINUS
                }
        ;
 
-
-func_table: func_expr                              { $$ = $1; }
+func_table: func_expr_windowless                   { $$ = $1; }
        ;
 
 
@@ -11079,15 +11080,7 @@ c_expr:        columnref                               { $$ = $1; }
                }
        ;
 
-/*
- * func_expr is split out from c_expr just so that we have a classification
- * for "everything that is a function call or looks like one".  This isn't
- * very important, but it saves us having to document which variants are
- * legal in the backwards-compatible functional-index syntax for CREATE INDEX.
- * (Note that many of the special SQL functions wouldn't actually make any
- * sense as functional index entries, but we ignore that consideration here.)
- */
-func_expr: func_name '(' ')' over_clause
+func_application: func_name '(' ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = $1;
@@ -11096,11 +11089,11 @@ func_expr:    func_name '(' ')' over_clause
                    n->agg_star = FALSE;
                    n->agg_distinct = FALSE;
                    n->func_variadic = FALSE;
-                   n->over = $4;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | func_name '(' func_arg_list ')' over_clause
+           | func_name '(' func_arg_list ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = $1;
@@ -11109,11 +11102,11 @@ func_expr:    func_name '(' ')' over_clause
                    n->agg_star = FALSE;
                    n->agg_distinct = FALSE;
                    n->func_variadic = FALSE;
-                   n->over = $5;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | func_name '(' VARIADIC func_arg_expr ')' over_clause
+           | func_name '(' VARIADIC func_arg_expr ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = $1;
@@ -11122,11 +11115,11 @@ func_expr:    func_name '(' ')' over_clause
                    n->agg_star = FALSE;
                    n->agg_distinct = FALSE;
                    n->func_variadic = TRUE;
-                   n->over = $6;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')' over_clause
+           | func_name '(' func_arg_list ',' VARIADIC func_arg_expr ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = $1;
@@ -11135,11 +11128,11 @@ func_expr:    func_name '(' ')' over_clause
                    n->agg_star = FALSE;
                    n->agg_distinct = FALSE;
                    n->func_variadic = TRUE;
-                   n->over = $8;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | func_name '(' func_arg_list sort_clause ')' over_clause
+           | func_name '(' func_arg_list sort_clause ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = $1;
@@ -11148,11 +11141,11 @@ func_expr:    func_name '(' ')' over_clause
                    n->agg_star = FALSE;
                    n->agg_distinct = FALSE;
                    n->func_variadic = FALSE;
-                   n->over = $6;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | func_name '(' ALL func_arg_list opt_sort_clause ')' over_clause
+           | func_name '(' ALL func_arg_list opt_sort_clause ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = $1;
@@ -11165,11 +11158,11 @@ func_expr:    func_name '(' ')' over_clause
                     * for that in FuncCall at the moment.
                     */
                    n->func_variadic = FALSE;
-                   n->over = $7;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | func_name '(' DISTINCT func_arg_list opt_sort_clause ')' over_clause
+           | func_name '(' DISTINCT func_arg_list opt_sort_clause ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = $1;
@@ -11178,11 +11171,11 @@ func_expr:    func_name '(' ')' over_clause
                    n->agg_star = FALSE;
                    n->agg_distinct = TRUE;
                    n->func_variadic = FALSE;
-                   n->over = $7;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | func_name '(' '*' ')' over_clause
+           | func_name '(' '*' ')'
                {
                    /*
                     * We consider AGGREGATE(*) to invoke a parameterless
@@ -11201,11 +11194,48 @@ func_expr:    func_name '(' ')' over_clause
                    n->agg_star = TRUE;
                    n->agg_distinct = FALSE;
                    n->func_variadic = FALSE;
-                   n->over = $5;
+                   n->over = NULL;
                    n->location = @1;
                    $$ = (Node *)n;
                }
-           | COLLATION FOR '(' a_expr ')'
+        ;
+
+
+/*
+ * func_expr and its cousin func_expr_windowless is split out from c_expr just 
+ * so that we have classifications for "everything that is a function call or 
+ * looks like one".  This isn't very important, but it saves us having to document 
+ * which variants are legal in the backwards-compatible functional-index syntax 
+ * for CREATE INDEX.
+ * (Note that many of the special SQL functions wouldn't actually make any
+ * sense as functional index entries, but we ignore that consideration here.)
+ */
+func_expr: func_application over_clause 
+               {
+                   FuncCall *n = (FuncCall*)$1;
+                   n->over = $2;
+                   $$ = (Node*)n;
+               } 
+           | func_expr_common_subexpr
+               { $$ = $1; }
+       ;
+
+/* 
+ * As func_expr but does not accept WINDOW functions directly (they
+ * can still be contained in arguments for functions etc.)
+ * Use this when window expressions are not allowed, so to disambiguate 
+ * the grammar. (e.g. in CREATE INDEX)
+ */
+func_expr_windowless: 
+           func_application                        { $$ = $1; }
+           | func_expr_common_subexpr              { $$ = $1; }
+       ;
+
+/*
+ * Special expression 
+ */
+func_expr_common_subexpr:  
+           COLLATION FOR '(' a_expr ')'
                {
                    FuncCall *n = makeNode(FuncCall);
                    n->funcname = SystemFuncName("pg_collation_for");
@@ -12794,6 +12824,7 @@ unreserved_keyword:
            | OPERATOR
            | OPTION
            | OPTIONS
+           | OVER
            | OWNED
            | OWNER
            | PARSER
@@ -12992,7 +13023,6 @@ type_func_name_keyword:
            | NATURAL
            | NOTNULL
            | OUTER_P
-           | OVER
            | OVERLAPS
            | RIGHT
            | SIMILAR
index 68a13b7a7ba7fb77fabec033f39df98c5592a503..b3d72a9ae3b0082965c0c78a56477a40f8f1cd6c 100644 (file)
@@ -270,7 +270,7 @@ PG_KEYWORD("or", OR, RESERVED_KEYWORD)
 PG_KEYWORD("order", ORDER, RESERVED_KEYWORD)
 PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD)
 PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD)
-PG_KEYWORD("over", OVER, TYPE_FUNC_NAME_KEYWORD)
+PG_KEYWORD("over", OVER, UNRESERVED_KEYWORD)
 PG_KEYWORD("overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD)
 PG_KEYWORD("overlay", OVERLAY, COL_NAME_KEYWORD)
 PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD)
index 752c7b42ff341bf895405e5f3f558dedb1986e63..ecc1c2c6113da89bc625ac3b2def9cce7fa3b15f 100644 (file)
@@ -989,9 +989,9 @@ ERROR:  window functions are not allowed in GROUP BY
 LINE 1: SELECT rank() OVER (ORDER BY 1), count(*) FROM empsalary GRO...
                ^
 SELECT * FROM rank() OVER (ORDER BY random());
-ERROR:  window functions are not allowed in functions in FROM
+ERROR:  syntax error at or near "ORDER"
 LINE 1: SELECT * FROM rank() OVER (ORDER BY random());
-                      ^
+                                   ^
 DELETE FROM empsalary WHERE (rank() OVER (ORDER BY random())) > 10;
 ERROR:  window functions are not allowed in WHERE
 LINE 1: DELETE FROM empsalary WHERE (rank() OVER (ORDER BY random())...