From 2e5fda7b7e0613b4b7c69d69b609e639deac7c17 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 3 Oct 2001 20:54:22 +0000
Subject: [PATCH] DROP AGGREGATE and COMMENT ON AGGREGATE now accept the
 expected syntax 'aggname (aggtype)'.  The old syntax 'aggname aggtype' is
 still accepted for backwards compatibility.  Fix pg_dump, which was actually
 broken for most cases of user-defined aggregates.  Clean up error messages
 associated with these commands.

---
 doc/src/sgml/ref/comment.sgml         | 13 +++---
 doc/src/sgml/ref/drop_aggregate.sgml  |  8 ++--
 src/backend/commands/comment.c        | 23 ++++------
 src/backend/commands/remove.c         | 39 +++++-----------
 src/backend/parser/analyze.c          |  8 ++--
 src/backend/parser/gram.y             | 65 ++++++++++++++-------------
 src/bin/pg_dump/common.c              | 15 ++-----
 src/bin/pg_dump/pg_dump.c             | 15 ++++---
 src/bin/pg_dump/pg_dump.h             |  3 +-
 src/interfaces/ecpg/preproc/preproc.y | 53 +++++++++++-----------
 src/test/regress/expected/errors.out  | 18 ++++----
 src/test/regress/sql/drop.sql         |  6 +--
 src/test/regress/sql/errors.sql       | 16 +++----
 src/tutorial/complex.source           |  4 +-
 14 files changed, 133 insertions(+), 153 deletions(-)

diff --git a/doc/src/sgml/ref/comment.sgml b/doc/src/sgml/ref/comment.sgml
index 0ccff62a30c..dc913d49068 100644
--- a/doc/src/sgml/ref/comment.sgml
+++ b/doc/src/sgml/ref/comment.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.9 2001/09/03 12:57:49 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/comment.sgml,v 1.10 2001/10/03 20:54:20 tgl Exp $
 Postgres documentation
 -->
 
@@ -25,11 +25,10 @@ Postgres documentation
   <synopsis>
 COMMENT ON
 [
-  [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
-  <replaceable class="PARAMETER">object_name</replaceable> |
-  COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable>|
-  AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> <replaceable class="PARAMETER">agg_type</replaceable>|
-  FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...)|
+  [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] <replaceable class="PARAMETER">object_name</replaceable> |
+  COLUMN <replaceable class="PARAMETER">table_name</replaceable>.<replaceable class="PARAMETER">column_name</replaceable> |
+  AGGREGATE <replaceable class="PARAMETER">agg_name</replaceable> (<replaceable class="PARAMETER">agg_type</replaceable>) |
+  FUNCTION <replaceable class="PARAMETER">func_name</replaceable> (<replaceable class="PARAMETER">arg1</replaceable>, <replaceable class="PARAMETER">arg2</replaceable>, ...) |
   OPERATOR <replaceable class="PARAMETER">op</replaceable> (<replaceable class="PARAMETER">leftoperand_type</replaceable> <replaceable class="PARAMETER">rightoperand_type</replaceable>) |
   TRIGGER <replaceable class="PARAMETER">trigger_name</replaceable> ON <replaceable class="PARAMETER">table_name</replaceable>
 ] IS <replaceable class="PARAMETER">'text'</replaceable>
@@ -102,7 +101,7 @@ COMMENT
    <command>COMMENT</command> adds a comment to an object that can be 
     easily retrieved with <command>psql</command>'s
     <command>\dd</command>, <command>\d+</command>, or <command>\l+</command> commands.
-    To remove a comment, use <literal>NULL</literal>.
+    To remove a comment, write <literal>NULL</literal>.
     Comments are automatically dropped when the object is dropped.
   </para>
  </refsect1>
