diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 9ebf207199c4f895300c58d43821a317903bb694..dc8247691ab8c504f581b3adc64c2e2bfe84794e 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -19,6 +19,7 @@
 #include "catalog/pg_aggregate.h"
 #include "catalog/pg_database.h"
 #include "catalog/pg_description.h"
+#include "catalog/pg_operator.h"
 #include "catalog/pg_proc.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_shadow.h"
@@ -658,6 +659,7 @@ void CommentProc(char *function, List *arguments, char *comment)
 
 void CommentOperator(char *opername, List *arguments, char *comment) {
 
+  Form_pg_operator data;
   HeapTuple optuple;
   Oid oid, leftoid = InvalidOid, rightoid = InvalidOid;
   bool defined;
@@ -719,6 +721,14 @@ void CommentOperator(char *opername, List *arguments, char *comment) {
   }
   #endif
 
+  /*** Get the procedure associated with the operator ***/
+
+  data = (Form_pg_operator) GETSTRUCT(optuple);
+  oid = regproctooid(data->oprcode);
+  if (oid == InvalidOid) {
+	  elog(ERROR, "operator '%s' does not have an underlying function", opername);
+  }
+  
   /*** Call CreateComments() to create/drop the comments ***/
 
   CreateComments(oid, comment);
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 9b6d6414188530346bc51145627f2c0d3a3275d0..f111ca57ab7c0ea6d4f0e24122a9874f47ae4d9e 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.38 2000/01/18 07:29:58 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.39 2000/01/18 18:09:02 momjian Exp $
  *
  * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
  *
@@ -289,6 +289,14 @@ dumpSchema(FILE *fout,
 				g_comment_start, g_comment_end);
 	flagInhAttrs(tblinfo, numTables, inhinfo, numInherits);
 
+	if (!tablename && fout)
+	{
+		if (g_verbose)
+			fprintf(stderr, "%s dumping out database comment %s\n",
+					g_comment_start, g_comment_end);
+		dumpDBComment(fout);
+	}
+
 	if (!tablename && fout)
 	{
 		if (g_verbose)
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 82e55c3bfcbad2c2d663b940144856411150298f..a4f2676edd71e9989a6f2b0f70ffdbc688c959f2 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -21,7 +21,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.134 2000/01/18 07:29:58 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.135 2000/01/18 18:09:02 momjian Exp $
  *
  * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
  *
@@ -78,6 +78,7 @@
 
 #include "pg_dump.h"
 
+static void dumpComment(FILE *outfile, const char *target, const char *oid);
 static void dumpSequence(FILE *fout, TableInfo tbinfo);
 static void dumpACL(FILE *fout, TableInfo tbinfo);
 static void dumpTriggers(FILE *fout, const char *tablename,
@@ -1136,6 +1137,8 @@ clearTableInfo(TableInfo *tblinfo, int numTables)
 		/* Process Attributes */
 		for (j = 0; j < tblinfo[i].numatts; j++)
 		{
+			if (tblinfo[i].attoids[j])
+				free(tblinfo[i].attoids[j]);
 			if (tblinfo[i].attnames[j])
 				free(tblinfo[i].attnames[j]);
 			if (tblinfo[i].typnames[j])
@@ -1225,6 +1228,8 @@ clearIndInfo(IndInfo *ind, int numIndices)
 		return;
 	for (i = 0; i < numIndices; ++i)
 	{
+		if (ind[i].indoid)
+			free(ind[i].indoid);
 		if (ind[i].indexrelname)
 			free(ind[i].indexrelname);
 		if (ind[i].indrelname)
@@ -1692,7 +1697,8 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 		if (tblinfo[i].ntrig > 0)
 		{
 			PGresult   *res2;
-			int			i_tgname,
+			int			i_tgoid,
+				        i_tgname,
 						i_tgfoid,
 						i_tgtype,
 						i_tgnargs,
@@ -1707,7 +1713,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 						g_comment_end);
 
 			resetPQExpBuffer(query);
-			appendPQExpBuffer(query, "SELECT tgname, tgfoid, tgtype, tgnargs, tgargs "
+			appendPQExpBuffer(query, "SELECT tgname, tgfoid, tgtype, tgnargs, tgargs, oid "
 					"from pg_trigger "
 					"where tgrelid = '%s'::oid ",
 					tblinfo[i].oid);
@@ -1730,7 +1736,10 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 			i_tgtype = PQfnumber(res2, "tgtype");
 			i_tgnargs = PQfnumber(res2, "tgnargs");
 			i_tgargs = PQfnumber(res2, "tgargs");
+			i_tgoid = PQfnumber(res2, "oid");
 			tblinfo[i].triggers = (char **) malloc(ntups2 * sizeof(char *));
+			tblinfo[i].trcomments = (char **) malloc(ntups2 * sizeof(char *));
+			tblinfo[i].troids = (char **) malloc(ntups2 * sizeof(char *));
 			resetPQExpBuffer(query);
 			for (i2 = 0; i2 < ntups2; i2++)
 			{
@@ -1842,11 +1851,27 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 				}
 				appendPQExpBuffer(query, ");\n");
 				tblinfo[i].triggers[i2] = strdup(query->data);
+
+				/*** Initialize trcomments and troids ***/
+				
+				resetPQExpBuffer(query);
+				appendPQExpBuffer(query, "TRIGGER %s ", 
+								  fmtId(PQgetvalue(res2, i2, i_tgname), force_quotes));
+				appendPQExpBuffer(query, "ON %s",
+								  fmtId(tblinfo[i].relname, force_quotes));
+				tblinfo[i].trcomments[i2] = strdup(query->data);
+				tblinfo[i].troids[i2] = strdup(PQgetvalue(res2, i2, i_tgoid));
+
 			}
 			PQclear(res2);
 		}
 		else
+		{
 			tblinfo[i].triggers = NULL;
+			tblinfo[i].trcomments = NULL;
+			tblinfo[i].troids = NULL;
+		}
+		  
 	}
 
 	PQclear(res);
@@ -1928,6 +1953,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 	int			i_atttypmod;
 	int			i_attnotnull;
 	int			i_atthasdef;
+	int         i_attoid;
 	PGresult	*res;
 	int			ntups;
 
@@ -1951,7 +1977,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 					g_comment_end);
 
 		resetPQExpBuffer(q);
-		appendPQExpBuffer(q, "SELECT a.attnum, a.attname, t.typname, a.atttypmod, "
+		appendPQExpBuffer(q, "SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, "
 				"a.attnotnull, a.atthasdef "
 				"from pg_attribute a, pg_type t "
 				"where a.attrelid = '%s'::oid and a.atttypid = t.oid "
@@ -1967,6 +1993,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
 		ntups = PQntuples(res);
 
+		i_attoid = PQfnumber(res, "attoid");
 		i_attname = PQfnumber(res, "attname");
 		i_typname = PQfnumber(res, "typname");
 		i_atttypmod = PQfnumber(res, "atttypmod");
@@ -1974,6 +2001,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		i_atthasdef = PQfnumber(res, "atthasdef");
 
 		tblinfo[i].numatts = ntups;
+		tblinfo[i].attoids = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].attnames = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].typnames = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].atttypmod = (int *) malloc(ntups * sizeof(int));
@@ -1984,6 +2012,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		tblinfo[i].numParents = 0;
 		for (j = 0; j < ntups; j++)
 		{
+			tblinfo[i].attoids[j] = strdup(PQgetvalue(res, j, i_attoid));
 			tblinfo[i].attnames[j] = strdup(PQgetvalue(res, j, i_attname));
 			tblinfo[i].typnames[j] = strdup(PQgetvalue(res, j, i_typname));
 			tblinfo[i].atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
@@ -2047,6 +2076,7 @@ getIndices(int *numIndices)
 	int			i_indkey;
 	int			i_indclass;
 	int			i_indisunique;
+	int         i_indoid;
 
 	/*
 	 * find all the user-defined indices. We do not handle partial
@@ -2058,7 +2088,7 @@ getIndices(int *numIndices)
 	 */
 
 	appendPQExpBuffer(query,
-	    "SELECT t1.relname as indexrelname, t2.relname as indrelname, "
+	    "SELECT t1.oid as indoid, t1.relname as indexrelname, t2.relname as indrelname, "
 			"i.indproc, i.indkey, i.indclass, "
 			"a.amname as indamname, i.indisunique "
 			"from pg_index i, pg_class t1, pg_class t2, pg_am a "
@@ -2083,6 +2113,7 @@ getIndices(int *numIndices)
 
 	memset((char *) indinfo, 0, ntups * sizeof(IndInfo));
 
+	i_indoid = PQfnumber(res, "indoid");
 	i_indexrelname = PQfnumber(res, "indexrelname");
 	i_indrelname = PQfnumber(res, "indrelname");
 	i_indamname = PQfnumber(res, "indamname");
@@ -2093,6 +2124,7 @@ getIndices(int *numIndices)
 
 	for (i = 0; i < ntups; i++)
 	{
+		indinfo[i].indoid = strdup(PQgetvalue(res, i, i_indoid));
 		indinfo[i].indexrelname = strdup(PQgetvalue(res, i, i_indexrelname));
 		indinfo[i].indrelname = strdup(PQgetvalue(res, i, i_indrelname));
 		indinfo[i].indamname = strdup(PQgetvalue(res, i, i_indamname));
@@ -2109,6 +2141,100 @@ getIndices(int *numIndices)
 	return indinfo;
 }
 
+/*------------------------------------------------------------------
+ * dumpComments -- 
+ *
+ * This routine is used to dump any comments associated with the 
+ * oid handed to this routine. The routine takes a constant character
+ * string for the target part of the object and the oid of the object
+ * whose comments are to be dumped. It is perfectly acceptable
+ * to hand an oid to this routine which has not been commented. In
+ * addition, the routine takes the stdio FILE handle to which the 
+ * output should be written.
+ *------------------------------------------------------------------
+*/
+
+void dumpComment(FILE *fout, const char *target, const char *oid) {
+
+	PGresult *res;
+	PQExpBuffer query;
+	int i_description;
+
+	/*** Build query to find comment ***/
+
+	query = createPQExpBuffer();
+	appendPQExpBuffer(query, "SELECT description FROM pg_description WHERE objoid = ");
+	appendPQExpBuffer(query, oid);
+
+	/*** Execute query ***/
+
+	res = PQexec(g_conn, query->data);
+	if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
+		fprintf(stderr, "DumpComment: SELECT failed: '%s'.\n",
+				PQerrorMessage(g_conn));
+		exit_nicely(g_conn);
+	}
+
+	/*** If a comment exists, build COMMENT ON statement ***/
+
+	if (PQntuples(res) != 0) {
+		i_description = PQfnumber(res, "description");
+		fprintf(fout, "COMMENT ON %s IS '%s';\n", 
+				target, checkForQuote(PQgetvalue(res, 0, i_description)));
+	}
+
+	/*** Clear the statement buffer and return ***/
+
+	PQclear(res);
+    
+}
+
+/*------------------------------------------------------------------
+ * dumpDBComment -- 
+ *
+ * This routine is used to dump any comments associated with the 
+ * database to which we are currently connected. If the user chose 
+ * to dump the schema of the database, then this is the first
+ * statement issued.
+ *------------------------------------------------------------------
+*/
+
+void dumpDBComment(FILE *fout) {
+
+	PGresult *res;
+	PQExpBuffer query;
+	int i_oid;
+
+	/*** Build query to find comment ***/
+
+	query = createPQExpBuffer();
+	appendPQExpBuffer(query, "SELECT oid FROM pg_database WHERE datname = '%s'",
+					  PQdb(g_conn));
+
+	/*** Execute query ***/
+
+	res = PQexec(g_conn, query->data);
+	if (!res || PQresultStatus(res) != PGRES_TUPLES_OK) {
+		fprintf(stderr, "dumpDBComment: SELECT failed: '%s'.\n",
+				PQerrorMessage(g_conn));
+		exit_nicely(g_conn);
+	}
+
+	/*** If a comment exists, build COMMENT ON statement ***/
+
+	if (PQntuples(res) != 0) {
+		i_oid = PQfnumber(res, "oid");
+		resetPQExpBuffer(query);
+		appendPQExpBuffer(query, "DATABASE %s", fmtId(PQdb(g_conn), force_quotes));
+		dumpComment(fout, query->data, PQgetvalue(res, 0, i_oid));
+	}
+
+	/*** Clear the statement buffer and return ***/
+
+	PQclear(res);
+	
+}
+
 /*
  * dumpTypes
  *	  writes out to fout the queries to recreate all the user-defined types
@@ -2188,6 +2314,13 @@ dumpTypes(FILE *fout, FuncInfo *finfo, int numFuncs,
 			appendPQExpBuffer(q, ");\n");
 
 		fputs(q->data, fout);
+
+		/*** Dump Type Comments ***/
+
+		resetPQExpBuffer(q);
+		appendPQExpBuffer(q, "TYPE %s", fmtId(tinfo[i].typname, force_quotes));
+		dumpComment(fout, q->data, tinfo[i].oid);
+
 	}
 }
 
