Re: two-argument aggregates and SQL 2003

Поиск
Список
Период
Сортировка
От Tom Lane
Тема Re: two-argument aggregates and SQL 2003
Дата
Msg-id 26420.1145054239@sss.pgh.pa.us
обсуждение исходный текст
Ответ на two-argument aggregates and SQL 2003  ("Sergey E. Koposov" <math@sai.msu.ru>)
Список pgsql-hackers
I wrote [ in an off-list reply to Mark Dilger ]:
> I don't think this solves the parsing problem at all.  The problem as I
> see it is that given
>     CREATE AGGREGATE foo (bar ...
> it's not obvious whether bar is a def_elem name (old syntax) or a type
> name (new syntax).  It's possible that we can get bison to eat both
> anyway on the basis that the lookahead token must be '=' at this point
> for old syntax while it could not be '=' for new syntax.

I did some idle investigation of this and found that it's indeed
possible, as long as we make the further restriction that none of the
definition-list keywords used by old-style CREATE AGGREGATE be keywords
of the SQL grammar.  (We could probably allow selected ones if we had
to, but using ColLabel rather than IDENT in the patch below leads to
tons of reduce/reduce conflicts...)  Attached is a proof-of-concept
patch, which doesn't do anything useful as-is because none of the rest
of the backend has been updated, but it does prove that bison can be
made to handle CREATE AGGREGATE syntax with an initial list of type
names.  For instance the first example in
http://www.postgresql.org/docs/8.1/static/xaggr.html
would become

CREATE AGGREGATE complex_sum (complex)
(
    sfunc = complex_add,
    stype = complex,
    initcond = '(0,0)'
);

I'm inclined to flesh this out and apply it with or without any further
work by Sergey, simply because it makes the syntax of CREATE AGGREGATE
more in harmony with DROP AGGREGATE and the other AGGREGATE commands.
Any objections out there?

Another thing we could look into is doing something similar to CREATE
OPERATOR, so that it names the new operator the same way you would do
in DROP OPERATOR.  Not sure if this is worth the trouble or not, as
I don't find DROP OPERATOR amazingly intuitive.

            regards, tom lane

*** src/backend/parser/gram.y.orig    Wed Mar 22 19:19:29 2006
--- src/backend/parser/gram.y    Fri Apr 14 17:50:52 2006
***************
*** 224,231 ****

  %type <list>    stmtblock stmtmulti
                  OptTableElementList TableElementList OptInherit definition
                opt_distinct opt_definition func_args
                func_args_list func_as createfunc_opt_list alterfunc_opt_list
                  oper_argtypes RuleActionList RuleActionMulti
                  opt_column_list columnList opt_name_list
                  sort_clause opt_sort_clause sortby_list index_params
--- 224,232 ----

  %type <list>    stmtblock stmtmulti
                  OptTableElementList TableElementList OptInherit definition
                opt_distinct opt_definition func_args
                func_args_list func_as createfunc_opt_list alterfunc_opt_list
+                 aggr_args aggr_args_list old_aggr_definition old_aggr_list
                  oper_argtypes RuleActionList RuleActionMulti
                  opt_column_list columnList opt_name_list
                  sort_clause opt_sort_clause sortby_list index_params
***************
*** 246,252 ****
  %type <defelt>    createfunc_opt_item common_func_opt_item
  %type <fun_param> func_arg
  %type <fun_param_mode> arg_class
! %type <typnam>    func_return func_type aggr_argtype

  %type <boolean>  TriggerForType OptTemp
  %type <oncommit> OnCommitOption
--- 247,253 ----
  %type <defelt>    createfunc_opt_item common_func_opt_item
  %type <fun_param> func_arg
  %type <fun_param_mode> arg_class
! %type <typnam>    func_return func_type

  %type <boolean>  TriggerForType OptTemp
  %type <oncommit> OnCommitOption
***************
*** 285,291 ****

  %type <node>    TableElement ConstraintElem TableFuncElement
  %type <node>    columnDef
! %type <defelt>    def_elem
  %type <node>    def_arg columnElem where_clause
                  a_expr b_expr c_expr func_expr AexprConst indirection_el
                  columnref in_expr having_clause func_table array_expr
--- 286,292 ----

  %type <node>    TableElement ConstraintElem TableFuncElement
  %type <node>    columnDef
! %type <defelt>    def_elem old_aggr_elem
  %type <node>    def_arg columnElem where_clause
                  a_expr b_expr c_expr func_expr AexprConst indirection_el
                  columnref in_expr having_clause func_table array_expr
***************
*** 2671,2681 ****
   *****************************************************************************/

  DefineStmt:
!             CREATE AGGREGATE func_name definition
                  {
                      DefineStmt *n = makeNode(DefineStmt);
                      n->kind = OBJECT_AGGREGATE;
                      n->defnames = $3;
                      n->definition = $4;
                      $$ = (Node *)n;
                  }
--- 2672,2692 ----
   *****************************************************************************/

  DefineStmt:
!             CREATE AGGREGATE func_name aggr_args definition
                  {
                      DefineStmt *n = makeNode(DefineStmt);
                      n->kind = OBJECT_AGGREGATE;
                      n->defnames = $3;
+                     /* XXX put args somewhere */
+                     n->definition = $5;
+                     $$ = (Node *)n;
+                 }
+             | CREATE AGGREGATE func_name old_aggr_definition
+                 {
+                     /* old-style syntax for CREATE AGGREGATE */
+                     DefineStmt *n = makeNode(DefineStmt);
+                     n->kind = OBJECT_AGGREGATE;
+                     n->defnames = $3;
                      n->definition = $4;
                      $$ = (Node *)n;
                  }
***************
*** 2764,2769 ****
--- 2775,2802 ----
              | Sconst                        { $$ = (Node *)makeString($1); }
          ;

+ aggr_args:    '(' aggr_args_list ')'                    { $$ = $2; }
+             | '(' '*' ')'                            { $$ = NIL; }
+         ;
+
+ aggr_args_list:
+             Typename                                { $$ = list_make1($1); }
+             | aggr_args_list ',' Typename            { $$ = lappend($1, $3); }
+         ;
+
+ old_aggr_definition: '(' old_aggr_list ')'            { $$ = $2; }
+         ;
+
+ old_aggr_list: old_aggr_elem                        { $$ = list_make1($1); }
+             | old_aggr_list ',' old_aggr_elem        { $$ = lappend($1, $3); }
+         ;
+
+ old_aggr_elem:  IDENT '=' def_arg
+                 {
+                     $$ = makeDefElem($1, (Node *)$3);
+                 }
+         ;
+

  /*****************************************************************************
   *
***************
*** 2960,2966 ****
   *    COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
   *                   CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT |
   *                   CAST | COLUMN | SCHEMA | TABLESPACE | ROLE ] <objname> |
!  *                 AGGREGATE <aggname> (<aggtype>) |
   *                 FUNCTION <funcname> (arg1, arg2, ...) |
   *                 OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
   *                 TRIGGER <triggername> ON <relname> |
--- 2993,2999 ----
   *    COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
   *                   CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT |
   *                   CAST | COLUMN | SCHEMA | TABLESPACE | ROLE ] <objname> |
!  *                 AGGREGATE <aggname> (arg1, ...) |
   *                 FUNCTION <funcname> (arg1, arg2, ...) |
   *                 OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
   *                 TRIGGER <triggername> ON <relname> |
***************
*** 2980,2993 ****
                      n->comment = $6;
                      $$ = (Node *) n;
                  }
!             | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')'
!             IS comment_text
                  {
                      CommentStmt *n = makeNode(CommentStmt);
                      n->objtype = OBJECT_AGGREGATE;
                      n->objname = $4;
!                     n->objargs = list_make1($6);
!                     n->comment = $9;
                      $$ = (Node *) n;
                  }
              | COMMENT ON FUNCTION func_name func_args IS comment_text
--- 3013,3025 ----
                      n->comment = $6;
                      $$ = (Node *) n;
                  }
!             | COMMENT ON AGGREGATE func_name aggr_args IS comment_text
                  {
                      CommentStmt *n = makeNode(CommentStmt);
                      n->objtype = OBJECT_AGGREGATE;
                      n->objname = $4;
!                     n->objargs = $5;
!                     n->comment = $7;
                      $$ = (Node *) n;
                  }
              | COMMENT ON FUNCTION func_name func_args IS comment_text
***************
*** 3844,3850 ****
   *        QUERY:
   *
   *        DROP FUNCTION funcname (arg1, arg2, ...) [ RESTRICT | CASCADE ]
!  *        DROP AGGREGATE aggname (aggtype) [ RESTRICT | CASCADE ]
   *        DROP OPERATOR opname (leftoperand_typ, rightoperand_typ) [ RESTRICT | CASCADE ]
   *
   *****************************************************************************/
--- 3876,3882 ----
   *        QUERY:
   *
   *        DROP FUNCTION funcname (arg1, arg2, ...) [ RESTRICT | CASCADE ]
!  *        DROP AGGREGATE aggname (arg1, ...) [ RESTRICT | CASCADE ]
   *        DROP OPERATOR opname (leftoperand_typ, rightoperand_typ) [ RESTRICT | CASCADE ]
   *
   *****************************************************************************/
***************
*** 3861,3881 ****
          ;

  RemoveAggrStmt:
!             DROP AGGREGATE func_name '(' aggr_argtype ')' opt_drop_behavior
                  {
                          RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
                          n->aggname = $3;
!                         n->aggtype = $5;
!                         n->behavior = $7;
                          $$ = (Node *)n;
                  }
          ;

- aggr_argtype:
-             Typename                                { $$ = $1; }
-             | '*'                                    { $$ = NULL; }
-         ;
-
  RemoveOperStmt:
              DROP OPERATOR any_operator '(' oper_argtypes ')' opt_drop_behavior
                  {
--- 3893,3908 ----
          ;

  RemoveAggrStmt:
!             DROP AGGREGATE func_name aggr_args opt_drop_behavior
                  {
                          RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
                          n->aggname = $3;
!                         n->aggtype = $4;
!                         n->behavior = $5;
                          $$ = (Node *)n;
                  }
          ;

  RemoveOperStmt:
              DROP OPERATOR any_operator '(' oper_argtypes ')' opt_drop_behavior
                  {
***************
*** 4013,4025 ****
   *
   *****************************************************************************/

! RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name
                  {
                      RenameStmt *n = makeNode(RenameStmt);
                      n->renameType = OBJECT_AGGREGATE;
                      n->object = $3;
!                     n->objarg = list_make1($5);
!                     n->newname = $9;
                      $$ = (Node *)n;
                  }
              | ALTER CONVERSION_P any_name RENAME TO name
--- 4040,4052 ----
   *
   *****************************************************************************/

! RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
                  {
                      RenameStmt *n = makeNode(RenameStmt);
                      n->renameType = OBJECT_AGGREGATE;
                      n->object = $3;
!                     n->objarg = $4;
!                     n->newname = $7;
                      $$ = (Node *)n;
                  }
              | ALTER CONVERSION_P any_name RENAME TO name
***************
*** 4153,4165 ****
   *****************************************************************************/

  AlterObjectSchemaStmt:
!             ALTER AGGREGATE func_name '(' aggr_argtype ')' SET SCHEMA name
                  {
                      AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
                      n->objectType = OBJECT_AGGREGATE;
                      n->object = $3;
!                     n->objarg = list_make1($5);
!                     n->newschema = $9;
                      $$ = (Node *)n;
                  }
              | ALTER DOMAIN_P any_name SET SCHEMA name
--- 4180,4192 ----
   *****************************************************************************/

  AlterObjectSchemaStmt:
!             ALTER AGGREGATE func_name aggr_args SET SCHEMA name
                  {
                      AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
                      n->objectType = OBJECT_AGGREGATE;
                      n->object = $3;
!                     n->objarg = $4;
!                     n->newschema = $7;
                      $$ = (Node *)n;
                  }
              | ALTER DOMAIN_P any_name SET SCHEMA name
***************
*** 4211,4223 ****
   *
   *****************************************************************************/

! AlterOwnerStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' OWNER TO RoleId
                  {
                      AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                      n->objectType = OBJECT_AGGREGATE;
                      n->object = $3;
!                     n->objarg = list_make1($5);
!                     n->newowner = $9;
                      $$ = (Node *)n;
                  }
              | ALTER CONVERSION_P any_name OWNER TO RoleId
--- 4238,4250 ----
   *
   *****************************************************************************/

! AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                  {
                      AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                      n->objectType = OBJECT_AGGREGATE;
                      n->object = $3;
!                     n->objarg = $4;
!                     n->newowner = $7;
                      $$ = (Node *)n;
                  }
              | ALTER CONVERSION_P any_name OWNER TO RoleId

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Josh Berkus
Дата:
Сообщение: Re: Summer of Code
Следующее
От: markir@paradise.net.nz
Дата:
Сообщение: Re: Is full_page_writes=off safe in conjunction with PITR?