diff --git a/doc/src/sgml/ref/drop_aggregate.sgml b/doc/src/sgml/ref/drop_aggregate.sgml
index 6b67a84fb79..937d6ac4948 100644
--- a/doc/src/sgml/ref/drop_aggregate.sgml
+++ b/doc/src/sgml/ref/drop_aggregate.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_aggregate.sgml,v 1.12 2001/09/03 12:57:49 petere Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/ref/drop_aggregate.sgml,v 1.13 2001/10/03 20:54:20 tgl Exp $
 Postgres documentation
 -->
 
@@ -23,7 +23,7 @@ Postgres documentation
    <date>1999-07-20</date>
   </refsynopsisdivinfo>
   <synopsis>
-DROP AGGREGATE <replaceable class="PARAMETER">name</replaceable> <replaceable class="PARAMETER">type</replaceable>
+DROP AGGREGATE <replaceable class="PARAMETER">name</replaceable> ( <replaceable class="PARAMETER">type</replaceable> )
   </synopsis>
 
   <refsect2 id="R2-SQL-DROPAGGREGATE-1">
@@ -81,7 +81,7 @@ DROP
      </varlistentry>
      <varlistentry>
       <term><computeroutput>
-ERROR: RemoveAggregate: aggregate '<replaceable class="parameter">agg</replaceable>' for '<replaceable class="parameter">name</replaceable>' does not exist
+ERROR: RemoveAggregate: aggregate '<replaceable class="parameter">name</replaceable>' for type <replaceable class="parameter">type</replaceable> does not exist
        </computeroutput></term>
       <listitem>
        <para>
@@ -133,7 +133,7 @@ ERROR: RemoveAggregate: aggregate '<replaceable class="parameter">agg</replaceab
    <literal>int4</literal>:
   </para>
   <programlisting>
-DROP AGGREGATE myavg int4;
+DROP AGGREGATE myavg(int4);
   </programlisting>
  </refsect1>
 
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 4bf6993d02a..14e591288a2 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -7,7 +7,7 @@
  * Copyright (c) 1999-2001, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.32 2001/08/10 18:57:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/comment.c,v 1.33 2001/10/03 20:54:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,6 +25,7 @@
 #include "catalog/pg_type.h"
 #include "commands/comment.h"
 #include "miscadmin.h"
+#include "parser/parse_agg.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_func.h"
 #include "parser/parse.h"
