]> granicus.if.org Git - postgresql/commitdiff
Support the syntax
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 15 Apr 2006 17:45:46 +0000 (17:45 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 15 Apr 2006 17:45:46 +0000 (17:45 +0000)
CREATE AGGREGATE aggname (input_type) (parameter_list)
along with the old syntax where the input type was named in the parameter
list.  This fits more naturally with the way that the aggregate is identified
in DROP AGGREGATE and other utility commands; furthermore it has a natural
extension to handle multiple-input aggregates, where the basetype-parameter
method would get ugly.  In fact, this commit fixes the grammar and all the
utility commands to support multiple-input aggregates; but DefineAggregate
rejects it because the executor isn't fixed yet.
I didn't do anything about treating agg(*) as a zero-input aggregate instead
of artificially making it a one-input aggregate, but that should be considered
in combination with supporting multi-input aggregates.

17 files changed:
doc/src/sgml/ref/create_aggregate.sgml
doc/src/sgml/xaggr.sgml
src/backend/commands/aggregatecmds.c
src/backend/commands/alter.c
src/backend/commands/comment.c
src/backend/commands/functioncmds.c
src/backend/commands/operatorcmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/parser/parse_func.c
src/backend/tcop/utility.c
src/include/commands/defrem.h
src/include/nodes/nodes.h
src/include/nodes/parsenodes.h
src/include/parser/parse_func.h
src/test/regress/expected/errors.out

index 70362f650395e12219398b9d5649aefdfc1f842a..5eb0741c9c216a9487834b62b191c8cb14ec936f 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.33 2005/11/04 23:14:02 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_aggregate.sgml,v 1.34 2006/04/15 17:45:18 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -20,8 +20,18 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
+CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( <replaceable class="PARAMETER">input_data_type</replaceable> ) (
+    SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
+    STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
+    [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
+    [ , INITCOND = <replaceable class="PARAMETER">initial_condition</replaceable> ]
+    [ , SORTOP = <replaceable class="PARAMETER">sort_operator</replaceable> ]
+)
+
+or the old syntax
+
 CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
-    BASETYPE = <replaceable class="PARAMETER">input_data_type</replaceable>,
+    BASETYPE = <replaceable class="PARAMETER">base_type</replaceable>,
     SFUNC = <replaceable class="PARAMETER">sfunc</replaceable>,
     STYPE = <replaceable class="PARAMETER">state_data_type</replaceable>
     [ , FINALFUNC = <replaceable class="PARAMETER">ffunc</replaceable> ]
@@ -87,7 +97,7 @@ CREATE AGGREGATE <replaceable class="PARAMETER">name</replaceable> (
   <para>
    An aggregate function may provide an initial condition,
    that is, an initial value for the internal state value.
-   This is specified and stored in the database as a column of type
+   This is specified and stored in the database as a value of type
    <type>text</type>, but it must be a valid external representation
    of a constant of the state value data type.  If it is not supplied
    then the state value starts out null.
@@ -146,8 +156,9 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
    Ordinarily, a data type's <literal>&lt;</> operator is the proper sort
    operator for <function>MIN</>, and <literal>&gt;</> is the proper sort
    operator for <function>MAX</>.  Note that the optimization will never
-   actually take effect unless the specified operator is the <quote>less than</quote> or
-   <quote>greater than</quote> strategy member of a B-tree index operator class.
+   actually take effect unless the specified operator is the <quote>less
+   than</quote> or <quote>greater than</quote> strategy member of a B-tree
+   index operator class.
   </para>
  </refsect1>
 
@@ -170,13 +181,27 @@ SELECT col FROM tab ORDER BY col USING sortop LIMIT 1;
     <listitem>
      <para>
       The input data type on which this aggregate function operates.
-      This can be specified as <literal>"ANY"</> for an aggregate that
+      This can be specified as <literal>*</> for an aggregate that
       does not examine its input values (an example is
       <function>count(*)</function>).
      </para>
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><replaceable class="PARAMETER">base_type</replaceable></term>
+    <listitem>
+     <para>
+      In the old syntax for <command>CREATE AGGREGATE</>, the input data type
+      is specified by a <literal>basetype</> parameter rather than being
+      written next to the aggregate name.  Note that this syntax allows
+      only one input parameter.  To define an aggregate that does not examine
+      its input values, specify the <literal>basetype</> as
+      <literal>"ANY"</> (not <literal>*</>).
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><replaceable class="PARAMETER">sfunc</replaceable></term>
     <listitem>
index bbb4055b916d77e1e5ceecc946eb7df7fc7586bc..db6c077cbf61927aaa1da62f2c8373a95d402720 100644 (file)
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/xaggr.sgml,v 1.30 2006/03/10 19:10:49 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/xaggr.sgml,v 1.31 2006/04/15 17:45:33 tgl Exp $ -->
 
  <sect1 id="xaggr">
   <title>User-Defined Aggregates</title>
    The aggregate definition would be:
    
 <screen>
-CREATE AGGREGATE complex_sum (
+CREATE AGGREGATE sum (complex)
+(
     sfunc = complex_add,
-    basetype = complex,
     stype = complex,
     initcond = '(0,0)'
 );
 
-SELECT complex_sum(a) FROM test_complex;
+SELECT sum(a) FROM test_complex;
 
complex_sum
--------------
  sum
+-----------
  (34,53.9)
 </screen>
 
-   (In practice, we'd just name the aggregate <function>sum</function> and rely on
-   <productname>PostgreSQL</productname> to figure out which kind
-   of sum to apply to a column of type <type>complex</type>.)
+   (Notice that we are relying on function overloading: there is more than
+    one aggregate named <function>sum</>, but
+   <productname>PostgreSQL</productname> can figure out which kind
+   of sum applies to a column of type <type>complex</type>.)
   </para>
 
   <para>
@@ -99,9 +100,9 @@ SELECT complex_sum(a) FROM test_complex;
    looks like:
 
 <programlisting>
-CREATE AGGREGATE avg (
+CREATE AGGREGATE avg (float8)
+(
     sfunc = float8_accum,
-    basetype = float8,
     stype = float8[],
     finalfunc = float8_avg,
     initcond = '{0,0}'
@@ -116,14 +117,14 @@ CREATE AGGREGATE avg (
    See <xref linkend="extend-types-polymorphic">
    for an explanation of polymorphic functions.
    Going a step further, the aggregate function itself may be specified
-   with a polymorphic base type and state type, allowing a single
+   with a polymorphic input type and state type, allowing a single
    aggregate definition to serve for multiple input data types.
    Here is an example of a polymorphic aggregate:
 
 <programlisting>
-CREATE AGGREGATE array_accum (
+CREATE AGGREGATE array_accum (anyelement)
+(
     sfunc = array_append,
-    basetype = anyelement,
     stype = anyarray,
     initcond = '{}'
 );
@@ -167,7 +168,7 @@ SELECT attrelid::regclass, array_accum(atttypid)
 <programlisting>
         if (fcinfo->context &amp;&amp; IsA(fcinfo->context, AggState))
 </programlisting>
-   One reason for checking this is that when it is true, the left input
+   One reason for checking this is that when it is true, the first input
    must be a temporary transition value and can therefore safely be modified
    in-place rather than allocating a new copy.  (This is the <emphasis>only</>
    case where it is safe for a function to modify a pass-by-reference input.)
index 3c0855238e25ae31597900385705d9ea45d0972d..7b954edd381212263ef5b46a6429ef0d41642ba5 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.33 2006/03/14 22:48:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/aggregatecmds.c,v 1.34 2006/04/15 17:45:33 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
 
 /*
  *     DefineAggregate
+ *
+ * "oldstyle" signals the old (pre-8.2) style where the aggregate input type
+ * is specified by a BASETYPE element in the parameters.  Otherwise,
+ * "args" defines the input type(s).
  */
 void
-DefineAggregate(List *names, List *parameters)
+DefineAggregate(List *name, List *args, bool oldstyle, List *parameters)
 {
        char       *aggName;
        Oid                     aggNamespace;
@@ -59,7 +63,7 @@ DefineAggregate(List *names, List *parameters)
        ListCell   *pl;
 
        /* Convert list of names to a name and namespace */
-       aggNamespace = QualifiedNameGetCreationNamespace(names, &aggName);
+       aggNamespace = QualifiedNameGetCreationNamespace(name, &aggName);
 
        /* Check we have creation rights in target namespace */
        aclresult = pg_namespace_aclcheck(aggNamespace, GetUserId(), ACL_CREATE);
@@ -103,10 +107,6 @@ DefineAggregate(List *names, List *parameters)
        /*
         * make sure we have our required definitions
         */
-       if (baseType == NULL)
-               ereport(ERROR,
-                               (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
-                                errmsg("aggregate basetype must be specified")));
        if (transType == NULL)
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
@@ -117,20 +117,63 @@ DefineAggregate(List *names, List *parameters)
                                 errmsg("aggregate sfunc must be specified")));
 
        /*
-        * look up the aggregate's base type (input datatype) and transtype.
-        *
-        * We have historically allowed the command to look like basetype = 'ANY'
-        * so we must do a case-insensitive comparison for the name ANY.  Ugh.
+        * look up the aggregate's input datatype.
+        */
+       if (oldstyle)
+       {
+               /*
+                * Old style: use basetype parameter.  This supports only one input.
+                *
+                * Historically we allowed the command to look like basetype = 'ANY'
+                * so we must do a case-insensitive comparison for the name ANY. Ugh.
+                */
+               if (baseType == NULL)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+                                        errmsg("aggregate input type must be specified")));
+
+               if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0)
+                       baseTypeId = ANYOID;
+               else
+                       baseTypeId = typenameTypeId(NULL, baseType);
+       }
+       else
+       {
+               /*
+                * New style: args is a list of TypeNames.  For the moment, though,
+                * we allow at most one.
+                */
+               if (baseType != NULL)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
+                                        errmsg("basetype is redundant with aggregate input type specification")));
+
+               if (args == NIL)
+               {
+                       /* special case for agg(*) */
+                       baseTypeId = ANYOID;
+               }
+               else if (list_length(args) != 1)
+               {
+                       /* temporarily reject > 1 arg */
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+                                        errmsg("aggregates can have only one input")));
+                       baseTypeId = InvalidOid;        /* keep compiler quiet */
+               }
+               else
+               {
+                       baseTypeId = typenameTypeId(NULL, (TypeName *) linitial(args));
+               }
+       }
+
+       /*
+        * look up the aggregate's transtype.
         *
-        * basetype can be a pseudo-type, but transtype can't, since we need to be
+        * transtype can't be a pseudo-type, since we need to be
         * able to store values of the transtype.  However, we can allow
         * polymorphic transtype in some cases (AggregateCreate will check).
         */