@@ -2294,6 +2427,7 @@ dumpOneFunc(FILE *fout, FuncInfo *finfo, int i,
 			TypeInfo *tinfo, int numTypes)
 {
 	PQExpBuffer	q = createPQExpBuffer();
+	PQExpBuffer fnlist = createPQExpBuffer();
 	int			j;
 	char		*func_def;
 	char		func_lang[NAMEDATALEN + 1];
@@ -2381,6 +2515,9 @@ dumpOneFunc(FILE *fout, FuncInfo *finfo, int i,
 		appendPQExpBuffer(q, "%s%s",
 				(j > 0) ? "," : "",
 				fmtId(typname, false));
+		appendPQExpBuffer(fnlist, "%s%s",
+						  (j > 0) ? "," : "",
+						  fmtId(typname, false));
 	}
 	appendPQExpBuffer(q, " ) RETURNS %s%s AS '%s' LANGUAGE '%s';\n",
 			(finfo[i].retset) ? " SETOF " : "",
@@ -2389,6 +2526,14 @@ dumpOneFunc(FILE *fout, FuncInfo *finfo, int i,
 
 	fputs(q->data, fout);
 
+	/*** Dump Function Comments ***/
+
+	resetPQExpBuffer(q);
+	appendPQExpBuffer(q, "FUNCTION %s ",
+					  fmtId(finfo[i].proname, force_quotes));
+	appendPQExpBuffer(q, "( %s )", fnlist->data);
+	dumpComment(fout, q->data, finfo[i].oid);
+
 }
 
 /*
@@ -2602,6 +2747,14 @@ dumpAggs(FILE *fout, AggInfo *agginfo, int numAggs,
 				finalfunc->data);
 
 		fputs(q->data, fout);
+
+		/*** Dump Aggregate Comments ***/
+
+		resetPQExpBuffer(q);
+		appendPQExpBuffer(q, "AGGREGATE %s %s", agginfo[i].aggname, 
+						  fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype), false));
+		dumpComment(fout, q->data, agginfo[i].oid);
+
 	}
 }
 