@@ -568,7 +569,7 @@ static void
 CommentAggregate(char *aggregate, List *arguments, char *comment)
 {
 	TypeName   *aggtype = (TypeName *) lfirst(arguments);
-	char	   *aggtypename = NULL;
+	char	   *aggtypename;
 	Oid			baseoid,
 				oid;
 	Oid			classoid;
@@ -590,12 +591,12 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
 
 	if (!pg_aggr_ownercheck(GetUserId(), aggregate, baseoid))
 	{
-		if (aggtypename)
-			elog(ERROR, "you are not permitted to comment on aggregate '%s' with type '%s'",
-				 aggregate, aggtypename);
-		else
-			elog(ERROR, "you are not permitted to comment on aggregate '%s'",
+		if (baseoid == InvalidOid)
+			elog(ERROR, "you are not permitted to comment on aggregate '%s' for all types",
 				 aggregate);
+		else
+			elog(ERROR, "you are not permitted to comment on aggregate '%s' for type %s",
+				 aggregate, format_type_be(baseoid));
 	}
 
 	/* Now, attempt to find the actual tuple in pg_aggregate */
@@ -605,13 +606,7 @@ CommentAggregate(char *aggregate, List *arguments, char *comment)
 						 ObjectIdGetDatum(baseoid),
 						 0, 0);
 	if (!OidIsValid(oid))
-	{
-		if (aggtypename)
-			elog(ERROR, "aggregate type '%s' does not exist for aggregate '%s'",
-				 aggtypename, aggregate);
-		else
-			elog(ERROR, "aggregate '%s' does not exist", aggregate);
-	}
+		agg_error("CommentAggregate", aggregate, baseoid);
 
 	/* pg_aggregate doesn't have a hard-coded OID, so must look it up */
 
diff --git a/src/backend/commands/remove.c b/src/backend/commands/remove.c
index 50b483f21fd..4e46f7f9d20 100644
--- a/src/backend/commands/remove.c
+++ b/src/backend/commands/remove.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.62 2001/08/10 18:57:34 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/remove.c,v 1.63 2001/10/03 20:54:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -22,9 +22,11 @@
 #include "commands/comment.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
+#include "parser/parse_agg.h"
 #include "parser/parse_expr.h"
 #include "parser/parse_func.h"
 #include "utils/acl.h"
+#include "utils/builtins.h"
 #include "utils/syscache.h"
 
 
@@ -354,7 +356,7 @@ RemoveAggregate(char *aggName, char *aggType)
 {
 	Relation	relation;
 	HeapTuple	tup;
-	Oid			basetypeID = InvalidOid;
+	Oid			basetypeID;
 	bool		defined;
 
 	/*
@@ -363,8 +365,7 @@ RemoveAggregate(char *aggName, char *aggType)
 	 *
 	 * else if the basetype is blank, then attempt to find an aggregate with
 	 * a basetype of zero.	This is valid. It means that the aggregate is
-	 * to apply to all basetypes.  ie, a counter of some sort.
-	 *
+	 * to apply to all basetypes (eg, COUNT).
 	 */
 
 	if (aggType)
@@ -374,20 +375,16 @@ RemoveAggregate(char *aggName, char *aggType)
 			elog(ERROR, "RemoveAggregate: type '%s' does not exist", aggType);
 	}
 	else
-		basetypeID = 0;
+		basetypeID = InvalidOid;
 
 	if (!pg_aggr_ownercheck(GetUserId(), aggName, basetypeID))
 	{
-		if (aggType)
-		{
-			elog(ERROR, "RemoveAggregate: aggregate '%s' on type '%s': permission denied",
-				 aggName, aggType);
-		}
-		else
-		{
-			elog(ERROR, "RemoveAggregate: aggregate '%s': permission denied",
+		if (basetypeID == InvalidOid)
+			elog(ERROR, "RemoveAggregate: aggregate '%s' for all types: permission denied",
 				 aggName);
-		}
+		else
+			elog(ERROR, "RemoveAggregate: aggregate '%s' for type %s: permission denied",
+				 aggName, format_type_be(basetypeID));
 	}
 
 	relation = heap_openr(AggregateRelationName, RowExclusiveLock);
@@ -398,19 +395,7 @@ RemoveAggregate(char *aggName, char *aggType)
 						 0, 0);
 
 	if (!HeapTupleIsValid(tup))
-	{
-		heap_close(relation, RowExclusiveLock);
-		if (aggType)
-		{
-			elog(ERROR, "RemoveAggregate: aggregate '%s' for '%s' does not exist",
-				 aggName, aggType);
-		}
-		else
-		{
-			elog(ERROR, "RemoveAggregate: aggregate '%s' for all types does not exist",
-				 aggName);
-		}
-	}
+		agg_error("RemoveAggregate", aggName, basetypeID);
 
 	/* Remove any comments related to this aggregate */
 	DeleteComments(tup->t_data->t_oid, RelationGetRelid(relation));
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index f8da1a4e1cc..d4af6f68619 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.199 2001/10/03 05:29:12 thomas Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.200 2001/10/03 20:54:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2811,8 +2811,10 @@ transformTypeRefsList(ParseState *pstate, List *l)
 
 	foreach(ele, l)
 	{
-		if (IsA(lfirst(ele), TypeName))
-			transformTypeRef(pstate, (TypeName *) lfirst(ele));
+		Node   *elem = lfirst(ele);
+
+		if (elem && IsA(elem, TypeName))
+			transformTypeRef(pstate, (TypeName *) elem);
 	}
 }
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 071f4bfdbda..02bb31512ea 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.257 2001/10/03 05:29:12 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.258 2001/10/03 20:54:21 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -217,8 +217,7 @@ static void doNegateFloat(Value *v);
 %type <boolean>	opt_freeze, analyze_keyword
 
 %type <ival>	copy_dirn, direction, reindex_type, drop_type,