-       if (pg_strcasecmp(TypeNameToString(baseType), "ANY") == 0)
-               baseTypeId = ANYOID;
-       else
-               baseTypeId = typenameTypeId(NULL, baseType);
-
        transTypeId = typenameTypeId(NULL, transType);
        if (get_typtype(transTypeId) == 'p' &&
                transTypeId != ANYARRAYOID &&
@@ -159,28 +202,16 @@ DefineAggregate(List *names, List *parameters)
  *             Deletes an aggregate.
  */
 void
-RemoveAggregate(RemoveAggrStmt *stmt)
+RemoveAggregate(RemoveFuncStmt *stmt)
 {
-       List       *aggName = stmt->aggname;
-       TypeName   *aggType = stmt->aggtype;
-       Oid                     basetypeID;
+       List       *aggName = stmt->name;
+       List       *aggArgs = stmt->args;
        Oid                     procOid;
        HeapTuple       tup;
        ObjectAddress object;
 
-       /*
-        * if a basetype is passed in, then attempt to find an aggregate for that
-        * specific type.
-        *
-        * else attempt to find an aggregate with a basetype of ANYOID. This means
-        * that the aggregate is to apply to all basetypes (eg, COUNT).
-        */
-       if (aggType)
-               basetypeID = typenameTypeId(NULL, aggType);
-       else
-               basetypeID = ANYOID;
-
-       procOid = find_aggregate_func(aggName, basetypeID, false);
+       /* Look up function and make sure it's an aggregate */
+       procOid = LookupAggNameTypeNames(aggName, aggArgs, false);
 
        /*
         * Find the function tuple, do permissions and validity checks
@@ -198,8 +229,6 @@ RemoveAggregate(RemoveAggrStmt *stmt)
                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
                                           NameListToString(aggName));
 
-       /* find_aggregate_func already checked it is an aggregate */
-
        ReleaseSysCache(tup);
 
        /*
@@ -214,9 +243,8 @@ RemoveAggregate(RemoveAggrStmt *stmt)
 
 
 void
-RenameAggregate(List *name, TypeName *basetype, const char *newname)
+RenameAggregate(List *name, List *args, const char *newname)
 {
-       Oid                     basetypeOid;
        Oid                     procOid;
        Oid                     namespaceOid;
        HeapTuple       tup;
@@ -224,20 +252,10 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
        Relation        rel;
        AclResult       aclresult;
 
-       /*
-        * if a basetype is passed in, then attempt to find an aggregate for that
-        * specific type; else attempt to find an aggregate with a basetype of
-        * ANYOID. This means that the aggregate applies to all basetypes (eg,
-        * COUNT).
-        */
-       if (basetype)
-               basetypeOid = typenameTypeId(NULL, basetype);
-       else
-               basetypeOid = ANYOID;
-
        rel = heap_open(ProcedureRelationId, RowExclusiveLock);
 
-       procOid = find_aggregate_func(name, basetypeOid, false);
+       /* Look up function and make sure it's an aggregate */
+       procOid = LookupAggNameTypeNames(name, args, false);
 
        tup = SearchSysCacheCopy(PROCOID,
                                                         ObjectIdGetDatum(procOid),
@@ -254,22 +272,13 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
                                                         PointerGetDatum(&procForm->proargtypes),
                                                         ObjectIdGetDatum(namespaceOid),
                                                         0))
-       {
-               if (basetypeOid == ANYOID)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_DUPLICATE_FUNCTION),
-                                        errmsg("function %s(*) already exists in schema \"%s\"",
-                                                       newname,
-                                                       get_namespace_name(namespaceOid))));
-               else
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_DUPLICATE_FUNCTION),
-                                        errmsg("function %s already exists in schema \"%s\"",
-                                                       funcname_signature_string(newname,
-                                                                                                         procForm->pronargs,
-                                                                                          procForm->proargtypes.values),
-                                                       get_namespace_name(namespaceOid))));
-       }
+               ereport(ERROR,
+                               (errcode(ERRCODE_DUPLICATE_FUNCTION),
+                                errmsg("function %s already exists in schema \"%s\"",
+                                               funcname_signature_string(newname,
+                                                                                                 procForm->pronargs,
+                                                                                                 procForm->proargtypes.values),
+                                               get_namespace_name(namespaceOid))));
 
        /* must be owner */
        if (!pg_proc_ownercheck(procOid, GetUserId()))