@@ -2918,6 +3071,22 @@ dumpTables(FILE *fout, TableInfo *tblinfo, int numTables,
 			if (!aclsSkip)
 				dumpACL(fout, tblinfo[i]);
 
+			  /* Dump Field Comments */
+
+			for (j = 0; j < tblinfo[i].numatts; j++) {	     	   
+				resetPQExpBuffer(q);
+				appendPQExpBuffer(q, "COLUMN %s", fmtId(tblinfo[i].relname, force_quotes));
+				appendPQExpBuffer(q, ".");
+				appendPQExpBuffer(q, "%s", fmtId(tblinfo[i].attnames[j], force_quotes));
+				dumpComment(fout, q->data, tblinfo[i].attoids[j]);
+			}
+	  
+			/* Dump Table Comments */
+			
+			resetPQExpBuffer(q);
+			appendPQExpBuffer(q, "TABLE %s", fmtId(tblinfo[i].relname, force_quotes));
+			dumpComment(fout, q->data, tblinfo[i].oid);
+			
 		}
 	}
 }
@@ -3086,6 +3255,13 @@ dumpIndices(FILE *fout, IndInfo *indinfo, int numIndices,
 			}
 			else
 				fprintf(fout, " %s );\n", attlist->data);
+
+			/* Dump Index Comments */
+
+			resetPQExpBuffer(q);
+			appendPQExpBuffer(q, "INDEX %s", id1->data);
+			dumpComment(fout, q->data, indinfo[i].indoid);
+			
 		}
 	}
 