-		opt_column, event, comment_type, comment_cl,
-		comment_ag, comment_fn, comment_op, comment_tg
+		opt_column, event, comment_type
 
 %type <ival>	fetch_how_many
 
@@ -2011,7 +2010,7 @@ TruncateStmt:  TRUNCATE opt_table relation_name
  *  the object associated with the comment. The form of the statement is:
  *
  *  COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ] 
- *               <objname> | AGGREGATE <aggname> <aggtype> | FUNCTION 
+ *               <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION 
  *		 <funcname> (arg1, arg2, ...) | OPERATOR <op> 
  *		 (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
  *		 <relname> ] IS 'text'
@@ -2028,50 +2027,61 @@ CommentStmt:	COMMENT ON comment_type name IS comment_text
 				n->comment = $6;
 				$$ = (Node *) n;
 			}
-		| COMMENT ON comment_cl relation_name '.' attr_name IS comment_text
+		| COMMENT ON COLUMN relation_name '.' attr_name IS comment_text
 			{
 				CommentStmt *n = makeNode(CommentStmt);
-				n->objtype = $3;
+				n->objtype = COLUMN;
 				n->objname = $4;
 				n->objproperty = $6;
 				n->objlist = NULL;
 				n->comment = $8;
 				$$ = (Node *) n;
 			}
-		| COMMENT ON comment_ag name aggr_argtype IS comment_text
+		| COMMENT ON AGGREGATE name '(' aggr_argtype ')' IS comment_text
 			{
 				CommentStmt *n = makeNode(CommentStmt);
-				n->objtype = $3;
+				n->objtype = AGGREGATE;
+				n->objname = $4;
+				n->objproperty = NULL;
+				n->objlist = makeList1($6);
+				n->comment = $9;
+				$$ = (Node *) n;
+			}
+		| COMMENT ON AGGREGATE name aggr_argtype IS comment_text
+			{
+				/* Obsolete syntax, but must support for awhile */
+				CommentStmt *n = makeNode(CommentStmt);
+				n->objtype = AGGREGATE;
 				n->objname = $4;
 				n->objproperty = NULL;
 				n->objlist = makeList1($5);
 				n->comment = $7;
 				$$ = (Node *) n;
 			}
-		| COMMENT ON comment_fn func_name func_args IS comment_text
+		| COMMENT ON FUNCTION func_name func_args IS comment_text
 			{
 				CommentStmt *n = makeNode(CommentStmt);
-				n->objtype = $3;
+				n->objtype = FUNCTION;
 				n->objname = $4;
 				n->objproperty = NULL;
 				n->objlist = $5;
 				n->comment = $7;
 				$$ = (Node *) n;
 			}
-		| COMMENT ON comment_op all_Op '(' oper_argtypes ')' IS comment_text
+		| COMMENT ON OPERATOR all_Op '(' oper_argtypes ')' IS comment_text
 			{
 				CommentStmt *n = makeNode(CommentStmt);
-				n->objtype = $3;
+				n->objtype = OPERATOR;
 				n->objname = $4;
 				n->objproperty = NULL;
 				n->objlist = $6;
 				n->comment = $9;
 				$$ = (Node *) n;
 			}
-		| COMMENT ON comment_tg name ON relation_name IS comment_text
+		| COMMENT ON TRIGGER name ON relation_name IS comment_text
 			{
 				CommentStmt *n = makeNode(CommentStmt);
-				n->objtype = $3;
+				n->objtype = TRIGGER;
 				n->objname = $4;
 				n->objproperty = $6;
 				n->objlist = NULL;
@@ -2089,21 +2099,6 @@ comment_type:	DATABASE { $$ = DATABASE; }
 		| VIEW { $$ = VIEW; }
 		;		
 
-comment_cl:	COLUMN { $$ = COLUMN; }
-		;
-
-comment_ag:	AGGREGATE { $$ = AGGREGATE; }
-		;
-
-comment_fn:	FUNCTION { $$ = FUNCTION; }
-		;
-
-comment_op:	OPERATOR { $$ = OPERATOR; }
-		;
-
-comment_tg:	TRIGGER { $$ = TRIGGER; }
-		; 
-
 comment_text:	Sconst { $$ = $1; }
 		| NULL_P { $$ = NULL; }
 		;
@@ -2601,7 +2596,7 @@ func_type:	Typename
  *		QUERY:
  *
  *		DROP FUNCTION funcname (arg1, arg2, ...)
- *		DROP AGGREGATE aggname aggtype
+ *		DROP AGGREGATE aggname (aggtype)
  *		DROP OPERATOR opname (leftoperand_typ rightoperand_typ)
  *
  *****************************************************************************/
@@ -2615,8 +2610,16 @@ RemoveFuncStmt:  DROP FUNCTION func_name func_args
 				}
 		;
 
