diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 7cb3ea430bb7968216befd4b58f83971a920a4af..20c847ea63c64d283434d3336b50a59595585f90 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.257 2002/04/29 17:30:18 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.258 2002/05/06 18:33:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -79,7 +79,7 @@ static void dumpComment(Archive *fout, const char *target, const char *oid,
 			const char *((*deps)[]));
 static void dumpOneDomain(Archive *fout, TypeInfo *tinfo);
 static void dumpSequence(Archive *fout, TableInfo tbinfo, const bool schemaOnly, const bool dataOnly);
-static void dumpACL(Archive *fout, TableInfo tbinfo);
+static void dumpACL(Archive *fout, TableInfo *tbinfo);
 static void dumpTriggers(Archive *fout, const char *tablename,
 			 TableInfo *tblinfo, int numTables);
 static void dumpRules(Archive *fout, const char *tablename,
@@ -4129,58 +4129,27 @@ GetPrivileges(Archive *AH, const char *s)
 		return strdup(aclbuf);
 }
 
-/*
- * The name says it all; a function to append a string if the dest
- * is big enough. If not, it does a realloc.
- */
-static void
-strcatalloc(char **dest, int *dSize, char *src)
-{
-	int			dLen = strlen(*dest);
-	int			sLen = strlen(src);
-
-	if ((dLen + sLen) >= *dSize)
-	{
-		*dSize = (dLen + sLen) * 2;
-		*dest = realloc(*dest, *dSize);
-	}
-	strcpy(*dest + dLen, src);
-}
-
 
 /*
  * dumpACL:
- *	  Write out grant/revoke information
- *	  Called for sequences and tables
+ *	  Write out grant/revoke information for a table, view or sequence
  */
-
 static void
-dumpACL(Archive *fout, TableInfo tbinfo)
+dumpACL(Archive *fout, TableInfo *tbinfo)
 {
-	const char *acls = tbinfo.relacl;
+	const char *acls = tbinfo->relacl;
 	char	   *aclbuf,
 			   *tok,
 			   *eqpos,
 			   *priv;
 	char	   *objoid;
-	char	   *sql;
-	char		tmp[1024];
-	int			sSize = 4096;
+	PQExpBuffer sql;
+	bool		found_owner_privs = false;
 
 	if (strlen(acls) == 0)
 		return;					/* table has default permissions */
 
-	/*
-	 * Allocate a larginsh buffer for the output SQL.
-	 */
-	sql = (char *) malloc(sSize);
-
-	/*
-	 * Revoke Default permissions for PUBLIC. Is this actually necessary,
-	 * or is it just a waste of time?
-	 */
-	sprintf(sql, "REVOKE ALL on %s from PUBLIC;\n",
-			fmtId(tbinfo.relname, force_quotes));
+	sql = createPQExpBuffer();
 
 	/* Make a working copy of acls so we can use strtok */
 	aclbuf = strdup(acls);
@@ -4202,9 +4171,10 @@ dumpACL(Archive *fout, TableInfo tbinfo)
 		if (!eqpos)
 		{
 			write_msg(NULL, "could not parse ACL list ('%s') for relation %s\n",
-					  acls, tbinfo.relname);
+					  acls, tbinfo->relname);
 			exit_nicely();
 		}
+		*eqpos = '\0';			/* it's ok to clobber aclbuf */
 
 		/*
 		 * Parse the privileges (right-hand side).	Skip if there are
@@ -4213,41 +4183,69 @@ dumpACL(Archive *fout, TableInfo tbinfo)
 		priv = GetPrivileges(fout, eqpos + 1);
 		if (*priv)
 		{
-			sprintf(tmp, "GRANT %s on %s to ",
-					priv, fmtId(tbinfo.relname, force_quotes));
-			strcatalloc(&sql, &sSize, tmp);
-
-			/*
-			 * Note: fmtId() can only be called once per printf, so don't
-			 * try to merge printing of username into the above printf.
-			 */
-			if (eqpos == tok)
+			if (strcmp(tok, tbinfo->usename) == 0)
 			{
-				/* Empty left-hand side means "PUBLIC" */
-				strcatalloc(&sql, &sSize, "PUBLIC;\n");
+				/*
+				 * For the owner, the default privilege level is ALL.
+				 */
+				found_owner_privs = true;
+				if (strcmp(priv, "ALL") != 0)
+				{
+					/* NB: only one fmtId per appendPQExpBuffer! */
+					appendPQExpBuffer(sql, "REVOKE ALL ON %s FROM ",
+									  fmtId(tbinfo->relname, force_quotes));
+					appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
+					appendPQExpBuffer(sql, "GRANT %s ON %s TO ",
+									  priv,
+									  fmtId(tbinfo->relname, force_quotes));
+					appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
+				}
 			}
 			else
 			{
-				*eqpos = '\0';	/* it's ok to clobber aclbuf */
-				if (strncmp(tok, "group ", strlen("group ")) == 0)
-					sprintf(tmp, "GROUP %s;\n",
-							fmtId(tok + strlen("group "), force_quotes));
+				/*
+				 * Otherwise can assume we are starting from no privs.
+				 */
+				appendPQExpBuffer(sql, "GRANT %s ON %s TO ",
+								  priv,
+								  fmtId(tbinfo->relname, force_quotes));
+				if (eqpos == tok)
+				{
+					/* Empty left-hand side means "PUBLIC" */
+					appendPQExpBuffer(sql, "PUBLIC;\n");
+				}
+				else if (strncmp(tok, "group ", strlen("group ")) == 0)
+					appendPQExpBuffer(sql, "GROUP %s;\n",
+									  fmtId(tok + strlen("group "),
+											force_quotes));
 				else
-					sprintf(tmp, "%s;\n", fmtId(tok, force_quotes));
-				strcatalloc(&sql, &sSize, tmp);
+					appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes));
 			}
 		}
 		free(priv);
 	}
 
+	/*
+	 * If we didn't find any owner privs, the owner must have revoked 'em all
+	 */
+	if (!found_owner_privs && *tbinfo->usename)
+	{
+		appendPQExpBuffer(sql, "REVOKE ALL ON %s FROM ",
+						  fmtId(tbinfo->relname, force_quotes));
+		appendPQExpBuffer(sql, "%s;\n", fmtId(tbinfo->usename, force_quotes));
+	}
+
 	free(aclbuf);
 
-	if (tbinfo.viewdef != NULL)
-		objoid = tbinfo.viewoid;
+	if (tbinfo->viewdef != NULL)
+		objoid = tbinfo->viewoid;
 	else
-		objoid = tbinfo.oid;
+		objoid = tbinfo->oid;
+
+	ArchiveEntry(fout, objoid, tbinfo->relname, "ACL",
+				 NULL, sql->data, "", "", "", NULL, NULL);
 
-	ArchiveEntry(fout, objoid, tbinfo.relname, "ACL", NULL, sql, "", "", "", NULL, NULL);
+	destroyPQExpBuffer(sql);
 }
 
 static void
@@ -4350,7 +4348,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
 			/* becomeUser(fout, tblinfo[i].usename); */
 			dumpSequence(fout, tblinfo[i], schemaOnly, dataOnly);
 			if (!aclsSkip)
-				dumpACL(fout, tblinfo[i]);
+				dumpACL(fout, &tblinfo[i]);
 		}
 	}
 	if (serialSeq)
@@ -4486,7 +4484,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
 							 NULL, NULL);
 
 				if (!aclsSkip)
-					dumpACL(fout, tblinfo[i]);
+					dumpACL(fout, &tblinfo[i]);
 
 			}