@@ -3354,6 +3530,12 @@ dumpSequence(FILE *fout, TableInfo tbinfo)
 
 	fputs(query->data, fout);
 
+	/* Dump Sequence Comments */
+
+	resetPQExpBuffer(query);
+	appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo.relname, force_quotes));
+	dumpComment(fout, query->data, tbinfo.oid);
+
 	if (called == 'f')
 		return;					/* nothing to do more */
 
@@ -3383,6 +3565,7 @@ dumpTriggers(FILE *fout, const char *tablename,
 		{
 			becomeUser(fout, tblinfo[i].usename);
 			fputs(tblinfo[i].triggers[j], fout);
+			dumpComment(fout, tblinfo[i].trcomments[j], tblinfo[i].troids[j]);
 		}
 	}
 }
@@ -3399,6 +3582,8 @@ dumpRules(FILE *fout, const char *tablename,
 	PQExpBuffer	query = createPQExpBuffer();
 
 	int			i_definition;
+	int         i_oid;
+	int         i_rulename;
 
 	if (g_verbose)
 		fprintf(stderr, "%s dumping out rules %s\n",
@@ -3417,7 +3602,7 @@ dumpRules(FILE *fout, const char *tablename,
 		 */
 		resetPQExpBuffer(query);
 		appendPQExpBuffer(query, "SELECT pg_get_ruledef(pg_rewrite.rulename) "
-				"AS definition FROM pg_rewrite, pg_class "
+				"AS definition, pg_rewrite.oid, pg_rewrite.rulename FROM pg_rewrite, pg_class "
 				"WHERE pg_class.relname = '%s' "
 				"AND pg_rewrite.ev_class = pg_class.oid "
 				"ORDER BY pg_rewrite.oid",
@@ -3433,13 +3618,25 @@ dumpRules(FILE *fout, const char *tablename,
 
 		nrules = PQntuples(res);
 		i_definition = PQfnumber(res, "definition");
+		i_oid = PQfnumber(res, "oid");
+		i_rulename = PQfnumber(res, "rulename");
 
 		/*
 		 * Dump them out
 		 */
-		for (i = 0; i < nrules; i++)
+
+		for (i = 0; i < nrules; i++) {
+			
 			fprintf(fout, "%s\n", PQgetvalue(res, i, i_definition));
 
+			/* Dump rule comments */
+
+			resetPQExpBuffer(query);
+			appendPQExpBuffer(query, "RULE %s", fmtId(PQgetvalue(res, i, i_rulename), force_quotes));
+			dumpComment(fout, query->data, PQgetvalue(res, i, i_oid));
+			
+		}
+
 		PQclear(res);
 	}
 }
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 80c6e4928cca8782f933e00fbe9d9f7fb8ac7fdd..5b5e296e5c1d3352908a513a99018caee3fa15b3 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_dump.h,v 1.45 2000/01/16 03:54:58 tgl Exp $
+ * $Id: pg_dump.h,v 1.46 2000/01/18 18:09:02 momjian Exp $
  *
  * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
  *
@@ -74,6 +74,7 @@ typedef struct _tableInfo
 								 * attribute if the value is 1, then this
 								 * attribute is an inherited attribute */
 	char	  **attnames;		/* the attribute names */
+	char      **attoids;        /* oids of the various attributes */
 	char	  **typnames;		/* fill out attributes */
 	bool	   *notnull;		/* Not null constraints of an attribute */
 	char	  **adef_expr;		/* DEFAULT expressions */
@@ -93,6 +94,8 @@ typedef struct _tableInfo
 	char	  **check_expr;		/* [CONSTRAINT name] CHECK expressions */
 	int			ntrig;			/* # of triggers */
 	char	  **triggers;		/* CREATE TRIGGER ... */
+	char      **trcomments;     /* COMMENT ON TRIGGER ... */
+	char      **troids;         /* TRIGGER oids */
     char       *primary_key;    /* PRIMARY KEY of the table, if any */
 } TableInfo;
 
@@ -104,6 +107,7 @@ typedef struct _inhInfo
 
 typedef struct _indInfo
 {
+	char       *indoid;         /* oid of the pg_class entry for the index */
 	char	   *indexrelname;	/* name of the secondary index class */
 	char	   *indrelname;		/* name of the indexed heap class */
 	char	   *indamname;		/* name of the access method (e.g. btree,
@@ -210,6 +214,7 @@ extern TableInfo *getTables(int *numTables, FuncInfo *finfo, int numFuncs);
 extern InhInfo *getInherits(int *numInherits);
 extern void getTableAttrs(TableInfo *tbinfo, int numTables);
 extern IndInfo *getIndices(int *numIndices);
+extern void dumpDBComment(FILE *outfile);
 extern void dumpTypes(FILE *fout, FuncInfo *finfo, int numFuncs,
 		  TypeInfo *tinfo, int numTypes);
 extern void dumpProcLangs(FILE *fout, FuncInfo *finfo, int numFuncs,