-RemoveAggrStmt:  DROP AGGREGATE func_name aggr_argtype
+RemoveAggrStmt:  DROP AGGREGATE func_name '(' aggr_argtype ')'
+				{
+						RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
+						n->aggname = $3;
+						n->aggtype = (Node *) $5;
+						$$ = (Node *)n;
+				}
+		| DROP AGGREGATE func_name aggr_argtype
 				{
+						/* Obsolete syntax, but must support for awhile */
 						RemoveAggrStmt *n = makeNode(RemoveAggrStmt);
 						n->aggname = $3;
 						n->aggtype = (Node *) $4;
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 2fc9430630a..f1ba9aed4b4 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.57 2001/07/03 20:21:47 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.58 2001/10/03 20:54:21 tgl Exp $
  *
  * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
  *
@@ -56,7 +56,7 @@ static int	strInArray(const char *pattern, char **arr, int arr_size);
  * findTypeByOid
  *	  given an oid of a type, return its typename
  *
- * if oid is "0", return "opaque" -- this is a special case
+ * Can return various special cases for oid 0.
  *
  * NOTE:  should hash this, but just do linear search for now
  */
@@ -68,19 +68,12 @@ findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts)
 
 	if (strcmp(oid, "0") == 0)
 	{
-
 		if ((opts & zeroAsOpaque) != 0)
-		{
-
 			return g_opaque_type;
-
-		}
 		else if ((opts & zeroAsAny) != 0)
-		{
-
 			return "'any'";
-
-		}
+		else if ((opts & zeroAsStar) != 0)
+			return "*";
 	}
 
 	for (i = 0; i < numTypes; i++)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index a510293b8ce..8da63e6e651 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.232 2001/10/03 05:23:12 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.233 2001/10/03 20:54:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3706,7 +3706,9 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
 
 		resetPQExpBuffer(aggSig);
 		appendPQExpBuffer(aggSig, "%s(%s)", agginfo[i].aggname,
-						  findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName));
+						  findTypeByOid(tinfo, numTypes,
+										agginfo[i].aggbasetype,
+										zeroAsStar + useBaseTypeName));
 
 		if (!agginfo[i].convertok)
 		{
@@ -3721,7 +3723,8 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
 			continue;
 		}
 