@@ -295,29 +304,18 @@ RenameAggregate(List *name, TypeName *basetype, const char *newname)
  * Change aggregate owner
  */
 void
-AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId)
+AlterAggregateOwner(List *name, List *args, Oid newOwnerId)
 {
-       Oid                     basetypeOid;
        Oid                     procOid;
        HeapTuple       tup;
        Form_pg_proc procForm;
        Relation        rel;
        AclResult       aclresult;
 
-       /*
-        * if a basetype is passed in, then attempt to find an aggregate for that
-        * specific type; else attempt to find an aggregate with a basetype of
-        * ANYOID. This means that the aggregate applies to all basetypes (eg,
-        * COUNT).
-        */
-       if (basetype)
-               basetypeOid = typenameTypeId(NULL, basetype);
-       else
-               basetypeOid = ANYOID;
-
        rel = heap_open(ProcedureRelationId, RowExclusiveLock);
 
-       procOid = find_aggregate_func(name, basetypeOid, false);
+       /* Look up function and make sure it's an aggregate */
+       procOid = LookupAggNameTypeNames(name, args, false);
 
        tup = SearchSysCacheCopy(PROCOID,
                                                         ObjectIdGetDatum(procOid),
index 3c99fd9e0391b1ea01ea4c368c9f64ac6643d0e2..2b7c9250b31c9d2751796f5b4e6474b2d7ceeacc 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.18 2006/03/05 15:58:23 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.19 2006/04/15 17:45:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,9 +47,7 @@ ExecRenameStmt(RenameStmt *stmt)
        switch (stmt->renameType)
        {
                case OBJECT_AGGREGATE:
-                       RenameAggregate(stmt->object,
-                                                       (TypeName *) linitial(stmt->objarg),
-                                                       stmt->newname);
+                       RenameAggregate(stmt->object, stmt->objarg, stmt->newname);
                        break;
 
                case OBJECT_CONVERSION:
@@ -152,8 +150,12 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
        switch (stmt->objectType)
        {
                case OBJECT_AGGREGATE:
+                       AlterFunctionNamespace(stmt->object, stmt->objarg, true,
+                                                                  stmt->newschema);
+                       break;
+
                case OBJECT_FUNCTION:
-                       AlterFunctionNamespace(stmt->object, stmt->objarg,
+                       AlterFunctionNamespace(stmt->object, stmt->objarg, false,
                                                                   stmt->newschema);
                        break;
 
@@ -186,9 +188,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
        switch (stmt->objectType)
        {
                case OBJECT_AGGREGATE:
-                       AlterAggregateOwner(stmt->object,
-                                                               (TypeName *) linitial(stmt->objarg),
-                                                               newowner);
+                       AlterAggregateOwner(stmt->object, stmt->objarg, newowner);
                        break;
 
                case OBJECT_CONVERSION:
@@ -204,6 +204,7 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
                        break;
 
                case OBJECT_OPERATOR:
+                       Assert(list_length(stmt->objarg) == 2);
                        AlterOperatorOwner(stmt->object,
                                                           (TypeName *) linitial(stmt->objarg),
                                                           (TypeName *) lsecond(stmt->objarg),
index 07d82785254094dbf11ecbd619ab2d28cc8066ec..ec4762750f9a55e1fb1ea869e81f29559b218b41 100644 (file)
@@ -7,7 +7,7 @@
  * Copyright (c) 1996-2006, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.88 2006/03/14 22:48:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/comment.c,v 1.89 2006/04/15 17:45:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -868,28 +868,17 @@ CommentType(List *typename, char *comment)
  *
  * This routine is used to allow a user to provide comments on an
  * aggregate function. The aggregate function is determined by both
- * its name and its argument type, which, with the comments are
- * the three parameters handed to this routine.
+ * its name and its argument type(s).
  */
 static void
 CommentAggregate(List *aggregate, List *arguments, char *comment)
 {
-       TypeName   *aggtype = (TypeName *) linitial(arguments);
-       Oid                     baseoid,
-                               oid;
-
-       /* First, attempt to determine the base aggregate oid */
-       if (aggtype)
-               baseoid = typenameTypeId(NULL, aggtype);
-       else
-               baseoid = ANYOID;
-
-       /* Now, attempt to find the actual tuple in pg_proc */
+       Oid                     oid;
 
-       oid = find_aggregate_func(aggregate, baseoid, false);
+       /* Look up function and make sure it's an aggregate */
+       oid = LookupAggNameTypeNames(aggregate, arguments, false);
 
        /* Next, validate the user's attempt to comment */
-
        if (!pg_proc_ownercheck(oid, GetUserId()))
                aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
                                           NameListToString(aggregate));
index 1da1cf66cb346bcfd9d2ee8e32611a4bb14dc21a..96929a0d6c434ea4e51392b2a78936fbad90826e 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.73 2006/03/14 22:48:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/functioncmds.c,v 1.74 2006/04/15 17:45:34 tgl Exp $
  *
  * DESCRIPTION
  *       These routines take the parse tree and pick out the
@@ -678,7 +678,7 @@ CreateFunction(CreateFunctionStmt *stmt)
 void
 RemoveFunction(RemoveFuncStmt *stmt)
 {
-       List       *functionName = stmt->funcname;
+       List       *functionName = stmt->name;
        List       *argTypes = stmt->args;      /* list of TypeName nodes */
        Oid                     funcOid;
        HeapTuple       tup;
@@ -1440,10 +1440,13 @@ DropCastById(Oid castOid)
 }
 
 /*
- * Execute ALTER FUNCTION SET SCHEMA
+ * Execute ALTER FUNCTION/AGGREGATE SET SCHEMA
+ *
+ * These commands are identical except for the lookup procedure, so share code.
  */
 void
-AlterFunctionNamespace(List *name, List *argtypes, const char *newschema)
+AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
+                                          const char *newschema)
 {
        Oid                     procOid;
        Oid                     oldNspOid;
@@ -1455,7 +1458,10 @@ AlterFunctionNamespace(List *name, List *argtypes, const char *newschema)
        procRel = heap_open(ProcedureRelationId, RowExclusiveLock);
 
        /* get function OID */
-       procOid = LookupFuncNameTypeNames(name, argtypes, false);
+       if (isagg)
+               procOid = LookupAggNameTypeNames(name, argtypes, false);
+       else
+               procOid = LookupFuncNameTypeNames(name, argtypes, false);
 
        /* check permissions on function */
        if (!pg_proc_ownercheck(procOid, GetUserId()))
index c40dbf9d8214c23f9317ea6a489fb271f7c36488..54f50a84771c892bcb25909d03a3d42362ef6abc 100644 (file)
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.29 2006/03/14 22:48:18 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/operatorcmds.c,v 1.30 2006/04/15 17:45:34 tgl Exp $
  *
  * DESCRIPTION
  *       The "DefineFoo" routines take the parse tree and pick out the
@@ -201,15 +201,16 @@ DefineOperator(List *names, List *parameters)
  *             Deletes an operator.
  */
 void
-RemoveOperator(RemoveOperStmt *stmt)
+RemoveOperator(RemoveFuncStmt *stmt)
 {
-       List       *operatorName = stmt->opname;
+       List       *operatorName = stmt->name;
        TypeName   *typeName1 = (TypeName *) linitial(stmt->args);
        TypeName   *typeName2 = (TypeName *) lsecond(stmt->args);
        Oid                     operOid;
        HeapTuple       tup;
        ObjectAddress object;
 
+       Assert(list_length(stmt->args) == 2);
        operOid = LookupOperNameTypeNames(NULL, operatorName,
                                                                          typeName1, typeName2,
                                                                          false, -1);
index c7e2a7fff867e9a7fc96d8e03a46d11c9b91e9ca..cd8ebe1f5d68b1780217349026fdd34c77f0c7f1 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.332 2006/03/23 00:19:29 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.333 2006/04/15 17:45:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1942,7 +1942,9 @@ _copyDefineStmt(DefineStmt *from)
        DefineStmt *newnode = makeNode(DefineStmt);
 
        COPY_SCALAR_FIELD(kind);
+       COPY_SCALAR_FIELD(oldstyle);
        COPY_NODE_FIELD(defnames);
+       COPY_NODE_FIELD(args);
        COPY_NODE_FIELD(definition);
 
        return newnode;
@@ -2055,36 +2057,13 @@ _copyAlterFunctionStmt(AlterFunctionStmt *from)
        return newnode;
 }
 
-static RemoveAggrStmt *
-_copyRemoveAggrStmt(RemoveAggrStmt *from)
-{
-       RemoveAggrStmt *newnode = makeNode(RemoveAggrStmt);
-
-       COPY_NODE_FIELD(aggname);
-       COPY_NODE_FIELD(aggtype);
-       COPY_SCALAR_FIELD(behavior);
-
-       return newnode;
-}
-
 static RemoveFuncStmt *
 _copyRemoveFuncStmt(RemoveFuncStmt *from)
 {
        RemoveFuncStmt *newnode = makeNode(RemoveFuncStmt);
 
-       COPY_NODE_FIELD(funcname);
-       COPY_NODE_FIELD(args);
-       COPY_SCALAR_FIELD(behavior);
-
-       return newnode;
-}
-
-static RemoveOperStmt *
-_copyRemoveOperStmt(RemoveOperStmt *from)
-{
-       RemoveOperStmt *newnode = makeNode(RemoveOperStmt);
-
-       COPY_NODE_FIELD(opname);
+       COPY_SCALAR_FIELD(kind);
+       COPY_NODE_FIELD(name);
        COPY_NODE_FIELD(args);
        COPY_SCALAR_FIELD(behavior);
 
@@ -3092,15 +3071,9 @@ copyObject(void *from)
                case T_AlterFunctionStmt:
                        retval = _copyAlterFunctionStmt(from);
                        break;
-               case T_RemoveAggrStmt:
-                       retval = _copyRemoveAggrStmt(from);
-                       break;
                case T_RemoveFuncStmt:
                        retval = _copyRemoveFuncStmt(from);
                        break;
-               case T_RemoveOperStmt:
-                       retval = _copyRemoveOperStmt(from);
-                       break;
                case T_RemoveOpClassStmt:
                        retval = _copyRemoveOpClassStmt(from);
                        break;
index 8d413b87c58d60e38be5ea53cffa25bcb2ac0857..9aa0b399b7c12c39ddfb35f6ab9cff4539bf71b0 100644 (file)
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.268 2006/03/23 00:19:29 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.269 2006/04/15 17:45:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -909,7 +909,9 @@ static bool
 _equalDefineStmt(DefineStmt *a, DefineStmt *b)
 {
        COMPARE_SCALAR_FIELD(kind);
+       COMPARE_SCALAR_FIELD(oldstyle);
        COMPARE_NODE_FIELD(defnames);
+       COMPARE_NODE_FIELD(args);
        COMPARE_NODE_FIELD(definition);
 
        return true;
@@ -1006,30 +1008,11 @@ _equalAlterFunctionStmt(AlterFunctionStmt *a, AlterFunctionStmt *b)
        return true;
 }
 
-static bool
-_equalRemoveAggrStmt(RemoveAggrStmt *a, RemoveAggrStmt *b)
-{
-       COMPARE_NODE_FIELD(aggname);
-       COMPARE_NODE_FIELD(aggtype);
-       COMPARE_SCALAR_FIELD(behavior);
-
-       return true;
-}
-
 static bool
 _equalRemoveFuncStmt(RemoveFuncStmt *a, RemoveFuncStmt *b)
 {
-       COMPARE_NODE_FIELD(funcname);
-       COMPARE_NODE_FIELD(args);
-       COMPARE_SCALAR_FIELD(behavior);
-
-       return true;
-}
-
-static bool
-_equalRemoveOperStmt(RemoveOperStmt *a, RemoveOperStmt *b)
-{
-       COMPARE_NODE_FIELD(opname);
+       COMPARE_SCALAR_FIELD(kind);
+       COMPARE_NODE_FIELD(name);
        COMPARE_NODE_FIELD(args);
        COMPARE_SCALAR_FIELD(behavior);
 
@@ -2112,15 +2095,9 @@ equal(void *a, void *b)
                case T_AlterFunctionStmt:
                        retval = _equalAlterFunctionStmt(a, b);
                        break;
-               case T_RemoveAggrStmt:
-                       retval = _equalRemoveAggrStmt(a, b);
-                       break;
                case T_RemoveFuncStmt:
                        retval = _equalRemoveFuncStmt(a, b);
                        break;
-               case T_RemoveOperStmt:
-                       retval = _equalRemoveOperStmt(a, b);
-                       break;
                case T_RemoveOpClassStmt:
                        retval = _equalRemoveOpClassStmt(a, b);
                        break;
index 43277e458774dd88266a2a310f44431920d5eec2..1c1c07bd1b4fc8da0576b67771a1c4175c0759db 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.537 2006/03/23 00:19:29 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.538 2006/04/15 17:45:34 tgl Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -224,8 +224,9 @@ static void doNegateFloat(Value *v);
 
 %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
+                               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,7 +247,7 @@ static void doNegateFloat(Value *v);
 %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 <typnam> func_return func_type
 
 %type <boolean>  TriggerForType OptTemp
 %type <oncommit> OnCommitOption
@@ -285,7 +286,7 @@ static void doNegateFloat(Value *v);
 
 %type <node>   TableElement ConstraintElem TableFuncElement
 %type <node>   columnDef
-%type <defelt> def_elem
+%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,11 +2672,24 @@ DropAssertStmt:
  *****************************************************************************/
 
 DefineStmt:
-                       CREATE AGGREGATE func_name definition
+                       CREATE AGGREGATE func_name aggr_args definition
                                {
                                        DefineStmt *n = makeNode(DefineStmt);
                                        n->kind = OBJECT_AGGREGATE;
+                                       n->oldstyle = false;
                                        n->defnames = $3;
+                                       n->args = $4;
+                                       n->definition = $5;
+                                       $$ = (Node *)n;
+                               }
+                       | CREATE AGGREGATE func_name old_aggr_definition
+                               {
+                                       /* old-style (pre-8.2) syntax for CREATE AGGREGATE */
+                                       DefineStmt *n = makeNode(DefineStmt);
+                                       n->kind = OBJECT_AGGREGATE;
+                                       n->oldstyle = true;
+                                       n->defnames = $3;
+                                       n->args = NIL;
                                        n->definition = $4;
                                        $$ = (Node *)n;
                                }
@@ -2683,7 +2697,9 @@ DefineStmt:
                                {
                                        DefineStmt *n = makeNode(DefineStmt);
                                        n->kind = OBJECT_OPERATOR;
+                                       n->oldstyle = false;
                                        n->defnames = $3;
+                                       n->args = NIL;
                                        n->definition = $4;
                                        $$ = (Node *)n;
                                }
@@ -2691,7 +2707,9 @@ DefineStmt:
                                {
                                        DefineStmt *n = makeNode(DefineStmt);
                                        n->kind = OBJECT_TYPE;
+                                       n->oldstyle = false;
                                        n->defnames = $3;
+                                       n->args = NIL;
                                        n->definition = $4;
                                        $$ = (Node *)n;
                                }
@@ -2700,7 +2718,9 @@ DefineStmt:
                                        /* Shell type (identified by lack of definition) */
                                        DefineStmt *n = makeNode(DefineStmt);
                                        n->kind = OBJECT_TYPE;
+                                       n->oldstyle = false;
                                        n->defnames = $3;
+                                       n->args = NIL;
                                        n->definition = NIL;
                                        $$ = (Node *)n;
                                }
@@ -2764,6 +2784,28 @@ def_arg: func_type                                               { $$ = (Node *)$1; }
                        | 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,7 +3002,7 @@ TruncateStmt:
  *     COMMENT ON [ [ DATABASE | DOMAIN | INDEX | SEQUENCE | TABLE | TYPE | VIEW |
  *                                CONVERSION | LANGUAGE | OPERATOR CLASS | LARGE OBJECT |
  *                                CAST | COLUMN | SCHEMA | TABLESPACE | ROLE ] <objname> |
- *                              AGGREGATE <aggname> (<aggtype>) |
+ *                              AGGREGATE <aggname> (arg1, ...) |
  *                              FUNCTION <funcname> (arg1, arg2, ...) |
  *                              OPERATOR <op> (leftoperand_typ, rightoperand_typ) |
  *                              TRIGGER <triggername> ON <relname> |
@@ -2980,14 +3022,13 @@ CommentStmt:
                                        n->comment = $6;
                                        $$ = (Node *) n;
                                }
-                       | COMMENT ON AGGREGATE func_name '(' aggr_argtype ')'
-                       IS comment_text
+                       | COMMENT ON AGGREGATE func_name aggr_args IS comment_text
                                {
                                        CommentStmt *n = makeNode(CommentStmt);
                                        n->objtype = OBJECT_AGGREGATE;
                                        n->objname = $4;
-                                       n->objargs = list_make1($6);
-                                       n->comment = $9;
+                                       n->objargs = $5;
+                                       n->comment = $7;
                                        $$ = (Node *) n;
                                }
                        | COMMENT ON FUNCTION func_name func_args IS comment_text
@@ -3844,7 +3885,7 @@ opt_restrict:
  *             QUERY:
  *
  *             DROP FUNCTION funcname (arg1, arg2, ...) [ RESTRICT | CASCADE ]
- *             DROP AGGREGATE aggname (aggtype) [ RESTRICT | CASCADE ]
+ *             DROP AGGREGATE aggname (arg1, ...) [ RESTRICT | CASCADE ]
  *             DROP OPERATOR opname (leftoperand_typ, rightoperand_typ) [ RESTRICT | CASCADE ]
  *
  *****************************************************************************/
@@ -3853,7 +3894,8 @@ RemoveFuncStmt:
                        DROP FUNCTION func_name func_args opt_drop_behavior
                                {
                                        RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
-                                       n->funcname = $3;
+                                       n->kind = OBJECT_FUNCTION;
+                                       n->name = $3;
                                        n->args = extractArgTypes($4);
                                        n->behavior = $5;
                                        $$ = (Node *)n;
@@ -3861,26 +3903,23 @@ RemoveFuncStmt:
                ;
 
 RemoveAggrStmt:
-                       DROP AGGREGATE func_name '(' aggr_argtype ')' opt_drop_behavior
+                       DROP AGGREGATE func_name aggr_args opt_drop_behavior
                                {
-                                               RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
-                                               n->aggname = $3;
-                                               n->aggtype = $5;
-                                               n->behavior = $7;
-                                               $$ = (Node *)n;
+                                       RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
+                                       n->kind = OBJECT_AGGREGATE;
+                                       n->name = $3;
+                                       n->args = $4;
+                                       n->behavior = $5;
+                                       $$ = (Node *)n;
                                }
                ;
 
-aggr_argtype:
-                       Typename                                                                { $$ = $1; }
-                       | '*'                                                                   { $$ = NULL; }
-               ;
-
 RemoveOperStmt:
                        DROP OPERATOR any_operator '(' oper_argtypes ')' opt_drop_behavior
                                {
-                                       RemoveOperStmt *n = makeNode(RemoveOperStmt);
-                                       n->opname = $3;
+                                       RemoveFuncStmt *n = makeNode(RemoveFuncStmt);
+                                       n->kind = OBJECT_OPERATOR;
+                                       n->name = $3;
                                        n->args = $5;
                                        n->behavior = $7;
                                        $$ = (Node *)n;
@@ -4013,13 +4052,13 @@ opt_force:      FORCE                                                                   {  $$ = TRUE; }
  *
  *****************************************************************************/
 
-RenameStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' RENAME TO name
+RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name
                                {
                                        RenameStmt *n = makeNode(RenameStmt);
                                        n->renameType = OBJECT_AGGREGATE;
                                        n->object = $3;
-                                       n->objarg = list_make1($5);
-                                       n->newname = $9;
+                                       n->objarg = $4;
+                                       n->newname = $7;
                                        $$ = (Node *)n;
                                }
                        | ALTER CONVERSION_P any_name RENAME TO name
@@ -4153,13 +4192,13 @@ opt_column: COLUMN                                                                      { $$ = COLUMN; }
  *****************************************************************************/
 
 AlterObjectSchemaStmt:
-                       ALTER AGGREGATE func_name '(' aggr_argtype ')' SET SCHEMA name
+                       ALTER AGGREGATE func_name aggr_args SET SCHEMA name
                                {
                                        AlterObjectSchemaStmt *n = makeNode(AlterObjectSchemaStmt);
                                        n->objectType = OBJECT_AGGREGATE;
                                        n->object = $3;
-                                       n->objarg = list_make1($5);
-                                       n->newschema = $9;
+                                       n->objarg = $4;
+                                       n->newschema = $7;
                                        $$ = (Node *)n;
                                }
                        | ALTER DOMAIN_P any_name SET SCHEMA name
@@ -4211,13 +4250,13 @@ AlterObjectSchemaStmt:
  *
  *****************************************************************************/
 
-AlterOwnerStmt: ALTER AGGREGATE func_name '(' aggr_argtype ')' OWNER TO RoleId
+AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
                                {
                                        AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
                                        n->objectType = OBJECT_AGGREGATE;
                                        n->object = $3;
-                                       n->objarg = list_make1($5);
-                                       n->newowner = $9;
+                                       n->objarg = $4;
+                                       n->newowner = $7;
                                        $$ = (Node *)n;
                                }
                        | ALTER CONVERSION_P any_name OWNER TO RoleId
index 35e826881fd1534a2a46ba214904c81811ee8099..d7c04620b288074c149cdfaf0d77ce11e89709f3 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.185 2006/03/14 22:48:21 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/parser/parse_func.c,v 1.186 2006/04/15 17:45:40 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1115,65 +1115,6 @@ func_signature_string(List *funcname, int nargs, const Oid *argtypes)
                                                                         nargs, argtypes);
 }
 
-/*
- * find_aggregate_func
- *             Convenience routine to check that a function exists and is an
- *             aggregate.
- *
- * Note: basetype is ANYOID if we are looking for an aggregate on
- * all types.
- */
-Oid
-find_aggregate_func(List *aggname, Oid basetype, bool noError)
-{
-       Oid                     oid;
-       HeapTuple       ftup;
-       Form_pg_proc pform;
-
-       oid = LookupFuncName(aggname, 1, &basetype, true);
-
-       if (!OidIsValid(oid))
-       {
-               if (noError)
-                       return InvalidOid;
-               if (basetype == ANYOID)
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                                        errmsg("aggregate %s(*) does not exist",
-                                                       NameListToString(aggname))));
-               else
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_UNDEFINED_FUNCTION),
-                                        errmsg("aggregate %s(%s) does not exist",
-                                                       NameListToString(aggname),
-                                                       format_type_be(basetype))));
-       }
-
-       /* Make sure it's an aggregate */
-       ftup = SearchSysCache(PROCOID,
-                                                 ObjectIdGetDatum(oid),
-                                                 0, 0, 0);
-       if (!HeapTupleIsValid(ftup))    /* should not happen */
-               elog(ERROR, "cache lookup failed for function %u", oid);
-       pform = (Form_pg_proc) GETSTRUCT(ftup);
-
-       if (!pform->proisagg)
-       {
-               ReleaseSysCache(ftup);
-               if (noError)
-                       return InvalidOid;
-               /* we do not use the (*) notation for functions... */
-               ereport(ERROR,
-                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                                errmsg("function %s(%s) is not an aggregate",
-                                         NameListToString(aggname), format_type_be(basetype))));
-       }
-
-       ReleaseSysCache(ftup);
-
-       return oid;
-}
-
 /*
  * LookupFuncName
  *             Given a possibly-qualified function name and a set of argument types,
@@ -1246,3 +1187,101 @@ LookupFuncNameTypeNames(List *funcname, List *argtypes, bool noError)
 
        return LookupFuncName(funcname, argcount, argoids, noError);
 }
+
+/*
+ * LookupAggNameTypeNames
+ *             Find an aggregate function given a name and list of TypeName nodes.
+ *
+ * This is almost like LookupFuncNameTypeNames, but the error messages refer
+ * to aggregates rather than plain functions, and we verify that the found
+ * function really is an aggregate, and we recognize the convention used by
+ * the grammar that agg(*) translates to a NIL list, which we have to treat
+ * as one ANY argument.  (XXX this ought to be changed)
+ */
+Oid
+LookupAggNameTypeNames(List *aggname, List *argtypes, bool noError)
+{
+       Oid                     argoids[FUNC_MAX_ARGS];
+       int                     argcount;
+       int                     i;
+       ListCell   *args_item;
+       Oid                     oid;
+       HeapTuple       ftup;
+       Form_pg_proc pform;
+
+       argcount = list_length(argtypes);
+       if (argcount > FUNC_MAX_ARGS)
+               ereport(ERROR,
+                               (errcode(ERRCODE_TOO_MANY_ARGUMENTS),
+                                errmsg("functions cannot have more than %d arguments",
+                                               FUNC_MAX_ARGS)));
+
+       if (argcount == 0)
+       {
+               /* special case for agg(*) */
+               argoids[0] = ANYOID;
+               argcount = 1;
+       }
+       else
+       {
+               args_item = list_head(argtypes);
+               for (i = 0; i < argcount; i++)
+               {
+                       TypeName   *t = (TypeName *) lfirst(args_item);
+
+                       argoids[i] = LookupTypeName(NULL, t);
+
+                       if (!OidIsValid(argoids[i]))
+                               ereport(ERROR,
+                                               (errcode(ERRCODE_UNDEFINED_OBJECT),
+                                                errmsg("type \"%s\" does not exist",
+                                                               TypeNameToString(t))));
+
+                       args_item = lnext(args_item);
+               }
+       }
+
+       oid = LookupFuncName(aggname, argcount, argoids, true);
+
+       if (!OidIsValid(oid))
+       {
+               if (noError)
+                       return InvalidOid;
+               if (argcount == 1 && argoids[0] == ANYOID)
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_FUNCTION),
+                                        errmsg("aggregate %s(*) does not exist",
+                                                       NameListToString(aggname))));
+               else
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_UNDEFINED_FUNCTION),
+                                        errmsg("aggregate %s does not exist",
+                                                       func_signature_string(aggname,
+                                                                                                 argcount, argoids))));
+       }
+
+       /* Make sure it's an aggregate */
+       ftup = SearchSysCache(PROCOID,
+                                                 ObjectIdGetDatum(oid),
+                                                 0, 0, 0);
+       if (!HeapTupleIsValid(ftup))    /* should not happen */
+               elog(ERROR, "cache lookup failed for function %u", oid);
+       pform = (Form_pg_proc) GETSTRUCT(ftup);
+
+       if (!pform->proisagg)
+       {
+               ReleaseSysCache(ftup);
+               if (noError)
+                       return InvalidOid;
+               /* we do not use the (*) notation for functions... */
+               ereport(ERROR,
+                               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                                errmsg("function %s is not an aggregate",
+                                               func_signature_string(aggname,
+                                                                                         argcount, argoids))));
+       }
+
+       ReleaseSysCache(ftup);
+
+       return oid;
+}
index 2a75ed24bbdd1d469d36dd613eb3d0693709d64f..b54d50702b0fc08f242e196c96a45b25bf326c72 100644 (file)
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.255 2006/03/05 15:58:40 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.256 2006/04/15 17:45:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -333,7 +333,6 @@ check_xact_readonly(Node *parsetree)
                case T_CreateTrigStmt:
                case T_CompositeTypeStmt:
                case T_ViewStmt:
-               case T_RemoveAggrStmt:
                case T_DropCastStmt:
                case T_DropStmt:
                case T_DropdbStmt:
@@ -341,7 +340,6 @@ check_xact_readonly(Node *parsetree)
                case T_RemoveFuncStmt:
                case T_DropRoleStmt:
                case T_DropPLangStmt:
-               case T_RemoveOperStmt:
                case T_RemoveOpClassStmt:
                case T_DropPropertyStmt:
                case T_GrantStmt:
@@ -730,7 +728,7 @@ ProcessUtility(Node *parsetree,
                        break;
 
                        /*
-                        * **************** object creation / destruction ******************
+                        * **************** object creation / destruction *****************
                         */
                case T_DefineStmt:
                        {
@@ -739,12 +737,15 @@ ProcessUtility(Node *parsetree,
                                switch (stmt->kind)
                                {
                                        case OBJECT_AGGREGATE:
-                                               DefineAggregate(stmt->defnames, stmt->definition);
+                                               DefineAggregate(stmt->defnames, stmt->args,
+                                                                               stmt->oldstyle, stmt->definition);
                                                break;
                                        case OBJECT_OPERATOR:
+                                               Assert(stmt->args == NIL);
                                                DefineOperator(stmt->defnames, stmt->definition);
                                                break;
                                        case OBJECT_TYPE:
+                                               Assert(stmt->args == NIL);
                                                DefineType(stmt->defnames, stmt->definition);
                                                break;
                                        default:
@@ -815,16 +816,27 @@ ProcessUtility(Node *parsetree,
                        AlterSequence((AlterSeqStmt *) parsetree);
                        break;
 
-               case T_RemoveAggrStmt:
-                       RemoveAggregate((RemoveAggrStmt *) parsetree);
-                       break;
-
                case T_RemoveFuncStmt:
-                       RemoveFunction((RemoveFuncStmt *) parsetree);
-                       break;
+                       {
+                               RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
 
-               case T_RemoveOperStmt:
-                       RemoveOperator((RemoveOperStmt *) parsetree);
+                               switch (stmt->kind)
+                               {
+                                       case OBJECT_FUNCTION:
+                                               RemoveFunction(stmt);
+                                               break;
+                                       case OBJECT_AGGREGATE:
+                                               RemoveAggregate(stmt);
+                                               break;
+                                       case OBJECT_OPERATOR:
+                                               RemoveOperator(stmt);
+                                               break;
+                                       default:
+                                               elog(ERROR, "unrecognized object type: %d",
+                                                        (int) stmt->kind);
+                                               break;
+                               }
+                       }
                        break;
 
                case T_CreatedbStmt:
@@ -1576,16 +1588,21 @@ CreateCommandTag(Node *parsetree)
                        tag = "ALTER SEQUENCE";
                        break;
 
-               case T_RemoveAggrStmt:
-                       tag = "DROP AGGREGATE";
-                       break;
-
                case T_RemoveFuncStmt:
-                       tag = "DROP FUNCTION";
-                       break;
-
-               case T_RemoveOperStmt:
-                       tag = "DROP OPERATOR";
+                       switch (((RemoveFuncStmt *) parsetree)->kind)
+                       {
+                               case OBJECT_FUNCTION:
+                                       tag = "DROP FUNCTION";
+                                       break;
+                               case OBJECT_AGGREGATE:
+                                       tag = "DROP AGGREGATE";
+                                       break;
+                               case OBJECT_OPERATOR:
+                                       tag = "DROP OPERATOR";
+                                       break;
+                               default:
+                                       tag = "???";
+                       }
                        break;
 
                case T_CreatedbStmt:
index 99e061d2defc78c7fb3b23b5807855c640e0ea80..f6ed06f3dbf292dec1b9b0617b28e98657cf9a08 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.71 2006/03/05 15:58:55 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.72 2006/04/15 17:45:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -57,22 +57,23 @@ extern void AlterFunction(AlterFunctionStmt *stmt);
 extern void CreateCast(CreateCastStmt *stmt);
 extern void DropCast(DropCastStmt *stmt);
 extern void DropCastById(Oid castOid);
-extern void AlterFunctionNamespace(List *name, List *argtypes,
+extern void AlterFunctionNamespace(List *name, List *argtypes, bool isagg,
                                           const char *newschema);
 
 /* commands/operatorcmds.c */
 extern void DefineOperator(List *names, List *parameters);
-extern void RemoveOperator(RemoveOperStmt *stmt);
+extern void RemoveOperator(RemoveFuncStmt *stmt);
 extern void RemoveOperatorById(Oid operOid);
 extern void AlterOperatorOwner(List *name, TypeName *typeName1,
                                   TypeName *typename2, Oid newOwnerId);
 extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId);
 
 /* commands/aggregatecmds.c */
-extern void DefineAggregate(List *names, List *parameters);
-extern void RemoveAggregate(RemoveAggrStmt *stmt);
-extern void RenameAggregate(List *name, TypeName *basetype, const char *newname);
-extern void AlterAggregateOwner(List *name, TypeName *basetype, Oid newOwnerId);
+extern void DefineAggregate(List *name, List *args, bool oldstyle,
+                                                       List *parameters);
+extern void RemoveAggregate(RemoveFuncStmt *stmt);
+extern void RenameAggregate(List *name, List *args, const char *newname);
+extern void AlterAggregateOwner(List *name, List *args, Oid newOwnerId);
 
 /* commands/opclasscmds.c */
 extern void DefineOpClass(CreateOpClassStmt *stmt);
index b8415378d950238a80e7ba6cea4cd2c103144e40..fe5ab018f5daf137a04911e0d31cb58ecb68be37 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.184 2006/03/07 01:00:18 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.185 2006/04/15 17:45:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -241,9 +241,7 @@ typedef enum NodeTag
        T_IndexStmt,
        T_CreateFunctionStmt,
        T_AlterFunctionStmt,
-       T_RemoveAggrStmt,
        T_RemoveFuncStmt,
-       T_RemoveOperStmt,
        T_RenameStmt,
        T_RuleStmt,
        T_NotifyStmt,
index d6f7c4a95aacd146421edbd25b76e8ceec7f20da..e4eb385df87c983a7d94162dadc1e18c1b3e19e7 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.306 2006/03/23 00:19:30 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.307 2006/04/15 17:45:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1242,7 +1242,9 @@ typedef struct DefineStmt
 {
        NodeTag         type;
        ObjectType      kind;                   /* aggregate, operator, type */
+       bool            oldstyle;               /* hack to signal old CREATE AGG syntax */
        List       *defnames;           /* qualified name (list of Value strings) */
+       List       *args;                       /* a list of TypeName (if needed) */
        List       *definition;         /* a list of DefElem */
 } DefineStmt;
 
@@ -1456,41 +1458,18 @@ typedef struct AlterFunctionStmt
 } AlterFunctionStmt;
 
 /* ----------------------
- *             Drop Aggregate Statement
- * ----------------------
- */
-typedef struct RemoveAggrStmt
-{
-       NodeTag         type;
-       List       *aggname;            /* aggregate to drop */
-       TypeName   *aggtype;            /* TypeName for input datatype, or NULL */
-       DropBehavior behavior;          /* RESTRICT or CASCADE behavior */
-} RemoveAggrStmt;
-
-/* ----------------------
- *             Drop Function Statement
+ *             Drop {Function|Aggregate|Operator} Statement
  * ----------------------
  */
 typedef struct RemoveFuncStmt
 {
        NodeTag         type;
-       List       *funcname;           /* function to drop */
+       ObjectType      kind;                   /* function, aggregate, operator */
+       List       *name;                       /* qualified name of object to drop */
        List       *args;                       /* types of the arguments */
        DropBehavior behavior;          /* RESTRICT or CASCADE behavior */
 } RemoveFuncStmt;
 
-/* ----------------------
- *             Drop Operator Statement
- * ----------------------
- */
-typedef struct RemoveOperStmt
-{
-       NodeTag         type;
-       List       *opname;                     /* operator to drop */
-       List       *args;                       /* types of the arguments */
-       DropBehavior behavior;          /* RESTRICT or CASCADE behavior */
-} RemoveOperStmt;
-
 /* ----------------------
  *             Drop Operator Class Statement
  * ----------------------
index 13aa706a044ab8ca096b0b4f013e114f229461bc..486e5ea44da88f0fb879ced55b92ba96b231ea22 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.55 2006/03/14 22:48:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_func.h,v 1.56 2006/04/15 17:45:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,11 +72,11 @@ extern const char *funcname_signature_string(const char *funcname,
 extern const char *func_signature_string(List *funcname,
                                          int nargs, const Oid *argtypes);
 
-extern Oid     find_aggregate_func(List *aggname, Oid basetype, bool noError);
-
 extern Oid LookupFuncName(List *funcname, int nargs, const Oid *argtypes,
                           bool noError);
 extern Oid LookupFuncNameTypeNames(List *funcname, List *argtypes,
                                                bool noError);
+extern Oid LookupAggNameTypeNames(List *aggname, List *argtypes,
+                                               bool noError);
 
 #endif   /* PARSE_FUNC_H */
index 8c97e4106b1343492497d166cf135bd9f3025f0b..ba5ecedc0a22d2507934cf71840cf0c465a07c9e 100644 (file)
@@ -133,7 +133,7 @@ ERROR:  function int2um(integer) does not exist
 create aggregate newcnt1 (sfunc = int4inc,
                          stype = int4,
                          initcond = '0');
-ERROR:  aggregate basetype must be specified
+ERROR:  aggregate input type must be specified
 --
 -- DROP INDEX