-		name = findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsAny + useBaseTypeName);
+		name = findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype,
+							 zeroAsAny + useBaseTypeName);
 		if (name == NULL)
 		{
 			write_msg(NULL, "WARNING: aggregate function \"%s\" (oid %s) not dumped\n",
@@ -3738,7 +3741,8 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
 		}
 		appendPQExpBuffer(details, "BASETYPE = %s, ", name);
 
-		name = findTypeByOid(tinfo, numTypes, agginfo[i].aggtranstype, zeroAsOpaque + useBaseTypeName);
+		name = findTypeByOid(tinfo, numTypes, agginfo[i].aggtranstype,
+							 zeroAsOpaque + useBaseTypeName);
 		if (name == NULL)
 		{
 			write_msg(NULL, "WARNING: aggregate function \"%s\" (oid %s) not dumped\n",
@@ -3781,8 +3785,7 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
 		/*** Dump Aggregate Comments ***/
 
 		resetPQExpBuffer(q);
-		appendPQExpBuffer(q, "AGGREGATE %s %s", agginfo[i].aggname,
-						  findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName));
+		appendPQExpBuffer(q, "AGGREGATE %s", aggSig->data);
 		dumpComment(fout, q->data, agginfo[i].oid, "pg_aggregate", 0, NULL);
 	}
 
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 02833d37985..1282045895e 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_dump.h,v 1.71 2001/10/01 21:31:52 tgl Exp $
+ * $Id: pg_dump.h,v 1.72 2001/10/03 20:54:21 tgl Exp $
  *
  * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
  *
@@ -223,6 +223,7 @@ typedef enum _OidOptions
 {
 	zeroAsOpaque = 1,
 	zeroAsAny = 2,
+	zeroAsStar = 4,
 	useBaseTypeName = 1024
 } OidOptions;
 
diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y
index f6ef9749225..881f0c042e2 100644
--- a/src/interfaces/ecpg/preproc/preproc.y
+++ b/src/interfaces/ecpg/preproc/preproc.y
@@ -327,15 +327,15 @@ make_name(void)
 %type  <str>	createdb_opt_list opt_encoding OptInherit Geometric
 %type  <str>    DropdbStmt ClusterStmt grantee RevokeStmt Bit bit
 %type  <str>	GrantStmt privileges operation_commalist operation PosAllConst
-%type  <str>	opt_cursor ConstraintsSetStmt comment_tg AllConst
+%type  <str>	opt_cursor ConstraintsSetStmt AllConst
 %type  <str>	case_expr when_clause_list case_default case_arg when_clause
 %type  <str>    select_clause opt_select_limit select_limit_value ConstraintTimeSpec
 %type  <str>    select_offset_value ReindexStmt join_type opt_boolean
 %type  <str>	join_qual update_list AlterSchemaStmt joined_table
 %type  <str>	opt_level opt_lock lock_type OptGroupList OptGroupElem
-%type  <str>    OptConstrFromTable comment_op OptTempTableName StringConst
-%type  <str>    constraints_set_list constraints_set_namelist comment_fn
-%type  <str>	constraints_set_mode comment_type comment_cl comment_ag
+%type  <str>    OptConstrFromTable OptTempTableName StringConst
+%type  <str>    constraints_set_list constraints_set_namelist
+%type  <str>	constraints_set_mode comment_type
 %type  <str>	CreateGroupStmt AlterGroupStmt DropGroupStmt key_delete
 %type  <str>	opt_force key_update CreateSchemaStmt PosIntStringConst
 %type  <str>    IntConst PosIntConst grantee_list func_type opt_or_replace
@@ -1635,7 +1635,7 @@ from_in:   IN 	{ $$ = make_str("in"); }
  *  the object associated with the comment. The form of the statement is:
  *
  *  COMMENT ON [ [ DATABASE | INDEX | RULE | SEQUENCE | TABLE | TYPE | VIEW ]
- *               <objname> | AGGREGATE <aggname> <aggtype> | FUNCTION
+ *               <objname> | AGGREGATE <aggname> (<aggtype>) | FUNCTION
  *              <funcname> (arg1, arg2, ...) | OPERATOR <op>
  *              (leftoperand_typ rightoperand_typ) | TRIGGER <triggername> ON
  *              <relname> ] IS 'text'
@@ -1645,25 +1645,29 @@ CommentStmt:   COMMENT ON comment_type name IS comment_text
                         {
                                 $$ = cat_str(5, make_str("comment on"), $3, $4, make_str("is"), $6);
                         }
-                | COMMENT ON comment_cl relation_name '.' attr_name IS comment_text
+                | COMMENT ON COLUMN relation_name '.' attr_name IS comment_text
                         { 
-                                $$ = cat_str(7, make_str("comment on"), $3, $4, make_str("."), $6, make_str("is"), $8);
+                                $$ = cat_str(6, make_str("comment on column"), $4, make_str("."), $6, make_str("is"), $8);
 			}
-                | COMMENT ON comment_ag name aggr_argtype IS comment_text
+                | COMMENT ON AGGREGATE name '(' aggr_argtype ')' IS comment_text
                         {
-                                $$ = cat_str(6, make_str("comment on"), $3, $4, $5, make_str("is"), $7);
+                                $$ = cat_str(6, make_str("comment on aggregate"), $4, make_str("("), $6, make_str(") is"), $9);
 			}
-		| COMMENT ON comment_fn func_name func_args IS comment_text
+                | COMMENT ON AGGREGATE name aggr_argtype IS comment_text
+                        {
+                                $$ = cat_str(5, make_str("comment on aggregate"), $4, $5, make_str("is"), $7);
+			}
+		| COMMENT ON FUNCTION func_name func_args IS comment_text
 			{
-                                $$ = cat_str(6, make_str("comment on"), $3, $4, $5, make_str("is"), $7);
+                                $$ = cat_str(5, make_str("comment on function"), $4, $5, make_str("is"), $7);
 			}
-		| COMMENT ON comment_op all_Op '(' oper_argtypes ')' IS comment_text
+		| COMMENT ON OPERATOR all_Op '(' oper_argtypes ')' IS comment_text
 			{
-				$$ = cat_str(7, make_str("comment on"), $3, $4, make_str("("), $6, make_str(") is"), $9);
+				$$ = cat_str(6, make_str("comment on operator"), $4, make_str("("), $6, make_str(") is"), $9);
 			}
-		| COMMENT ON comment_tg name ON relation_name IS comment_text
+		| COMMENT ON TRIGGER name ON relation_name IS comment_text
                         {
-                                $$ = cat_str(7, make_str("comment on"), $3, $4, make_str("on"), $6, make_str("is"), $8);
+                                $$ = cat_str(6, make_str("comment on trigger"), $4, make_str("on"), $6, make_str("is"), $8);
 			}
 			;
 
@@ -1676,16 +1680,6 @@ comment_type:  DATABASE 	{ $$ = make_str("database"); }
                 | VIEW		{ $$ = make_str("view"); }
 		;
 
-comment_cl:    COLUMN		{ $$ = make_str("column"); }
-
-comment_ag:    AGGREGATE	{ $$ = make_str("aggregate"); }
-
-comment_fn:    FUNCTION		{ $$ = make_str("function"); }
-
-comment_op:    OPERATOR		{ $$ = make_str("operator"); }
-
-comment_tg:    TRIGGER		{ $$ = make_str("trigger"); }
-
 comment_text:    StringConst		{ $$ = $1; }
                | NULL_P		{ $$ = make_str("null"); }
                ;
@@ -1967,7 +1961,7 @@ func_type:	Typename
  *		QUERY:
  *
  *             DROP FUNCTION funcname (arg1, arg2, ...)
- *             DROP AGGREGATE aggname aggtype
+ *             DROP AGGREGATE aggname (aggtype)
  *             DROP OPERATOR opname (leftoperand_typ rightoperand_typ) 
  *
  *****************************************************************************/
@@ -1978,8 +1972,13 @@ RemoveFuncStmt:  DROP FUNCTION func_name func_args
 				}
 		;
 
-RemoveAggrStmt:  DROP AGGREGATE func_name aggr_argtype
+RemoveAggrStmt:  DROP AGGREGATE func_name '(' aggr_argtype ')'
+				{
+						$$ = cat_str(5, make_str("drop aggregate"), $3, make_str("("), $5, make_str(")"));
+				}
+		| DROP AGGREGATE func_name aggr_argtype
 				{
+						/* Obsolete syntax, but must support for awhile */
 						$$ = cat_str(3, make_str("drop aggregate"), $3, $4);
 				}
 		;
diff --git a/src/test/regress/expected/errors.out b/src/test/regress/expected/errors.out
index b3396b5ec61..f652fb1eb05 100644
--- a/src/test/regress/expected/errors.out
+++ b/src/test/regress/expected/errors.out
@@ -129,21 +129,21 @@ ERROR:  index "nonesuch" does not exist
 -- missing aggregate name 
 drop aggregate;
 ERROR:  parser: parse error at or near ";"
--- bad aggregate name 
-drop aggregate 314159;
-ERROR:  parser: parse error at or near "314159"
--- no such aggregate 
-drop aggregate nonesuch;
-ERROR:  parser: parse error at or near ";"
 -- missing aggregate type
 drop aggregate newcnt1;
 ERROR:  parser: parse error at or near ";"
+-- bad aggregate name 
+drop aggregate 314159 (int);
+ERROR:  parser: parse error at or near "314159"
 -- bad aggregate type
-drop aggregate newcnt nonesuch;
+drop aggregate newcnt (nonesuch);
 ERROR:  RemoveAggregate: type 'nonesuch' does not exist
+-- no such aggregate 
+drop aggregate nonesuch (int4);
+ERROR:  RemoveAggregate: aggregate 'nonesuch' for type integer does not exist
 -- no such aggregate for type
-drop aggregate newcnt float4;
-ERROR:  RemoveAggregate: aggregate 'newcnt' for 'float4' does not exist
+drop aggregate newcnt (float4);
+ERROR:  RemoveAggregate: aggregate 'newcnt' for type real does not exist
 --
 -- REMOVE FUNCTION
  
diff --git a/src/test/regress/sql/drop.sql b/src/test/regress/sql/drop.sql
index fc89483208e..a466e6f7c21 100644
--- a/src/test/regress/sql/drop.sql
+++ b/src/test/regress/sql/drop.sql
@@ -73,11 +73,11 @@ DROP TYPE widget;
 --
 -- AGGREGATE REMOVAL
 --
-DROP AGGREGATE newavg int4;
+DROP AGGREGATE newavg (int4);
 
-DROP AGGREGATE newsum int4;
+DROP AGGREGATE newsum (int4);
 
-DROP AGGREGATE newcnt int4;
+DROP AGGREGATE newcnt (int4);
 
 
 --
diff --git a/src/test/regress/sql/errors.sql b/src/test/regress/sql/errors.sql
index 86c4e4fe60f..949f6405998 100644
--- a/src/test/regress/sql/errors.sql
+++ b/src/test/regress/sql/errors.sql
@@ -147,20 +147,20 @@ drop index nonesuch;
 -- missing aggregate name 
 drop aggregate;
 
--- bad aggregate name 
-drop aggregate 314159;
-
--- no such aggregate 
-drop aggregate nonesuch;
-
 -- missing aggregate type
 drop aggregate newcnt1;
 
+-- bad aggregate name 
+drop aggregate 314159 (int);
+
 -- bad aggregate type
-drop aggregate newcnt nonesuch;
+drop aggregate newcnt (nonesuch);
+
+-- no such aggregate 
+drop aggregate nonesuch (int4);
 
 -- no such aggregate for type
-drop aggregate newcnt float4;
+drop aggregate newcnt (float4);
 
 
 --
diff --git a/src/tutorial/complex.source b/src/tutorial/complex.source
index fb6bb9fde97..fdd66506671 100644
--- a/src/tutorial/complex.source
+++ b/src/tutorial/complex.source
@@ -7,7 +7,7 @@
 --
 -- Copyright (c) 1994, Regents of the University of California
 --
--- $Id: complex.source,v 1.9 2001/08/21 16:36:06 tgl Exp $
+-- $Id: complex.source,v 1.10 2001/10/03 20:54:22 tgl Exp $
 --
 ---------------------------------------------------------------------------
 
@@ -285,6 +285,6 @@ DROP OPERATOR <= (complex, complex);
 DROP OPERATOR = (complex, complex);
 DROP OPERATOR >= (complex, complex);
 DROP OPERATOR > (complex, complex);
-DROP AGGREGATE complex_sum complex;
+DROP AGGREGATE complex_sum (complex);
 DROP TYPE complex;
 DROP TABLE test_complex, complex_ops_tmp;
-- 
GitLab